Fix arcs on outer angle dimensions
This commit is contained in:
committed by
Yorik van Havre
parent
cbd9eb18c6
commit
9b2fec818c
@@ -389,7 +389,7 @@ void QGIViewDimension::draw()
|
||||
normExt = Base::Vector3d (-dirExt.y,dirExt.x, 0); //normal to extension lines (req'd?)
|
||||
|
||||
// Get magnitude of angle between dimension line and horizontal
|
||||
double angle = atan2f(dirDim.y,dirDim.x);
|
||||
double angle = atan2(dirDim.y,dirDim.x);
|
||||
if (angle < 0.0) {
|
||||
angle = 2 * M_PI + angle; //map to +ve angle
|
||||
}
|
||||
@@ -915,70 +915,79 @@ void QGIViewDimension::draw()
|
||||
} else if(strcmp(dimType, "Angle") == 0) {
|
||||
// Only use two straight line edeges for angle
|
||||
anglePoints pts = dim->getAnglePoints();
|
||||
Base::Vector3d X(1.0,0.0,0.0);
|
||||
Base::Vector3d vertex = Rez::guiX(pts.vertex);
|
||||
Base::Vector3d legEnd0 = Rez::guiX(pts.ends.first);
|
||||
Base::Vector3d legEnd1 = Rez::guiX(pts.ends.second);
|
||||
Base::Vector3d p0 = vertex;
|
||||
Base::Vector3d dir1 = legEnd0 - vertex;
|
||||
Base::Vector3d dir2 = legEnd1 - vertex;
|
||||
Base::Vector3d dir0 = legEnd0 - vertex;
|
||||
Base::Vector3d dir1 = legEnd1 - vertex;
|
||||
Base::Vector3d d0 = dir0;
|
||||
d0.Normalize();
|
||||
Base::Vector3d d1 = dir1;
|
||||
d1.Normalize();
|
||||
Base::Vector3d leg0 = dir0;
|
||||
Base::Vector3d leg1 = dir1;
|
||||
// Qt y coordinates are flipped
|
||||
dir0.y *= -1.;
|
||||
dir1.y *= -1.;
|
||||
dir2.y *= -1.;
|
||||
|
||||
Base::Vector3d labelVec = (lblCenter - p0);
|
||||
double insideAngle = dir0.GetAngle(dir1); // [0,PI]
|
||||
double outsideAngle = 2*M_PI - insideAngle; // [PI,2PI]
|
||||
Base::Vector3d tempCross = d0.Cross(d1);
|
||||
double insideDir = tempCross.z;
|
||||
bool ccwInner = true;
|
||||
if (insideDir > 0.0) {
|
||||
ccwInner = false;
|
||||
}
|
||||
|
||||
Base::Vector3d labelVec = (lblCenter - vertex); //dir from label to vertex
|
||||
QFontMetrics fm(datumLabel->font());
|
||||
int h = fm.height();
|
||||
double radius = labelVec.Length();
|
||||
radius -= h * 0.6; // Adjust the radius so the label isn't over the line
|
||||
|
||||
double labelangle = atan2(-labelVec.y, labelVec.x); //angle with +X axis on [-PI,+PI]
|
||||
if (labelangle < 0) { //map to [0,2PI)
|
||||
labelangle += 2.0 * M_PI;
|
||||
}
|
||||
|
||||
double startangle = atan2(dir1.y,dir1.x);
|
||||
double range = atan2(-dir1.y*dir2.x+dir1.x*dir2.y,
|
||||
dir1.x*dir2.x+dir1.y*dir2.y);
|
||||
QRectF arcRect(vertex.x - radius, vertex.y - radius, 2. * radius, 2. * radius);
|
||||
Base::Vector3d ar0Pos = vertex + d0 * radius;
|
||||
Base::Vector3d ar1Pos = vertex + d1 * radius;
|
||||
|
||||
double endangle = startangle + range;
|
||||
|
||||
float bbX = datumLabel->boundingRect().width();
|
||||
float bbY = datumLabel->boundingRect().height();
|
||||
|
||||
// Get font height
|
||||
QFontMetrics fm(datumLabel->font());
|
||||
|
||||
int h = fm.height();
|
||||
double length = labelVec.Length();
|
||||
length -= h * 0.6; // Adjust the length so the label isn't over the line
|
||||
|
||||
Base::Vector3d p1 = legEnd0;
|
||||
Base::Vector3d p2 = legEnd1;
|
||||
double startangle = atan2(dir0.y,dir0.x);
|
||||
if (startangle < 0) {
|
||||
startangle += 2.0 * M_PI;
|
||||
}
|
||||
double endangle = atan2(dir1.y,dir1.x);
|
||||
if (endangle < 0) {
|
||||
endangle += 2.0 * M_PI;
|
||||
}
|
||||
|
||||
Base::Vector3d startExt0 = legEnd0;
|
||||
Base::Vector3d startExt1 = legEnd1;
|
||||
// add an offset from the ends
|
||||
p1 += (p1-p0).Normalize() * 5.;
|
||||
p2 += (p2-p0).Normalize() * 5.;
|
||||
|
||||
Base::Vector3d ar1Pos = p0;
|
||||
Base::Vector3d ar2Pos = p0;
|
||||
|
||||
ar1Pos += Base::Vector3d(cos(startangle) * length, -sin(startangle) * length, 0.);
|
||||
ar2Pos += Base::Vector3d(cos(endangle) * length , -sin(endangle) * length, 0.);
|
||||
double offsetFudge = 5.0;
|
||||
startExt0 += d0 * offsetFudge;
|
||||
startExt1 += d1 * offsetFudge;
|
||||
|
||||
// Draw the path
|
||||
QPainterPath path;
|
||||
|
||||
// Only draw extension lines if outside arc
|
||||
if(length > (p1-p0).Length()) {
|
||||
path.moveTo(p1.x, p1.y);
|
||||
p1 = ar1Pos + (p1-p0).Normalize() * Rez::guiX(5.); //a bit past arrow head on leg 1
|
||||
path.lineTo(p1.x, p1.y);
|
||||
double extFudge = 5.0;
|
||||
if(radius > (startExt0-vertex).Length()) {
|
||||
path.moveTo(startExt0.x, startExt0.y);
|
||||
Base::Vector3d endExt0 = ar0Pos + d0*Rez::guiX(extFudge);
|
||||
path.lineTo(endExt0.x, endExt0.y);
|
||||
}
|
||||
|
||||
if(length > (p2-p0).Length()) {
|
||||
path.moveTo(p2.x, p2.y);
|
||||
p2 = ar2Pos + (p2-p0).Normalize() * Rez::guiX(5.); //a bit past leg 2 arrow head on leg 2
|
||||
path.lineTo(p2.x, p2.y);
|
||||
if(radius > (startExt1-vertex).Length()) {
|
||||
path.moveTo(startExt1.x, startExt1.y);
|
||||
Base::Vector3d endExt1 = ar1Pos + d1*Rez::guiX(extFudge);
|
||||
path.lineTo(endExt1.x, endExt1.y);
|
||||
}
|
||||
|
||||
|
||||
bool isOutside = true; //label is outside angle end-vertex-end?
|
||||
|
||||
// TODO find a better solution for this. Addmitedely not tidy
|
||||
// ###############
|
||||
// Treat zero as positive to be consistent for horizontal lines
|
||||
if(std::abs(startangle) < FLT_EPSILON)
|
||||
startangle = 0;
|
||||
@@ -986,60 +995,38 @@ void QGIViewDimension::draw()
|
||||
if(std::abs(endangle) < FLT_EPSILON)
|
||||
endangle = 0;
|
||||
|
||||
if(startangle >= 0 && endangle >= 0) { //Both are in positive side
|
||||
double langle = labelangle;
|
||||
if(labelangle < 0)
|
||||
langle += M_PI * 2;
|
||||
if(endangle - startangle > 0) {
|
||||
if(langle > startangle && langle < endangle)
|
||||
isOutside = false;
|
||||
} else {
|
||||
if(langle < startangle && langle > endangle)
|
||||
isOutside = false;
|
||||
}
|
||||
} else if(startangle < 0 && endangle < 0) { //both are in negative side
|
||||
double langle = labelangle;
|
||||
if(labelangle > 0)
|
||||
langle -= M_PI * 2;
|
||||
if(endangle - startangle < 0) {
|
||||
if(langle > endangle && langle < startangle) //clockwise
|
||||
isOutside = false;
|
||||
} else {
|
||||
if(langle < endangle && langle > startangle) //anticlockwise
|
||||
isOutside = false;
|
||||
}
|
||||
} else if(startangle >= 0 && endangle < 0) {
|
||||
if(labelangle < startangle && labelangle > endangle) //clockwise
|
||||
isOutside = false;
|
||||
|
||||
} else if(startangle < 0 && endangle >= 0) {
|
||||
//Both are in positive side
|
||||
|
||||
if(labelangle > startangle && labelangle < endangle) //clockwise
|
||||
isOutside = false;
|
||||
//https://stackoverflow.com/questions/13640931/how-to-determine-if-a-vector-is-between-two-other-vectors
|
||||
bool isOutside = true;
|
||||
if ( ((d0.Cross(labelVec)).Dot(d0.Cross(d1)) >= 0.0) &&
|
||||
((d1.Cross(labelVec)).Dot(d1.Cross(d0)) >= 0.0) ) {
|
||||
isOutside = false;
|
||||
}
|
||||
|
||||
QRectF arcRect(p0.x - length, p0.y - length, 2. * length, 2. * length);
|
||||
path.arcMoveTo(arcRect, endangle * 180 / M_PI);
|
||||
double innerAngle = fabs(endangle - startangle) * 180.0/M_PI;
|
||||
double outerAngle = 360.0 - innerAngle;
|
||||
path.arcMoveTo(arcRect, startangle * 180 / M_PI);
|
||||
double actualSweep = 0.0;
|
||||
if(isOutside) {
|
||||
updateDim(true);
|
||||
if(labelangle > endangle)
|
||||
{
|
||||
path.arcMoveTo(arcRect, endangle * 180 / M_PI);
|
||||
path.arcTo(arcRect, endangle * 180 / M_PI, - outerAngle);
|
||||
} else {
|
||||
path.arcMoveTo(arcRect, startangle * 180 / M_PI);
|
||||
path.arcTo(arcRect, startangle * 180 / M_PI, outerAngle);
|
||||
if (ccwInner) { //inner is ccw so outer is cw and sweep is -ve
|
||||
actualSweep = -outsideAngle;
|
||||
} else { //inner is cw so outer is ccw and sweep is +ve
|
||||
actualSweep = outsideAngle;
|
||||
}
|
||||
} else {
|
||||
updateDim(false);
|
||||
path.arcTo(arcRect, endangle * 180 / M_PI, -range * 180 / M_PI);
|
||||
if (ccwInner) { //inner is ccw and sweep is +ve
|
||||
actualSweep = insideAngle;
|
||||
} else { //inner is cw and sweep is -ve
|
||||
actualSweep = -insideAngle;
|
||||
}
|
||||
}
|
||||
path.arcTo(arcRect, startangle * 180 / M_PI, actualSweep*180.0/M_PI);
|
||||
|
||||
dimLines->setPath(path);
|
||||
|
||||
// aHead1->setDirMode(true);
|
||||
// aHead2->setDirMode(true);
|
||||
// aHead1->setDirection(a1Dir);
|
||||
// aHead2->setDirection(a2Dir);
|
||||
aHead1->flip(true);
|
||||
aHead1->setStyle(QGIArrow::getPrefArrowStyle());
|
||||
aHead1->setSize(QGIArrow::getPrefArrowSize());
|
||||
@@ -1048,26 +1035,25 @@ void QGIViewDimension::draw()
|
||||
aHead2->setSize(QGIArrow::getPrefArrowSize());
|
||||
aHead2->draw();
|
||||
|
||||
Base::Vector3d norm1 = p1-p0; //(-dir1.y, dir1.x, 0.);
|
||||
Base::Vector3d norm2 = p2-p0; //(-dir2.y, dir2.x, 0.);
|
||||
aHead1->setPos(ar0Pos.x,ar0Pos.y );
|
||||
aHead2->setPos(ar1Pos.x,ar1Pos.y );
|
||||
|
||||
Base::Vector3d avg = (norm1 + norm2) / 2.;
|
||||
Base::Vector3d norm1 = leg0;
|
||||
Base::Vector3d norm2 = leg1;
|
||||
Base::Vector3d avg = (norm1 + norm2) / 2.; //midline of legs
|
||||
|
||||
norm1 = norm1.ProjectToLine(avg, norm1);
|
||||
norm2 = norm2.ProjectToLine(avg, norm2);
|
||||
|
||||
aHead1->setPos(ar1Pos.x,ar1Pos.y );
|
||||
aHead2->setPos(ar2Pos.x,ar2Pos.y );
|
||||
|
||||
float ar1angle = atan2(-norm1.y, -norm1.x) * 180 / M_PI;
|
||||
float ar2angle = atan2(norm2.y, norm2.x) * 180 / M_PI;
|
||||
float ar0angle = atan2(-norm1.y, -norm1.x) * 180 / M_PI;
|
||||
float ar1angle = atan2(norm2.y, norm2.x) * 180 / M_PI;
|
||||
|
||||
if(isOutside) {
|
||||
aHead1->setRotation(ar1angle + 180.);
|
||||
aHead2->setRotation(ar2angle + 180.);
|
||||
aHead1->setRotation(ar0angle + 180.);
|
||||
aHead2->setRotation(ar1angle + 180.);
|
||||
} else {
|
||||
aHead1->setRotation(ar1angle);
|
||||
aHead2->setRotation(ar2angle);
|
||||
aHead1->setRotation(ar0angle);
|
||||
aHead2->setRotation(ar1angle);
|
||||
}
|
||||
|
||||
// Set the angle of the dimension text
|
||||
@@ -1082,8 +1068,9 @@ void QGIViewDimension::draw()
|
||||
lAngle += M_PI; // langle + 180 Flip
|
||||
}
|
||||
|
||||
float bbX = datumLabel->boundingRect().width();
|
||||
float bbY = datumLabel->boundingRect().height();
|
||||
datumLabel->setTransformOriginPoint(bbX / 2., bbY /2.);
|
||||
|
||||
datumLabel->setRotation(lAngle * 180 / M_PI);
|
||||
|
||||
} //endif Distance/Diameter/Radius/Angle
|
||||
|
||||
Reference in New Issue
Block a user