diff --git a/src/Mod/TechDraw/App/DrawUtil.cpp b/src/Mod/TechDraw/App/DrawUtil.cpp index c686caefae..575fe01f3c 100644 --- a/src/Mod/TechDraw/App/DrawUtil.cpp +++ b/src/Mod/TechDraw/App/DrawUtil.cpp @@ -584,7 +584,7 @@ bool DrawUtil::isBetween(const Base::Vector3d pt, const Base::Vector3d end1, con Base::Vector3d DrawUtil::Intersect2d(Base::Vector3d p1, Base::Vector3d d1, Base::Vector3d p2, Base::Vector3d d2) { - Base::Vector3d result(0,0,0); + Base::Vector3d result(0.0, 0.0, 0.0); Base::Vector3d p12(p1.x+d1.x, p1.y+d1.y, 0.0); double A1 = d1.y; double B1 = -d1.x; @@ -608,6 +608,34 @@ Base::Vector3d DrawUtil::Intersect2d(Base::Vector3d p1, Base::Vector3d d1, return result; } +Base::Vector2d DrawUtil::Intersect2d(Base::Vector2d p1, Base::Vector2d d1, + Base::Vector2d p2, Base::Vector2d d2) +{ + Base::Vector2d result(0.0, 0.0); + Base::Vector2d p12(p1.x+d1.x, p1.y+d1.y); + double A1 = d1.y; + double B1 = -d1.x; + double C1 = A1*p1.x + B1*p1.y; + + Base::Vector2d p22(p2.x+d2.x, p2.y+d2.y); + 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; +} + + std::string DrawUtil::shapeToString(TopoDS_Shape s) { std::ostringstream buffer; diff --git a/src/Mod/TechDraw/App/DrawUtil.h b/src/Mod/TechDraw/App/DrawUtil.h index 41cdc91805..57a714e572 100644 --- a/src/Mod/TechDraw/App/DrawUtil.h +++ b/src/Mod/TechDraw/App/DrawUtil.h @@ -109,6 +109,8 @@ class TechDrawExport DrawUtil { //! 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); + static Base::Vector2d Intersect2d(Base::Vector2d p1, Base::Vector2d d1, + Base::Vector2d p2, Base::Vector2d d2); static Base::Vector3d gpPnt2V3(const gp_Pnt gp) { return Base::Vector3d(gp.X(),gp.Y(),gp.Z()); } static gp_Pnt V32gpPnt(const Base::Vector3d v) { return gp_Pnt(v.x,v.y,v.z); } static std::string shapeToString(TopoDS_Shape s); diff --git a/src/Mod/TechDraw/App/DrawViewDimension.cpp b/src/Mod/TechDraw/App/DrawViewDimension.cpp index 6978d681c1..9137b3ecf4 100644 --- a/src/Mod/TechDraw/App/DrawViewDimension.cpp +++ b/src/Mod/TechDraw/App/DrawViewDimension.cpp @@ -131,6 +131,10 @@ DrawViewDimension::DrawViewDimension(void) UnderTolerance.setConstraints(&ToleranceConstraint); ADD_PROPERTY_TYPE(Inverted, (false), "", App::Prop_Output, "The dimensional value is displayed inverted"); + ADD_PROPERTY_TYPE(AngleOverride,(false), "Override", App::Prop_Output, "User specified angles"); + ADD_PROPERTY_TYPE(LineAngle,(0.0), "Override", App::Prop_Output, "Dimension line angle"); + ADD_PROPERTY_TYPE(ExtensionAngle,(0.0), "Override", App::Prop_Output, "Extension line angle"); + // hide the DrawView properties that don't apply to Dimensions ScaleType.setStatus(App::Property::ReadOnly, true); ScaleType.setStatus(App::Property::Hidden, true); diff --git a/src/Mod/TechDraw/App/DrawViewDimension.h b/src/Mod/TechDraw/App/DrawViewDimension.h index c4efe316ec..5765e0b2b1 100644 --- a/src/Mod/TechDraw/App/DrawViewDimension.h +++ b/src/Mod/TechDraw/App/DrawViewDimension.h @@ -110,6 +110,10 @@ public: App::PropertyQuantityConstraint OverTolerance; App::PropertyQuantityConstraint UnderTolerance; + App::PropertyBool AngleOverride; + App::PropertyAngle LineAngle; + App::PropertyAngle ExtensionAngle; + enum RefType{ invalidRef, oneEdge, diff --git a/src/Mod/TechDraw/Gui/QGIViewDimension.cpp b/src/Mod/TechDraw/Gui/QGIViewDimension.cpp index 05d22be0cd..a1eb2d7123 100644 --- a/src/Mod/TechDraw/Gui/QGIViewDimension.cpp +++ b/src/Mod/TechDraw/Gui/QGIViewDimension.cpp @@ -77,6 +77,7 @@ #include "QGIViewDimension.h" #include "ViewProviderDimension.h" #include "DrawGuiUtil.h" +#include "QGIVertex.h" #define NORMAL 0 #define PRE 1 @@ -864,6 +865,12 @@ Base::Vector2d QGIViewDimension::getAsmeRefJointPoint(const Base::BoundBox2d &la labelRectangle.GetCenter().y); } +//find intersection of line L (through linePoint at angle lineAngle) and a line perpendicular to L +//passing through perpendicularPoint +//tricky vector algebra note: +//a*b is the magnitude of the projection of a onto b +//so we project a vector linePoint-perpendicularPoint onto unit vector in lineAngle direction giving +//the distance from linePoint to intersection, then make a displacement vector and add it to linePoint Base::Vector2d QGIViewDimension::computePerpendicularIntersection(const Base::Vector2d &linePoint, const Base::Vector2d &perpendicularPoint, double lineAngle) { @@ -872,6 +879,12 @@ Base::Vector2d QGIViewDimension::computePerpendicularIntersection(const Base::Ve lineAngle); } +//calculate the end points of 1 extension line +//originPoint - a point on the distance line (end point) +//linePoint - point on dimension line that is perpendicular projection of distance line point +// onto dimension line +//1 extension line end point is the return value +//1 extension line end point is modified parameter startPoint Base::Vector2d QGIViewDimension::computeExtensionLinePoints(const Base::Vector2d &originPoint, const Base::Vector2d &linePoint, double hintAngle, double overhangSize, double gapSize, Base::Vector2d &startPoint) @@ -1254,6 +1267,9 @@ void QGIViewDimension::drawSingleLine(QPainterPath &painterPath, const Base::Vec painterPath.lineTo(toQtGui(lineOrigin + Base::Vector2d::FromPolar(endPosition, lineAngle))); } + +//adds line segments to painterPath from lineOrigin along lineAngle +//segment length is determined by drawMarking entries void QGIViewDimension::drawMultiLine(QPainterPath &painterPath, const Base::Vector2d &lineOrigin, double lineAngle, const std::vector> &drawMarking) const { @@ -1330,6 +1346,11 @@ void QGIViewDimension::drawMultiArc(QPainterPath &painterPath, const Base::Vecto while (currentIndex != entryIndex); } + +//adds dimension line to painterPath +//dimension line starts at targetPoint and continues for a distance (startPosition?) along lineAngle +//jointPosition - distance of reference line from 1 extension line?? +//lineAngle - Clockwise angle of distance line with horizontal void QGIViewDimension::drawDimensionLine(QPainterPath &painterPath, const Base::Vector2d &targetPoint, double lineAngle, double startPosition, double jointPosition, const Base::BoundBox2d &labelRectangle, int arrowCount, int standardStyle, bool flipArrows) const @@ -1387,6 +1408,14 @@ void QGIViewDimension::drawDimensionArc(QPainterPath &painterPath, const Base::V drawArrows(arrowCount, arrowPositions, arrowAngles, flipArrows); } +//draw any of 3 distance dimension types +//startPoint, endPoint - ends of actual distance line +//lineAngle - angle of actual line with horizontal +//target points - projection of reference line ends on to extension line +//startCross & endCross - real intersection of extension lines and dimension line +//dimension line - main annotation line +//reference line - line under dimension text in referenced styles +//joint points - ends of reference line void QGIViewDimension::drawDistanceExecutive(const Base::Vector2d &startPoint, const Base::Vector2d &endPoint, double lineAngle, const Base::BoundBox2d &labelRectangle, int standardStyle, int renderExtent, bool flipArrows) const @@ -1396,6 +1425,7 @@ void QGIViewDimension::drawDistanceExecutive(const Base::Vector2d &startPoint, c Base::Vector2d labelCenter(labelRectangle.GetCenter()); double labelAngle = 0.0; + //startCross and endCross are points where extension line intersects dimension line Base::Vector2d startCross; Base::Vector2d endCross; int arrowCount = renderExtent >= ViewProviderDimension::REND_EXTENT_NORMAL @@ -1404,7 +1434,9 @@ void QGIViewDimension::drawDistanceExecutive(const Base::Vector2d &startPoint, c if (standardStyle == ViewProviderDimension::STD_STYLE_ISO_REFERENCING || standardStyle == ViewProviderDimension::STD_STYLE_ASME_REFERENCING) { - // The dimensional value text must stay horizontal + // The dimensional value text must stay horizontal in these styles + + //jointPoints are the ends of the reference line Base::Vector2d jointPoints[2]; if (standardStyle == ViewProviderDimension::STD_STYLE_ISO_REFERENCING) { @@ -1416,7 +1448,7 @@ void QGIViewDimension::drawDistanceExecutive(const Base::Vector2d &startPoint, c jointPoints[1] = getAsmeRefJointPoint(labelRectangle, true); } - // Find target points, i.e. points where the extension line intersects the dimension line + //targetPoints are the projection of reference line endpoints onto endPoint's extension line Base::Vector2d targetPoints[2]; targetPoints[0] = computePerpendicularIntersection(jointPoints[0], endPoint, lineAngle); targetPoints[1] = computePerpendicularIntersection(jointPoints[1], endPoint, lineAngle); @@ -1427,6 +1459,9 @@ void QGIViewDimension::drawDistanceExecutive(const Base::Vector2d &startPoint, c lineDirection *= normalizeStartPosition(startPosition, lineAngle); // Find the positions where the reference line attaches to the dimension line + //jointPoints are the ends of the reference line + //targetPoints - projection of reference line on to extension line + //jointPositions - displacement of jointPoints from ext line double jointPositions[2]; jointPositions[0] = lineDirection*(jointPoints[0] - targetPoints[0]); jointPositions[1] = lineDirection*(jointPoints[1] - targetPoints[1]); @@ -1463,6 +1498,7 @@ void QGIViewDimension::drawDistanceExecutive(const Base::Vector2d &startPoint, c selected = 0; } + //find points where extension lines meet dimension line endCross = targetPoints[selected]; startCross = targetPoints[selected] + Base::Vector2d::FromPolar(startPosition, lineAngle); @@ -1470,12 +1506,14 @@ void QGIViewDimension::drawDistanceExecutive(const Base::Vector2d &startPoint, c labelRectangle, arrowCount, standardStyle, flipArrows); Base::Vector2d outsetPoint(standardStyle == ViewProviderDimension::STD_STYLE_ISO_REFERENCING - ? getIsoRefOutsetPoint(labelRectangle, selected == 1) + ? getIsoRefOutsetPoint(labelRectangle, selected == 1) // 0 = left, 1 = right : getAsmeRefOutsetPoint(labelRectangle, selected == 1)); + //add the reference line to the QPainterPath distancePath.moveTo(toQtGui(outsetPoint)); distancePath.lineTo(toQtGui(jointPoints[selected])); } + else if (standardStyle == ViewProviderDimension::STD_STYLE_ISO_ORIENTED) { // We may rotate the label so no leader and reference lines are needed double placementFactor = getIsoStandardLinePlacement(lineAngle); @@ -1490,24 +1528,26 @@ void QGIViewDimension::drawDistanceExecutive(const Base::Vector2d &startPoint, c lineAngle + M_PI_2)); // Compute the dimensional line start and end crossings with (virtual) extension lines + //check for isometric direction and if iso compute non-perpendicular intersection of dim line and ext lines + Base::Vector2d lineDirection(Base::Vector2d::FromPolar(1.0, lineAngle)); startCross = computePerpendicularIntersection(labelProjection, startPoint, lineAngle); endCross = computePerpendicularIntersection(labelProjection, endPoint, lineAngle); // Find linear coefficients of crossings - Base::Vector2d lineDirection(Base::Vector2d::FromPolar(1.0, lineAngle)); double startPosition = arrowCount > 1 ? lineDirection*(startCross - endCross) : 0.0; double labelPosition = lineDirection*(labelProjection - endCross); drawDimensionLine(distancePath, endCross, lineAngle, startPosition, labelPosition, labelRectangle, arrowCount, standardStyle, flipArrows); } + else if (standardStyle == ViewProviderDimension::STD_STYLE_ASME_INLINED) { // Text must remain horizontal, but it may split the leader line + Base::Vector2d lineDirection(Base::Vector2d::FromPolar(1.0, lineAngle)); startCross = computePerpendicularIntersection(labelCenter, startPoint, lineAngle); endCross = computePerpendicularIntersection(labelCenter, endPoint, lineAngle); // Find linear coefficients of crossings - Base::Vector2d lineDirection(Base::Vector2d::FromPolar(1.0, lineAngle)); double startPosition = arrowCount > 1 ? lineDirection*(startCross - endCross) : 0.0; double labelPosition = lineDirection*(labelCenter - endCross); @@ -1530,13 +1570,192 @@ void QGIViewDimension::drawDistanceExecutive(const Base::Vector2d &startPoint, c Base::Vector2d extensionOrigin; Base::Vector2d extensionTarget(computeExtensionLinePoints(endPoint, endCross, lineAngle + M_PI_2, getDefaultExtensionLineOverhang(), gapSize, extensionOrigin)); - + //draw 1st extension line distancePath.moveTo(toQtGui(extensionOrigin)); distancePath.lineTo(toQtGui(extensionTarget)); if (arrowCount > 1) { extensionTarget = computeExtensionLinePoints(startPoint, startCross, lineAngle + M_PI_2, getDefaultExtensionLineOverhang(), gapSize, extensionOrigin); + //draw second extension line + distancePath.moveTo(toQtGui(extensionOrigin)); + distancePath.lineTo(toQtGui(extensionTarget)); + } + } + + datumLabel->setTransformOriginPoint(datumLabel->boundingRect().center()); + datumLabel->setRotation(toQtDeg(labelAngle)); + + dimLines->setPath(distancePath); +} + +//draw any of 3 distance dimension types with user override of dimension and extension line directions +//startPoint, endPoint - ends of actual distance line +//lineAngle - desired angle of dimension line with horizontal +//extensionAngle - desired angle of extension lines with horizontal +void QGIViewDimension::drawDistanceOverride(const Base::Vector2d &startPoint, const Base::Vector2d &endPoint, + double lineAngle, const Base::BoundBox2d &labelRectangle, + int standardStyle, int renderExtent, bool flipArrows, double extensionAngle) const +{ + QPainterPath distancePath; + + Base::Vector2d labelCenter(labelRectangle.GetCenter()); + double labelAngle = 0.0; + + //startCross and endCross are points where extension lines intersect dimension line + Base::Vector2d startCross; + Base::Vector2d endCross; + Base::Vector2d lineDirection(Base::Vector2d::FromPolar(1.0, lineAngle)); + Base::Vector2d extensionDirection(Base::Vector2d::FromPolar(1.0, extensionAngle)); + + int arrowCount = renderExtent >= ViewProviderDimension::REND_EXTENT_NORMAL + || renderExtent == ViewProviderDimension::REND_EXTENT_CONFINED + ? 2 : 1; + + if (standardStyle == ViewProviderDimension::STD_STYLE_ISO_REFERENCING + || standardStyle == ViewProviderDimension::STD_STYLE_ASME_REFERENCING) { + // The dimensional value text must stay horizontal in these styles + + //refEndPoints are the ends of the reference line + Base::Vector2d refEndPoints[2]; + + if (standardStyle == ViewProviderDimension::STD_STYLE_ISO_REFERENCING) { + refEndPoints[0] = getIsoRefJointPoint(labelRectangle, false); + refEndPoints[1] = getIsoRefJointPoint(labelRectangle, true); + } + else { + refEndPoints[0] = getAsmeRefJointPoint(labelRectangle, false); + refEndPoints[1] = getAsmeRefJointPoint(labelRectangle, true); + } + + //targetPoints are the projection of reference line endpoints onto endPoint's extension line + Base::Vector2d targetPoints[2]; + targetPoints[0] = DrawUtil::Intersect2d(refEndPoints[0], lineDirection, endPoint, extensionDirection); + targetPoints[1] = DrawUtil::Intersect2d(refEndPoints[1], lineDirection, endPoint, extensionDirection); + Base::Vector2d pointOnStartExtension = DrawUtil::Intersect2d(endPoint, lineDirection, startPoint, extensionDirection); + double startPosition = arrowCount > 1 ? lineDirection*( pointOnStartExtension - endPoint) : 0.0; + + // Compute and normalize (i.e. make < 0) the start position + lineDirection *= normalizeStartPosition(startPosition, lineAngle); + + // Find the positions where the reference line attaches to the dimension line + //refEndPoints are the ends of the reference line + //targetPoints - projection of reference line on to extension line + //jointPositions - displacement of refEndPoints from extension line + double jointPositions[2]; + jointPositions[0] = lineDirection*(refEndPoints[0] - targetPoints[0]); + jointPositions[1] = lineDirection*(refEndPoints[1] - targetPoints[1]); + + // Orient the leader line angle correctly towards the target point + double angles[2]; + angles[0] = jointPositions[0] > 0.0 ? DrawUtil::angleComposition(lineAngle, M_PI) : lineAngle; + angles[1] = jointPositions[1] > 0.0 ? DrawUtil::angleComposition(lineAngle, M_PI) : lineAngle; + + // Select the placement, where the label is not obscured by the leader line + // or (if both behave the same) the one that bends the reference line less + double strikeFactors[2]; + + std::vector> lineMarking; + constructDimensionLine(targetPoints[0], lineAngle, startPosition, jointPositions[0], + labelRectangle, arrowCount, standardStyle, flipArrows, lineMarking); + strikeFactors[0] = computeLineStrikeFactor(labelRectangle, targetPoints[0], lineAngle, lineMarking); + + lineMarking.clear(); + constructDimensionLine(targetPoints[1], lineAngle, startPosition, jointPositions[1], + labelRectangle, arrowCount, standardStyle, flipArrows, lineMarking); + strikeFactors[1] = computeLineStrikeFactor(labelRectangle, targetPoints[1], lineAngle, lineMarking); + + int selected = compareAngleStraightness(0.0, angles[0], angles[1], strikeFactors[0], strikeFactors[1]); + if (selected == 0) { + // Select the side closer, so the label is on the outer side of the dimension line + Base::Vector2d perpendicularDir(lineDirection.Perpendicular()); + if (fabs((refEndPoints[0] - endPoint)*perpendicularDir) + > fabs((refEndPoints[1] - endPoint)*perpendicularDir)) { + selected = 1; + } + } + else if (selected < 0) { + selected = 0; + } + + //find points where extension lines meet dimension line + Base::Vector2d pointOnDimLine(refEndPoints[selected].x, refEndPoints[selected].y); + startCross = DrawUtil::Intersect2d(startPoint, extensionDirection, pointOnDimLine, lineDirection); + endCross = DrawUtil::Intersect2d(endPoint, extensionDirection, pointOnDimLine, lineDirection); + + drawDimensionLine(distancePath, endCross, lineAngle, startPosition, jointPositions[selected], + labelRectangle, arrowCount, standardStyle, flipArrows); + + Base::Vector2d outsetPoint(standardStyle == ViewProviderDimension::STD_STYLE_ISO_REFERENCING + ? getIsoRefOutsetPoint(labelRectangle, selected == 1) // 0 = left, 1 = right + : getAsmeRefOutsetPoint(labelRectangle, selected == 1)); + + //add the reference line to the QPainterPath + distancePath.moveTo(toQtGui(outsetPoint)); + distancePath.lineTo(toQtGui(refEndPoints[selected])); + } + + else if (standardStyle == ViewProviderDimension::STD_STYLE_ISO_ORIENTED) { + // We may rotate the label so no leader and reference lines are needed + double placementFactor = getIsoStandardLinePlacement(lineAngle); + labelAngle = placementFactor > 0.0 ? DrawUtil::angleComposition(lineAngle, M_PI) : lineAngle; + + // Find out the projection of label center on the line with given angle + Base::Vector2d labelProjection( + labelCenter + + Base::Vector2d::FromPolar( + placementFactor*(labelRectangle.Height()*0.5 + + getDefaultIsoDimensionLineSpacing()), + lineAngle + M_PI_2)); + + // Compute the dimensional line start and end crossings with (virtual) extension lines + startCross = DrawUtil::Intersect2d(startPoint, extensionDirection, labelProjection, lineDirection); + endCross = DrawUtil::Intersect2d(endPoint, extensionDirection, labelProjection, lineDirection); + + // Find linear coefficients of crossings + double startPosition = arrowCount > 1 ? lineDirection*(startCross - endCross) : 0.0; + double labelPosition = lineDirection*(labelProjection - endCross); + + drawDimensionLine(distancePath, endCross, lineAngle, startPosition, labelPosition, + labelRectangle, arrowCount, standardStyle, flipArrows); + } + + else if (standardStyle == ViewProviderDimension::STD_STYLE_ASME_INLINED) { + // Text must remain horizontal, but it may split the leader line + startCross = DrawUtil::Intersect2d(startPoint, extensionDirection, labelCenter, lineDirection); + endCross = DrawUtil::Intersect2d(endPoint, extensionDirection, labelCenter, lineDirection); + + // Find linear coefficients of crossings + double startPosition = arrowCount > 1 ? lineDirection*(startCross - endCross) : 0.0; + double labelPosition = lineDirection*(labelCenter - endCross); + + drawDimensionLine(distancePath, endCross, lineAngle, startPosition, labelPosition, + labelRectangle, arrowCount, standardStyle, flipArrows); + } + else { + Base::Console().Error("QGIVD::drawDistanceExecutive - this Standard&Style is not supported: %d\n", + standardStyle); + arrowCount = 0; + } + + if (arrowCount > 0 && renderExtent >= ViewProviderDimension::REND_EXTENT_REDUCED) { + double gapSize = 0.0; + if (standardStyle == ViewProviderDimension::STD_STYLE_ASME_REFERENCING + || standardStyle == ViewProviderDimension::STD_STYLE_ASME_INLINED) { + gapSize = getDefaultAsmeExtensionLineGap(); + } + + Base::Vector2d extensionOrigin; + Base::Vector2d extensionTarget(computeExtensionLinePoints(endPoint, endCross, lineAngle + M_PI_2, + getDefaultExtensionLineOverhang(), gapSize, extensionOrigin)); + //draw 1st extension line + distancePath.moveTo(toQtGui(extensionOrigin)); + distancePath.lineTo(toQtGui(extensionTarget)); + + if (arrowCount > 1) { + extensionTarget = computeExtensionLinePoints(startPoint, startCross, lineAngle + M_PI_2, + getDefaultExtensionLineOverhang(), gapSize, extensionOrigin); + //draw second extension line distancePath.moveTo(toQtGui(extensionOrigin)); distancePath.lineTo(toQtGui(extensionTarget)); } @@ -1738,8 +1957,6 @@ void QGIViewDimension::drawRadiusExecutive(const Base::Vector2d ¢erPoint, co void QGIViewDimension::drawDistance(TechDraw::DrawViewDimension *dimension, ViewProviderDimension *viewProvider) const { - QPainterPath distancePath; - Base::BoundBox2d labelRectangle(fromQtGui(mapRectFromItem(datumLabel, datumLabel->boundingRect()))); pointPair linePoints = dimension->getLinearPoints(); @@ -1760,8 +1977,17 @@ void QGIViewDimension::drawDistance(TechDraw::DrawViewDimension *dimension, View int renderExtent = viewProvider->RenderingExtent.getValue(); bool flipArrows = viewProvider->FlipArrowheads.getValue(); - drawDistanceExecutive(fromQtApp(linePoints.first), fromQtApp(linePoints.second), lineAngle, - labelRectangle, standardStyle, renderExtent, flipArrows); + + if (dimension->AngleOverride.getValue()) { + drawDistanceOverride(fromQtApp(linePoints.first), fromQtApp(linePoints.second), + dimension->LineAngle.getValue() * M_PI / 180.0, + labelRectangle, standardStyle, renderExtent, flipArrows, + dimension->ExtensionAngle.getValue() * M_PI / 180.0); + + } else { + drawDistanceExecutive(fromQtApp(linePoints.first), fromQtApp(linePoints.second), lineAngle, + labelRectangle, standardStyle, renderExtent, flipArrows); + } } void QGIViewDimension::drawRadius(TechDraw::DrawViewDimension *dimension, ViewProviderDimension *viewProvider) const @@ -2137,7 +2363,7 @@ QColor QGIViewDimension::prefNormalColor() } //! find the closest isometric axis given an ortho vector -Base::Vector3d QGIViewDimension::findIsoDir(Base::Vector3d ortho) +Base::Vector3d QGIViewDimension::findIsoDir(Base::Vector3d ortho) const { std::vector isoDirs = { Base::Vector3d(0.866,0.5,0.0), //iso X Base::Vector3d(-0.866,-0.5,0.0), //iso -X @@ -2161,7 +2387,7 @@ Base::Vector3d QGIViewDimension::findIsoDir(Base::Vector3d ortho) } //! find the iso extension direction corresponding to an iso dist direction -Base::Vector3d QGIViewDimension::findIsoExt(Base::Vector3d dir) +Base::Vector3d QGIViewDimension::findIsoExt(Base::Vector3d dir) const { Base::Vector3d dirExt(1,0,0); Base::Vector3d isoX(0.866,0.5,0.0); //iso X @@ -2331,5 +2557,19 @@ double QGIViewDimension::toQtDeg(double a) return -a*180.0/M_PI; } +void QGIViewDimension::makeMarkC(double x, double y, QColor c) const +{ + QGIVertex* vItem = new QGIVertex(-1); + vItem->setParentItem(const_cast(this)); + vItem->setPos(x,y); + vItem->setWidth(2.0); + vItem->setRadius(20.0); + vItem->setNormalColor(c); + vItem->setFillColor(c); + vItem->setPrettyNormal(); + vItem->setZValue(ZVALUE::VERTEX); +} + + #include diff --git a/src/Mod/TechDraw/Gui/QGIViewDimension.h b/src/Mod/TechDraw/Gui/QGIViewDimension.h index 81d2e3e437..c0fc99149a 100644 --- a/src/Mod/TechDraw/Gui/QGIViewDimension.h +++ b/src/Mod/TechDraw/Gui/QGIViewDimension.h @@ -236,6 +236,10 @@ protected: void drawDistanceExecutive(const Base::Vector2d &startPoint, const Base::Vector2d &endPoint, double lineAngle, const Base::BoundBox2d &labelRectangle, int standardStyle, int renderExtent, bool flipArrows) const; + void drawDistanceOverride(const Base::Vector2d &startPoint, const Base::Vector2d &endPoint, + double lineAngle, const Base::BoundBox2d &labelRectangle, + int standardStyle, int renderExtent, bool flipArrows, double extensionAngle) const; + void drawRadiusExecutive(const Base::Vector2d ¢erPoint, const Base::Vector2d &midPoint, double radius, double endAngle, double startRotation, const Base::BoundBox2d &labelRectangle, double centerOverhang, int standardStyle, int renderExtent, bool flipArrow) const; @@ -249,8 +253,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); + Base::Vector3d findIsoDir(Base::Vector3d ortho) const; + Base::Vector3d findIsoExt(Base::Vector3d isoDir) const; QString getPrecision(void); virtual void mouseReleaseEvent( QGraphicsSceneMouseEvent * event) override; @@ -264,6 +268,8 @@ protected: double m_lineWidth; void arrowPositionsToFeature(const Base::Vector2d positions[]) const; + void makeMarkC(double x, double y, QColor c = Qt::red) const; + private: static inline Base::Vector2d fromQtApp(const Base::Vector3d &v) { return Base::Vector2d(v.x, -v.y); } diff --git a/src/Mod/TechDraw/Gui/TaskDimension.cpp b/src/Mod/TechDraw/Gui/TaskDimension.cpp index 337f1a8b6e..7cd8cb6e40 100644 --- a/src/Mod/TechDraw/Gui/TaskDimension.cpp +++ b/src/Mod/TechDraw/Gui/TaskDimension.cpp @@ -26,12 +26,15 @@ #include #endif // #ifndef _PreComp_ +# include + #include #include #include #include #include +#include #include #include @@ -41,6 +44,8 @@ #include #include +#include +#include #include "QGIViewDimension.h" #include "ViewProviderDimension.h" @@ -124,7 +129,22 @@ TaskDimension::TaskDimension(QGIViewDimension *parent, ViewProviderDimension *di connect(ui->qsbFontSize, SIGNAL(valueChanged(double)), this, SLOT(onFontsizeChanged())); ui->comboDrawingStyle->setCurrentIndex(dimensionVP->StandardAndStyle.getValue()); connect(ui->comboDrawingStyle, SIGNAL(currentIndexChanged(int)), this, SLOT(onDrawingStyleChanged())); - } + } + + // Lines + ui->rbOverride->setChecked(parent->dvDimension->AngleOverride.getValue()); + connect(ui->rbOverride, SIGNAL(toggled(bool)), this, SLOT(onOverrideToggled())); + ui->dsbDimAngle->setValue(parent->dvDimension->LineAngle.getValue()); + connect(ui->dsbDimAngle, SIGNAL(valueChanged(double)), this, SLOT(onDimAngleChanged())); + ui->dsbExtAngle->setValue(parent->dvDimension->ExtensionAngle.getValue()); + connect(ui->dsbExtAngle, SIGNAL(valueChanged(double)), this, SLOT(onExtAngleChanged())); + connect(ui->pbDimUseDefault, SIGNAL(clicked()), this, SLOT(onDimUseDefaultClicked())); + connect(ui->pbDimUseSelection, SIGNAL(clicked()), this, SLOT(onDimUseSelectionClicked())); + connect(ui->pbExtUseDefault, SIGNAL(clicked()), this, SLOT(onExtUseDefaultClicked())); + connect(ui->pbExtUseSelection, SIGNAL(clicked()), this, SLOT(onExtUseSelectionClicked())); + + Gui::Document* doc = m_dimensionVP->getDocument(); + doc->openCommand("TaskDimension"); } TaskDimension::~TaskDimension() @@ -294,6 +314,104 @@ void TaskDimension::onDrawingStyleChanged() recomputeFeature(); } +void TaskDimension::onOverrideToggled() +{ + m_parent->dvDimension->AngleOverride.setValue(ui->rbOverride->isChecked()); + recomputeFeature(); + +} + +void TaskDimension::onDimAngleChanged() +{ + m_parent->dvDimension->LineAngle.setValue(ui->dsbDimAngle->value()); + recomputeFeature(); +} + +void TaskDimension::onExtAngleChanged() +{ + m_parent->dvDimension->ExtensionAngle.setValue(ui->dsbExtAngle->value()); + recomputeFeature(); +} + +void TaskDimension::onDimUseDefaultClicked() +{ + pointPair points = m_parent->dvDimension->getLinearPoints(); + //duplicate coordinate conversion logic from QGIViewDimension + Base::Vector2d first2(points.first.x, -points.first.y); + Base::Vector2d second2(points.second.x, -points.second.y); + double lineAngle = (second2 - first2).Angle(); + ui->dsbDimAngle->setValue(lineAngle * 180.0 / M_PI); +} + +void TaskDimension::onDimUseSelectionClicked() +{ + std::pair result = getAngleFromSelection(); + if (result.second) { + ui->dsbDimAngle->setValue(result.first * 180.0 / M_PI); + } +} + +void TaskDimension::onExtUseDefaultClicked() +{ + pointPair points = m_parent->dvDimension->getLinearPoints(); + //duplicate coordinate conversion logic from QGIViewDimension + Base::Vector2d first2(points.first.x, -points.first.y); + Base::Vector2d second2(points.second.x, -points.second.y); + Base::Vector2d lineDirection = second2 - first2; + Base::Vector2d extensionDirection(-lineDirection.y, lineDirection.x); + double extensionAngle = extensionDirection.Angle(); + ui->dsbExtAngle->setValue(extensionAngle * 180.0 / M_PI); +} +void TaskDimension::onExtUseSelectionClicked() +{ + std::pair result = getAngleFromSelection(); + if (result.second) { + ui->dsbExtAngle->setValue(result.first * 180.0 / M_PI); + } +} + +std::pair TaskDimension::getAngleFromSelection() +{ + std::pair result; + result.first = 0.0; + result.second = true; + std::vector selection = Gui::Selection().getSelectionEx(); + TechDraw::DrawViewPart * objFeat = 0; + std::vector SubNames; + if (!selection.empty()) { + objFeat = static_cast (selection.front().getObject()); + SubNames = selection.front().getSubNames(); + if (SubNames.size() == 2) { //expecting Vertices + std::string geomName0 = DrawUtil::getGeomTypeFromName(SubNames[0]); + int geomIndex0 = DrawUtil::getIndexFromName(SubNames[0]); + std::string geomName1 = DrawUtil::getGeomTypeFromName(SubNames[1]); + int geomIndex1 = DrawUtil::getIndexFromName(SubNames[1]); + if ((geomName0 == "Vertex") && (geomName1 == "Vertex")) { + TechDraw::VertexPtr v0 = objFeat->getProjVertexByIndex(geomIndex0); + TechDraw::VertexPtr v1 = objFeat->getProjVertexByIndex(geomIndex1); + Base::Vector2d v02(v0->point().x, -v0->point().y); + Base::Vector2d v12(v1->point().x, -v1->point().y); + result.first = (v12 - v02).Angle(); + return result; + } + } else if (SubNames.size() == 1) { //expecting Edge + std::string geomName0 = DrawUtil::getGeomTypeFromName(SubNames[0]); + int geomIndex0 = DrawUtil::getIndexFromName(SubNames[0]); + if (geomName0 == "Edge") { + TechDraw::BaseGeomPtr edge = objFeat->getGeomByIndex(geomIndex0); + Base::Vector2d v02(edge->getStartPoint().x, -edge->getStartPoint().y); + Base::Vector2d v12(edge->getEndPoint().x, -edge->getEndPoint().y); + result.first = (v12 - v02).Angle(); + return result; + } + } + } + + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Incorrect Selection"), + QObject::tr("Select 2 Vertexes or 1 Edge")); + result.second = false; + return result; +} ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TaskDlgDimension::TaskDlgDimension(QGIViewDimension *parent, ViewProviderDimension *dimensionVP) : diff --git a/src/Mod/TechDraw/Gui/TaskDimension.h b/src/Mod/TechDraw/Gui/TaskDimension.h index 1a53d08b73..1c74283cdd 100644 --- a/src/Mod/TechDraw/Gui/TaskDimension.h +++ b/src/Mod/TechDraw/Gui/TaskDimension.h @@ -60,11 +60,19 @@ private Q_SLOTS: void onColorChanged(); void onFontsizeChanged(); void onDrawingStyleChanged(); + void onOverrideToggled(); + void onDimAngleChanged(); + void onExtAngleChanged(); + void onDimUseDefaultClicked(); + void onDimUseSelectionClicked(); + void onExtUseDefaultClicked(); + void onExtUseSelectionClicked(); private: std::unique_ptr ui; QGIViewDimension *m_parent; ViewProviderDimension *m_dimensionVP; + std::pair getAngleFromSelection(); }; class TaskDlgDimension : public Gui::TaskView::TaskDialog diff --git a/src/Mod/TechDraw/Gui/TaskDimension.ui b/src/Mod/TechDraw/Gui/TaskDimension.ui index f6a54c1dd7..690867e09f 100644 --- a/src/Mod/TechDraw/Gui/TaskDimension.ui +++ b/src/Mod/TechDraw/Gui/TaskDimension.ui @@ -7,7 +7,7 @@ 0 0 330 - 417 + 698 @@ -166,7 +166,7 @@ be used instead if the dimension value - Specifies the undertolerance format in printf() style, or arbitrary text + Specifies the undertolerance format in printf() style, or arbitrary text @@ -305,6 +305,115 @@ be used instead if the dimension value + + + + Lines + + + + + + + + Extension line angle + + + + + + + Set dimension line angle to default (ortho view). + + + Use default + + + + + + + Use override angles if checked. Use default angles if unchecked. + + + Override angles + + + + + + + Set dimension line angle to match selected edge or vertices. + + + Use selection + + + + + + + Angle of dimension line with drawing X axis (degrees) + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + -360.000000000000000 + + + 360.000000000000000 + + + + + + + Angle of extension lines with drawing X axis (degrees) + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + -360.000000000000000 + + + 360.000000000000000 + + + + + + + Dimension line angle + + + + + + + Set extension line angle to match selected edge or vertices. + + + Use selection + + + + + + + Set extension line angle to default (ortho). + + + Use default + + + + + + + +