diff --git a/src/Mod/TechDraw/App/DrawUtil.cpp b/src/Mod/TechDraw/App/DrawUtil.cpp index 7427b93047..3bad4b48b8 100644 --- a/src/Mod/TechDraw/App/DrawUtil.cpp +++ b/src/Mod/TechDraw/App/DrawUtil.cpp @@ -437,6 +437,45 @@ double DrawUtil::getDefaultLineWeight(std::string lineType) return weight; } +bool DrawUtil::isBetween(const Base::Vector3d pt, const Base::Vector3d end1, const Base::Vector3d end2) +{ + bool result = false; + double segLength = (end2 - end1).Length(); + double l1 = (pt - end1).Length(); + double l2 = (pt - end2).Length(); + if (fpCompare(segLength,l1 + l2)) { + result = true; + } + return result; +} + +Base::Vector3d DrawUtil::Intersect2d(Base::Vector3d p1, Base::Vector3d d1, + Base::Vector3d p2, Base::Vector3d d2) +{ + Base::Vector3d result(0,0,0); + Base::Vector3d p12(p1.x+d1.x, p1.y+d1.y, 0.0); + double A1 = d1.y; + double B1 = -d1.x; + double C1 = A1*p1.x + B1*p1.y; + + Base::Vector3d p22(p2.x+d2.x, p2.y+d2.y, 0.0); + double A2 = d2.y; + double B2 = -d2.x; + double C2 = A2*p2.x + B2*p2.y; + + double det = A1*B2 - A2*B1; + if(det == 0){ + Base::Console().Message("Lines are parallel\n"); + }else{ + double x = (B2*C1 - B1*C2)/det; + double y = (A1*C2 - A2*C1)/det; + result.x = x; + result.y = y; + } + + return result; +} + //============================ // various debugging routines. void DrawUtil::dumpVertexes(const char* text, const TopoDS_Shape& s) diff --git a/src/Mod/TechDraw/App/DrawUtil.h b/src/Mod/TechDraw/App/DrawUtil.h index 1a9234845a..a54f6c0912 100644 --- a/src/Mod/TechDraw/App/DrawUtil.h +++ b/src/Mod/TechDraw/App/DrawUtil.h @@ -77,7 +77,11 @@ class TechDrawExport DrawUtil { static double getDefaultLineWeight(std::string s); static Base::Vector3d vector23(const Base::Vector2d& v2) { return Base::Vector3d(v2.x,v2.y,0.0); } static Base::Vector2d vector32(const Base::Vector3d& v3) { return Base::Vector2d(v3.x,v3.y); } - + //! is pt between end1 and end2? + static bool isBetween(const Base::Vector3d pt, const Base::Vector3d end1, const Base::Vector3d end2); + //! find intersection in 2d for 2 lines in point+direction form + static Base::Vector3d Intersect2d(Base::Vector3d p1, Base::Vector3d d1, + Base::Vector3d p2, Base::Vector3d d2); //debugging routines diff --git a/src/Mod/TechDraw/App/DrawViewPart.cpp b/src/Mod/TechDraw/App/DrawViewPart.cpp index f51122788a..71264c2ed2 100644 --- a/src/Mod/TechDraw/App/DrawViewPart.cpp +++ b/src/Mod/TechDraw/App/DrawViewPart.cpp @@ -807,6 +807,17 @@ void DrawViewPart::unsetupObject() } +//! is this an Isometric projection? +bool DrawViewPart::isIso(void) const +{ + bool result = false; + Base::Vector3d dir = Direction.getValue(); + if ( DrawUtil::fpCompare(fabs(dir.x),fabs(dir.y)) && + DrawUtil::fpCompare(fabs(dir.x),fabs(dir.z)) ) { + result = true; + } + return result; +} PyObject *DrawViewPart::getPyObject(void) { diff --git a/src/Mod/TechDraw/App/DrawViewPart.h b/src/Mod/TechDraw/App/DrawViewPart.h index 42c3e68bde..11887d79de 100644 --- a/src/Mod/TechDraw/App/DrawViewPart.h +++ b/src/Mod/TechDraw/App/DrawViewPart.h @@ -157,6 +157,7 @@ public: virtual TopoDS_Shape getSourceShape(void) const; virtual std::vector getShapesFromObject(App::DocumentObject* docObj) const; virtual TopoDS_Shape getSourceShapeFused(void) const; + bool isIso(void) const; protected: TechDrawGeometry::GeometryObject *geometryObject; @@ -175,7 +176,7 @@ protected: Base::Vector3d wDir; //paperspace Z Base::Vector3d shapeCentroid; void getRunControl(void); - + bool m_sectionEdges; bool m_handleFaces; diff --git a/src/Mod/TechDraw/Gui/QGIArrow.cpp b/src/Mod/TechDraw/Gui/QGIArrow.cpp index d269e79da3..b6bf29d560 100644 --- a/src/Mod/TechDraw/Gui/QGIArrow.cpp +++ b/src/Mod/TechDraw/Gui/QGIArrow.cpp @@ -44,7 +44,9 @@ using namespace TechDrawGui; QGIArrow::QGIArrow() : m_fill(Qt::SolidPattern), m_size(5.0), - m_style(0) + m_style(0), + m_dirMode(false), + m_dir(Base::Vector3d(1.0,0.0,0.0)) { isFlipped = false; m_brush.setStyle(m_fill); @@ -63,11 +65,23 @@ void QGIArrow::flip(bool state) { void QGIArrow::draw() { QPainterPath path; if (m_style == 0) { - path = makeFilledTriangle(m_size,m_size/6.0,isFlipped); //"arrow l/w sb 3/1" ?? + if (m_dirMode) { + path = makeFilledTriangle(getDirection(), m_size,m_size/6.0); + } else { + path = makeFilledTriangle(m_size,m_size/6.0,isFlipped); //"arrow l/w sb 3/1" ?? + } } else if (m_style == 1) { - path = makeOpenArrow(m_size,m_size/3.0,isFlipped); //broad arrow? + if (m_dirMode) { + path = makeOpenArrow(getDirection(), m_size,m_size/3.0); //broad arrow? + } else { + path = makeOpenArrow(m_size,m_size/3.0,isFlipped); + } } else if (m_style == 2) { - path = makeHashMark(m_size/2.0,m_size/2.0,isFlipped); //big enough? + if (m_dirMode) { + path = makeHashMark(getDirection(), m_size/2.0,m_size/2.0); //big enough? + } else { + path = makeHashMark(m_size/2.0,m_size/2.0,isFlipped); //big enough? + } } else if (m_style == 3) { path = makeDot(m_size/2.0,m_size/2.0,isFlipped); } else if (m_style == 4) { @@ -100,6 +114,25 @@ QPainterPath QGIArrow::makeFilledTriangle(double length, double width, bool flip return path; } +QPainterPath QGIArrow::makeFilledTriangle(Base::Vector3d dir, double length, double width) +{ +//(0,0) is tip of arrow +// dir is direction arrow points + Base::Vector3d negDir = -dir; + negDir.Normalize(); + Base::Vector3d perp(-negDir.y,negDir.x, 0.0); + Base::Vector3d barb1 = negDir * length + perp * width; + Base::Vector3d barb2 = negDir * length - perp * width; + + QPainterPath path; + path.moveTo(QPointF(0.,0.)); + path.lineTo(QPointF(Rez::guiX(barb1.x),Rez::guiX(barb1.y))); + path.lineTo(QPointF(Rez::guiX(barb2.x),Rez::guiX(barb2.y))); + path.closeSubpath(); + m_fill = Qt::SolidPattern; + return path; +} + QPainterPath QGIArrow::makeOpenArrow(double length, double width, bool flipped) { //(0,0) is tip of arrow @@ -115,6 +148,24 @@ QPainterPath QGIArrow::makeOpenArrow(double length, double width, bool flipped) return path; } +QPainterPath QGIArrow::makeOpenArrow(Base::Vector3d dir, double length, double width) +{ +//(0,0) is tip of arrow + Base::Vector3d negDir = -dir; + negDir.Normalize(); + Base::Vector3d perp(-negDir.y,negDir.x, 0.0); + Base::Vector3d barb1 = negDir * length + perp * width; + Base::Vector3d barb2 = negDir * length - perp * width; + + QPainterPath path; + path.moveTo(QPointF(Rez::guiX(barb1.x),Rez::guiX(barb1.y))); + path.lineTo(QPointF(0.,0.)); + path.lineTo(QPointF(Rez::guiX(barb2.x),Rez::guiX(barb2.y))); + m_fill = Qt::NoBrush; + return path; +} + + QPainterPath QGIArrow::makeHashMark(double length, double width, bool flipped) //Arch tick { double adjWidth = 1.0; @@ -130,6 +181,22 @@ QPainterPath QGIArrow::makeHashMark(double length, double width, bool flipped) return path; } +QPainterPath QGIArrow::makeHashMark(Base::Vector3d dir, double length, double width) //Arch tick +{ + double adjWidth = 1.0; + Base::Vector3d negDir = -dir; + negDir.Normalize(); + Base::Vector3d perp(-negDir.y,negDir.x, 0.0); + Base::Vector3d barb1 = negDir * length - perp * (adjWidth * width); + Base::Vector3d barb2 = dir * length + perp * (adjWidth * width); + + QPainterPath path; + path.moveTo(QPointF(Rez::guiX(barb1.x),Rez::guiX(barb1.y))); + path.lineTo(QPointF(Rez::guiX(barb2.x),Rez::guiX(barb2.y))); + m_fill = Qt::NoBrush; + return path; +} + QPainterPath QGIArrow::makeDot(double length, double width, bool flipped) //closed dot { Q_UNUSED(flipped); diff --git a/src/Mod/TechDraw/Gui/QGIArrow.h b/src/Mod/TechDraw/Gui/QGIArrow.h index cfe1e2542c..758afab897 100644 --- a/src/Mod/TechDraw/Gui/QGIArrow.h +++ b/src/Mod/TechDraw/Gui/QGIArrow.h @@ -23,6 +23,8 @@ #ifndef DRAWINGGUI_QGRAPHICSITEMARROW_H #define DRAWINGGUI_QGRAPHICSITEMARROW_H +#include + # include "QGIPrimPath.h" QT_BEGIN_NAMESPACE @@ -49,6 +51,10 @@ public: void setSize(double s); int getStyle() { return m_style; } void setStyle(int s) { m_style = s; } + bool getDirMode() { return m_dirMode; } + void setDirMode(bool b) { m_dirMode = b; } + Base::Vector3d getDirection(void) { return m_dir; } + void setDirection(Base::Vector3d v) { m_dir = v; } static int getPrefArrowStyle(); static double getPrefArrowSize(); @@ -56,8 +62,11 @@ public: protected: QPainterPath makeFilledTriangle(double length, double width, bool flipped); + QPainterPath makeFilledTriangle(Base::Vector3d dir, double length, double width); QPainterPath makeOpenArrow(double length, double width, bool flipped); + QPainterPath makeOpenArrow(Base::Vector3d dir, double length, double width); QPainterPath makeHashMark(double length, double width, bool flipped); + QPainterPath makeHashMark(Base::Vector3d dir, double length, double width); QPainterPath makeDot(double length, double width, bool flipped); QPainterPath makeOpenDot(double length, double width, bool flipped); @@ -67,6 +76,8 @@ private: double m_size; int m_style; bool isFlipped; + bool m_dirMode; + Base::Vector3d m_dir; }; } diff --git a/src/Mod/TechDraw/Gui/QGIView.cpp b/src/Mod/TechDraw/Gui/QGIView.cpp index 834cb5812d..aab7f8e14c 100644 --- a/src/Mod/TechDraw/Gui/QGIView.cpp +++ b/src/Mod/TechDraw/Gui/QGIView.cpp @@ -575,3 +575,8 @@ void QGIView::makeMark(double x, double y) cmItem->setZValue(ZVALUE::VERTEX); } +void QGIView::makeMark(Base::Vector3d v) +{ + makeMark(v.x,v.y); +} + diff --git a/src/Mod/TechDraw/Gui/QGIView.h b/src/Mod/TechDraw/Gui/QGIView.h index 0538bc5ec4..bc8521645f 100644 --- a/src/Mod/TechDraw/Gui/QGIView.h +++ b/src/Mod/TechDraw/Gui/QGIView.h @@ -77,6 +77,7 @@ public: virtual void drawCaption(void); virtual void rotateView(void); void makeMark(double x, double y); + void makeMark(Base::Vector3d v); /** Methods to ensure that Y-Coordinates are orientated correctly. diff --git a/src/Mod/TechDraw/Gui/QGIViewDimension.cpp b/src/Mod/TechDraw/Gui/QGIViewDimension.cpp index dee4c7ae89..414ab1a9c9 100644 --- a/src/Mod/TechDraw/Gui/QGIViewDimension.cpp +++ b/src/Mod/TechDraw/Gui/QGIViewDimension.cpp @@ -339,39 +339,57 @@ void QGIViewDimension::draw() QString labelText = datumLabel->toPlainText(); Base::Vector3d lblCenter(datumLabel->X(), datumLabel->Y(), 0); //already gui coords - //const std::vector &objects = dim->References2D.getValues(); - //const std::vector &SubNames = dim->References2D.getSubValues(); - const char *dimType = dim->Type.getValueAsString(); - if (strcmp(dimType, "Distance") == 0 || + if (strcmp(dimType, "Distance") == 0 || strcmp(dimType, "DistanceX") == 0 || strcmp(dimType, "DistanceY") == 0) { pointPair pts = dim->getLinearPoints(); - Base::Vector3d distStart, distEnd; //start/end points of distance to measure - distStart = Rez::guiX(pts.first); - distEnd = Rez::guiX(pts.second); + Base::Vector3d startDist, endDist, midDist; //start/end/mid points of distance line + startDist = Rez::guiX(pts.first); + endDist = Rez::guiX(pts.second); + Base::Vector3d vecDist = (endDist - startDist); // +/- aligned method // dimension text legible from bottom or right // text outside arrows (not between) // text to left of vertical dims // text above horizontal dims - double offsetFudge = 2.0; - double textOffset = 1.0 * Rez::guiX(vp->Fontsize.getValue()) + offsetFudge; - Base::Vector3d dir, norm; //direction/normal vectors of distance line (not dimension Line) + Base::Vector3d dirDist, normDist; //direction/normal vectors of distance line + Base::Vector3d dirExt, normExt; + Base::Vector3d dirDim, normDim; + Base::Vector3d dirIso; + dirDist = vecDist; + dirDist.Normalize(); + normDist = Base::Vector3d (-dirDist.y,dirDist.x, 0); //normal to distance direction + //toward dimension line? if (strcmp(dimType, "Distance") == 0 ) { - dir = (distEnd-distStart); + //distance and dimension lines parallel + dirDim = dirDist; + normDim = Base::Vector3d (-dirDist.y,dirDist.x, 0); } else if (strcmp(dimType, "DistanceX") == 0 ) { - dir = Base::Vector3d ( ((distEnd.x - distStart.x >= FLT_EPSILON) ? 1 : -1) , 0, 0); + //distance and dimension lines not (neccessarily) parallel + dirDim = Base::Vector3d ( ((endDist.x - startDist.x >= FLT_EPSILON) ? 1 : -1) , 0, 0); + normDim = Base::Vector3d (-dirDim.y,dirDim.x, 0); } else if (strcmp(dimType, "DistanceY") == 0 ) { - dir = Base::Vector3d (0, ((distEnd.y - distStart.y >= FLT_EPSILON) ? 1 : -1) , 0); + //distance and dimension lines not (neccessarily) parallel + dirDim = Base::Vector3d (0, ((endDist.y - startDist.y >= FLT_EPSILON) ? 1 : -1) , 0); + normDim = Base::Vector3d (-dirDim.y, dirDim.x, 0); } - dir.Normalize(); - norm = Base::Vector3d (-dir.y,dir.x, 0); //normal to dimension direction - // Get magnitude of angle between dir and horizontal - double angle = atan2f(dir.y,dir.x); + //for ortho drawing extension lines are para to normDim, perp to dirDist + dirExt = normDim; + dirIso = normDim; + if (refObj->isIso()) { + //is this dimension an iso dimension? ie points +/-isoX,+/-isoY,+/-isoZ + dirIso = findIsoDir(dirDist); + dirExt = findIsoExt(dirIso); + } + dirExt.Normalize(); + 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); if (angle < 0.0) { angle = 2 * M_PI + angle; //map to +ve angle } @@ -389,103 +407,98 @@ void QGIViewDimension::draw() isFlipped = true; } - Base::Vector3d textNorm = norm; - if (std::abs(dir.x) < FLT_EPSILON) { + Base::Vector3d textNorm = normDim; + if (std::abs(dirDist.x) < FLT_EPSILON) { //this is DistanceY? textNorm = Base::Vector3d(1.0,0.0,0.0); //force text to left of dim line - } else if (std::abs(dir.y) < FLT_EPSILON) { + } else if (std::abs(dirDist.y) < FLT_EPSILON) { //this is DistanceX? textNorm = Base::Vector3d(0.0,1.0,0.0); //force text above dim line } else { if (isFlipped) { - textNorm = -norm; + textNorm = -textNorm; } } - // when the dimension line is not parallel to (distStart-distEnd) (ie DistanceY on side of a Cone) the projection of - // (distStart-distEnd) on dimLine.norm is not zero, distEnd is considered as reference and distStart - // is replaced by its projection distStart_ - // wf: in this case we can't use one of the Distance? end points as a reference for dim/ext lines. So we use the projection of - // startpoint(distStart) onto dimLine - // m = |proj(A on B)| = dot(A,unit(B) - // m = |proj(dimLine on normal)| = dot(dimLine,normal) - // newstartpt = oldstart + m*normal - float normproj12 = (distEnd-distStart).x * norm.x + (distEnd-distStart).y * norm.y; //dot(dirDimline, normal) - Base::Vector3d distStart_ = distStart + norm * normproj12; - Base::Vector3d distMid = (distStart_ + distEnd) / 2.0; + // +/- pos of startDist vs endDist for vert/horiz Dims + // distStartDelta sb zero for normal dims + float distStartDelta = vecDist.Dot(normDim); // component of distance vector in dim line direction + Base::Vector3d startDistAdj = startDist + normDim * distStartDelta; + midDist = (startDistAdj + endDist) / 2.0; -// QFont font = datumLabel->font(); //font metrics gives answers in pixels, not mm -// QFontMetrics fm(font); -// int w = fm.width(labelText); //why is this different than diameter/radius? -// int h = fm.height(); - double lblWidth = datumLabel->boundingRect().width(); + //offset of dimLine from dimText + double offsetFudge = 2.0; + double textOffset = 1.0 * Rez::guiX(vp->Fontsize.getValue()) + offsetFudge; + + //fauxCenter is where the dimText would be if it was on the dimLine + Base::Vector3d fauxCenter = lblCenter + textOffset * dirExt; + Base::Vector3d vec = fauxCenter - midDist; + float sepDistDir = vec.x * dirExt.x + vec.y * dirExt.y; //dist between distance & dimension along extension - Base::Vector3d fauxCenter = lblCenter + textOffset * textNorm; - Base::Vector3d vec = fauxCenter - distEnd; //endof dist line to center of dimline - float perpDistance = vec.x * norm.x + vec.y * norm.y; //dot(vec,norm) the perp distance between distance & dimension lines. margin = Rez::guiX(2.f); float scaler = 1.; - float offset1 = (perpDistance + normproj12 < 0) ? -margin : margin; - float offset2 = (perpDistance < 0) ? -margin : margin; + float extStartOffset = (sepDistDir + distStartDelta < 0) ? -margin : margin; + float extEndOffset = (sepDistDir < 0) ? -margin : margin; - Base::Vector3d ext1End = distStart_ + norm * (perpDistance + offset1 * scaler); //extension line 1 end - Base::Vector3d ext2End = distEnd + norm * (perpDistance + offset2 * scaler); + Base::Vector3d startIntercept = DrawUtil::Intersect2d(startDist, dirExt, + fauxCenter,dirDim); + Base::Vector3d endIntercept = DrawUtil::Intersect2d(endDist, dirExt, + fauxCenter,dirDim); + + + Base::Vector3d extStartEnd = startIntercept + dirExt * (extStartOffset * scaler); //the little bit past the dimline + Base::Vector3d extEndEnd = endIntercept + dirExt * (extEndOffset * scaler); - // Calculate the start/end for the Dimension lines //dim1Tip is the position of 1 arrow point (lhs on a horizontal) //dim2Tail is the position of the other arrow point (rhs) - //case 1: inner placement: text between extensions & fits. arros point out from inside + //case 1: inner placement: text between extensions & fits. arros point out from inside (default) //case 2: inner placement2: text too big to fit. arrows point in from outside //case 3: outer placement: text is outside extensions. arrows point in, 1 arrow tracks dimText - //case1 - inner placement, text fits within extension lines - Base::Vector3d dim1Tip = distStart_ + norm * perpDistance; - Base::Vector3d dim1Tail = distMid + norm * perpDistance; - Base::Vector3d dim2Tip = distMid + norm * perpDistance; - Base::Vector3d dim2Tail = distEnd + norm * perpDistance; + Base::Vector3d dim1Tip = startIntercept; + Base::Vector3d dim1Tail = fauxCenter; + Base::Vector3d dim2Tip = endIntercept; + Base::Vector3d dim2Tail = fauxCenter; + Base::Vector3d a1Dir = -dirDim; + Base::Vector3d a2Dir = dirDim; - bool flipTriang = false; - - double dimSpan = (dim2Tail - dim1Tip).Length(); - double fauxToDim1 = (fauxCenter - dim1Tip).Length(); //label to end #1 - double fauxToDim2 = (fauxCenter - dim2Tail).Length(); + double dimSpan = (extEndEnd - extStartEnd).Length(); //distance between extension lines + double fauxToDim1 = (fauxCenter - dim1Tip).Length(); //label to arrow #1 + double fauxToDim2 = (fauxCenter - dim2Tip).Length(); //label to end #2 double tailLength = Rez::guiX(10.f) * scaler; - //case2 - innerPlacement * text > span - if ((lblWidth > dimSpan) && - (fauxToDim1 < dimSpan) && - (fauxToDim2 < dimSpan)) { //fauxcenter is between extensions - dim1Tail = dim1Tip - tailLength * dir; - dim2Tip = dim2Tail + tailLength * dir; - flipTriang = true; + //case2 - innerPlacement && text > span + double lblWidth = datumLabel->boundingRect().width(); + if ((DrawUtil::isBetween(fauxCenter, dim1Tip, dim2Tip)) && + (lblWidth > dimSpan) ) { + dim1Tail = dim1Tip - tailLength * dirDim; + a1Dir = dirDim; + a2Dir = -dirDim; + dim2Tail = dim2Tip + tailLength * dirDim; } - //case3 - outerPlacement - if ((fauxToDim1 < fauxToDim2) && - (dimSpan < fauxToDim2) ) { - dim1Tail = fauxCenter; - dim2Tip = dim2Tail + tailLength * dir; - flipTriang = true; - } else if ((fauxToDim2 < fauxToDim1) && - (dimSpan < fauxToDim1) ) { - dim1Tail = dim1Tip - tailLength * dir; - dim2Tip = fauxCenter; - flipTriang = true; - } else { - //a different case + if (!DrawUtil::isBetween(fauxCenter, dim1Tip, dim2Tip)) { + //case3 - outerPlacement + a1Dir = dirDim; + a2Dir = -dirDim; + if (fauxToDim1 < fauxToDim2) { + dim1Tail = fauxCenter; + dim2Tail = dim2Tip + tailLength * dirDim; + } else { + dim1Tail = dim1Tip - tailLength * dirDim; + dim2Tail = fauxCenter; + } } // Extension lines QPainterPath path; - path.moveTo(distStart.x, distStart.y); - path.lineTo(ext1End.x, ext1End.y); + path.moveTo(startDist.x, startDist.y); + path.lineTo(extStartEnd.x, extStartEnd.y); - path.moveTo(distEnd.x, distEnd.y); - path.lineTo(ext2End.x, ext2End.y); + path.moveTo(endDist.x, endDist.y); + path.lineTo(extEndEnd.x, extEndEnd.y); - //Dimension lines + //Dimension lines (arrow shafts) //TODO: line tip goes just a bit too far. overlaps the arrowhead's point - //default arrow perpDistance is 5.0 - path.moveTo(dim1Tip.x, dim1Tip.y); path.lineTo(dim1Tail.x, dim1Tail.y); @@ -501,26 +514,23 @@ void QGIViewDimension::draw() double angleOption = 0.0; //put lblText angle adjustments here datumLabel->setRotation((angle * 180 / M_PI) + angleOption); + aHead1->setDirMode(true); + aHead2->setDirMode(true); + aHead1->setDirection(a1Dir); + aHead2->setDirection(a2Dir); + aHead1->setStyle(QGIArrow::getPrefArrowStyle()); aHead1->setSize(QGIArrow::getPrefArrowSize()); aHead1->draw(); - aHead2->flip(true); aHead2->setStyle(QGIArrow::getPrefArrowStyle()); aHead2->setSize(QGIArrow::getPrefArrowSize()); aHead2->draw(); - angle = atan2f(dir.y,dir.x); - float arrowAngle = angle * 180 / M_PI; - arrowAngle -= 180.; - if(flipTriang){ - aHead1->setRotation(arrowAngle + 180.); - aHead2->setRotation(arrowAngle + 180.); - } else { - aHead1->setRotation(arrowAngle); - aHead2->setRotation(arrowAngle); - } aHead1->setPos(dim1Tip.x, dim1Tip.y); - aHead2->setPos(dim2Tail.x, dim2Tail.y); + aHead2->setPos(dim2Tip.x, dim2Tip.y); + + aHead1->setDirMode(false); + aHead2->setDirMode(false); } else if(strcmp(dimType, "Diameter") == 0) { // terminology: Dimension Text, Dimension Line(s), Extension Lines, Arrowheads @@ -1169,4 +1179,57 @@ QColor QGIViewDimension::getNormalColor() return m_colNormal; } +//! find the closest isometric axis given an ortho vector +Base::Vector3d QGIViewDimension::findIsoDir(Base::Vector3d ortho) +{ + std::vector isoDirs = { Base::Vector3d(0.866,0.5,0.0), //iso X + Base::Vector3d(-0.866,-0.5,0.0), //iso -X + Base::Vector3d(-0.866,0.5,0.0), //iso -Y? + Base::Vector3d(0.866,-0.5,0.0), //iso +Y? + Base::Vector3d(0.0,-1.0,0.0), //iso -Z + Base::Vector3d(0.0,1.0,0.0) }; //iso Z + std::vector angles; + for (auto& iso: isoDirs) { + angles.push_back(ortho.GetAngle(iso)); + } + int idx = 0; + double min = angles[0]; + for (int i = 1; i < 6; i++) { + if (angles[i] < min) { + idx = i; + min = angles[i]; + } + } + return isoDirs[idx]; +} + +//! find the iso extension direction corresponding to an iso dist direction +Base::Vector3d QGIViewDimension::findIsoExt(Base::Vector3d dir) +{ + Base::Vector3d dirExt(1,0,0); + Base::Vector3d isoX(0.866,0.5,0.0); //iso X + Base::Vector3d isoXr(-0.866,-0.5,0.0); //iso -X + Base::Vector3d isoY(-0.866,0.5,0.0); //iso -Y? + Base::Vector3d isoYr(0.866,-0.5,0.0); //iso +Y? + Base::Vector3d isoZ(0.0,1.0,0.0); //iso Z + Base::Vector3d isoZr(0.0,-1.0,0.0); //iso -Z + if (dir.IsEqual(isoX, FLT_EPSILON)) { + dirExt = isoY; + } else if (dir.IsEqual(-isoX, FLT_EPSILON)) { + dirExt = -isoY; + } else if (dir.IsEqual(isoY, FLT_EPSILON)) { + dirExt = isoZ; + } else if (dir.IsEqual(-isoY, FLT_EPSILON)) { + dirExt = -isoZ; + } else if (dir.IsEqual(isoZ, FLT_EPSILON)) { + dirExt = isoX; + } else if (dir.IsEqual(-isoZ, FLT_EPSILON)) { + dirExt = -isoX; + } else { //tarfu + Base::Console().Message("QGIVD::findIsoExt - %s - input is not iso axis\n", getViewObject()->getNameInDocument()); + } + + return dirExt; +} + #include diff --git a/src/Mod/TechDraw/Gui/QGIViewDimension.h b/src/Mod/TechDraw/Gui/QGIViewDimension.h index d5a2938e71..9b77efb286 100644 --- a/src/Mod/TechDraw/Gui/QGIViewDimension.h +++ b/src/Mod/TechDraw/Gui/QGIViewDimension.h @@ -116,6 +116,8 @@ protected: const QVariant &value ) override; virtual void setSvgPens(void); virtual void setPens(void); + Base::Vector3d findIsoDir(Base::Vector3d ortho); + Base::Vector3d findIsoExt(Base::Vector3d isoDir); protected: bool hasHover;