From 17a01963e02eebd57f957f0b161b081f53d4d62d Mon Sep 17 00:00:00 2001 From: "Zheng, Lei" Date: Thu, 15 Feb 2024 08:05:23 -0500 Subject: [PATCH] Toponaming/Part: transfer in linearize --- src/Mod/Part/App/TopoShape.h | 10 ++++ src/Mod/Part/App/TopoShapeExpansion.cpp | 78 +++++++++++++++++++++++++ 2 files changed, 88 insertions(+) diff --git a/src/Mod/Part/App/TopoShape.h b/src/Mod/Part/App/TopoShape.h index b6bbd06133..25b6790111 100644 --- a/src/Mod/Part/App/TopoShape.h +++ b/src/Mod/Part/App/TopoShape.h @@ -317,6 +317,10 @@ public: bool isInfinite() const; /// Checks whether the shape is a planar face bool isPlanar(double tol = 1.0e-7) const; + /// Check if this shape is a single linear edge, works on BSplineCurve and BezierCurve + bool isLinearEdge(Base::Vector3d *dir = nullptr, Base::Vector3d *base = nullptr) const; + /// Check if this shape is a single planar face, works on BSplineSurface and BezierSurface + bool isPlanarFace(double tol=1e-7) const; //@} /** @name Boolean operation*/ @@ -680,6 +684,12 @@ public: } //@} + /** Try to simplify geometry of any linear/planar subshape to line/plane + * + * @return Return true if the shape is modified + */ + bool linearize(bool face, bool edge); + static TopAbs_ShapeEnum shapeType(const char* type, bool silent = false); static TopAbs_ShapeEnum shapeType(char type, bool silent = false); TopAbs_ShapeEnum shapeType(bool silent = false) const; diff --git a/src/Mod/Part/App/TopoShapeExpansion.cpp b/src/Mod/Part/App/TopoShapeExpansion.cpp index c7c7081cbf..4da7445a77 100644 --- a/src/Mod/Part/App/TopoShapeExpansion.cpp +++ b/src/Mod/Part/App/TopoShapeExpansion.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -71,6 +72,8 @@ #include "Geometry.h" #include +#include +#include "Geometry.h" FC_LOG_LEVEL_INIT("TopoShape", true, true) // NOLINT @@ -2490,6 +2493,81 @@ TopoShape TopoShape::splitWires(std::vector* inner, SplitWireReorient return TopoShape {}; } +bool TopoShape::isLinearEdge(Base::Vector3d* dir, Base::Vector3d* base) const +{ + if (isNull() || getShape().ShapeType() != TopAbs_EDGE) { + return false; + } + + if (!GeomCurve::isLinear(BRepAdaptor_Curve(TopoDS::Edge(getShape())).Curve().Curve(), + dir, + base)) { + return false; + } + + // BRep_Tool::Curve() will transform the returned geometry, so no need to + // check the shape's placement. + return true; +} + +bool TopoShape::isPlanarFace(double tol) const +{ + if (isNull() || getShape().ShapeType() != TopAbs_FACE) { + return false; + } + + return GeomSurface::isPlanar(BRepAdaptor_Surface(TopoDS::Face(getShape())).Surface().Surface(), + nullptr, + tol); +} + +bool TopoShape::linearize(bool face, bool edge) +{ + bool touched = false; + BRep_Builder builder; + // Note: changing edge geometry seems to mess up with face (or shell, or solid) + // Probably need to do some fix afterwards. + if (edge) { + for (auto& edge : getSubTopoShapes(TopAbs_EDGE)) { + TopoDS_Edge e = TopoDS::Edge(edge.getShape()); + BRepAdaptor_Curve curve(e); + if (curve.GetType() == GeomAbs_Line || !edge.isLinearEdge()) { + continue; + } + std::unique_ptr geo( + Geometry::fromShape(e.Located(TopLoc_Location()).Oriented(TopAbs_FORWARD))); + std::unique_ptr gline(static_cast(geo.get())->toLine()); + if (gline) { + touched = true; + builder.UpdateEdge(e, + Handle(Geom_Curve)::DownCast(gline->handle()), + e.Location(), + BRep_Tool::Tolerance(e)); + } + } + } + if (face) { + for (auto& face : getSubTopoShapes(TopAbs_FACE)) { + TopoDS_Face f = TopoDS::Face(face.getShape()); + BRepAdaptor_Surface surf(f); + if (surf.GetType() == GeomAbs_Plane || !face.isPlanarFace()) { + continue; + } + std::unique_ptr geo( + Geometry::fromShape(f.Located(TopLoc_Location()).Oriented(TopAbs_FORWARD))); + std::unique_ptr gplane(static_cast(geo.get())->toPlane()); + if (gplane) { + touched = true; + builder.UpdateFace(f, + Handle(Geom_Surface)::DownCast(gplane->handle()), + f.Location(), + BRep_Tool::Tolerance(f)); + } + } + } + return touched; +} + struct MapperFill: Part::TopoShape::Mapper { BRepFill_Generator& maker;