X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FBuildPlugin%2FBuildPlugin_Wire.cpp;h=c7caa85812a46170e654e5298e309f35a53b494e;hb=4cb749258f33b7de231da5bb50140407c0599d30;hp=54ae7a95bac6b5594c4508390b269ee9c90ac8c0;hpb=a94fc319f2aa64b43c9a73b5ff7063923648faec;p=modules%2Fshaper.git diff --git a/src/BuildPlugin/BuildPlugin_Wire.cpp b/src/BuildPlugin/BuildPlugin_Wire.cpp index 54ae7a95b..c7caa8581 100644 --- a/src/BuildPlugin/BuildPlugin_Wire.cpp +++ b/src/BuildPlugin/BuildPlugin_Wire.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2017 CEA/DEN, EDF R&D +// Copyright (C) 2014-2019 CEA/DEN, EDF R&D // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -12,28 +12,43 @@ // // 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_Wire.h" +#include #include #include #include +#include +#include #include #include #include +#include -#include +#include +#include +#include +#include #include +#include + #include +static bool buildSketchWires(FeaturePtr theSketchFeature, GeomShapePtr theSketchShape, + bool isIntersect, + ListOfShape& theWires, GeomMakeShapePtr& theAlgo, + std::string& theError); + +static bool buildWire(const ListOfShape& theEdges, GeomShapePtr& theWire, std::string& theError); + //================================================================================================= BuildPlugin_Wire::BuildPlugin_Wire() { @@ -43,6 +58,9 @@ BuildPlugin_Wire::BuildPlugin_Wire() void BuildPlugin_Wire::initAttributes() { data()->addAttribute(BASE_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId()); + + data()->addAttribute(INTERSECT_ID(), ModelAPI_AttributeBoolean::typeId()); + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), INTERSECT_ID()); } //================================================================================================= @@ -59,13 +77,25 @@ void BuildPlugin_Wire::execute() return; } + AttributeBooleanPtr anIntersectAttr = boolean(INTERSECT_ID()); + bool isIntersect = anIntersectAttr->isInitialized() && anIntersectAttr->value(); + // Collect base shapes. ListOfShape anEdges; + std::list< std::pair > aSketches; for(int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) { AttributeSelectionPtr aSelection = aSelectionList->value(anIndex); GeomShapePtr aShape = aSelection->value(); if(!aShape.get()) { aShape = aSelection->context()->shape(); + + std::shared_ptr aSketchShape = + std::dynamic_pointer_cast(aShape); + if (aSketchShape) { + FeaturePtr aSketchFeature = ModelAPI_Feature::feature(aSelection->context()); + aSketches.push_back(std::pair(aSketchFeature, aSketchShape)); + continue; + } } for(GeomAPI_ShapeExplorer anExp(aShape, GeomAPI_Shape::EDGE); anExp.more(); anExp.next()) { GeomShapePtr anEdge = anExp.current(); @@ -73,27 +103,57 @@ void BuildPlugin_Wire::execute() } } - // Create wire. - GeomShapePtr aWire = GeomAlgoAPI_WireBuilder::wire(anEdges); - if(!aWire.get()) { - setError("Error: Result wire is empty. Probably it has disconnected edges or non-manifold."); - return; - } + int aResultIndex = 0; + std::string anError; - // Store result. - ResultBodyPtr aResultBody = document()->createBody(data()); - aResultBody->store(aWire); - for(GeomAPI_ShapeExplorer anExp(aWire, GeomAPI_Shape::EDGE); anExp.more(); anExp.next()) { - GeomShapePtr anEdgeInResult = anExp.current(); - for(ListOfShape::const_iterator anIt = anEdges.cbegin(); anIt != anEdges.cend(); ++anIt) { - std::shared_ptr anEdgeInList(new GeomAPI_Edge(*anIt)); - if(anEdgeInList->isEqual(anEdgeInResult)) { - aResultBody->modified(anEdgeInList, anEdgeInResult, "Edge"); - break; + if (!anEdges.empty()) { + // Create wire from the list of edges. + GeomShapePtr aWire; + if (!buildWire(anEdges, aWire, anError)) { + setError(anError); + return; + } + + // Store result. + ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex); + aResultBody->store(aWire); + for (GeomAPI_ShapeExplorer anExp(aWire, GeomAPI_Shape::EDGE); anExp.more(); anExp.next()) { + GeomShapePtr anEdgeInResult = anExp.current(); + for (ListOfShape::const_iterator anIt = anEdges.cbegin(); anIt != anEdges.cend(); ++anIt) { + std::shared_ptr anEdgeInList(new GeomAPI_Edge(*anIt)); + if (anEdgeInList->isEqual(anEdgeInResult)) { + aResultBody->modified(anEdgeInList, anEdgeInResult); + break; + } } } + setResult(aResultBody, aResultIndex); + ++aResultIndex; } - setResult(aResultBody); + + // create wires from sketches + for (std::list >::iterator anIt = aSketches.begin(); + anIt != aSketches.end(); ++anIt) { + ListOfShape aWires; + GeomMakeShapePtr aMakeShapeList; + if (!buildSketchWires(anIt->first, anIt->second, isIntersect, + aWires, aMakeShapeList, anError)) { + setError(anError); + return; + } + + for (ListOfShape::iterator aWIt = aWires.begin(); aWIt != aWires.end(); ++aWIt) { + ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex); + ListOfShape aSketches; + aSketches.push_back(anIt->second); + aResultBody->storeModified(aSketches, *aWIt, aMakeShapeList); + aResultBody->loadModifiedShapes(aMakeShapeList, anIt->second, GeomAPI_Shape::EDGE); + setResult(aResultBody, aResultIndex); + ++aResultIndex; + } + } + + removeResults(aResultIndex); } //================================================================================================= @@ -217,3 +277,142 @@ bool BuildPlugin_Wire::addContour() return true; } + + + +// ===================== Auxiliary functions ============================================== + +bool buildWire(const ListOfShape& theEdges, GeomShapePtr& theWire, std::string& theError) +{ + theWire = GeomAlgoAPI_WireBuilder::wire(theEdges); + if (!theWire.get()) { + theError = "Error: Result wire is empty. Probably it has disconnected edges or non-manifold."; + return false; + } + return true; +} + +bool buildSketchWires(FeaturePtr theSketchFeature, GeomShapePtr theSketchShape, bool isIntersect, + ListOfShape& theWires, GeomMakeShapePtr& theAlgo, std::string& theError) +{ + ListOfShape aSketchEdges = + std::dynamic_pointer_cast(theSketchShape)->getEdges(); + + std::shared_ptr anAlgoList(new GeomAlgoAPI_MakeShapeList); + if (isIntersect) { + std::set aProcessedEdges; + // perform sketch builder first + AttributePointPtr anOrigin = std::dynamic_pointer_cast( + theSketchFeature->attribute(SketchPlugin_Sketch::ORIGIN_ID())); + AttributeDirPtr aNormal = std::dynamic_pointer_cast( + theSketchFeature->attribute(SketchPlugin_Sketch::NORM_ID())); + AttributeDirPtr aDirX = std::dynamic_pointer_cast( + theSketchFeature->attribute(SketchPlugin_Sketch::DIRX_ID())); + std::shared_ptr aSketchBuilder(new GeomAlgoAPI_SketchBuilder( + anOrigin->pnt(), aDirX->dir(), aNormal->dir(), theSketchShape)); + + anAlgoList->appendAlgo(aSketchBuilder); + + // collect wires from faces + const ListOfShape& aFaces = aSketchBuilder->faces(); + for (ListOfShape::const_iterator anIt = aFaces.begin(); anIt != aFaces.end(); ++anIt) { + for (GeomAPI_ShapeExplorer aWExp(*anIt, GeomAPI_Shape::WIRE); aWExp.more(); aWExp.next()) { + GeomAPI_ShapeExplorer aEExp(aWExp.current(), GeomAPI_Shape::EDGE); + if (aProcessedEdges.find(aEExp.current()) != aProcessedEdges.end()) + continue; // wire is already processed + // mark edges as processed + for (; aEExp.more(); aEExp.next()) + aProcessedEdges.insert(aEExp.current()); + // store the wire + theWires.push_back(aWExp.current()); + } + } + + // collect unused edges + ListOfShape aCopy; + for (ListOfShape::iterator anIt = aSketchEdges.begin(); anIt != aSketchEdges.end(); ++anIt) { + ListOfShape anImages; + aSketchBuilder->modified(*anIt, anImages); + for (ListOfShape::iterator anEdge = anImages.begin(); anEdge != anImages.end(); ++anEdge) + if (aProcessedEdges.find(*anEdge) == aProcessedEdges.end()) + aCopy.push_back(*anEdge); + } + + if (aCopy.size() > 1) { + // split these edges + std::shared_ptr aGeneralFuse(new GeomAlgoAPI_PaveFiller(aCopy)); + if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed( + aGeneralFuse, BuildPlugin_Wire::ID(), theError)) + return false; + anAlgoList->appendAlgo(aGeneralFuse); + + // collect edges after the split + aSketchEdges.clear(); + for (GeomAPI_ShapeExplorer anExp(aGeneralFuse->shape(), GeomAPI_Shape::EDGE); + anExp.more(); anExp.next()) + aSketchEdges.push_back(anExp.current()); + } + else + aSketchEdges = aCopy; + } + + // connect least edges to wires + typedef std::list ListOfWires; + ListOfWires aNewWires; + typedef std::map MapVertexWire; + MapVertexWire aMapVW; + for (ListOfShape::iterator aEIt = aSketchEdges.begin(); aEIt != aSketchEdges.end(); ++aEIt) { + GeomEdgePtr anEdge = (*aEIt)->edge(); + GeomVertexPtr aStartV, aEndV; + anEdge->vertices(aStartV, aEndV); + MapVertexWire::iterator aFoundStart = aMapVW.find(aStartV); + MapVertexWire::iterator aFoundEnd = aMapVW.find(aEndV); + if (aFoundStart == aMapVW.end()) { + if (aFoundEnd == aMapVW.end()) { + // new wire + aNewWires.push_back(ListOfShape()); + ListOfWires::iterator aNewW = --aNewWires.end(); + aNewW->push_back(anEdge); + aMapVW[aStartV] = aNewW; + aMapVW[aEndV] = aNewW; + continue; + } + } + else { + if (aFoundEnd == aMapVW.end()) { + // swap found vertices for correct further processing + aFoundEnd = aFoundStart; + aStartV = aEndV; + } + else { + // both vertices are found => close the loop + aFoundStart->second->push_back(anEdge); + if (aFoundStart->second != aFoundEnd->second) { + aFoundStart->second->insert(aFoundStart->second->end(), + aFoundEnd->second->begin(), aFoundEnd->second->end()); + aNewWires.erase(aFoundEnd->second); + } + aMapVW.erase(aFoundStart); + aMapVW.erase(aFoundEnd); + continue; + } + } + // add edge to existing wire, substitute the connection point + // by the other boundary point of the edge + aFoundEnd->second->push_back(anEdge); + aMapVW[aStartV] = aFoundEnd->second; + aMapVW.erase(aFoundEnd); + } + + // generate new wires from the sets of edges + for (ListOfWires::iterator anIt = aNewWires.begin(); anIt != aNewWires.end(); ++anIt) { + GeomShapePtr aWire; + if (!buildWire(*anIt, aWire, theError)) + return false; + theWires.push_back(aWire); + } + + theAlgo = anAlgoList; + return true; +}