From 5a7697182577e7d8c959b54baaece591ce8273d2 Mon Sep 17 00:00:00 2001 From: jfa Date: Tue, 24 May 2022 22:28:45 +0300 Subject: [PATCH] Implement Arcs mode for offset in case of multiple output wires --- src/GeomAlgoAPI/GeomAlgoAPI_Fillet1D.cpp | 77 ++++++++++++++++++++---- src/GeomAlgoAPI/GeomAlgoAPI_Fillet1D.h | 20 ++++-- src/Model/Model_AttributeIntArray.cpp | 3 +- src/SketchPlugin/SketchPlugin_Offset.cpp | 54 ++++++----------- 4 files changed, 100 insertions(+), 54 deletions(-) diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Fillet1D.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_Fillet1D.cpp index d1313e663..2dd7dbed0 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_Fillet1D.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_Fillet1D.cpp @@ -22,12 +22,14 @@ #include #include #include +#include #include #include #include #include #include +#include #include @@ -66,14 +68,64 @@ GeomAlgoAPI_Fillet1D::GeomAlgoAPI_Fillet1D(const GeomShapePtr& theBaseWire, build(theBaseWire, theFilletVertices, theFilletRadius); } -void GeomAlgoAPI_Fillet1D::build(const GeomShapePtr& theBaseWire, +void GeomAlgoAPI_Fillet1D::build(const GeomShapePtr& theBaseShape, const ListOfShape& theFilletVertices, const double theRadius) { - if (!theBaseWire || theFilletVertices.empty() || theRadius < 0.) + if (!theBaseShape.get() || theFilletVertices.empty() || theRadius < 0.) return; myFailedVertices.clear(); + GeomShapePtr aShape; + + if (theBaseShape->isWire()) + aShape = buildWire(theBaseShape, theFilletVertices, theRadius); + else if (theBaseShape->isCompound()) { + std::list aShapes; + for (GeomAPI_ShapeIterator it (theBaseShape); it.more(); it.next()) { + GeomShapePtr aSubShape = it.current(); + if (aSubShape->isWire()) { + // get only fillet vertices of current wire + ListOfShape aFilletVertices; + std::set aFilletVerticesSet + (theFilletVertices.begin(), theFilletVertices.end()); + for (GeomAPI_WireExplorer anExp(aSubShape->wire()); anExp.more(); anExp.next()) { + if (aFilletVerticesSet.find(anExp.currentVertex()) != aFilletVerticesSet.end()) + aFilletVertices.push_back(anExp.currentVertex()); + } + + GeomShapePtr aShape_i = buildWire(aSubShape, aFilletVertices, theRadius); + if (aShape_i.get() != NULL) + aShapes.push_back(aShape_i); + else + aShapes.push_back(aSubShape); + } + else { + setDone(false); + myError = "Input shape for fillet is neither a wire nor a compound of wires"; + return; + } + } + aShape = GeomAlgoAPI_CompoundBuilder::compound(aShapes); + myModified[theBaseShape].push_back(aShape); + } else { + setDone(false); + myError = "Input shape for fillet is neither a wire nor a compound"; + return; + } + + setShape(aShape); + setDone(myFailedVertices.empty()); +} + +GeomShapePtr GeomAlgoAPI_Fillet1D::buildWire(const GeomShapePtr& theBaseWire, + const ListOfShape& theFilletVertices, + const double theRadius) +{ + std::shared_ptr aShape; + if (!theBaseWire.get() || theFilletVertices.empty() || theRadius < 0.) + return aShape; + // store all edges of a base wire as modified, because they will be rebuild by ShapeFix for (GeomAPI_WireExplorer aWExp(theBaseWire->wire()); aWExp.more(); aWExp.next()) { GeomShapePtr aCurrent = aWExp.current(); @@ -103,7 +155,7 @@ void GeomAlgoAPI_Fillet1D::build(const GeomShapePtr& theBaseWire, GeomPlanePtr aPlane = GeomAlgoAPI_ShapeTools::findPlane(anEdges); if (!aPlane) - return; // non-planar edges + return aShape; // non-planar edges TopoDS_Edge anEdge1 = TopoDS::Edge(anEdges.front()->impl()); TopoDS_Edge anEdge2 = TopoDS::Edge(anEdges.back()->impl()); @@ -148,9 +200,10 @@ void GeomAlgoAPI_Fillet1D::build(const GeomShapePtr& theBaseWire, aNewEdges.push_back(aWExp.current()); for (ListOfShape::iterator anIt = aNewEdges.begin(); anIt != aNewEdges.end(); ++anIt) aBuilder.Add(aNewWire, TopoDS::Edge((*anIt)->impl())); - } - for (MapModified::iterator aGenIt = myGenerated.begin(); aGenIt != myGenerated.end(); ++aGenIt) { - for (ListOfShape::iterator anIt = aGenIt->second.begin(); anIt != aGenIt->second.end(); ++anIt) + + ListOfShape aNewEdges1; + generated(aWExp.currentVertex(), aNewEdges1); + for (ListOfShape::iterator anIt = aNewEdges1.begin(); anIt != aNewEdges1.end(); ++anIt) aBuilder.Add(aNewWire, TopoDS::Edge((*anIt)->impl())); } // fix the wire connectivity @@ -161,7 +214,7 @@ void GeomAlgoAPI_Fillet1D::build(const GeomShapePtr& theBaseWire, aNewWire = aFixWire.WireAPIMake(); if (aNewWire.IsNull()) { myFailedVertices = theFilletVertices; - return; + return aShape; } // update the map of modified shapes, because the edges are changed by ShapeFix @@ -197,12 +250,10 @@ void GeomAlgoAPI_Fillet1D::build(const GeomShapePtr& theBaseWire, aNewWire = aReorderedWire; } - std::shared_ptr aShape(new GeomAPI_Shape()); - aShape->setImpl(new TopoDS_Shape(aNewWire)); - myModified[theBaseWire].push_back(aShape); - - setShape(aShape); - setDone(myFailedVertices.empty()); + std::shared_ptr aResShape(new GeomAPI_Shape); + aResShape->setImpl(new TopoDS_Shape(aNewWire)); + myModified[theBaseWire].push_back(aResShape); + return aResShape; } void GeomAlgoAPI_Fillet1D::generated(const GeomShapePtr theOldShape, diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Fillet1D.h b/src/GeomAlgoAPI/GeomAlgoAPI_Fillet1D.h index a1065bd48..187df078b 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_Fillet1D.h +++ b/src/GeomAlgoAPI/GeomAlgoAPI_Fillet1D.h @@ -34,8 +34,8 @@ class GeomAlgoAPI_Fillet1D : public GeomAlgoAPI_MakeShape public: /// Run fillet operation on a set of vertices with fixed radius. - /// \param theBaseWire a changing Wire - /// \param theFilletVertices list of edges the fillet is performed on + /// \param theBaseWire a wire or a compound of wires + /// \param theFilletVertices list of vertices the fillet is performed on /// \param theFilletRadius radius of the fillet GEOMALGOAPI_EXPORT GeomAlgoAPI_Fillet1D(const GeomShapePtr& theBaseWire, const ListOfShape& theFilletVertices, @@ -57,14 +57,22 @@ public: const ListOfShape& failedVertices() const { return myFailedVertices; } private: - /// Perform 1d-fillet on wire - /// \param theBaseWire a changing wire - /// \param theFilletVertices list of vertices of filler + /// Perform 1d-fillet on a wire or a compound of wires + /// \param theBaseShape the base wire or a compound of wires for fillet + /// \param theFilletVertices list of vertices of fillet /// \param theRadius fillet radius - void build(const GeomShapePtr& theBaseWire, + void build(const GeomShapePtr& theBaseShape, const ListOfShape& theFilletVertices, const double theRadius); + /// Perform 1d-fillet on wire + /// \param theBaseWire the base wire for fillet + /// \param theFilletVertices list of vertices of fillet + /// \param theRadius fillet radius + GeomShapePtr buildWire(const GeomShapePtr& theBaseWire, + const ListOfShape& theFilletVertices, + const double theRadius); + private: MapModified myGenerated; MapModified myModified; diff --git a/src/Model/Model_AttributeIntArray.cpp b/src/Model/Model_AttributeIntArray.cpp index 69c000f9c..5e1239a58 100644 --- a/src/Model/Model_AttributeIntArray.cpp +++ b/src/Model/Model_AttributeIntArray.cpp @@ -54,7 +54,8 @@ void Model_AttributeIntArray::setSize(const int theSize, bool sendUpdated) } else { // reset the old array if (theSize) { if (theSize != myArray->Length()) { // old data is not kept, a new array is created - Handle(TColStd_HArray1OfInteger) aNewArray = new TColStd_HArray1OfInteger(0, theSize - 1); + Handle(TColStd_HArray1OfInteger) aNewArray = + new TColStd_HArray1OfInteger(0, theSize - 1, 0); myArray->ChangeArray(aNewArray); if (sendUpdated) owner()->data()->sendAttributeUpdated(this); diff --git a/src/SketchPlugin/SketchPlugin_Offset.cpp b/src/SketchPlugin/SketchPlugin_Offset.cpp index 84a77e964..c175d42f0 100644 --- a/src/SketchPlugin/SketchPlugin_Offset.cpp +++ b/src/SketchPlugin/SketchPlugin_Offset.cpp @@ -821,39 +821,31 @@ void SketchPlugin_Offset::makeFillet // find vertices for fillet std::set aFilletVertices; - // ??? TODO: if aResWire is a compound of wires - process each wire ??? - if (aResWire->isWire()) { - for (MapShapeToShapes::const_iterator anIt = aSubshapes.begin(); - anIt != aSubshapes.end(); ++anIt) { - // vertex should have 2 adjacent edges - if (anIt->second.size() != 2) - continue; + for (MapShapeToShapes::const_iterator anIt = aSubshapes.begin(); + anIt != aSubshapes.end(); ++anIt) { + // vertex should have 2 adjacent edges + if (anIt->second.size() != 2) + continue; - // both edges should be linear - ListOfShape anEdges; - anEdges.insert(anEdges.end(), anIt->second.begin(), anIt->second.end()); - GeomEdgePtr anEdge1 (new GeomAPI_Edge(anEdges.front())); - GeomEdgePtr anEdge2 (new GeomAPI_Edge(anEdges.back())); - if (!anEdge1->isLine() || !anEdge2->isLine()) - continue; + // both edges should be linear + ListOfShape anEdges; + anEdges.insert(anEdges.end(), anIt->second.begin(), anIt->second.end()); + GeomEdgePtr anEdge1 (new GeomAPI_Edge(anEdges.front())); + GeomEdgePtr anEdge2 (new GeomAPI_Edge(anEdges.back())); + if (!anEdge1->isLine() || !anEdge2->isLine()) + continue; - // skip vertices, which smoothly connect adjacent edges - GeomVertexPtr aSharedVertex(new GeomAPI_Vertex(anIt->first)); - if (GeomAlgoAPI_ShapeTools::isTangent(anEdge1, anEdge2, aSharedVertex)) - continue; + // skip vertices, which smoothly connect adjacent edges + GeomVertexPtr aSharedVertex(new GeomAPI_Vertex(anIt->first)); + if (GeomAlgoAPI_ShapeTools::isTangent(anEdge1, anEdge2, aSharedVertex)) + continue; - aFilletVertices.insert(anIt->first); - } + aFilletVertices.insert(anIt->first); } if (!aFilletVertices.empty()) { isOK = false; // the wire needs correction - ListOfShape aVerticesList; - for (GeomAPI_WireExplorer anExp (aResWire->wire()); anExp.more(); anExp.next()) { - GeomShapePtr aVertex = anExp.currentVertex(); - if (aFilletVertices.find(aVertex) != aFilletVertices.end()) - aVerticesList.push_back(aVertex); - } + ListOfShape aVerticesList (aFilletVertices.begin(), aFilletVertices.end()); // Fillet1D on all linear edges intersections std::shared_ptr aFilletBuilder @@ -867,8 +859,7 @@ void SketchPlugin_Offset::makeFillet } else { ListOfShape aFailedVertices = aFilletBuilder->failedVertices(); - if (aFailedVertices.size() != 0 && - aFailedVertices.size() != aVerticesList.size()) { + if (aFailedVertices.size() != 0) { // Exclude failed vertices and also vertices, joined // with failed by one edge, and run algorithm once again ListOfShape::iterator itVertices = aFailedVertices.begin(); @@ -897,12 +888,7 @@ void SketchPlugin_Offset::makeFillet } else { // Fillet1D one more try - ListOfShape aVerticesList1; - for (GeomAPI_WireExplorer anExp (aResWire->wire()); anExp.more(); anExp.next()) { - GeomShapePtr aVertex = anExp.currentVertex(); - if (aFilletVertices.find(aVertex) != aFilletVertices.end()) - aVerticesList1.push_back(aVertex); - } + ListOfShape aVerticesList1 (aFilletVertices.begin(), aFilletVertices.end()); std::shared_ptr aFilletBuilder1 (new GeomAlgoAPI_Fillet1D(aResWire, aVerticesList1, theValue)); -- 2.39.2