+
+
+
+// ===================== 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<GeomAPI_PlanarEdges>(theSketchShape)->getEdges();
+
+ std::shared_ptr<GeomAlgoAPI_MakeShapeList> anAlgoList(new GeomAlgoAPI_MakeShapeList);
+ if (isIntersect) {
+ std::set<GeomShapePtr, GeomAPI_Shape::Comparator> aProcessedEdges;
+ // perform sketch builder first
+ AttributePointPtr anOrigin = std::dynamic_pointer_cast<GeomDataAPI_Point>(
+ theSketchFeature->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
+ AttributeDirPtr aNormal = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
+ theSketchFeature->attribute(SketchPlugin_Sketch::NORM_ID()));
+ AttributeDirPtr aDirX = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
+ theSketchFeature->attribute(SketchPlugin_Sketch::DIRX_ID()));
+ std::shared_ptr<GeomAlgoAPI_SketchBuilder> 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<GeomAlgoAPI_PaveFiller> 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<ListOfShape> ListOfWires;
+ ListOfWires aNewWires;
+ typedef std::map<GeomVertexPtr, ListOfWires::iterator,
+ GeomAPI_Vertex::GeometricComparator> 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;
+}