From 74556bced867fdc8a8ac2b6e93b2b602d87e84b2 Mon Sep 17 00:00:00 2001 From: wandererfan Date: Tue, 9 Apr 2024 08:30:45 -0400 Subject: [PATCH] [TD]handle odd projection cs in broken view --- src/Mod/TechDraw/App/DrawBrokenView.cpp | 384 +++++++++++++++++------- src/Mod/TechDraw/App/DrawBrokenView.h | 17 +- src/Mod/TechDraw/App/DrawUtil.cpp | 24 +- src/Mod/TechDraw/App/DrawUtil.h | 2 + src/Mod/TechDraw/Gui/QGIBreakLine.cpp | 2 +- src/Mod/TechDraw/Gui/QGIViewPart.cpp | 7 +- 6 files changed, 307 insertions(+), 129 deletions(-) diff --git a/src/Mod/TechDraw/App/DrawBrokenView.cpp b/src/Mod/TechDraw/App/DrawBrokenView.cpp index c44b216f94..0e28dc3b87 100644 --- a/src/Mod/TechDraw/App/DrawBrokenView.cpp +++ b/src/Mod/TechDraw/App/DrawBrokenView.cpp @@ -224,6 +224,10 @@ TopoDS_Shape DrawBrokenView::apply1Break(const App::DocumentObject& breakObj, co builder.MakeCompound(result); builder.Add(result, cut0); builder.Add(result, cut1); + + // BRepTools::Write(cut0, "DBVcut0.brep"); //debug + // BRepTools::Write(cut1, "DBVcut1.brep"); + return result; } @@ -241,32 +245,27 @@ TopoDS_Shape DrawBrokenView::compressShape(const TopoDS_Shape& shapeToCompress) //! move the broken pieces in the input shape "right" to close up the removed areas. //! note: breaks and pieces should not intersect by this point //! a break: BbbbbbbB -//! a piece: PpppP no need to move -//! a piece: PppppP move right by removed(B) +//! a piece: PpppP move right by removed(B) +//! a piece: PppppP no need to move TopoDS_Shape DrawBrokenView::compressHorizontal(const TopoDS_Shape& shapeToCompress)const { // Base::Console().Message("DBV::compressHorizontal()\n"); auto pieces = getPieces(shapeToCompress); auto breaksAll = Breaks.getValues(); - // ?? not sure about using closestBasis here. - auto moveDirection = DU::closestBasis(DU::toVector3d(getProjectionCS().XDirection())); + auto moveDirection = DU::closestBasisOriented(DU::toVector3d(getProjectionCS().XDirection())); bool descend = false; auto sortedBreaks = makeSortedBreakList(breaksAll, moveDirection, descend); - auto limits = getPieceUpperLimits(pieces, moveDirection); + auto limits = getPieceLimits(pieces, moveDirection); // for each break, move all the pieces left of the break to the right by the removed amount // for the break for (auto& breakItem : sortedBreaks) { // check each break against all the pieces - Base::Vector3d netBreakDisplace = moveDirection * (removedLengthFromObj(*breakItem.breakObj) - Gap.getValue()); + Base::Vector3d netBreakDisplace = + moveDirection * (removedLengthFromObj(*breakItem.breakObj) - Gap.getValue()); size_t iPiece{0}; - for (auto& pieceHighLimit : limits) { + for (auto& pieceLimit : limits) { // check each piece against the current break - // We have a problem with low digits here. The cut operations and later - // bounding box creation may generate pieceHighLimits that are slightly - // off. We know that the pieces were cut by a break, so we use a fuzzy - // comparison. - if (pieceHighLimit < breakItem.lowLimit || - DU::fpCompare(pieceHighLimit, breakItem.lowLimit, Precision::Confusion()) ) { + if (moveThisPiece(pieceLimit, breakItem, moveDirection)) { // piece is to left of break, so needs to move right TopoDS_Shape temp = ShapeUtils::moveShape(pieces.at(iPiece), netBreakDisplace); pieces.at(iPiece) = temp; @@ -293,20 +292,21 @@ TopoDS_Shape DrawBrokenView::compressVertical(const TopoDS_Shape& shapeToCompre auto pieces = getPieces(shapeToCompress); auto breaksAll = Breaks.getValues(); // not sure about using closestBasis here. may prevent oblique breaks later. - auto moveDirection = DU::closestBasis(DU::toVector3d(getProjectionCS().YDirection())); + auto moveDirection = DU::closestBasisOriented(DU::toVector3d(getProjectionCS().YDirection())); + bool descend = false; auto sortedBreaks = makeSortedBreakList(breaksAll, moveDirection, descend); - auto limits = getPieceUpperLimits(pieces, moveDirection); - // for each break, move all the pieces above the break down by the removed amount + auto limits = getPieceLimits(pieces, moveDirection); + // for each break, move all the pieces below the break up by the removed amount // for the break for (auto& breakItem : sortedBreaks) { // check each break against all the pieces - Base::Vector3d netBreakDisplace = moveDirection * (removedLengthFromObj(*breakItem.breakObj) - Gap.getValue()); + Base::Vector3d netBreakDisplace = + moveDirection * (removedLengthFromObj(*breakItem.breakObj) - Gap.getValue()); size_t iPiece{0}; - for (auto& pieceHighLimit : limits) { + for (auto& pieceLimit : limits) { // check each piece against the current break using a fuzzy equality - if (pieceHighLimit < breakItem.lowLimit || - DU::fpCompare(pieceHighLimit, breakItem.lowLimit, Precision::Confusion()) ) { + if (moveThisPiece(pieceLimit, breakItem, moveDirection)) { // piece is below the break, move it up TopoDS_Shape temp = ShapeUtils::moveShape(pieces.at(iPiece), netBreakDisplace); pieces.at(iPiece) = temp; @@ -330,6 +330,10 @@ TopoDS_Shape DrawBrokenView::compressVertical(const TopoDS_Shape& shapeToCompre //! plane normal) and a point inside the half space (pointInSpace). TopoDS_Shape DrawBrokenView::makeHalfSpace(Base::Vector3d planePoint, Base::Vector3d planeNormal, Base::Vector3d pointInSpace) const { + // Base::Console().Message("DBV::makeHalfSpace - planePoint: %s normal: %s pointInSpace: %s\n", + // DU::formatVector(planePoint).c_str(), + // DU::formatVector(planeNormal).c_str(), + // DU::formatVector(pointInSpace).c_str()); gp_Pnt origin = DU::togp_Pnt(planePoint); gp_Dir axis = DU::togp_Dir(planeNormal); gp_Pln plane(origin, axis); @@ -361,13 +365,21 @@ std::pair DrawBrokenView::breakPointsFromObj(con //! perpendicular to the break lines. Base::Vector3d DrawBrokenView::directionFromObj(const App::DocumentObject& breakObj) const { + // Base::Console().Message("DBV::directionFromObj()\n"); std::pair ends = breakPointsFromObj(breakObj); Base::Vector3d direction = ends.second - ends.first; direction.Normalize(); + // does this need to be oriented? return DU::closestBasis(direction); } +//! extract the breakDirection from the break object in a form the gui will understand. +Base::Vector3d DrawBrokenView::guiDirectionFromObj(const App::DocumentObject& breakObj) const +{ + return projectPoint(directionFromObj(breakObj)); +} + //! calculate the length to be removed as specified by break object. double DrawBrokenView::removedLengthFromObj(const App::DocumentObject& breakObj) const { @@ -445,12 +457,28 @@ std::pair DrawBrokenView::breakPointsFromSketch( TopoDS_Edge last = sketchEdges.back(); if ((isVertical(first) && isVertical(last)) || (isHorizontal(first) && isHorizontal(last))) { + // get points on each edge that are in line with the center of the sketch + // along the break direction + Bnd_Box edgeBox; + edgeBox.SetGap(0.0); + BRepBndLib::AddOptimal(first, edgeBox); + BRepBndLib::AddOptimal(last, edgeBox); + double xMin = 0, xMax = 0, yMin = 0, yMax = 0, zMin = 0, zMax = 0; + edgeBox.Get(xMin, yMin, zMin, xMax, yMax, zMax); + Base::Vector3d center( (xMin + xMax) / 2.0, + (yMin + yMax) / 2.0, + (zMin + zMax) / 2.0 ); auto ends0 = SU::getEdgeEnds(first); - // trouble here if the break points are wildly out of line? - // std::pair makeCardinal(p0, p1) to force horiz or vert? - auto break0 = (ends0.first + ends0.second) / 2.0; + auto dir0 = ends0.second - ends0.first; + dir0.Normalize(); + // get a point on edge first on a perpendicular line through center + auto break0 = center.Perpendicular(ends0.first, dir0); + auto ends1 = SU::getEdgeEnds(last); - auto break1 = (ends1.first + ends1.second) / 2.0; + auto dir1 = ends1.second - ends1.first; + dir1.Normalize(); + auto break1 = center.Perpendicular(ends1.first, dir1); + return { break0, break1 }; } @@ -496,31 +524,29 @@ std::pair DrawBrokenView::breakBoundsFromObj(con //! broken view. used in making break lines. std::pair DrawBrokenView::breakBoundsFromSketch(const App::DocumentObject& breakObj) const { - // Base::Console().Message("DBV::breakBoundsFromSketch()\n"); + //Base::Console().Message("DBV::breakBoundsFromSketch()\n"); std::pair breakPoints = breakPointsFromObj(breakObj); - Base::Vector3d anchor = (breakPoints.first + breakPoints.second) / 2.0; + Base::Vector3d center = (breakPoints.first + breakPoints.second) / 2.0; Base::Vector3d breakDir = directionFromObj(breakObj); breakDir.Normalize(); - Base::Vector3d lineDir = makePerpendicular(breakDir); - lineDir.Normalize(); - - // is this right? or do we need to project the points first? Should be alright - // if the break points are not skewed? - double removed = (breakPoints.first - breakPoints.second).Length(); + Base::Vector3d perpDir = makePerpendicular(breakDir); + perpDir.Normalize(); // get the midpoint of the zigzags - Base::Vector3d ptOnLine0 = anchor + breakDir * removed / 2.0; - Base::Vector3d ptOnLine1 = anchor - breakDir * removed / 2.0; + Base::Vector3d ptOnLine0 = center + breakDir * removedLengthFromObj(breakObj) / 2.0; + Base::Vector3d ptOnLine1 = center - breakDir * removedLengthFromObj(breakObj) / 2.0; double lineLength = breaklineLength(breakObj); - Base::Vector3d corner0 = ptOnLine0 - lineDir * lineLength / 2.0; - Base::Vector3d corner1 = ptOnLine1 + lineDir * lineLength / 2.0; + Base::Vector3d corner0 = ptOnLine0 - perpDir * lineLength / 2.0; + Base::Vector3d corner1 = ptOnLine1 + perpDir * lineLength / 2.0; corner0 = mapPoint3dToView(corner0); corner1 = mapPoint3dToView(corner1); + // these are unscaled, unrotated points return{corner0, corner1}; } + //! extract the boundary of the break lines from an edge std::pair DrawBrokenView::breakBoundsFromEdge(const App::DocumentObject& breakObj) const { @@ -732,15 +758,15 @@ std::vector DrawBrokenView::edgesFromCompound(TopoDS_Shape compound } -//! find the upper limits of each piece's bounding box in direction (if we support oblique projection directions, then the +//! find the limits of each piece's bounding box in cardinal direction (if we support oblique projection directions, then the //! piece will have to be transformed to align with OXYZ cardinal axes as in DrawViewPart::getSizeAlongVector) -std::vector DrawBrokenView::getPieceUpperLimits(const std::vector& pieces, Base::Vector3d direction) +PieceLimitList DrawBrokenView::getPieceLimits(const std::vector& pieces, Base::Vector3d direction) { // Base::Console().Message("DBV::getPieceUpperLimits(%s)\n", DU::formatVector(direction).c_str()); Base::Vector3d stdX{1.0, 0.0, 0.0}; Base::Vector3d stdY{0.0, 1.0, 0.0}; Base::Vector3d stdZ{0.0, 0.0, 1.0}; - std::vector limits; + PieceLimitList limits; limits.reserve(pieces.size()); for (auto& item : pieces) { Bnd_Box pieceBox; @@ -748,13 +774,21 @@ std::vector DrawBrokenView::getPieceUpperLimits(const std::vector DrawBrokenView::getPieces(TopoDS_Shape brokenShape) //! sort the breaks that match direction by their minimum limit BreakList DrawBrokenView::makeSortedBreakList(const std::vector& breaks, Base::Vector3d direction, bool descend) const { + // Base::Console().Message("DBV::makeSortedBreakList(%d, %s)\n", breaks.size(), + // DU::formatVector(direction).c_str()); Base::Vector3d stdX{1.0, 0.0, 0.0}; Base::Vector3d stdY{0.0, 1.0, 0.0}; Base::Vector3d stdZ{0.0, 0.0, 1.0}; @@ -786,7 +822,7 @@ BreakList DrawBrokenView::makeSortedBreakList(const std::vector= breakItem.highLimit) { - // leave alone, this break doesn't affect us - continue; - } + if (isDirectionReversed(direction)) { + if (pointCoord <= breakItem.lowLimit) { + // h--------l -ve + // p + // point is right/above break + // leave alone, this break doesn't affect us + continue; + } - if (pointCoord < breakItem.lowLimit || - DU::fpCompare(pointCoord, breakItem.lowLimit, Precision::Confusion()) ) { - // move right/up by the removed area less the gap - shift += removedLengthFromObj(*breakItem.breakObj) - Gap.getValue(); - continue; - } + if (pointCoord > breakItem.highLimit || + DU::fpCompare(pointCoord, breakItem.highLimit, Precision::Confusion()) ) { + // h--------l -ve + // p + // point is left/below break, but we + shift += removedLengthFromObj(*breakItem.breakObj) - Gap.getValue(); + continue; + } - // break.start < value < break.end - point is in the break area - // we move our point by a fraction of the Gap length - double penetration = pointCoord - breakItem.lowLimit; - double removed = removedLengthFromObj(*breakItem.breakObj); - double factor = 1 - (penetration / removed); - double netRemoved = breakItem.highLimit - factor * Gap.getValue(); - shift += netRemoved - pointCoord; + // h--------l -ve + // p + // break.start < value < break.end - point is in the break area + // we move our point by a fraction of the Gap length + double penetration = fabs(pointCoord - breakItem.highLimit); // start(high) to point + double removed = removedLengthFromObj(*breakItem.breakObj); + double factor = 1 - (penetration / removed); + double netRemoved = breakItem.lowLimit - factor * Gap.getValue(); + shift += fabs(netRemoved - pointCoord); + + + } else { + if (pointCoord >= breakItem.highLimit) { + // l--------h +ve + // p + // leave alone, this break doesn't affect us + continue; + } + + if (pointCoord < breakItem.lowLimit || + DU::fpCompare(pointCoord, breakItem.lowLimit, Precision::Confusion()) ) { + // l--------h +ve + // p + // move right/up by the removed area less the gap + shift += removedLengthFromObj(*breakItem.breakObj) - Gap.getValue(); + continue; + } + + // l--------h +ve + // p + // break.start < value < break.end - point is in the break area + // we move our point by a fraction of the Gap length + double penetration = fabs(pointCoord - breakItem.lowLimit); + double removed = removedLengthFromObj(*breakItem.breakObj); + double factor = 1 - (penetration / removed); + double netRemoved = breakItem.highLimit - factor * Gap.getValue(); + shift += fabs(netRemoved - pointCoord); + } } return shift; @@ -963,30 +1044,67 @@ double DrawBrokenView::shiftAmountShrink(double pointCoord, const BreakList& sor //! returns the amount a compressed coordinate needs to be shifted to reverse the effect of breaking //! the source shapes -double DrawBrokenView::shiftAmountExpand(double pointCoord, const BreakList& sortedBreaks) const +double DrawBrokenView::shiftAmountExpand(double pointCoord, Base::Vector3d direction, const BreakList& sortedBreaks) const { - // Base::Console().Message("DBV::shiftAmountExpand(%.3f, %d)\n", pointCoord, sortedBreaks.size()); + // Base::Console().Message("DBV::shiftAmountExpand(%.3f, %s, %d)\n", pointCoord, + // DU::formatVector(direction).c_str(), sortedBreaks.size()); double shift{0}; for (auto& breakItem : sortedBreaks) { - if (pointCoord >= breakItem.highLimit) { - // leave alone, this break doesn't affect us - continue; - } + if (isDirectionReversed(direction)) { + if (pointCoord <= breakItem.lowLimit) { + // h--------l -ve + // p + // leave alone, this break doesn't affect us + continue; + } - if (pointCoord < breakItem.lowLimit || - DU::fpCompare(pointCoord, breakItem.lowLimit, Precision::Confusion()) ) { - // move by the whole removed area - shift += breakItem.netRemoved; - continue; - } + if (pointCoord > breakItem.highLimit || + DU::fpCompare(pointCoord, breakItem.highLimit, Precision::Confusion()) ) { + // h--------l -ve + // p - // break.start < value < break.end - point is in the break area - // we move our point by the break's net removed * the penetration factor - double gapPenetration = pointCoord - breakItem.lowLimit; - double removed = removedLengthFromObj(*breakItem.breakObj); - double factor = 1 - gapPenetration / Gap.getValue(); - double shiftAmount = factor * (removed - Gap.getValue()); - shift += shiftAmount; + // move by the whole removed area + shift += breakItem.netRemoved; + continue; + } + + // h--------l -ve + // p + // break.start < value < break.end - point is in the break area + // we move our point by the break's net removed * the penetration factor + double gapPenetration = fabs(pointCoord - breakItem.lowLimit); + double removed = removedLengthFromObj(*breakItem.breakObj); + double factor = gapPenetration / Gap.getValue(); + double shiftAmount = factor * (removed - Gap.getValue()); + shift += shiftAmount; + + } else { + if (pointCoord >= breakItem.highLimit) { + // l--------h +ve + // p + // leave alone, this break doesn't affect us + continue; + } + + if (pointCoord < breakItem.lowLimit || + DU::fpCompare(pointCoord, breakItem.lowLimit, Precision::Confusion()) ) { + // l--------h +ve + // p + // move by the whole removed area + shift += breakItem.netRemoved; + continue; + } + + // l--------h +ve + // p + // break.start < value < break.end - point is in the break area + // we move our point by the break's net removed * the penetration factor + double gapPenetration = pointCoord - breakItem.lowLimit; + double removed = removedLengthFromObj(*breakItem.breakObj); + double factor = 1 - gapPenetration / Gap.getValue(); + double shiftAmount = factor * (removed - Gap.getValue()); + shift += shiftAmount; + } } return shift; @@ -1014,6 +1132,46 @@ Base::Vector3d DrawBrokenView::makePerpendicular(Base::Vector3d inDir) const return DU::toVector3d(gRotated); } +//! true if this piece should be moved +bool DrawBrokenView::moveThisPiece(PieceLimitEntry piece, + BreakListEntry breakItem, + Base::Vector3d moveDirection) const +{ + if (isDirectionReversed(moveDirection)) { + // -ve direction + if (piece.lowLimit > breakItem.highLimit || + DU::fpCompare(piece.lowLimit, breakItem.highLimit, Precision::Confusion()) ) { + return true; + } + } else { + // +ve direction + if (piece.highLimit < breakItem.lowLimit || + DU::fpCompare(piece.highLimit, breakItem.lowLimit, Precision::Confusion()) ) { + return true; + } + } + return false; +} + +//! true if direction is the reversed of a cardinal direction. (1.0, 0.0, 0.0) +//! returns false, (-1.0, 0.0, 0.0) returns true; +bool DrawBrokenView::isDirectionReversed(Base::Vector3d direction) const +{ + Base::Vector3d stdX{1.0, 0.0, 0.0}; + Base::Vector3d stdY{0.0, 1.0, 0.0}; + Base::Vector3d stdZ{0.0, 0.0, 1.0}; + if (DU::fpCompare(std::fabs(direction.Dot(stdX)), 1.0, EWTOLERANCE)) { + return DU::fpCompare(direction.Dot(stdX), -1.0, EWTOLERANCE); + } + if (DU::fpCompare(std::fabs(direction.Dot(stdY)), 1.0, EWTOLERANCE)) { + return DU::fpCompare(direction.Dot(stdY), -1.0, EWTOLERANCE); + } + if (DU::fpCompare(std::fabs(direction.Dot(stdZ)), 1.0, EWTOLERANCE)) { + return DU::fpCompare(direction.Dot(stdZ), -1.0, EWTOLERANCE); + } + return false; +} + void DrawBrokenView::printBreakList(const std::string& text, const BreakList& inBreaks) const { Base::Console().Message("DBV - %s\n", text.c_str()); diff --git a/src/Mod/TechDraw/App/DrawBrokenView.h b/src/Mod/TechDraw/App/DrawBrokenView.h index bbd336793c..0371da8f4a 100644 --- a/src/Mod/TechDraw/App/DrawBrokenView.h +++ b/src/Mod/TechDraw/App/DrawBrokenView.h @@ -47,9 +47,14 @@ struct BreakListEntry { // TODO: can the gap size change during the lifetime of BreakListEntry? if // so, we need to save the gap size @ creation time? }; - using BreakList = std::vector; +struct PieceLimitEntry { + double lowLimit; + double highLimit; +}; +using PieceLimitList = std::vector; + class TechDrawExport DrawBrokenView: public TechDraw::DrawViewPart { PROPERTY_HEADER_WITH_OVERRIDE(TechDraw::DrawBrokenView); @@ -75,6 +80,7 @@ public: std::pair breakBoundsFromObj(const App::DocumentObject& breakObj) const; Base::Vector3d directionFromObj(const App::DocumentObject& breakObj) const; + Base::Vector3d guiDirectionFromObj(const App::DocumentObject& breakObj) const; static bool isBreakObject(const App::DocumentObject& breakObj); static bool isBreakObjectSketch(const App::DocumentObject& breakObj); @@ -114,7 +120,7 @@ private: TopoDS_Shape compressHorizontal(const TopoDS_Shape& inShape) const; TopoDS_Shape compressVertical(const TopoDS_Shape& inShape) const; - static std::vector getPieceUpperLimits(const std::vector& pieces, Base::Vector3d direction); + static PieceLimitList getPieceLimits(const std::vector& pieces, Base::Vector3d direction); BreakList makeSortedBreakList(const std::vector& breaks, Base::Vector3d direction, bool descend = false) const; BreakList makeSortedBreakListCompressed(const std::vector& breaks, Base::Vector3d moveDirection, bool descend = false) const; @@ -123,8 +129,8 @@ private: static bool breakLess(const BreakListEntry& entry0, const BreakListEntry& entry1); // double pointToLimit(const Base::Vector3d& inPoint, const Base::Vector3d& direction) const; - double shiftAmountShrink(double pointCoord, const BreakList& sortedBreaks) const; - double shiftAmountExpand(double pointCoord, const BreakList& sortedBreaks) const; + double shiftAmountShrink(double pointCoord, Base::Vector3d direction, const BreakList& sortedBreaks) const; + double shiftAmountExpand(double pointCoord, Base::Vector3d direction, const BreakList& sortedBreaks) const; void printBreakList(const std::string& text, const BreakList& inBreaks) const; @@ -132,6 +138,9 @@ private: scalePair(std::pair inPair) const; Base::Vector3d makePerpendicular(Base::Vector3d inDir) const; + bool moveThisPiece(PieceLimitEntry piece, BreakListEntry breakItem, Base::Vector3d moveDirection) const; + bool isDirectionReversed(Base::Vector3d direction) const; + Base::Vector3d m_unbrokenCenter; TopoDS_Shape m_compressedShape; diff --git a/src/Mod/TechDraw/App/DrawUtil.cpp b/src/Mod/TechDraw/App/DrawUtil.cpp index 79f1a4b0b7..5eb2562c04 100644 --- a/src/Mod/TechDraw/App/DrawUtil.cpp +++ b/src/Mod/TechDraw/App/DrawUtil.cpp @@ -861,18 +861,15 @@ double DrawUtil::getWidthInDirection(gp_Dir direction, TopoDS_Shape& shape) //! cardinal direction or the reverse of a cardinal direction. gp_Vec DrawUtil::maskDirection(gp_Vec inVec, gp_Dir directionToMask) { - if (directionToMask.XYZ().IsEqual(gp::OX().Direction().XYZ(), EWTOLERANCE) || - directionToMask.XYZ().IsEqual(gp::OX().Direction().Reversed().XYZ(), EWTOLERANCE)) { - return {0.0, inVec.Y(), inVec.Z()}; + if (fpCompare(std::fabs(directionToMask.Dot(gp::OX().Direction().XYZ())), 1.0, EWTOLERANCE)) { + return {0.0, inVec.Y(), inVec.Z()}; } - if (directionToMask.XYZ().IsEqual(gp::OY().Direction().XYZ(), EWTOLERANCE) || - directionToMask.XYZ().IsEqual(gp::OY().Direction().Reversed().XYZ(), EWTOLERANCE)) { + if (fpCompare(std::fabs(directionToMask.Dot(gp::OY().Direction().XYZ())), 1.0, EWTOLERANCE)) { return {inVec.X(), 0.0, inVec.Z()}; } - if (directionToMask.XYZ().IsEqual(gp::OZ().Direction().XYZ(), EWTOLERANCE) || - directionToMask.XYZ().IsEqual(gp::OZ().Direction().Reversed().XYZ(), EWTOLERANCE)) { + if (fpCompare(std::fabs(directionToMask.Dot(gp::OZ().Direction().XYZ())), 1.0, EWTOLERANCE)) { return {inVec.X(), inVec.Y(), 0.0}; } @@ -880,6 +877,19 @@ gp_Vec DrawUtil::maskDirection(gp_Vec inVec, gp_Dir directionToMask) return {}; } +Base::Vector3d DrawUtil::maskDirection(Base::Vector3d inVec, Base::Vector3d directionToMask) +{ + return toVector3d(maskDirection(togp_Vec(inVec), togp_Vec(directionToMask))); +} + +//! get the coordinate of inPoint for the cardinal unit direction. +double DrawUtil::coordinateForDirection(Base::Vector3d inPoint, Base::Vector3d cardinal) +{ + auto masked = maskDirection(inPoint, cardinal); + auto stripped = inPoint - masked; + return stripped.x + stripped.y + stripped.z; +} + //based on Function provided by Joe Dowsett, 2014 double DrawUtil::sensibleScale(double working_scale) { diff --git a/src/Mod/TechDraw/App/DrawUtil.h b/src/Mod/TechDraw/App/DrawUtil.h index 1f4580efce..1bc948b91b 100644 --- a/src/Mod/TechDraw/App/DrawUtil.h +++ b/src/Mod/TechDraw/App/DrawUtil.h @@ -154,6 +154,8 @@ public: static double getWidthInDirection(gp_Dir direction, TopoDS_Shape& shape); static gp_Vec maskDirection(gp_Vec inVec, gp_Dir directionToMask); + static Base::Vector3d maskDirection(Base::Vector3d inVec, Base::Vector3d directionToMask); + static double coordinateForDirection(Base::Vector3d inPoint, Base::Vector3d cardinal); static double getDefaultLineWeight(std::string s); //! is pt between end1 and end2? diff --git a/src/Mod/TechDraw/Gui/QGIBreakLine.cpp b/src/Mod/TechDraw/Gui/QGIBreakLine.cpp index 4dd9cde99d..1862c836e5 100644 --- a/src/Mod/TechDraw/Gui/QGIBreakLine.cpp +++ b/src/Mod/TechDraw/Gui/QGIBreakLine.cpp @@ -75,7 +75,7 @@ void QGIBreakLine::draw() Base::Vector3d horizontal{1.0, 0.0, 0.0}; prepareGeometryChange(); double offset = zigzagWidth / 2.0; - if (m_direction.IsEqual(horizontal, EWTOLERANCE)) { + if (DU::fpCompare(fabs(m_direction.Dot(horizontal)), 1.0, EWTOLERANCE)) { // m_direction connects the two cut points. The zigzags have // to be perpendicular to m_direction // 2x vertical zigzag diff --git a/src/Mod/TechDraw/Gui/QGIViewPart.cpp b/src/Mod/TechDraw/Gui/QGIViewPart.cpp index afb6d5c45b..ff3cf87664 100644 --- a/src/Mod/TechDraw/Gui/QGIViewPart.cpp +++ b/src/Mod/TechDraw/Gui/QGIViewPart.cpp @@ -1056,13 +1056,12 @@ void QGIViewPart::drawBreakLines() QGIBreakLine* breakLine = new QGIBreakLine(); addToGroup(breakLine); - Base::Vector3d direction = dbv->directionFromObj(*breakObj); - direction.Normalize(); + Base::Vector3d direction = dbv->guiDirectionFromObj(*breakObj); breakLine->setDirection(direction); - // the bounds describe two corners of the removed area + // the bounds describe two corners of the removed area in the view std::pair bounds = dbv->breakBoundsFromObj(*breakObj); // the bounds are in 3d form, so we need to invert & rez them - Base::Vector3d topLeft = Rez::guiX(DU::invertY(bounds.first)); + Base::Vector3d topLeft = Rez::guiX(DU::invertY(bounds.first)); Base::Vector3d bottomRight = Rez::guiX(DU::invertY(bounds.second)); breakLine->setBounds(topLeft, bottomRight); breakLine->setPos(0.0, 0.0);