| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| |
|
| | # include <cstdlib> |
| | # include <limits> |
| | # include <sstream> |
| |
|
| | # include <Bnd_Box.hxx> |
| | # include <BRepBndLib.hxx> |
| | # include <BRep_Builder.hxx> |
| | # include <BRepBuilderAPI_MakeEdge.hxx> |
| | # include <BRepExtrema_DistShapeShape.hxx> |
| | # include <Geom_Line.hxx> |
| | # include <gp_Pln.hxx> |
| | # include <TopoDS_Edge.hxx> |
| |
|
| | #include <App/Document.h> |
| | #include <App/DocumentObject.h> |
| | #include <Base/Console.h> |
| | #include <Base/Interpreter.h> |
| | #include <Base/Vector3D.h> |
| |
|
| | #include "DrawDimHelper.h" |
| | #include "Cosmetic.h" |
| | #include "DrawPage.h" |
| | #include "DrawUtil.h" |
| | #include "DrawViewDimension.h" |
| | #include "DrawViewDimExtent.h" |
| | #include "DrawViewPart.h" |
| | #include "Geometry.h" |
| | #include "GeometryObject.h" |
| |
|
| |
|
| | #define HORIZONTAL 0 |
| | #define VERTICAL 1 |
| | #define LENGTH 2 |
| |
|
| | using namespace TechDraw; |
| |
|
| | DrawViewDimension* DrawDimHelper::makeExtentDim(DrawViewPart* dvp, |
| | const std::string& dimType, ReferenceVector references2d) |
| | { |
| | std::vector<std::string> edgeNames; |
| | for (auto& ref : references2d) { |
| | if (ref.getSubName().empty()) { |
| | continue; |
| | } |
| | std::string geomType = DrawUtil::getGeomTypeFromName(ref.getSubName()); |
| | if (geomType == "Edge") { |
| | edgeNames.push_back(ref.getSubName()); |
| | } |
| | } |
| | int direction = dimType == "DistanceX" ? 0 : dimType == "DistanceY" ? 1 : 2; |
| |
|
| | return makeExtentDim(dvp, edgeNames, direction); |
| | } |
| |
|
| | DrawViewDimension* DrawDimHelper::makeExtentDim(DrawViewPart* dvp, std::vector<std::string> edgeNames, |
| | int direction) |
| | { |
| | |
| | |
| | if (!dvp) { |
| | return nullptr; |
| | } |
| |
|
| | std::string dimType = "DistanceX"; |
| | int dimNum = 0; |
| | if (direction == VERTICAL) { |
| | dimType = "DistanceY"; |
| | dimNum = 1; |
| | } |
| | else if (direction == LENGTH) { |
| | dimType = "Distance"; |
| | dimNum = 2; |
| | } |
| |
|
| | DrawPage* page = dvp->findParentPage(); |
| | std::string pageName = page->getNameInDocument(); |
| |
|
| | App::Document* doc = dvp->getDocument(); |
| | std::string dimName = doc->getUniqueObjectName("DimExtent"); |
| | Base::Interpreter().runStringArg( |
| | "App.activeDocument().addObject('TechDraw::DrawViewDimExtent', '%s')", dimName.c_str()); |
| | Base::Interpreter().runStringArg( |
| | "App.activeDocument().%s.translateLabel('DrawViewDimExtent', 'DimExtent', '%s')", |
| | dimName.c_str(), dimName.c_str()); Base::Interpreter().runStringArg( |
| | "App.activeDocument().%s.Type = '%s'", dimName.c_str(), dimType.c_str()); |
| | Base::Interpreter().runStringArg( |
| | "App.activeDocument().%s.DirExtent = %d", dimName.c_str(), dimNum); |
| |
|
| | auto* dimExt = freecad_cast<DrawViewDimExtent*>(doc->getObject(dimName.c_str())); |
| | if (!dimExt) { |
| | throw Base::TypeError("Dim extent not found"); |
| | } |
| | dimExt->Source.setValue(dvp, edgeNames); |
| | ReferenceVector newRefs; |
| | if (edgeNames.empty()) { |
| | ReferenceEntry emptyRef(dvp, std::string()); |
| | newRefs.push_back(emptyRef); |
| | } |
| | else { |
| | for (auto& edge : edgeNames) { |
| | ReferenceEntry ref(dvp, edge); |
| | newRefs.push_back(ref); |
| | } |
| | } |
| | dimExt->setReferences2d(newRefs); |
| |
|
| | Base::Interpreter().runStringArg("App.activeDocument().%s.addView(App.activeDocument().%s)", |
| | pageName.c_str(), |
| | dimName.c_str()); |
| |
|
| | dimExt->recomputeFeature(); |
| |
|
| | return dimExt; |
| | } |
| |
|
| | void DrawDimHelper::makeExtentDim3d(DrawViewPart* dvp, const std::string& dimType, ReferenceVector references3d) |
| | { |
| | int direction = dimType == "DistanceX" ? 0 : dimType == "DistanceY" ? 1 : 2; |
| | return makeExtentDim3d(dvp, references3d, direction); |
| | } |
| |
|
| | void DrawDimHelper::makeExtentDim3d(DrawViewPart* dvp, ReferenceVector references, int direction) |
| | { |
| | |
| | |
| | if (!dvp) { |
| | return; |
| | } |
| |
|
| | std::string dimType = "DistanceX"; |
| | int dimNum = 0; |
| | if (direction == VERTICAL) { |
| | dimType = "DistanceY"; |
| | dimNum = 1; |
| | } |
| |
|
| | DrawPage* page = dvp->findParentPage(); |
| | std::string pageName = page->getNameInDocument(); |
| |
|
| | App::Document* doc = dvp->getDocument(); |
| | std::string dimName = doc->getUniqueObjectName("DimExtent"); |
| | Base::Interpreter().runStringArg( |
| | "App.activeDocument().addObject('TechDraw::DrawViewDimExtent', '%s')", dimName.c_str()); |
| | Base::Interpreter().runStringArg( |
| | "App.activeDocument().%s.translateLabel('DrawViewDimExtent', 'DimExtent', '%s')", |
| | dimName.c_str(), dimName.c_str()); Base::Interpreter().runStringArg( |
| | "App.activeDocument().%s.Type = '%s'", dimName.c_str(), dimType.c_str()); |
| | Base::Interpreter().runStringArg( |
| | "App.activeDocument().%s.DirExtent = %d", dimName.c_str(), dimNum); |
| |
|
| | auto* dimExt = freecad_cast<DrawViewDimExtent*>(doc->getObject(dimName.c_str())); |
| | if (!dimExt) { |
| | throw Base::TypeError("Dim extent not found"); |
| | } |
| |
|
| | dimExt->Source.setValue(dvp); |
| |
|
| | std::vector<App::DocumentObject*> objs3d; |
| | std::vector<std::string> subs3d; |
| | for (auto& ref : references) { |
| | objs3d.push_back(ref.getObject()); |
| | subs3d.push_back(ref.getSubName()); |
| | } |
| | dimExt->Source3d.setValues(objs3d, subs3d); |
| |
|
| | ReferenceVector newRefs2d; |
| | ReferenceEntry emptyRef(dvp, std::string()); |
| | newRefs2d.push_back(emptyRef); |
| | dimExt->setReferences2d(newRefs2d); |
| |
|
| | dimExt->setReferences3d(references); |
| |
|
| | Base::Interpreter().runStringArg("App.activeDocument().%s.addView(App.activeDocument().%s)", |
| | pageName.c_str(), |
| | dimName.c_str()); |
| |
|
| | dimExt->recomputeFeature(); |
| | } |
| | std::pair<Base::Vector3d, Base::Vector3d> |
| | DrawDimHelper::minMax(DrawViewPart* dvp, std::vector<std::string> edgeNames, int direction) |
| | { |
| | |
| | std::pair<Base::Vector3d, Base::Vector3d> result; |
| | Base::Vector3d refMin; |
| | Base::Vector3d refMax; |
| |
|
| | gp_Ax3 projAx3; |
| | gp_Pln projPlane(projAx3); |
| |
|
| | BaseGeomPtrVector edgeGeomList; |
| | if (!edgeNames.empty() && !edgeNames.front().empty()) { |
| | |
| | for (auto& n : edgeNames) { |
| | std::string geomType = DrawUtil::getGeomTypeFromName(n); |
| | if (geomType == "Edge") { |
| | int i = DrawUtil::getIndexFromName(n); |
| | BaseGeomPtr bg = dvp->getGeomByIndex(i); |
| | if (bg) { |
| | edgeGeomList.push_back(bg); |
| | } |
| | } |
| | } |
| | } |
| | else { |
| | for (auto& edge : dvp->getEdgeGeometry()) { |
| | if (!edge->getCosmetic()) { |
| | |
| | edgeGeomList.push_back(edge); |
| | } |
| | } |
| | } |
| |
|
| | if (edgeGeomList.empty()) { |
| | return result; |
| | } |
| |
|
| | Bnd_Box edgeBbx; |
| | edgeBbx.SetGap(1.0); |
| |
|
| | std::vector<TopoDS_Edge> inEdges; |
| | for (auto& bg : edgeGeomList) { |
| | inEdges.push_back(bg->getOCCEdge()); |
| | BRepBndLib::Add(bg->getOCCEdge(), edgeBbx); |
| | } |
| |
|
| | double minX, minY, minZ, maxX, maxY, maxZ; |
| | edgeBbx.Get(minX, minY, minZ, maxX, maxY, maxZ); |
| | double xMid = (maxX + minX) / 2.0; |
| | double yMid = (maxY + minY) / 2.0; |
| |
|
| | gp_Pnt rightMid(maxX, yMid, 0.0); |
| | gp_Pnt leftMid(minX, yMid, 0.0); |
| | gp_Pnt topMid(xMid, maxY, 0.0); |
| | gp_Pnt bottomMid(xMid, minY, 0.0); |
| |
|
| | gp_Dir xDir(1.0, 0.0, 0.0); |
| | gp_Dir yDir(0.0, 1.0, 0.0); |
| |
|
| | if (direction == HORIZONTAL) { |
| | Handle(Geom_Line) lineLeft = new Geom_Line(leftMid, yDir); |
| | BRepBuilderAPI_MakeEdge mkEdgeLeft(lineLeft); |
| | TopoDS_Edge edgeLeft = mkEdgeLeft.Edge(); |
| | gp_Pnt leftPoint = findClosestPoint(inEdges, edgeLeft); |
| | Handle(Geom_Line) lineRight = new Geom_Line(rightMid, yDir); |
| | BRepBuilderAPI_MakeEdge mkEdgeRight(lineRight); |
| | TopoDS_Edge edgeRight = mkEdgeRight.Edge(); |
| | gp_Pnt rightPoint = findClosestPoint(inEdges, edgeRight); |
| |
|
| | refMin = Base::Vector3d(leftPoint.X(), leftPoint.Y(), 0.0); |
| | refMax = Base::Vector3d(rightPoint.X(), rightPoint.Y(), 0.0); |
| | } |
| | else if (direction == VERTICAL) { |
| | Handle(Geom_Line) lineBottom = new Geom_Line(bottomMid, xDir); |
| | BRepBuilderAPI_MakeEdge mkEdgeBottom(lineBottom); |
| | TopoDS_Edge edgeBottom = mkEdgeBottom.Edge(); |
| | gp_Pnt bottomPoint = findClosestPoint(inEdges, edgeBottom); |
| | Handle(Geom_Line) lineTop = new Geom_Line(topMid, xDir); |
| | BRepBuilderAPI_MakeEdge mkEdgeTop(lineTop); |
| | TopoDS_Edge edgeTop = mkEdgeTop.Edge(); |
| | gp_Pnt topPoint = findClosestPoint(inEdges, edgeTop); |
| | refMin = Base::Vector3d(bottomPoint.X(), bottomPoint.Y(), 0.0); |
| | refMax = Base::Vector3d(topPoint.X(), topPoint.Y(), 0.0); |
| | } |
| |
|
| | result.first = refMin; |
| | result.second = refMax; |
| | return result; |
| | } |
| |
|
| | |
| | |
| | gp_Pnt DrawDimHelper::findClosestPoint(std::vector<TopoDS_Edge> inEdges, TopoDS_Edge& boundary) |
| | { |
| | |
| | |
| | |
| | double minDistance(std::numeric_limits<float>::max()); |
| | gp_Pnt nearPoint; |
| | for (auto& edge : inEdges) { |
| | BRepExtrema_DistShapeShape extss(edge, boundary); |
| | if (!extss.IsDone()) { |
| | Base::Console().warning( |
| | "DDH::findClosestPoint - BRepExtrema_DistShapeShape failed - 1\n"); |
| | continue; |
| | } |
| | if (extss.NbSolution() == 0) { |
| | Base::Console().warning( |
| | "DDH::findClosestPoint - BRepExtrema_DistShapeShape failed - 2\n"); |
| | continue; |
| | } |
| | if (extss.Value() < minDistance) { |
| | minDistance = extss.Value(); |
| | nearPoint = extss.PointOnShape1(1); |
| | } |
| | } |
| | return nearPoint; |
| | } |
| |
|
| | std::pair<Base::Vector3d, Base::Vector3d> |
| | DrawDimHelper::minMax3d(DrawViewPart* dvp, ReferenceVector references, int direction) |
| | { |
| | |
| | std::pair<Base::Vector3d, Base::Vector3d> result; |
| | Base::Vector3d refMin; |
| | Base::Vector3d refMax; |
| |
|
| | gp_Ax3 projAx3; |
| | gp_Pln projPlane(projAx3); |
| |
|
| | BRep_Builder builder; |
| | TopoDS_Compound comp; |
| | builder.MakeCompound(comp); |
| | for (auto& ref : references) { |
| | auto tempGeom = ref.getGeometry(); |
| | if (tempGeom.IsNull()) { |
| | continue; |
| | } |
| | builder.Add(comp, tempGeom); |
| | } |
| | Base::Vector3d centroid = dvp->getOriginalCentroid(); |
| | TopoDS_Shape centeredShape = |
| | DrawViewPart::centerScaleRotate(dvp, comp, centroid); |
| |
|
| | |
| | TechDraw::GeometryObjectPtr go( |
| | std::make_shared<TechDraw::GeometryObject>(std::string(), nullptr)); |
| | go->setIsoCount(0); |
| | go->isPerspective(false); |
| | go->usePolygonHLR(false); |
| | go->projectShape(comp, dvp->getProjectionCS()); |
| | auto edges = go->getEdgeGeometry(); |
| |
|
| | if (edges.empty()) { |
| | return result; |
| | } |
| |
|
| | Bnd_Box shapeBbx; |
| | shapeBbx.SetGap(1.0); |
| |
|
| | std::vector<TopoDS_Edge> inEdges; |
| | for (auto& bg : edges) { |
| | inEdges.push_back(bg->getOCCEdge()); |
| | BRepBndLib::Add(bg->getOCCEdge(), shapeBbx); |
| | } |
| |
|
| | |
| | double minX, minY, minZ, maxX, maxY, maxZ; |
| | shapeBbx.Get(minX, minY, minZ, maxX, maxY, maxZ); |
| | double xMid = (maxX + minX) / 2.0; |
| | double yMid = (maxY + minY) / 2.0; |
| |
|
| | gp_Pnt rightMid(maxX, yMid, 0.0); |
| | gp_Pnt leftMid(minX, yMid, 0.0); |
| | gp_Pnt topMid(xMid, maxY, 0.0); |
| | gp_Pnt bottomMid(xMid, minY, 0.0); |
| |
|
| | gp_Dir xDir(1.0, 0.0, 0.0); |
| | gp_Dir yDir(0.0, 1.0, 0.0); |
| |
|
| | if (direction == HORIZONTAL) { |
| | Handle(Geom_Line) lineLeft = new Geom_Line(leftMid, yDir); |
| | BRepBuilderAPI_MakeEdge mkEdgeLeft(lineLeft); |
| | TopoDS_Edge edgeLeft = mkEdgeLeft.Edge(); |
| | gp_Pnt leftPoint = findClosestPoint(inEdges, edgeLeft); |
| | Handle(Geom_Line) lineRight = new Geom_Line(rightMid, yDir); |
| | BRepBuilderAPI_MakeEdge mkEdgeRight(lineRight); |
| | TopoDS_Edge edgeRight = mkEdgeRight.Edge(); |
| | gp_Pnt rightPoint = findClosestPoint(inEdges, edgeRight); |
| |
|
| | refMin = Base::Vector3d(leftPoint.X(), leftPoint.Y(), 0.0); |
| | refMax = Base::Vector3d(rightPoint.X(), rightPoint.Y(), 0.0); |
| | } |
| | else if (direction == VERTICAL) { |
| | Handle(Geom_Line) lineBottom = new Geom_Line(bottomMid, xDir); |
| | BRepBuilderAPI_MakeEdge mkEdgeBottom(lineBottom); |
| | TopoDS_Edge edgeBottom = mkEdgeBottom.Edge(); |
| | gp_Pnt bottomPoint = findClosestPoint(inEdges, edgeBottom); |
| | Handle(Geom_Line) lineTop = new Geom_Line(topMid, xDir); |
| | BRepBuilderAPI_MakeEdge mkEdgeTop(lineTop); |
| | TopoDS_Edge edgeTop = mkEdgeTop.Edge(); |
| | gp_Pnt topPoint = findClosestPoint(inEdges, edgeTop); |
| | refMin = Base::Vector3d(bottomPoint.X(), bottomPoint.Y(), 0.0); |
| | refMax = Base::Vector3d(topPoint.X(), topPoint.Y(), 0.0); |
| | } |
| |
|
| | result.first = refMin; |
| | result.second = refMax; |
| | return result; |
| | } |
| |
|
| | DrawViewDimension* |
| | DrawDimHelper::makeDistDim(DrawViewPart* dvp, std::string dimType, |
| | Base::Vector3d inMin, |
| | Base::Vector3d inMax, |
| | bool extent) |
| | { |
| | |
| | |
| | |
| | TechDraw::DrawPage* page = dvp->findParentPage(); |
| | std::string pageName = page->getNameInDocument(); |
| |
|
| | TechDraw::DrawViewDimension* dim = nullptr; |
| | App::Document* doc = dvp->getDocument(); |
| | std::string dimName = doc->getUniqueObjectName("Dimension"); |
| | if (extent) { |
| | dimName = doc->getUniqueObjectName("DimExtent"); |
| | } |
| |
|
| | std::vector<TechDraw::VertexPtr> gVerts = dvp->getVertexGeometry(); |
| |
|
| | |
| | Base::Vector3d cleanMin = DrawUtil::invertY(inMin); |
| | cleanMin = CosmeticVertex::makeCanonicalPoint(dvp, cleanMin); |
| | std::string tag1 = dvp->addCosmeticVertex(cleanMin); |
| | int iGV1 = dvp->add1CVToGV(tag1); |
| |
|
| | Base::Vector3d cleanMax = DrawUtil::invertY(inMax); |
| | cleanMax = CosmeticVertex::makeCanonicalPoint(dvp, cleanMax); |
| | std::string tag2 = dvp->addCosmeticVertex(cleanMax); |
| | int iGV2 = dvp->add1CVToGV(tag2); |
| |
|
| | gVerts = dvp->getVertexGeometry(); |
| | std::vector<App::DocumentObject*> objs; |
| | std::vector<std::string> subs; |
| |
|
| | std::stringstream ss; |
| | ss << "Vertex" << iGV1; |
| | std::string vertexName = ss.str(); |
| | subs.push_back(vertexName); |
| | objs.push_back(dvp); |
| |
|
| | ss.clear(); |
| | ss.str(std::string()); |
| | ss << "Vertex" << iGV2; |
| | vertexName = ss.str(); |
| | subs.push_back(vertexName); |
| | objs.push_back(dvp); |
| |
|
| | if (extent) { |
| | Base::Interpreter().runStringArg( |
| | "App.activeDocument().addObject('TechDraw::DrawViewDimExtent', '%s')", dimName.c_str()); |
| | Base::Interpreter().runStringArg( |
| | "App.activeDocument().%s.translateLabel('DrawViewDimExtent', 'DimExtent', '%s')", |
| | dimName.c_str(), dimName.c_str()); |
| | } |
| | else { |
| | Base::Interpreter().runStringArg( |
| | "App.activeDocument().addObject('TechDraw::DrawViewDimension', '%s')", dimName.c_str()); |
| | Base::Interpreter().runStringArg( |
| | "App.activeDocument().%s.translateLabel('DrawViewDimimension', 'Dimension', '%s')", |
| | dimName.c_str(), dimName.c_str()); |
| | } |
| |
|
| | Base::Interpreter().runStringArg( |
| | "App.activeDocument().%s.Type = '%s'", dimName.c_str(), dimType.c_str()); |
| |
|
| | dim = dynamic_cast<TechDraw::DrawViewDimension*>(doc->getObject(dimName.c_str())); |
| | if (!dim) { |
| | throw Base::TypeError("DDH::makeDistDim - dim not found\n"); |
| | } |
| | dim->References2D.setValues(objs, subs); |
| |
|
| | Base::Interpreter().runStringArg("App.activeDocument().%s.addView(App.activeDocument().%s)", |
| | pageName.c_str(), |
| | dimName.c_str()); |
| |
|
| | dvp->requestPaint(); |
| | return dim; |
| | } |
| |
|