Fix text position in Diamter Dim

This commit is contained in:
wandererfan
2018-07-30 11:42:06 -04:00
committed by Yorik van Havre
parent 4046b001b5
commit cd0b26a69c

View File

@@ -530,57 +530,64 @@ void QGIViewDimension::draw()
} else if(strcmp(dimType, "Diameter") == 0) {
// terminology: Dimension Text, Dimension Line(s), Extension Lines, Arrowheads
// was datumLabel, datum line/parallel line, perpendicular line, arw
Base::Vector3d arrow1Tip, arrow2Tip, dirDimLine; //was p1,p2,dir
Base::Vector3d arrow1Tip, arrow2Tip;
Base::Vector3d arrow1Tail, arrow2Tail;
Base::Vector3d arrow1Dir,arrow2Dir;
double radius;
Base::Vector3d pointOnCurve,curveCenter;
Base::Vector3d startExt1,endExt1,startExt2,endExt2;
arcPoints pts = dim->getArcPoints();
bool isArc = pts.isArc;
radius = Rez::guiX(pts.radius);
curveCenter = Rez::guiX(pts.center);
pointOnCurve = Rez::guiX(pts.onCurve.first);
// Note Bounding Box size is not the same width or height as text (only used for finding center)
float bbX = datumLabel->boundingRect().width();
float bbY = datumLabel->boundingRect().height();
dirDimLine = (lblCenter - curveCenter).Normalize(); //if lblCenter == curveCenter, this is (0,0,0)??
if (fabs(dirDimLine.Length()) < (Precision::Confusion())) {
dirDimLine = Base::Vector3d(-1.0,0.0,0.0);
Base::Vector3d startDist,endDist,dirDim;
startDist = Rez::guiX(pts.onCurve.first);
endDist = Rez::guiX(pts.onCurve.second);
dirDim = endDist - startDist;
if (fabs(dirDim.Length()) < Precision::Confusion()) {
dirDim = Base::Vector3d(1.0,0.0,0.0);
}
dirDim.Normalize();
Base::Vector3d fauxCenter = lblCenter;
//this is for inner placement only? recalced for outer?
arrow1Tip = curveCenter - dirDimLine * radius; //endpoint of diameter arrowhead1
arrow2Tip = curveCenter + dirDimLine * radius; //endpoint of diameter arrowhead2
//default arrow endpoints
arrow1Tip = curveCenter - dirDim * radius;
arrow2Tip = curveCenter + dirDim * radius;
arrow1Tail = curveCenter;
arrow2Tail = curveCenter;
QFontMetrics fm(datumLabel->font());
int textWidth = fm.width(labelText);
int charWidth = fm.width(QString::fromLatin1("M")); //full width character
int w = fm.width(labelText);
//int h = fm.height();
margin = Rez::guiX(5.f);
// Calculate the dimension line endpoints
// recalced for vert & horizontal snap & inner placement. not used for nosnap outer?
Base::Vector3d dLine1Tail = lblCenter - dirDimLine * (margin + w / 2); //position of tail of 1st dimension line
Base::Vector3d dLine2Tail = lblCenter + dirDimLine * (margin + w / 2);
double gapMargin = Rez::guiX(4.f);
margin = Rez::guiX(2.f);
float scaler = 1.;
double tip = (margin * scaler);
double gap = (gapMargin * scaler); //sb % of radius?
//offset of dimLine from dimText
double offsetFudge = 2.0;
double vertOffset = 1.0 * Rez::guiX(vp->Fontsize.getValue()) + offsetFudge;
double horizOffset = 1.0 * (textWidth/2.0) + (0.5 * charWidth) + offsetFudge; //a bit tight w/o more fudge
bool outerPlacement = false;
if ((lblCenter-curveCenter).Length() > radius) { //label is outside circle
outerPlacement = true;
}
// Reset transformation origin for datum label
// // Note Bounding Box size is not the same width or height as text (only used for finding center)
float bbX = datumLabel->boundingRect().width();
float bbY = datumLabel->boundingRect().height();
datumLabel->setTransformOriginPoint(bbX / 2, bbY /2);
int posMode = NoSnap;
bool isLeader = false;
QPainterPath path;
if(outerPlacement) {
// Select whether to snap vertically or hoziontally given tolerance
Base::Vector3d v = (lblCenter-arrow1Tip);
Base::Vector3d v = (lblCenter - curveCenter);
double angle = atan2(v.y, v.x);
double tolerance = 15.0; //deg
@@ -594,141 +601,169 @@ void QGIViewDimension::draw()
}
if(posMode == VerticalSnap) {
float tip = (lblCenter.y > curveCenter.y) ? margin: -margin;
//tip *= 0.5;
if (lblCenter.y > curveCenter.y) {
tip = tip;
gap = gap;
fauxCenter = Base::Vector3d(lblCenter.x,lblCenter.y + vertOffset,lblCenter.z);
} else {
tip = -tip;
gap = -gap;
fauxCenter = Base::Vector3d(lblCenter.x,lblCenter.y + vertOffset,lblCenter.z);
}
arrow1Tip.x = curveCenter.x - radius; //to left, on circle cl
arrow1Tip.y = lblCenter.y;
arrow1Tip.y = fauxCenter.y;
arrow1Tail.x = curveCenter.x;
arrow1Tail.y = arrow1Tip.y;
arrow1Dir = (arrow1Tip - arrow1Tail).Normalize();
path.moveTo(arrow1Tail.x, arrow1Tail.y);
path.lineTo(arrow1Tip.x, arrow1Tip.y);
arrow2Tip.x = curveCenter.x + radius;
arrow2Tip.y = lblCenter.y;
dLine1Tail = lblCenter;
dLine1Tail.x -= (margin + w / 2); //to left, on label cl
dLine2Tail = lblCenter;
dLine2Tail.x += (margin + w / 2);
// Extension line 1
path.moveTo(curveCenter.x - radius, curveCenter.y);
path.lineTo(arrow1Tip.x, arrow1Tip.y + tip);
path.moveTo(arrow1Tip.x, arrow1Tip.y); //dimension line, not arrowhead
path.lineTo(dLine1Tail.x, dLine1Tail.y);
// Extension line 2
path.moveTo(curveCenter.x + radius, curveCenter.y);
path.lineTo(arrow2Tip.x, arrow2Tip.y + tip);
path.moveTo(dLine2Tail.x, dLine2Tail.y);
arrow2Tip.y = fauxCenter.y;
arrow2Tail.x = curveCenter.x;
arrow2Tail.y = arrow2Tip.y;
arrow2Dir = (arrow2Tip - arrow2Tail).Normalize();
path.moveTo(arrow2Tail.x, arrow2Tail.y);
path.lineTo(arrow2Tip.x, arrow2Tip.y);
startExt1.x = curveCenter.x - radius;
startExt1.y = curveCenter.y + gap;
endExt1.x = startExt1.x;
endExt1.y = fauxCenter.y + tip;
startExt2.x = curveCenter.x + radius;
startExt2.y = curveCenter.y + gap;
endExt2.x = startExt2.x;
endExt2.y = fauxCenter.y + tip;
path.moveTo(startExt1.x, startExt1.y);
path.lineTo(endExt1.x, endExt1.y);
path.moveTo(startExt2.x, startExt2.y);
path.lineTo(endExt2.x, endExt2.y);
datumLabel->setRotation(0.);
} else if(posMode == HorizontalSnap) {
// Snapped Horizontally
float tip = (lblCenter.x > curveCenter.x) ? margin: -margin;
//tip *= 0.5;
if (lblCenter.x > curveCenter.x) {
tip = tip;
gap = gap;
fauxCenter = Base::Vector3d(lblCenter.x - horizOffset,lblCenter.y,lblCenter.z);
} else {
tip = -tip;
gap = -gap;
fauxCenter = Base::Vector3d(lblCenter.x + horizOffset,lblCenter.y,lblCenter.z);
}
arrow1Tip.x = fauxCenter.x;
arrow1Tip.y = curveCenter.y - radius;
arrow1Tip.x = lblCenter.x;
arrow1Tail.x = arrow1Tip.x;
arrow1Tail.y = curveCenter.y;
arrow1Dir = (arrow1Tip - arrow1Tail).Normalize();
path.moveTo(arrow1Tail.x, arrow1Tail.y);
path.lineTo(arrow1Tip.x, arrow1Tip.y);
arrow2Tip.x = fauxCenter.x;
arrow2Tip.y = curveCenter.y + radius;
arrow2Tip.x = lblCenter.x;
dLine1Tail = lblCenter;
dLine1Tail.y -= (margin + w / 2);
dLine2Tail = lblCenter;
dLine2Tail.y += (margin + w / 2);
// Extension lines
path.moveTo(curveCenter.x, curveCenter.y - radius);
path.lineTo(arrow1Tip.x + tip, arrow1Tip.y);
path.moveTo(arrow1Tip.x, arrow1Tip.y);
path.lineTo(dLine1Tail.x, dLine1Tail.y);
// Extension lines
path.moveTo(curveCenter.x, curveCenter.y + radius);
path.lineTo(arrow2Tip.x + tip, arrow2Tip.y);
path.moveTo(dLine2Tail.x, dLine2Tail.y);
arrow2Tail.x = arrow2Tip.x;
arrow2Tail.y = curveCenter.y;
arrow2Dir = (arrow2Tip - arrow2Tail).Normalize();
path.moveTo(arrow2Tail.x, arrow2Tail.y);
path.lineTo(arrow2Tip.x, arrow2Tip.y);
datumLabel->setRotation(-90.);
startExt1.x = curveCenter.x + gap;
startExt1.y = curveCenter.y - radius;
endExt1.x = fauxCenter.x + tip;
endExt1.y = startExt1.y;
startExt2.x = curveCenter.x + gap;
startExt2.y = curveCenter.y + radius;
endExt2.x = fauxCenter.x + tip;
endExt2.y = startExt2.y;
path.moveTo(startExt1.x, startExt1.y);
path.lineTo(endExt1.x, endExt1.y);
path.moveTo(startExt2.x, startExt2.y);
path.lineTo(endExt2.x, endExt2.y);
datumLabel->setRotation(0.0);
} else { //outer placement, NoSnap
float tip = (margin + w / 2); // spacer + 0.5*lblText.width() tip is actually tail?
tip = (lblCenter.x < curveCenter.x) ? tip : -tip; //if label on left then tip is +ve (ie to right)
isLeader = true;
float spacer = (margin + textWidth / 2);
spacer = (lblCenter.x < curveCenter.x) ? spacer : -spacer;
arrow1Tip = lblCenter; //this tip is really tail(ie end near lblText)
arrow1Tip.x += tip;
arrow1Tail = lblCenter;
arrow1Tail.x += spacer;
Base::Vector3d kinkPoint = arrow1Tail;
kinkPoint.x += (lblCenter.x < curveCenter.x) ? margin : - margin;
Base::Vector3d p3 = arrow1Tip;
p3.x += (lblCenter.x < curveCenter.x) ? margin : - margin; // p3 is a little farther away from lblText towards curveCenter in X
arrow1Tip = curveCenter + (kinkPoint - curveCenter).Normalize() * radius;
arrow2Tip = curveCenter + (p3 - curveCenter).Normalize() * radius; //point on curve aimed just short of label text
path.moveTo(arrow1Tip.x, arrow1Tip.y);
path.lineTo(p3[0], p3[1]);
path.lineTo(arrow2Tip.x, arrow2Tip.y);
path.moveTo(arrow1Tail.x, arrow1Tail.y);
path.lineTo(kinkPoint.x, kinkPoint.y);
path.lineTo(arrow1Tip.x, arrow1Tip.y);
arrow1Dir = (arrow1Tip - kinkPoint).Normalize();
datumLabel->setRotation(0.);
}
} else { //NOT outerplacement ie dimLines are inside circle
//text always rightside up inside circle
datumLabel->setRotation(0);
dLine1Tail = curveCenter - dirDimLine * margin;
dLine2Tail = curveCenter + dirDimLine * margin;
dirDim = (lblCenter - curveCenter).Normalize();
if (fabs(dirDim.Length()) < (Precision::Confusion())) {
dirDim = Base::Vector3d(-1.0,0.0,0.0);
}
arrow1Tip = curveCenter - dirDim * radius;
arrow1Tail = curveCenter;
arrow1Dir = (arrow1Tip - arrow1Tail).Normalize();
arrow2Tip = curveCenter + dirDim * radius;
arrow2Tail = curveCenter;
arrow2Dir = (arrow2Tip - arrow2Tail).Normalize();
path.moveTo(arrow1Tip.x, arrow1Tip.y);
path.lineTo(dLine1Tail.x, dLine1Tail.y);
path.moveTo(arrow1Tail.x, arrow1Tail.y);
path.lineTo(arrow1Tip.x, arrow1Tip.y);
path.moveTo(dLine2Tail.x, dLine2Tail.y);
path.moveTo(arrow2Tail.x, arrow2Tail.y);
path.lineTo(arrow2Tip.x, arrow2Tip.y);
}
aHead1->setStyle(QGIArrow::getPrefArrowStyle());
aHead1->setSize(QGIArrow::getPrefArrowSize());
aHead1->draw();
aHead2->flip(true);
aHead2->setStyle(QGIArrow::getPrefArrowStyle());
aHead2->setSize(QGIArrow::getPrefArrowSize());
aHead2->draw();
float arAngle = atan2(dirDimLine.y, dirDimLine.x) * 180 / M_PI;
aHead2->show();
if (!isLeader) {
aHead2->setStyle(QGIArrow::getPrefArrowStyle());
aHead2->setSize(QGIArrow::getPrefArrowSize());
}
//handle partial arc weird cases
//TODO: does anybody dimension Arcs with Diameter? doesn't Radius make more sense?
Base::Vector3d dLineStart;
Base::Vector3d kinkPoint;
margin = Rez::guiX(5.f); //space around label
double kinkLength = Rez::guiX(5.0); //sb % of horizontal dist(lblCenter,curveCenter)???
margin = Rez::guiX(5.f);
double kinkLength = Rez::guiX(5.0); //sb % of horizontal dist(lblCenter,curveCenter)???
QPainterPath arcPath;
if (isArc) {
aHead2->hide();
aHead1->flip(true);
aHead1->draw();
if (lblCenter.x > curveCenter.x) { // label to right of vert c/l
tip = tip;
gap = gap;
fauxCenter = Base::Vector3d(lblCenter.x - horizOffset,lblCenter.y,lblCenter.z);
kinkPoint = Base::Vector3d(fauxCenter.x - kinkLength,fauxCenter.y,fauxCenter.z);
} else {
tip = -tip;
gap = -gap;
fauxCenter = Base::Vector3d(lblCenter.x + horizOffset,lblCenter.y,lblCenter.z);
kinkPoint = Base::Vector3d(fauxCenter.x + kinkLength,fauxCenter.y,fauxCenter.z);
}
dirDim = (kinkPoint - curveCenter).Normalize();
pointOnCurve = curveCenter + (dirDim * radius);
Base::Vector3d startPt = Rez::guiX(pts.arcEnds.first);
Base::Vector3d endPt = Rez::guiX(pts.arcEnds.second);
kinkLength = (lblCenter.x < curveCenter.x) ? kinkLength : -kinkLength;
dirDimLine = lblCenter - curveCenter;
dirDimLine.Normalize();
Base::Vector3d labelEndDir(1.0,0.0,0.0);
if (lblCenter.x > pointOnCurve.x) { //label is to right of point
labelEndDir = -1.0 * labelEndDir;
}
dLineStart = lblCenter + labelEndDir * (margin + w / 2);
kinkPoint.y = dLineStart.y;
kinkPoint.x = dLineStart.x + kinkLength;
pointOnCurve = curveCenter + dirDimLine * radius;
if (!dim->leaderIntersectsArc(Rez::appX(dLineStart),Rez::appX(pointOnCurve))) { //keep pathological case within arc
if (!dim->leaderIntersectsArc(Rez::appX(kinkPoint),Rez::appX(pointOnCurve))) { //keep point within arc
if ((pointOnCurve - endPt).Length() < (pointOnCurve - startPt).Length()) {
if (!pts.arcCW ) {
pointOnCurve = endPt;
@@ -743,42 +778,54 @@ void QGIViewDimension::draw()
}
}
}
Base::Vector3d arVector = (kinkPoint - pointOnCurve);
arVector.Normalize();
arAngle = atan2(arVector.y, arVector.x) * 180 / M_PI;
path = QPainterPath();
path.moveTo(dLineStart.x,dLineStart.y);
path.lineTo(kinkPoint.x,kinkPoint.y);
path.lineTo(pointOnCurve.x,pointOnCurve.y);
arcPath.moveTo(fauxCenter.x,fauxCenter.y);
arcPath.lineTo(kinkPoint.x,kinkPoint.y);
arcPath.lineTo(pointOnCurve.x,pointOnCurve.y);
arrow1Dir = (pointOnCurve - kinkPoint).Normalize();
datumLabel->setRotation(0.);
}
dimLines->setPath(path);
if (isArc) {
dimLines->setPath(arcPath);
aHead1->setPos(pointOnCurve.x, pointOnCurve.y);
aHead1->setRotation(arAngle);
aHead1->setDirMode(true);
aHead1->setDirection(arrow1Dir);
aHead1->draw();
aHead1->show();
aHead2->hide();
} else if(outerPlacement) {
if(posMode > NoSnap) {
aHead1->setPos(arrow2Tip.x, arrow2Tip.y); //arrow 1's endpoint is arrow2Tip!?
aHead2->setPos(arrow1Tip.x, arrow1Tip.y);
aHead1->setRotation((posMode == HorizontalSnap) ? 90 : 0);
aHead2->setRotation((posMode == HorizontalSnap) ? 90 : 0);
} else {
Base::Vector3d vec = (arrow2Tip - curveCenter).Normalize();
float arAngle = atan2(-vec.y, -vec.x) * 180 / M_PI;
aHead1->setPos(arrow2Tip.x, arrow2Tip.y);
aHead1->setRotation(arAngle);
aHead2->hide(); //only 1 arrowhead for NoSnap + outerplacement (ie a leader)
if(posMode > NoSnap) { // Horizontal or Vertical snap
aHead1->setPos(arrow1Tip.x, arrow1Tip.y);
aHead1->setDirMode(true);
aHead1->setDirection(arrow1Dir);
aHead1->draw();
aHead1->show();
aHead2->setPos(arrow2Tip.x, arrow2Tip.y);
aHead2->setDirMode(true);
aHead2->setDirection(arrow2Dir);
aHead2->draw();
aHead2->show();
} else { //leader stye
aHead1->setPos(arrow1Tip.x, arrow1Tip.y);
aHead1->setDirMode(true);
aHead1->setDirection(arrow1Dir);
aHead1->draw();
aHead1->show();
aHead2->hide(); //only 1 arrowhead for NoSnap + outerplacement (ie a leader)
}
} else {
aHead1->setRotation(arAngle);
aHead2->setRotation(arAngle);
aHead1->setPos(arrow2Tip.x, arrow2Tip.y);
} else { //inner placement
aHead1->setPos(arrow1Tip.x, arrow1Tip.y);
aHead1->setDirMode(true);
aHead1->setDirection(arrow1Dir);
aHead1->draw();
aHead1->show();
aHead2->setPos(arrow2Tip.x, arrow2Tip.y);
aHead2->setDirMode(true);
aHead2->setDirection(arrow2Dir);
aHead2->draw();
aHead2->show();
aHead2->setPos(arrow1Tip.x, arrow1Tip.y);
}
// if (dim->CentreLines.getValue()) {