X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FBuildPlugin%2FBuildPlugin_Filling.cpp;h=40a7f495c42e00e05b93200b0710619d4d10d113;hb=06e7f5859095193fc7f498bd89a7d28009794f53;hp=7e2c884ced1522ec4055a6248901b5cd83984dc0;hpb=dfa8d5cc9a33eb949f364e1999dc36e75fd1ffe8;p=modules%2Fshaper.git diff --git a/src/BuildPlugin/BuildPlugin_Filling.cpp b/src/BuildPlugin/BuildPlugin_Filling.cpp index 7e2c884ce..40a7f495c 100644 --- a/src/BuildPlugin/BuildPlugin_Filling.cpp +++ b/src/BuildPlugin/BuildPlugin_Filling.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2017-20xx CEA/DEN, EDF R&D +// Copyright (C) 2017-2023 CEA, EDF // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -12,10 +12,9 @@ // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // -// See http://www.salome-platform.org/ or -// email : webmaster.salome@opencascade.com +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // #include "BuildPlugin_Filling.h" @@ -30,10 +29,14 @@ #include #include #include +#include +#include +#include #include #include #include +#include #include @@ -48,6 +51,15 @@ struct FillingParameters bool isApprox; }; +static bool isReverseClosedCurve(const GeomEdgePtr& theEdge1, + const GeomEdgePtr& theEdge2); +static bool isReverseOpenedCurve(const GeomEdgePtr& theEdge1, + const GeomEdgePtr& theEdge2, + const double theTolerance); +static void shiftStartPoint(GeomWirePtr& theWire, + const GeomEdgePtr& theRefEdge, + const double theTolerance); + //================================================================================================= BuildPlugin_Filling::BuildPlugin_Filling() @@ -67,8 +79,8 @@ void BuildPlugin_Filling::initAttributes() data()->addAttribute(TOLERANCE_3D_ID(), ModelAPI_AttributeDouble::typeId()); data()->addAttribute(APPROXIMATION_ID(), ModelAPI_AttributeBoolean::typeId()); - restoreDefaultParameters(); - string(ADVANCED_OPTIONS_ID())->setValue(""); + if (string(ADVANCED_OPTIONS_ID())->value().empty()) + restoreDefaultParameters(); } //================================================================================================= @@ -95,26 +107,26 @@ void BuildPlugin_Filling::execute() // get base objects list AttributeSelectionListPtr aSelectionList = selectionList(BASE_OBJECTS_ID()); - if (aSelectionList->size() <= 1) + if (aSelectionList->size() <= 1) { + setError("Not enough objects is selected"); return; + } // collect base shapes for(int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) { AttributeSelectionPtr aSelection = aSelectionList->value(anIndex); GeomEdgePtr anEdge = toEdge(aSelection->value(), aParameters.method); - if (!anEdge) { - myLastEdgeStartPoint = GeomPointPtr(); - myLastEdgeEndPoint = GeomPointPtr(); + if (!anEdge) return; - } aFilling->add(anEdge); } - myLastEdgeStartPoint = GeomPointPtr(); - myLastEdgeEndPoint = GeomPointPtr(); + myLastEdge = GeomEdgePtr(); // build result aFilling->build(aParameters.isApprox); - if (isAlgorithmFailed(aFilling)) { + std::string anError; + if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aFilling, getKind(), anError)) { + setError(anError); removeResults(0); return; } @@ -127,32 +139,11 @@ void BuildPlugin_Filling::execute() int anEdgeInd = 0; for(GeomAPI_ShapeExplorer anExp(aCreatedFace, GeomAPI_Shape::EDGE); anExp.more(); anExp.next()) { GeomShapePtr anEdge = anExp.current(); - aResultBody->generated(anEdge, "Edge_" + std::to_string((long long)anEdgeInd), ++anEdgeInd); + aResultBody->generated(anEdge, "Edge_" + std::to_string((long long)anEdgeInd)); } setResult(aResultBody, 0); } -bool BuildPlugin_Filling::isAlgorithmFailed( - const std::shared_ptr& theAlgorithm) -{ - if (!theAlgorithm->isDone()) { - static const std::string aFeatureError = "Error: filling algorithm failed."; - setError(aFeatureError); - return true; - } - if (theAlgorithm->shape()->isNull()) { - static const std::string aShapeError = "Error: Resulting shape of filling is Null."; - setError(aShapeError); - return true; - } - if (!theAlgorithm->isValid()) { - std::string aFeatureError = "Error: Resulting shape of filling is not valid."; - setError(aFeatureError); - return true; - } - return false; -} - //================================================================================================= void BuildPlugin_Filling::attributeChanged(const std::string& theID) { @@ -165,15 +156,20 @@ void BuildPlugin_Filling::attributeChanged(const std::string& theID) //================================================================================================= GeomEdgePtr BuildPlugin_Filling::toEdge(const GeomShapePtr& theShape, const std::string& theMethod) { + static const double TOLERANCE = 1.e-7; + GeomEdgePtr anEdge; switch (theShape->shapeType()) { case GeomAPI_Shape::EDGE: anEdge = GeomEdgePtr(new GeomAPI_Edge(GeomAlgoAPI_Copy(theShape).shape())); break; - case GeomAPI_Shape::WIRE: - anEdge = GeomAlgoAPI_ShapeTools::wireToEdge( - GeomWirePtr(new GeomAPI_Wire(theShape))); + case GeomAPI_Shape::WIRE: { + GeomWirePtr aWire(new GeomAPI_Wire(theShape)); + if (myLastEdge && theMethod == Method::AUTO_CORRECT_ORIENTATION()) + shiftStartPoint(aWire, myLastEdge, TOLERANCE); + anEdge = GeomAlgoAPI_ShapeTools::wireToEdge(aWire); break; + } default: break; } @@ -188,34 +184,18 @@ GeomEdgePtr BuildPlugin_Filling::toEdge(const GeomShapePtr& theShape, const std: // correct edge orientation according to filling method if (theMethod == Method::AUTO_CORRECT_ORIENTATION()) { // check the distance to previous edge boundaries, reverse edge if necessary - GeomPointPtr aStartPnt = anEdge->firstPoint(); - GeomPointPtr aEndPnt = anEdge->lastPoint(); - if (anEdge->orientation() == GeomAPI_Shape::REVERSED) { - aStartPnt = anEdge->lastPoint(); - aEndPnt = anEdge->firstPoint(); - } bool isReverse = false; - if (myLastEdgeStartPoint) { - double d1 = myLastEdgeStartPoint->distance(aStartPnt) - + myLastEdgeEndPoint->distance(aEndPnt); - double d2 = myLastEdgeStartPoint->distance(aEndPnt) - + myLastEdgeEndPoint->distance(aStartPnt); - if (fabs(d1 - d2) < 1.e-7) { - // undefined case => check distance to start point only - d1 = myLastEdgeStartPoint->distance(aStartPnt); - d2 = myLastEdgeStartPoint->distance(aEndPnt); - } - isReverse = d2 < d1; + if (myLastEdge) { + if (myLastEdge->firstPoint()->distance(myLastEdge->lastPoint()) < TOLERANCE && + anEdge->firstPoint()->distance(anEdge->lastPoint()) < TOLERANCE) + isReverse = isReverseClosedCurve(myLastEdge, anEdge); + else + isReverse = isReverseOpenedCurve(myLastEdge, anEdge, TOLERANCE); } - if (isReverse) { + myLastEdge = anEdge; + if (isReverse) anEdge->reverse(); - myLastEdgeStartPoint = aEndPnt; - myLastEdgeEndPoint = aStartPnt; - } else { - myLastEdgeStartPoint = aStartPnt; - myLastEdgeEndPoint = aEndPnt; - } } else if (theMethod == Method::USE_CURVE_INFORMATION()) { // make all edges FORWARD to avoid reversing the curves by GeomAlgoAPI_Filling algorithm @@ -235,3 +215,93 @@ void BuildPlugin_Filling::restoreDefaultParameters() real(TOLERANCE_3D_ID())->setValue(TOLERANCE_3D_DEFAULT()); boolean(APPROXIMATION_ID())->setValue(APPROXIMATION_DEFAULT()); } + + +//============ Auxiliary functions ======================================================== + +static std::pair edgeBoundaries(const GeomEdgePtr& theEdge) +{ + GeomPointPtr aStart = theEdge->firstPoint(); + GeomPointPtr anEnd = theEdge->lastPoint(); + if (theEdge->orientation() == GeomAPI_Shape::REVERSED) + std::swap(aStart, anEnd); + return std::pair(aStart, anEnd); +} + +static void edgePoints(const GeomEdgePtr& theEdge, std::list& thePoints) +{ + GeomAPI_Curve aCurve(theEdge); + static const int aNbSegments = 10; + double aStart = aCurve.startParam(); + double aEnd = aCurve.endParam(); + for (int i = 0; i <= aNbSegments; ++i) + thePoints.push_back(aCurve.getPoint(aStart * (1.0 - (double)i / aNbSegments) + + aEnd * (double)i / aNbSegments )); + if (theEdge->orientation() == GeomAPI_Shape::REVERSED) + thePoints.reverse(); +} + +bool isReverseClosedCurve(const GeomEdgePtr& theEdge1, + const GeomEdgePtr& theEdge2) +{ + std::list anEdge1Points, anEdge2Points; + edgePoints(theEdge1, anEdge1Points); + edgePoints(theEdge2, anEdge2Points); + + double d1 = 0.0; + double d2 = 0.0; + std::list::const_iterator anIt1 = anEdge1Points.begin(); + std::list::const_iterator anIt2 = anEdge2Points.begin(); + std::list::const_reverse_iterator anIt2Rev = anEdge2Points.rbegin(); + for (; anIt1 != anEdge1Points.end(); ++anIt1, ++anIt2, ++anIt2Rev) { + d1 += (*anIt1)->distance(*anIt2); + d2 += (*anIt1)->distance(*anIt2Rev); + } + return d2 < d1; +} + +bool isReverseOpenedCurve(const GeomEdgePtr& theEdge1, + const GeomEdgePtr& theEdge2, + const double theTolerance) +{ + std::pair anEdge1Points = edgeBoundaries(theEdge1); + std::pair anEdge2Points = edgeBoundaries(theEdge2); + double d1 = anEdge1Points.first->distance(anEdge2Points.first) + + anEdge1Points.second->distance(anEdge2Points.second); + double d2 = anEdge1Points.first->distance(anEdge2Points.second) + + anEdge1Points.second->distance(anEdge2Points.first); + if (fabs(d1 - d2) < theTolerance) { + // undefined case => check distance to start point only + d1 = anEdge1Points.first->distance(anEdge2Points.first); + d2 = anEdge1Points.first->distance(anEdge2Points.second); + } + return d2 < d1; +} + +void shiftStartPoint(GeomWirePtr& theWire, const GeomEdgePtr& theRefEdge, const double theTolerance) +{ + if (!theWire->isClosed()) { + GeomVertexPtr aV1, aV2; + GeomAlgoAPI_ShapeTools::findBounds(theWire, aV1, aV2); + if (aV1->point()->distance(aV2->point()) > theTolerance) + return; + } + + // find closest vertex on the wire to the start point on the edge + GeomPointPtr aFirstRefPnt = theRefEdge->firstPoint(); + ListOfShape aBegin, aEnd; + double aMinDist = 1.e100; + for (GeomAPI_WireExplorer anExp(theWire); anExp.more(); anExp.next()) { + double aDist = anExp.currentVertex()->point()->distance(aFirstRefPnt); + if (aDist < aMinDist) { + aMinDist = aDist; + aEnd.insert(aEnd.end(), aBegin.begin(), aBegin.end()); + aBegin.clear(); + } + aBegin.push_back(anExp.current()); + } + aBegin.insert(aBegin.end(), aEnd.begin(), aEnd.end()); + + GeomShapePtr aShape = GeomAlgoAPI_WireBuilder::wire(aBegin); + theWire.reset(new GeomAPI_Wire(aShape)); +}