From 084b33d3e481ca890446d112800b931aad631391 Mon Sep 17 00:00:00 2001 From: wandererfan Date: Sat, 23 Sep 2023 12:16:17 -0400 Subject: [PATCH] [TD]fix centerline rotation --- src/Mod/TechDraw/App/CenterLine.cpp | 179 +++++++++++++++------ src/Mod/TechDraw/App/CenterLine.h | 3 + src/Mod/TechDraw/App/CosmeticExtension.cpp | 11 +- src/Mod/TechDraw/App/ShapeUtils.cpp | 14 ++ src/Mod/TechDraw/App/ShapeUtils.h | 4 + 5 files changed, 161 insertions(+), 50 deletions(-) diff --git a/src/Mod/TechDraw/App/CenterLine.cpp b/src/Mod/TechDraw/App/CenterLine.cpp index 66f59d5725..bb68b56319 100644 --- a/src/Mod/TechDraw/App/CenterLine.cpp +++ b/src/Mod/TechDraw/App/CenterLine.cpp @@ -31,16 +31,16 @@ #include #endif +#include #include -#include #include "CenterLine.h" #include "DrawUtil.h" #include "DrawViewPart.h" #include "Geometry.h" -#include "GeometryObject.h" #include "CenterLinePy.h" +#include "ShapeUtils.h" using namespace TechDraw; using DU = DrawUtil; @@ -274,6 +274,84 @@ TechDraw::BaseGeomPtr CenterLine::scaledGeometry(const TechDraw::DrawViewPart* p return newGeom; } +TechDraw::BaseGeomPtr CenterLine::scaledAndRotatedGeometry(TechDraw::DrawViewPart* partFeat) +{ +// Base::Console().Message("CL::scaledGeometry() - m_type: %d\n", m_type); + double scale = partFeat->getScale(); + double viewAngleDeg = partFeat->Rotation.getValue(); + std::pair ends; + try { + if (m_faces.empty() && + m_edges.empty() && + m_verts.empty() ) { +// Base::Console().Message("CL::scaledGeometry - no geometry to scale!\n"); + //CenterLine was created by points without a geometry reference, + ends = calcEndPointsNoRef(m_start, m_end, scale, m_extendBy, + m_hShift, m_vShift, m_rotate, viewAngleDeg); + } else if (m_type == CLTYPE::FACE) { + ends = calcEndPoints(partFeat, + m_faces, + m_mode, m_extendBy, + m_hShift, m_vShift, m_rotate); + } else if (m_type == CLTYPE::EDGE) { + ends = calcEndPoints2Lines(partFeat, + m_edges, + m_mode, + m_extendBy, + m_hShift, m_vShift, m_rotate, m_flip2Line); + } else if (m_type == CLTYPE::VERTEX) { + ends = calcEndPoints2Points(partFeat, + m_verts, + m_mode, + m_extendBy, + m_hShift, m_vShift, m_rotate, m_flip2Line); + } + } + + catch (...) { + Base::Console().Error("CL::scaledGeometry - failed to calculate endpoints!\n"); + return nullptr; + } + + // inversion here breaks face cl. + Base::Vector3d p1 = ends.first; + Base::Vector3d p2 = ends.second; + if (p1.IsEqual(p2, 0.00001)) { + Base::Console().Warning("Centerline endpoints are equal. Could not draw.\n"); + //what to do here? //return current geom? + return m_geometry; + } + + TopoDS_Edge newEdge; + if (getType() == CLTYPE::FACE ) { + gp_Pnt gp1(DU::togp_Pnt(p1)); + gp_Pnt gp2(DU::togp_Pnt(p2)); + TopoDS_Edge e = BRepBuilderAPI_MakeEdge(gp1, gp2); + // Mirror shape in Y and scale + TopoDS_Shape s = ShapeUtils::mirrorShape(e, gp_Pnt(0.0, 0.0, 0.0), scale); + // rotate using OXYZ as the coordinate system + s = ShapeUtils::rotateShape(s, gp_Ax2(), - partFeat->Rotation.getValue()); + newEdge = TopoDS::Edge(s); + } else if (getType() == CLTYPE::EDGE || + getType() == CLTYPE::VERTEX) { + gp_Pnt gp1(DU::togp_Pnt(DU::invertY(p1 * scale))); + gp_Pnt gp2(DU::togp_Pnt(DU::invertY(p2 * scale))); + newEdge = BRepBuilderAPI_MakeEdge(gp1, gp2); + } + + TechDraw::BaseGeomPtr newGeom = TechDraw::BaseGeom::baseFactory(newEdge); + if (!newGeom) { + throw Base::RuntimeError("Failed to create center line"); + } + newGeom->setClassOfEdge(ecHARD); + newGeom->setHlrVisible( true); + newGeom->setCosmetic(true); + newGeom->source(CENTERLINE); + newGeom->setCosmeticTag(getTagAsString()); + + return newGeom; +} + std::string CenterLine::toString() const { std::stringstream ss; @@ -417,12 +495,20 @@ std::pair CenterLine::calcEndPoints(const DrawVi } } TopoDS_Shape faceEdgeCompound = DU::vectorToCompound(faceEdgesAll); - if (partFeat->Rotation.getValue() != 0.0) { - // align a copy of the input shape with the cardinal axes so we can use bbox to - // get size measurements - faceEdgeCompound = ShapeUtils::rotateShape(faceEdgeCompound, partFeat->getProjectionCS(), partFeat->Rotation.getValue() * -1.0); - } + if (partFeat->Rotation.getValue() != 0.0) { + // unrotate the input shape to align with the cardinal axes so we can use bbox to + // get size measurements + faceEdgeCompound = ShapeUtils::rotateShape(faceEdgeCompound, + partFeat->getProjectionCS(), + partFeat->Rotation.getValue() * -1.0); + } + // get the center of the unrotated, scaled face + Base::Vector3d faceCenter = ShapeUtils::findCentroidVec(faceEdgeCompound, partFeat->getProjectionCS()); + // we need to move the edges to the origin here to get the right limits from the bounding box + faceEdgeCompound = ShapeUtils::moveShape(faceEdgeCompound, faceCenter * -1.0); + + // get the bounding box of the centered and unrotated face BRepBndLib::AddOptimal(faceEdgeCompound, faceBox); if (faceBox.IsVoid()) { @@ -435,11 +521,14 @@ std::pair CenterLine::calcEndPoints(const DrawVi double Xspan = fabs(Xmax - Xmin); Xspan = (Xspan / 2.0); - double Xmid = Xmin + Xspan; - + double Xmid = 0.0; + Xmax = Xmid + Xspan; + Xmin = Xmid - Xspan; double Yspan = fabs(Ymax - Ymin); Yspan = (Yspan / 2.0); - double Ymid = Ymin + Yspan; + double Ymid = 0.0; + Ymax = Ymid + Yspan; + Ymin = Ymid - Yspan; Base::Vector3d p1, p2; if (mode == CenterLine::VERTICAL) { //vertical @@ -454,6 +543,12 @@ std::pair CenterLine::calcEndPoints(const DrawVi p2 = Base::Vector3d(Xmid, Ymin, 0.0); } + // now move the extents back to the face center. this should give us the scaled, + // unrotated ends of the cl (but in 3d coordinates, which will be handled at the time + // the cl is added to the view) + p1 += faceCenter; + p2 += faceCenter; + Base::Vector3d mid = (p1 + p2) / 2.0; //extend @@ -480,14 +575,9 @@ std::pair CenterLine::calcEndPoints(const DrawVi p2.y = p2.y + vss; } - // rotate the endpoints so that when the View's Rotation is applied, the - // centerline is aligned correctly std::pair result; result.first = p1 / scale; result.second = p2 / scale; - Base::Vector3d midpoint = (result.first + result.second) / 2.0; - result = rotatePointsAroundMid(result.first, result.second, midpoint, partFeat->Rotation.getValue() * -1.0); - return result; } @@ -511,7 +601,6 @@ std::pair CenterLine::calcEndPoints2Lines(const } double scale = partFeat->getScale(); - const std::vector dbEdges = partFeat->getEdgeGeometry(); std::vector edges; for (auto& en: edgeNames) { @@ -528,14 +617,15 @@ std::pair CenterLine::calcEndPoints2Lines(const } if (edges.size() != 2) { Base::Console().Message("CL::calcEndPoints2Lines - wrong number of edges: %d!\n", edges.size()); -// return result; throw Base::IndexError("CenterLine wrong number of edges."); } - Base::Vector3d l1p1 = edges.front()->getStartPoint(); - Base::Vector3d l1p2 = edges.front()->getEndPoint(); - Base::Vector3d l2p1 = edges.back()->getStartPoint(); - Base::Vector3d l2p2 = edges.back()->getEndPoint(); + // these points are centered, rotated, scaled and inverted. + // invert the points so the math works correctly + Base::Vector3d l1p1 = DU::invertY(edges.front()->getStartPoint()); + Base::Vector3d l1p2 = DU::invertY(edges.front()->getEndPoint()); + Base::Vector3d l2p1 = DU::invertY(edges.back()->getStartPoint()); + Base::Vector3d l2p2 = DU::invertY(edges.back()->getEndPoint()); // The centerline is drawn using the midpoints of the two lines that connect l1p1-l2p1 and l1p2-l2p2. // However, we don't know which point should be l1p1 to get a geometrically correct result, see @@ -568,14 +658,17 @@ std::pair CenterLine::calcEndPoints2Lines(const } //orientation - if (mode == CenterLine::VERTICAL && !inhibitVertical) { //Vertical - p1.x = mid.x; - p2.x = mid.x; - } else if (mode == CenterLine::HORIZONTAL && !inhibitHorizontal) { //Horizontal - p1.y = mid.y; - p2.y = mid.y; - } else if (mode == CenterLine::ALIGNED) { //Aligned - // no op + if (partFeat->Rotation.getValue() == 0.0) { + // if the view is rotated, then horizontal and vertical lose their meaning + if (mode == 0 && !inhibitVertical) { //Vertical + p1.x = mid.x; + p2.x = mid.x; + } else if (mode == 1 && !inhibitHorizontal) { //Horizontal + p1.y = mid.y; + p2.y = mid.y; + } else if (mode == 2) { //Aligned + // no op + } } //extend @@ -587,9 +680,7 @@ std::pair CenterLine::calcEndPoints2Lines(const //rotate if (!DrawUtil::fpCompare(rotate, 0.0)) { //rotate p1, p2 about mid - std::pair ends = rotatePointsAroundMid(p1, p2, mid, rotate); - p1 = ends.first; - p2 = ends.second; + std::tie(p1, p2) = rotatePointsAroundMid(p1, p2, mid, rotate); } //shift @@ -604,13 +695,9 @@ std::pair CenterLine::calcEndPoints2Lines(const p2.y = p2.y + vss; } - // rotate the endpoints so that when the View's Rotation is applied, the - // centerline is aligned correctly + // the cl will be scaled when drawn, so unscale now. result.first = p1 / scale; result.second = p2 / scale; - Base::Vector3d midpoint = (result.first + result.second) / 2.0; - result = rotatePointsAroundMid(result.first, result.second, midpoint, partFeat->Rotation.getValue() * -1.0); - return result; } @@ -647,8 +734,8 @@ std::pair CenterLine::calcEndPoints2Points(const throw Base::IndexError("CenterLine wrong number of points."); } - Base::Vector3d v1 = points.front()->point(); - Base::Vector3d v2 = points.back()->point(); + Base::Vector3d v1 = DU::invertY(points.front()->point()); + Base::Vector3d v2 = DU::invertY(points.back()->point()); Base::Vector3d mid = (v1 + v2) / 2.0; Base::Vector3d dir = v2 - v1; @@ -667,16 +754,20 @@ std::pair CenterLine::calcEndPoints2Points(const inhibitVertical = true; } - if (mode == CenterLine::VERTICAL && !inhibitVertical) { + //orientation + if (partFeat->Rotation.getValue() == 0.0) { + // if the view is rotated, then horizontal and vertical lose their meaning + if (mode == CenterLine::VERTICAL && !inhibitVertical) { //Vertical v1.x = mid.x; v2.x = mid.x; - } else if (mode == CenterLine::HORIZONTAL && !inhibitHorizontal) { + } else if (mode == CenterLine::HORIZONTAL && !inhibitHorizontal) { //Horizontal v1.y = mid.y; v2.y = mid.y; - } else if (mode == CenterLine::ALIGNED) { //Aligned - // no op + } else if (mode == CenterLine::ALIGNED) { //Aligned + // no op + } } double length = dir.Length(); @@ -714,8 +805,6 @@ std::pair CenterLine::calcEndPoints2Points(const p2.y = p2.y + vss; } - // in the case of points, we do not need to apply a rotation, since the points will - // rotated already std::pair result; result.first = p1 / scale; result.second = p2 / scale; diff --git a/src/Mod/TechDraw/App/CenterLine.h b/src/Mod/TechDraw/App/CenterLine.h index 5086cb324d..98c0b4a3e0 100644 --- a/src/Mod/TechDraw/App/CenterLine.h +++ b/src/Mod/TechDraw/App/CenterLine.h @@ -88,6 +88,7 @@ public: const int mode = 0, const bool flip = false); TechDraw::BaseGeomPtr scaledGeometry(const TechDraw::DrawViewPart* partFeat); + TechDraw::BaseGeomPtr scaledAndRotatedGeometry(TechDraw::DrawViewPart* partFeat); static std::pair rotatePointsAroundMid( const Base::Vector3d& p1, @@ -139,6 +140,8 @@ public: double getExtend() const; void setFlip(const bool f); bool getFlip() const; + void setType(const int type) { m_type = type; }; + int getType() const { return m_type; } Base::Vector3d m_start; Base::Vector3d m_end; diff --git a/src/Mod/TechDraw/App/CosmeticExtension.cpp b/src/Mod/TechDraw/App/CosmeticExtension.cpp index 7245d3f09e..f2174423a4 100644 --- a/src/Mod/TechDraw/App/CosmeticExtension.cpp +++ b/src/Mod/TechDraw/App/CosmeticExtension.cpp @@ -341,7 +341,7 @@ TechDraw::CosmeticEdge* CosmeticExtension::getCosmeticEdge(const std::string& ta } // None found - Base::Console().Message("CEx::getCosmeticEdge - CE for tag: %s not found.\n", tagString.c_str()); +// Base::Console().Message("CEx::getCosmeticEdge - CE for tag: %s not found.\n", tagString.c_str()); return nullptr; } @@ -416,10 +416,11 @@ int CosmeticExtension::add1CLToGE(const std::string& tag) // Base::Console().Message("CEx::add1CLToGE(%s) 2\n", tag.c_str()); TechDraw::CenterLine* cl = getCenterLine(tag); if (!cl) { - Base::Console().Message("CEx::add1CLToGE 2 - cl %s not found\n", tag.c_str()); +// Base::Console().Message("CEx::add1CLToGE 2 - cl %s not found\n", tag.c_str()); return -1; } - TechDraw::BaseGeomPtr scaledGeom = cl->scaledGeometry(getOwner()); + TechDraw::BaseGeomPtr scaledGeom = cl->scaledAndRotatedGeometry(getOwner()); +// TechDraw::BaseGeomPtr scaledGeom = cl->scaledGeometry(getOwner()); int iGE = getOwner()->getGeometryObject()->addCenterLine(scaledGeom, tag); return iGE; @@ -446,7 +447,8 @@ void CosmeticExtension::addCenterLinesToGeom() // Base::Console().Message("CE::addCenterLinesToGeom()\n"); const std::vector lines = CenterLines.getValues(); for (auto& cl : lines) { - TechDraw::BaseGeomPtr scaledGeom = cl->scaledGeometry(getOwner()); +// TechDraw::BaseGeomPtr scaledGeom = cl->scaledGeometry(getOwner()); + TechDraw::BaseGeomPtr scaledGeom = cl->scaledAndRotatedGeometry(getOwner()); if (!scaledGeom) { Base::Console().Error("CE::addCenterLinesToGeom - scaledGeometry is null\n"); continue; @@ -491,7 +493,6 @@ std::string CosmeticExtension::addCenterLine(TechDraw::BaseGeomPtr bg) return cl->getTagAsString(); } - //get CL by unique id TechDraw::CenterLine* CosmeticExtension::getCenterLine(const std::string& tagString) const { diff --git a/src/Mod/TechDraw/App/ShapeUtils.cpp b/src/Mod/TechDraw/App/ShapeUtils.cpp index a9e0d9d71f..c0497a1ad2 100644 --- a/src/Mod/TechDraw/App/ShapeUtils.cpp +++ b/src/Mod/TechDraw/App/ShapeUtils.cpp @@ -353,3 +353,17 @@ TopoDS_Shape ShapeUtils::centerShapeXY(const TopoDS_Shape& inShape, const gp_Ax2 Base::Vector3d centroid = DrawUtil::toVector3d(inputCenter); return ShapeUtils::moveShape(inShape, centroid * -1.0); } + +std::pair ShapeUtils::getEdgeEnds(TopoDS_Edge edge) +{ + std::pair result; + TopoDS_Vertex tvFirst, tvLast; + TopExp::Vertices(edge, tvFirst, tvLast); + gp_Pnt gpFirst = BRep_Tool::Pnt(tvFirst); + gp_Pnt gpLast = BRep_Tool::Pnt(tvLast); + + result.first = DU::toVector3d(gpFirst); + result.second = DU::toVector3d(gpLast); + return result; +} + diff --git a/src/Mod/TechDraw/App/ShapeUtils.h b/src/Mod/TechDraw/App/ShapeUtils.h index e831a8c8b7..2a8272e892 100644 --- a/src/Mod/TechDraw/App/ShapeUtils.h +++ b/src/Mod/TechDraw/App/ShapeUtils.h @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -104,6 +105,9 @@ public: static TopoDS_Shape projectSimpleShape(const TopoDS_Shape& shape, const gp_Ax2& CS); static TopoDS_Shape simpleProjection(const TopoDS_Shape& shape, const gp_Ax2& projCS); static TopoDS_Shape projectFace(const TopoDS_Shape& face, const gp_Ax2& CS); + + static std::pair getEdgeEnds(TopoDS_Edge edge); + }; }