From: azv Date: Fri, 29 Nov 2019 09:24:15 +0000 (+0300) Subject: Task 3.3 Build/Edge and Build/Wire on a whole Sketch (issue #3083) X-Git-Tag: V9_5_0a1~132 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=922c5eceb93e68e87e6e4d22583de0d1f25ff483;p=modules%2Fshaper.git Task 3.3 Build/Edge and Build/Wire on a whole Sketch (issue #3083) --- diff --git a/src/BuildAPI/BuildAPI_Edge.cpp b/src/BuildAPI/BuildAPI_Edge.cpp index 3371f01ea..e0816f833 100644 --- a/src/BuildAPI/BuildAPI_Edge.cpp +++ b/src/BuildAPI/BuildAPI_Edge.cpp @@ -31,11 +31,13 @@ BuildAPI_Edge::BuildAPI_Edge(const std::shared_ptr& theFeature //================================================================================================== BuildAPI_Edge::BuildAPI_Edge(const std::shared_ptr& theFeature, - const std::list& theBaseObjects) + const std::list& theBaseObjects, + const bool theComputeIntersections) : ModelHighAPI_Interface(theFeature) { if(initialize()) { fillAttribute(BuildPlugin_Edge::CREATION_BY_SEGMENTS(), mycreationMethod); + fillAttribute(theComputeIntersections, mycomputeIntersections); setBase(theBaseObjects); } } @@ -83,17 +85,23 @@ void BuildAPI_Edge::dump(ModelHighAPI_Dumper& theDumper) const theDumper << aBase->selection(BuildPlugin_Edge::FIRST_POINT()) << ", " << aBase->selection(BuildPlugin_Edge::SECOND_POINT()); } - else + else { theDumper << aBase->selectionList(BuildPlugin_Edge::BASE_OBJECTS_ID()); + + AttributeBooleanPtr isIntersect = aBase->boolean(BuildPlugin_Edge::INTERSECT_ID()); + if (isIntersect->isInitialized()) + theDumper << ", " << isIntersect; + } theDumper << ")" << std::endl; } //================================================================================================== EdgePtr addEdge(const std::shared_ptr& thePart, - const std::list& theBaseObjects) + const std::list& theBaseObjects, + const bool theComputeIntersections) { std::shared_ptr aFeature = thePart->addFeature(BuildAPI_Edge::ID()); - return EdgePtr(new BuildAPI_Edge(aFeature, theBaseObjects)); + return EdgePtr(new BuildAPI_Edge(aFeature, theBaseObjects, theComputeIntersections)); } EdgePtr addEdge(const std::shared_ptr& thePart, diff --git a/src/BuildAPI/BuildAPI_Edge.h b/src/BuildAPI/BuildAPI_Edge.h index 11a7fa902..e6a7e46d7 100644 --- a/src/BuildAPI/BuildAPI_Edge.h +++ b/src/BuildAPI/BuildAPI_Edge.h @@ -42,7 +42,8 @@ public: /// Constructor with values. BUILDAPI_EXPORT explicit BuildAPI_Edge(const std::shared_ptr& theFeature, - const std::list& theBaseObjects); + const std::list& theBaseObjects, + const bool theComputeIntersections = false); /// Constructor by points. BUILDAPI_EXPORT @@ -54,7 +55,7 @@ public: BUILDAPI_EXPORT virtual ~BuildAPI_Edge(); - INTERFACE_4(BuildPlugin_Edge::ID(), + INTERFACE_5(BuildPlugin_Edge::ID(), baseObjects, BuildPlugin_Edge::BASE_OBJECTS_ID(), ModelAPI_AttributeSelectionList, /** Base objects */, creationMethod, BuildPlugin_Edge::CREATION_METHOD(), @@ -62,7 +63,9 @@ public: firstPoint, BuildPlugin_Edge::FIRST_POINT(), ModelAPI_AttributeSelection, /** First point */, secondPoint, BuildPlugin_Edge::SECOND_POINT(), - ModelAPI_AttributeSelection, /** Second point */) + ModelAPI_AttributeSelection, /** Second point */, + computeIntersections, BuildPlugin_Edge::INTERSECT_ID(), + ModelAPI_AttributeBoolean, /** Intersect edges */) /// Modify base attribute of the feature. BUILDAPI_EXPORT @@ -80,7 +83,8 @@ typedef std::shared_ptr EdgePtr; /// \brief Create Edge feature. BUILDAPI_EXPORT EdgePtr addEdge(const std::shared_ptr& thePart, - const std::list& theBaseObjects); + const std::list& theBaseObjects, + const bool theComputeIntersection = false); /// \ingroup CPPHighAPI /// \brief Create Edge feature. BUILDAPI_EXPORT diff --git a/src/BuildAPI/BuildAPI_Wire.cpp b/src/BuildAPI/BuildAPI_Wire.cpp index 69c68be45..ffd58d48a 100644 --- a/src/BuildAPI/BuildAPI_Wire.cpp +++ b/src/BuildAPI/BuildAPI_Wire.cpp @@ -31,10 +31,12 @@ BuildAPI_Wire::BuildAPI_Wire(const std::shared_ptr& theFeature //================================================================================================== BuildAPI_Wire::BuildAPI_Wire(const std::shared_ptr& theFeature, - const std::list& theBaseObjects) + const std::list& theBaseObjects, + const bool theComputeIntersections) : ModelHighAPI_Interface(theFeature) { if(initialize()) { + fillAttribute(theComputeIntersections, mycomputeIntersections); setBase(theBaseObjects); } } @@ -60,7 +62,13 @@ void BuildAPI_Wire::dump(ModelHighAPI_Dumper& theDumper) const std::string aPartName = theDumper.name(aBase->document()); theDumper << aBase << " = model.addWire(" << aPartName << ", " - << aBase->selectionList(BuildPlugin_Wire::BASE_OBJECTS_ID()) << ")" << std::endl; + << aBase->selectionList(BuildPlugin_Wire::BASE_OBJECTS_ID()); + + AttributeBooleanPtr isIntersect = aBase->boolean(BuildPlugin_Wire::INTERSECT_ID()); + if (isIntersect->isInitialized()) + theDumper << ", " << isIntersect; + + theDumper << ")" << std::endl; } //================================================================================================== @@ -71,8 +79,9 @@ void BuildAPI_Wire::addContour() //================================================================================================== WirePtr addWire(const std::shared_ptr& thePart, - const std::list& theBaseObjects) + const std::list& theBaseObjects, + const bool theComputeIntersections) { std::shared_ptr aFeature = thePart->addFeature(BuildAPI_Wire::ID()); - return WirePtr(new BuildAPI_Wire(aFeature, theBaseObjects)); + return WirePtr(new BuildAPI_Wire(aFeature, theBaseObjects, theComputeIntersections)); } diff --git a/src/BuildAPI/BuildAPI_Wire.h b/src/BuildAPI/BuildAPI_Wire.h index 4934943d7..86e78837b 100644 --- a/src/BuildAPI/BuildAPI_Wire.h +++ b/src/BuildAPI/BuildAPI_Wire.h @@ -42,15 +42,18 @@ public: /// Constructor with values. BUILDAPI_EXPORT explicit BuildAPI_Wire(const std::shared_ptr& theFeature, - const std::list& theBaseObjects); + const std::list& theBaseObjects, + const bool theComputeIntersections = false); /// Destructor. BUILDAPI_EXPORT virtual ~BuildAPI_Wire(); - INTERFACE_1(BuildPlugin_Wire::ID(), + INTERFACE_2(BuildPlugin_Wire::ID(), baseObjects, BuildPlugin_Wire::BASE_OBJECTS_ID(), - ModelAPI_AttributeSelectionList, /** Base objects */) + ModelAPI_AttributeSelectionList, /** Base objects */, + computeIntersections, BuildPlugin_Wire::INTERSECT_ID(), + ModelAPI_AttributeBoolean, /** Intersect edges */) /// Modify base attribute of the feature. BUILDAPI_EXPORT @@ -72,6 +75,7 @@ typedef std::shared_ptr WirePtr; /// \brief Create Wire feature. BUILDAPI_EXPORT WirePtr addWire(const std::shared_ptr& thePart, - const std::list& theBaseObjects); + const std::list& theBaseObjects, + const bool theComputeIntersections = false); #endif // BuildAPI_Wire_H_ diff --git a/src/BuildPlugin/BuildPlugin_Edge.cpp b/src/BuildPlugin/BuildPlugin_Edge.cpp index 0f85ae3e4..2a07d390c 100644 --- a/src/BuildPlugin/BuildPlugin_Edge.cpp +++ b/src/BuildPlugin/BuildPlugin_Edge.cpp @@ -19,14 +19,18 @@ #include "BuildPlugin_Edge.h" +#include #include #include #include #include #include +#include #include #include +#include +#include #include #include @@ -64,6 +68,9 @@ void BuildPlugin_Edge::initAttributes() data()->addAttribute(FIRST_POINT(), ModelAPI_AttributeSelection::typeId()); data()->addAttribute(SECOND_POINT(), ModelAPI_AttributeSelection::typeId()); + + data()->addAttribute(INTERSECT_ID(), ModelAPI_AttributeBoolean::typeId()); + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), INTERSECT_ID()); } //================================================================================================= @@ -96,7 +103,6 @@ void BuildPlugin_Edge::edgesBySegments() // Collect base shapes. ListOfShape aListOfShapes; std::string aError; - int aResultIndex = 0; for(int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) { AttributeSelectionPtr aSelection = aSelectionList->value(anIndex); GeomShapePtr aShape; @@ -108,29 +114,48 @@ void BuildPlugin_Edge::edgesBySegments() setError("Error: Empty shape selected."); return; } + aListOfShapes.push_back(aShape); + } - if(aShape->shapeType() != GeomAPI_Shape::EDGE) { - setError("Error: Selected shape has wrong type. Only edges acceptable."); - return; - } + AttributeBooleanPtr isIntersect = boolean(INTERSECT_ID()); - // Copy shape. - GeomMakeShapePtr aCopyAlgo(new GeomAlgoAPI_Copy(aShape)); + GeomShapePtr aResult; + std::shared_ptr aPartitionAlgo; + if (isIntersect->isInitialized() && isIntersect->value()) { + aPartitionAlgo.reset(new GeomAlgoAPI_Partition(aListOfShapes, ListOfShape())); std::string anError; - if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aCopyAlgo, getKind(), anError)) { + if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aPartitionAlgo, getKind(), anError)) { setError(anError); return; } - // Store result. - ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex); + aResult = aPartitionAlgo->shape(); + } + else + aResult = GeomAlgoAPI_CompoundBuilder::compound(aListOfShapes); + + int aResultIndex = 0; + + // Explode on edges + std::set aProcessed; + for (GeomAPI_ShapeExplorer anExp(aResult, GeomAPI_Shape::EDGE); anExp.more(); anExp.next()) { + GeomShapePtr anEdge = anExp.current(); + if (aProcessed.find(anEdge) != aProcessed.end()) + continue; // vertex is already processed + aProcessed.insert(anEdge); - ListOfShape aBaseShapes; - aBaseShapes.push_back(aShape); - aResultBody->storeModified(aBaseShapes, aCopyAlgo->shape(), aCopyAlgo); - aResultBody->loadModifiedShapes(aCopyAlgo, aShape, GeomAPI_Shape::VERTEX); + std::shared_ptr aCopyAlgo(new GeomAlgoAPI_Copy(anEdge)); + std::shared_ptr aMakeShapeList(new GeomAlgoAPI_MakeShapeList); + if (aPartitionAlgo) + aMakeShapeList->appendAlgo(aPartitionAlgo); + aMakeShapeList->appendAlgo(aCopyAlgo); + + // Store result. + ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex); + aResultBody->storeModified(aListOfShapes, aCopyAlgo->shape(), aMakeShapeList); + aResultBody->loadModifiedShapes(aMakeShapeList, anEdge, GeomAPI_Shape::VERTEX); setResult(aResultBody, aResultIndex); ++aResultIndex; } diff --git a/src/BuildPlugin/BuildPlugin_Edge.h b/src/BuildPlugin/BuildPlugin_Edge.h index 27f1665ba..af142f55b 100644 --- a/src/BuildPlugin/BuildPlugin_Edge.h +++ b/src/BuildPlugin/BuildPlugin_Edge.h @@ -89,6 +89,13 @@ public: return MY_SECOND_POINT_ID; } + /// Attribute name of "Compute intersections" checkbox. + inline static const std::string& INTERSECT_ID() + { + static const std::string MY_INTERSECT_ID("intersect"); + return MY_INTERSECT_ID; + } + /// Request for initialization of data model of the feature: adding all attributes. BUILDPLUGIN_EXPORT virtual void initAttributes(); diff --git a/src/BuildPlugin/BuildPlugin_Validators.cpp b/src/BuildPlugin/BuildPlugin_Validators.cpp index 761fc6fa5..aef6b7fc8 100644 --- a/src/BuildPlugin/BuildPlugin_Validators.cpp +++ b/src/BuildPlugin/BuildPlugin_Validators.cpp @@ -116,12 +116,6 @@ bool BuildPlugin_ValidatorBaseForWire::isValid(const std::shared_ptrselectionList(theArguments.front()); if(!aSelectionList.get()) { theError = "Empty attribute \"%1\"."; @@ -129,25 +123,53 @@ bool BuildPlugin_ValidatorBaseForWire::isValid(const std::shared_ptrsize(); ++anIndex) { AttributeSelectionPtr aSelection = aSelectionList->value(anIndex); GeomShapePtr aShape = aSelection->value(); - if(!aShape.get()) { - if (aSelection->context().get()) - aShape = aSelection->context()->shape(); - } - if (aShape.get()) + ResultPtr aContext = aSelection->context(); + if (!aShape.get() && aContext.get()) + aShape = aContext->shape(); + + bool isProper = aShape.get() && + (aShape->shapeType() == GeomAPI_Shape::EDGE || aShape->shapeType() == aShapeType); + + if (isProper) aListOfShapes.push_back(aShape); + else { + // is it a sketch? + FeaturePtr aFeature = aSelection->contextFeature(); + if (!aFeature.get()) { + GeomShapePtr aValue = aSelection->value(); + // whole sketch is allowed only + if (aContext.get() && !aValue.get()) { + aFeature = ModelAPI_Feature::feature(aContext); + } + } + + if (!aFeature.get()) { + theError = "Error: Incorrect selection."; + return false; + } + + if (aFeature->getKind() != SketchPlugin_Sketch::ID()) { + theError = "Error: %1 shape is not allowed for selection."; + theError.arg(aFeature->getKind()); + return false; + } + } } - // Create wire. - GeomShapePtr aWire = GeomAlgoAPI_WireBuilder::wire(aListOfShapes); - if(!aWire.get()) { - theError = "Result wire empty. Probably it has disconnected edges or non-manifold."; - return false; + if (aShapeType == GeomAPI_Shape::WIRE) { + // Create wire. + GeomShapePtr aWire = GeomAlgoAPI_WireBuilder::wire(aListOfShapes); + if (!aWire.get() && !aListOfShapes.empty()) { + theError = "Result wire empty. Probably it has disconnected edges or non-manifold."; + return false; + } } return true; diff --git a/src/BuildPlugin/BuildPlugin_Wire.cpp b/src/BuildPlugin/BuildPlugin_Wire.cpp index 4fe602e84..c7caa8581 100644 --- a/src/BuildPlugin/BuildPlugin_Wire.cpp +++ b/src/BuildPlugin/BuildPlugin_Wire.cpp @@ -19,20 +19,36 @@ #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() { @@ -42,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()); } //================================================================================================= @@ -58,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(); @@ -72,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); - 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); } //================================================================================================= @@ -216,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; +} diff --git a/src/BuildPlugin/BuildPlugin_Wire.h b/src/BuildPlugin/BuildPlugin_Wire.h index c0b873174..5677bebb3 100644 --- a/src/BuildPlugin/BuildPlugin_Wire.h +++ b/src/BuildPlugin/BuildPlugin_Wire.h @@ -54,6 +54,13 @@ public: return MY_ADD_CONTOUR_ACTION_ID; } + /// Attribute name of "Compute intersections" checkbox. + inline static const std::string& INTERSECT_ID() + { + static const std::string MY_INTERSECT_ID("intersect"); + return MY_INTERSECT_ID; + } + /// \return the kind of a feature. BUILDPLUGIN_EXPORT virtual const std::string& getKind() { diff --git a/src/BuildPlugin/CMakeLists.txt b/src/BuildPlugin/CMakeLists.txt index e8a4e470f..2954b05c7 100644 --- a/src/BuildPlugin/CMakeLists.txt +++ b/src/BuildPlugin/CMakeLists.txt @@ -115,8 +115,18 @@ ADD_UNIT_TESTS(TestVertex.py TestEdge.py TestEdge_ByPoints.py TestEdge_ErrorMsg.py + TestEdge_WholeSketch_1.py + TestEdge_WholeSketch_2.py + TestEdge_WholeSketch_3.py + TestEdge_WholeSketch_4.py TestWire.py TestWire_ErrorMsg.py + TestWire_WholeSketch_1.py + TestWire_WholeSketch_2.py + TestWire_WholeSketch_3.py + TestWire_WholeSketch_4.py + TestWire_WholeSketch_5.py + TestWire_WholeSketch_6.py TestPolyline.py TestInterpolation.py TestFace.py diff --git a/src/BuildPlugin/Test/TestEdge.py b/src/BuildPlugin/Test/TestEdge.py index 83d163b5e..2e194941f 100644 --- a/src/BuildPlugin/Test/TestEdge.py +++ b/src/BuildPlugin/Test/TestEdge.py @@ -114,12 +114,6 @@ assert (len(anEdgeFeature2.results()) == 12) aSession.startOperation() anEdgeFeature3 = aPart.addFeature("Edge") aBaseObjectsList = anEdgeFeature3.selectionList("base_objects") -aBaseObjectsList.append(aSketchResult, None) -aSession.finishOperation() -assert (len(anEdgeFeature3.results()) == 0) - -aSession.startOperation() -aBaseObjectsList.clear() aShapeExplorer = GeomAPI_ShapeExplorer(aBoxShape, GeomAPI_Shape.VERTEX) aShape = aShapeExplorer.current() aBaseObjectsList.append(aBoxResult, aShape) diff --git a/src/BuildPlugin/Test/TestEdge_WholeSketch_1.py b/src/BuildPlugin/Test/TestEdge_WholeSketch_1.py new file mode 100644 index 000000000..aa7a9aa70 --- /dev/null +++ b/src/BuildPlugin/Test/TestEdge_WholeSketch_1.py @@ -0,0 +1,44 @@ +# Copyright (C) 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 +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# 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 +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# + +from salome.shaper import model +from GeomAPI import * + +model.begin() +partSet = model.moduleDocument() +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() +Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +SketchLine_1 = Sketch_1.addLine(0, -20, 45, -15) +SketchLine_2 = Sketch_1.addLine(45, -15, 10, 15) +SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint()) +SketchLine_3 = Sketch_1.addLine(10, 15, 25, -40) +SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint()) +model.do() +Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +SketchArc_1 = Sketch_2.addArc(-5, 10, -5, -10, 15, 10, False) +model.do() +Edge_1 = model.addEdge(Part_1_doc, [model.selection("COMPOUND", "all-in-Sketch_1"), model.selection("COMPOUND", "Sketch_2")], False) +model.end() + +model.testNbResults(Edge_1, 4) +model.testNbSubShapes(Edge_1, GeomAPI_Shape.EDGE, [1, 1, 1, 1]) +model.testNbSubShapes(Edge_1, GeomAPI_Shape.VERTEX, [2, 2, 2, 2]) + +assert(model.checkPythonDump()) diff --git a/src/BuildPlugin/Test/TestEdge_WholeSketch_2.py b/src/BuildPlugin/Test/TestEdge_WholeSketch_2.py new file mode 100644 index 000000000..855850244 --- /dev/null +++ b/src/BuildPlugin/Test/TestEdge_WholeSketch_2.py @@ -0,0 +1,44 @@ +# Copyright (C) 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 +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# 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 +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# + +from salome.shaper import model +from GeomAPI import * + +model.begin() +partSet = model.moduleDocument() +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() +Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +SketchLine_1 = Sketch_1.addLine(0, -20, 45, -15) +SketchLine_2 = Sketch_1.addLine(45, -15, 10, 15) +SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint()) +SketchLine_3 = Sketch_1.addLine(10, 15, 25, -40) +SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint()) +model.do() +Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +SketchArc_1 = Sketch_2.addArc(-5, 10, -5, -10, 15, 10, False) +model.do() +Edge_1 = model.addEdge(Part_1_doc, [model.selection("COMPOUND", "all-in-Sketch_1"), model.selection("COMPOUND", "Sketch_2")], True) +model.end() + +model.testNbResults(Edge_1, 8) +model.testNbSubShapes(Edge_1, GeomAPI_Shape.EDGE, [1, 1, 1, 1, 1, 1, 1, 1]) +model.testNbSubShapes(Edge_1, GeomAPI_Shape.VERTEX, [2, 2, 2, 2, 2, 2, 2, 2]) + +assert(model.checkPythonDump()) diff --git a/src/BuildPlugin/Test/TestEdge_WholeSketch_3.py b/src/BuildPlugin/Test/TestEdge_WholeSketch_3.py new file mode 100644 index 000000000..c725d124d --- /dev/null +++ b/src/BuildPlugin/Test/TestEdge_WholeSketch_3.py @@ -0,0 +1,44 @@ +# Copyright (C) 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 +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# 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 +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# + +from salome.shaper import model +from GeomAPI import * + +model.begin() +partSet = model.moduleDocument() +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() +Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +SketchLine_1 = Sketch_1.addLine(0, -20, 45, -15) +SketchLine_2 = Sketch_1.addLine(45, -15, 10, 15) +SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint()) +SketchLine_3 = Sketch_1.addLine(10, 15, 25, -40) +SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint()) +model.do() +Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +SketchArc_1 = Sketch_2.addArc(-5, 10, -5, -10, 15, 10, False) +model.do() +Edge_1 = model.addEdge(Part_1_doc, [model.selection("COMPOUND", "Sketch_1"), model.selection("EDGE", "Sketch_2/SketchArc_1_2")], False) +model.end() + +model.testNbResults(Edge_1, 4) +model.testNbSubShapes(Edge_1, GeomAPI_Shape.EDGE, [1, 1, 1, 1]) +model.testNbSubShapes(Edge_1, GeomAPI_Shape.VERTEX, [2, 2, 2, 2]) + +assert(model.checkPythonDump()) diff --git a/src/BuildPlugin/Test/TestEdge_WholeSketch_4.py b/src/BuildPlugin/Test/TestEdge_WholeSketch_4.py new file mode 100644 index 000000000..8ddd0ab0e --- /dev/null +++ b/src/BuildPlugin/Test/TestEdge_WholeSketch_4.py @@ -0,0 +1,44 @@ +# Copyright (C) 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 +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# 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 +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# + +from salome.shaper import model +from GeomAPI import * + +model.begin() +partSet = model.moduleDocument() +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() +Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +SketchLine_1 = Sketch_1.addLine(0, -20, 45, -15) +SketchLine_2 = Sketch_1.addLine(45, -15, 10, 15) +SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint()) +SketchLine_3 = Sketch_1.addLine(10, 15, 25, -40) +SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint()) +model.do() +Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +SketchArc_1 = Sketch_2.addArc(-5, 10, -5, -10, 15, 10, False) +model.do() +Edge_1 = model.addEdge(Part_1_doc, [model.selection("COMPOUND", "Sketch_1"), model.selection("EDGE", "Sketch_2/SketchArc_1_2")], True) +model.end() + +model.testNbResults(Edge_1, 8) +model.testNbSubShapes(Edge_1, GeomAPI_Shape.EDGE, [1, 1, 1, 1, 1, 1, 1, 1]) +model.testNbSubShapes(Edge_1, GeomAPI_Shape.VERTEX, [2, 2, 2, 2, 2, 2, 2, 2]) + +assert(model.checkPythonDump()) diff --git a/src/BuildPlugin/Test/TestWire.py b/src/BuildPlugin/Test/TestWire.py index 0bbbbce8f..fc4734adc 100644 --- a/src/BuildPlugin/Test/TestWire.py +++ b/src/BuildPlugin/Test/TestWire.py @@ -145,7 +145,7 @@ aSession.finishOperation() assert (len(aWireFeature2.results()) == 1) # ============================================================================= -# Test 4. Check Wire feature failed on incorrect input +# Test 4. Check Wire feature on the whole sketch # ============================================================================= aSession.startOperation() @@ -153,10 +153,15 @@ aWireFeature3 = aPart.addFeature("Wire") aBaseObjectsList = aWireFeature3.selectionList("base_objects") aBaseObjectsList.append(aSketchResult, None) aSession.finishOperation() -assert (len(aWireFeature3.results()) == 0) +assert (len(aWireFeature3.results()) == 1) + +# ============================================================================= +# Test 5. Check Wire feature failed on incorrect input +# ============================================================================= aSession.startOperation() -aBaseObjectsList.clear() +aWireFeature3 = aPart.addFeature("Wire") +aBaseObjectsList = aWireFeature3.selectionList("base_objects") aShapeExplorer = GeomAPI_ShapeExplorer(aBoxShape, GeomAPI_Shape.VERTEX) aShape = aShapeExplorer.current() aBaseObjectsList.append(aBoxResult, aShape) diff --git a/src/BuildPlugin/Test/TestWire_WholeSketch_1.py b/src/BuildPlugin/Test/TestWire_WholeSketch_1.py new file mode 100644 index 000000000..e64e66284 --- /dev/null +++ b/src/BuildPlugin/Test/TestWire_WholeSketch_1.py @@ -0,0 +1,44 @@ +# Copyright (C) 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 +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# 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 +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# + +from salome.shaper import model +from GeomAPI import * + +model.begin() +partSet = model.moduleDocument() +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() +Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +SketchLine_1 = Sketch_1.addLine(0, -20, 45, -15) +SketchLine_2 = Sketch_1.addLine(45, -15, 10, 15) +SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint()) +SketchLine_3 = Sketch_1.addLine(10, 15, 25, -40) +SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint()) +model.do() +Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +SketchArc_1 = Sketch_2.addArc(-5, 10, -5, -10, 15, 10, False) +model.do() +Wire_1 = model.addWire(Part_1_doc, [model.selection("COMPOUND", "all-in-Sketch_1"), model.selection("COMPOUND", "Sketch_2")], False) +model.end() + +model.testNbResults(Wire_1, 2) +model.testNbSubShapes(Wire_1, GeomAPI_Shape.EDGE, [3, 1]) +model.testNbSubShapes(Wire_1, GeomAPI_Shape.VERTEX, [6, 2]) + +assert(model.checkPythonDump()) diff --git a/src/BuildPlugin/Test/TestWire_WholeSketch_2.py b/src/BuildPlugin/Test/TestWire_WholeSketch_2.py new file mode 100644 index 000000000..e5db2e180 --- /dev/null +++ b/src/BuildPlugin/Test/TestWire_WholeSketch_2.py @@ -0,0 +1,44 @@ +# Copyright (C) 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 +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# 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 +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# + +from salome.shaper import model +from GeomAPI import * + +model.begin() +partSet = model.moduleDocument() +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() +Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +SketchLine_1 = Sketch_1.addLine(0, -20, 45, -15) +SketchLine_2 = Sketch_1.addLine(45, -15, 10, 15) +SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint()) +SketchLine_3 = Sketch_1.addLine(10, 15, 25, -40) +SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint()) +model.do() +Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +SketchArc_1 = Sketch_2.addArc(-5, 10, -5, -10, 15, 10, False) +model.do() +Wire_1 = model.addWire(Part_1_doc, [model.selection("COMPOUND", "all-in-Sketch_1"), model.selection("COMPOUND", "Sketch_2")], True) +model.end() + +model.testNbResults(Wire_1, 3) +model.testNbSubShapes(Wire_1, GeomAPI_Shape.EDGE, [3, 2, 1]) +model.testNbSubShapes(Wire_1, GeomAPI_Shape.VERTEX, [6, 4, 2]) + +assert(model.checkPythonDump()) diff --git a/src/BuildPlugin/Test/TestWire_WholeSketch_3.py b/src/BuildPlugin/Test/TestWire_WholeSketch_3.py new file mode 100644 index 000000000..bbc4dac3f --- /dev/null +++ b/src/BuildPlugin/Test/TestWire_WholeSketch_3.py @@ -0,0 +1,48 @@ +# Copyright (C) 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 +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# 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 +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# + +from salome.shaper import model +from GeomAPI import * + +model.begin() +partSet = model.moduleDocument() +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() +Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +SketchLine_1 = Sketch_1.addLine(-20.12530657814797, -34.87380706737215, -10.13449613893172, -4.005160196312613) +SketchLine_2 = Sketch_1.addLine(-15.5320876476665, -20.68212021382587, -37.87121169090271, -18.01751586506584) +SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_2.startPoint(), SketchLine_1.result()) +SketchLine_3 = Sketch_1.addLine(-37.87121169090271, -18.01751586506584, -28.23126689685475, -46.70782775211335) +SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint()) +SketchLine_4 = Sketch_1.addLine(-10.13449613893172, -4.005160196312613, -17.3289483797767, 22.37844327189705) +SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_4.startPoint()) +SketchLine_5 = Sketch_1.addLine(-17.3289483797767, 22.37844327189705, -36.60883796787262, 2.754269941156556) +SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint()) +SketchLine_6 = Sketch_1.addLine(-36.60883796787262, 2.754269941156556, -10.13449613893172, -4.005160196312613) +SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint()) +SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_6.endPoint()) +model.do() +Wire_1 = model.addWire(Part_1_doc, [model.selection("COMPOUND", "Sketch_1")]) +model.end() + +model.testNbResults(Wire_1, 2) +model.testNbSubShapes(Wire_1, GeomAPI_Shape.EDGE, [4, 2]) +model.testNbSubShapes(Wire_1, GeomAPI_Shape.VERTEX, [8, 4]) + +assert(model.checkPythonDump()) diff --git a/src/BuildPlugin/Test/TestWire_WholeSketch_4.py b/src/BuildPlugin/Test/TestWire_WholeSketch_4.py new file mode 100644 index 000000000..fee5553ff --- /dev/null +++ b/src/BuildPlugin/Test/TestWire_WholeSketch_4.py @@ -0,0 +1,48 @@ +# Copyright (C) 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 +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# 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 +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# + +from salome.shaper import model +from GeomAPI import * + +model.begin() +partSet = model.moduleDocument() +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() +Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +SketchLine_1 = Sketch_1.addLine(-20.12530657814797, -34.87380706737215, -10.13449613893172, -4.005160196312613) +SketchLine_2 = Sketch_1.addLine(-15.5320876476665, -20.68212021382587, -37.87121169090271, -18.01751586506584) +SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_2.startPoint(), SketchLine_1.result()) +SketchLine_3 = Sketch_1.addLine(-37.87121169090271, -18.01751586506584, -28.23126689685475, -46.70782775211335) +SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint()) +SketchLine_4 = Sketch_1.addLine(-10.13449613893172, -4.005160196312613, -17.3289483797767, 22.37844327189705) +SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_4.startPoint()) +SketchLine_5 = Sketch_1.addLine(-17.3289483797767, 22.37844327189705, -36.60883796787262, 2.754269941156556) +SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint()) +SketchLine_6 = Sketch_1.addLine(-36.60883796787262, 2.754269941156556, -10.13449613893172, -4.005160196312613) +SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint()) +SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_6.endPoint()) +model.do() +Wire_1 = model.addWire(Part_1_doc, [model.selection("COMPOUND", "Sketch_1")], True) +model.end() + +model.testNbResults(Wire_1, 3) +model.testNbSubShapes(Wire_1, GeomAPI_Shape.EDGE, [3, 2, 2]) +model.testNbSubShapes(Wire_1, GeomAPI_Shape.VERTEX, [6, 4, 4]) + +assert(model.checkPythonDump()) diff --git a/src/BuildPlugin/Test/TestWire_WholeSketch_5.py b/src/BuildPlugin/Test/TestWire_WholeSketch_5.py new file mode 100644 index 000000000..0a0777916 --- /dev/null +++ b/src/BuildPlugin/Test/TestWire_WholeSketch_5.py @@ -0,0 +1,48 @@ +# Copyright (C) 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 +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# 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 +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# + +from salome.shaper import model +from GeomAPI import * + +model.begin() +partSet = model.moduleDocument() +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() +Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +SketchLine_1 = Sketch_1.addLine(-20.13297844091623, -34.87132400696332, -10.14115693918956, -4.003004374441855) +SketchLine_2 = Sketch_1.addLine(-15.36017779982175, -20.12643132586926, -37.81263639928755, -17.52358908612689) +SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_2.startPoint(), SketchLine_1.result()) +SketchLine_3 = Sketch_1.addLine(-37.81263639928755, -17.52358908612689, -28.23126689685475, -46.70782775211335) +SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint()) +SketchLine_4 = Sketch_1.addLine(-10.14115693918956, -4.003004374441855, -17.3289483797767, 22.37844327189705) +SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_4.startPoint()) +SketchLine_5 = Sketch_1.addLine(-17.3289483797767, 22.37844327189705, -39.00238825664131, 1.575954908729718) +SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint()) +SketchLine_6 = Sketch_1.addLine(-39.00238825664131, 1.575954908729718, -25.86766799285223, -18.90833134866903) +SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint()) +SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_6.endPoint(), SketchLine_2.result()) +model.do() +Wire_1 = model.addWire(Part_1_doc, [model.selection("COMPOUND", "Sketch_1")]) +model.end() + +model.testNbResults(Wire_1, 2) +model.testNbSubShapes(Wire_1, GeomAPI_Shape.EDGE, [4, 2]) +model.testNbSubShapes(Wire_1, GeomAPI_Shape.VERTEX, [8, 4]) + +assert(model.checkPythonDump()) diff --git a/src/BuildPlugin/Test/TestWire_WholeSketch_6.py b/src/BuildPlugin/Test/TestWire_WholeSketch_6.py new file mode 100644 index 000000000..94f7c7a3e --- /dev/null +++ b/src/BuildPlugin/Test/TestWire_WholeSketch_6.py @@ -0,0 +1,48 @@ +# Copyright (C) 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 +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# 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 +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# + +from salome.shaper import model +from GeomAPI import * + +model.begin() +partSet = model.moduleDocument() +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() +Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +SketchLine_1 = Sketch_1.addLine(-20.13297844091623, -34.87132400696332, -10.14115693918956, -4.003004374441855) +SketchLine_2 = Sketch_1.addLine(-15.36017779982175, -20.12643132586926, -37.81263639928755, -17.52358908612689) +SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_2.startPoint(), SketchLine_1.result()) +SketchLine_3 = Sketch_1.addLine(-37.81263639928755, -17.52358908612689, -28.23126689685475, -46.70782775211335) +SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint()) +SketchLine_4 = Sketch_1.addLine(-10.14115693918956, -4.003004374441855, -17.3289483797767, 22.37844327189705) +SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_4.startPoint()) +SketchLine_5 = Sketch_1.addLine(-17.3289483797767, 22.37844327189705, -39.00238825664131, 1.575954908729718) +SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint()) +SketchLine_6 = Sketch_1.addLine(-39.00238825664131, 1.575954908729718, -25.86766799285223, -18.90833134866903) +SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint()) +SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_6.endPoint(), SketchLine_2.result()) +model.do() +Wire_1 = model.addWire(Part_1_doc, [model.selection("COMPOUND", "Sketch_1")], True) +model.end() + +model.testNbResults(Wire_1, 3) +model.testNbSubShapes(Wire_1, GeomAPI_Shape.EDGE, [5, 1, 2]) +model.testNbSubShapes(Wire_1, GeomAPI_Shape.VERTEX, [10, 2, 4]) + +assert(model.checkPythonDump()) diff --git a/src/BuildPlugin/doc/edgeFeature.rst b/src/BuildPlugin/doc/edgeFeature.rst index a94a22020..2dbc68c5e 100644 --- a/src/BuildPlugin/doc/edgeFeature.rst +++ b/src/BuildPlugin/doc/edgeFeature.rst @@ -14,7 +14,7 @@ The options to create edges: .. image:: images/edge_by_segments_32x32.png :align: left -**By edges** creates edges using already existing edges in other shapes. +**By edges** creates edges using already existing edges in other shapes or full sketches. .. image:: images/edge_by_points_32x32.png :align: left @@ -30,7 +30,8 @@ By edges .. centered:: Create by edges -Select one or several edges in the viewer. +Select one or several edges in the viewer. Also, the full sketch can be selected. In this case, all edges of the sketch will be processed. +Checkbox **Compute intersections** forces to split sketch edges in the points of intersection. **Apply** button creates edges. @@ -38,10 +39,11 @@ Select one or several edges in the viewer. **TUI Command**: -.. py:function:: model.addEdge(Part_doc, Shapes) +.. py:function:: model.addEdge(Part_doc, Shapes, Intersect) :param part: The current part object. :param list: A list of shapes. + :param bool: Split edges by intersection points. False by default. :return: Result object. Result diff --git a/src/BuildPlugin/doc/images/Edge.png b/src/BuildPlugin/doc/images/Edge.png index 4eaf230b3..9ca142f3a 100644 Binary files a/src/BuildPlugin/doc/images/Edge.png and b/src/BuildPlugin/doc/images/Edge.png differ diff --git a/src/BuildPlugin/doc/images/Wire.png b/src/BuildPlugin/doc/images/Wire.png index 13ada63fb..3248c8c03 100644 Binary files a/src/BuildPlugin/doc/images/Wire.png and b/src/BuildPlugin/doc/images/Wire.png differ diff --git a/src/BuildPlugin/doc/vertexFeature.rst b/src/BuildPlugin/doc/vertexFeature.rst index 370588cef..e27d3025f 100644 --- a/src/BuildPlugin/doc/vertexFeature.rst +++ b/src/BuildPlugin/doc/vertexFeature.rst @@ -26,7 +26,7 @@ Select one or several vertices in the viewer. It also allowed to select a whole **TUI Command**: -.. py:function:: model.addVertex(Part_doc, Shapes, doIntersect) +.. py:function:: model.addVertex(Part_doc, Shapes, Intersect) :param part: The current part object. :param list: A list of shapes. diff --git a/src/BuildPlugin/doc/wireFeature.rst b/src/BuildPlugin/doc/wireFeature.rst index 32d03e58f..1b9ba515a 100644 --- a/src/BuildPlugin/doc/wireFeature.rst +++ b/src/BuildPlugin/doc/wireFeature.rst @@ -20,16 +20,20 @@ The following property panel will be opened: Select one or several edges in the viewer. For automatic selection of a closed contour starting from the selected edge it is necessary to press **Add contour** button. +Moreover, the full sketch can be selected. In this case, a set of wires is composed using edges of the sketch. +Checkbox **Compute intersections** forces to split sketch edges in the points of intersection. + **Apply** button creates a wire. **Cancel** button cancels the operation. **TUI Command**: -.. py:function:: model.addWire(Part_doc, Shapes) +.. py:function:: model.addWire(Part_doc, Shapes, Intersect) :param part: The current part object. :param list: A list of shapes. + :param bool: Split edges by intersection points. False by default. :return: Result object. Result diff --git a/src/BuildPlugin/edge_widget.xml b/src/BuildPlugin/edge_widget.xml index f7ff11447..0433b9bb9 100644 --- a/src/BuildPlugin/edge_widget.xml +++ b/src/BuildPlugin/edge_widget.xml @@ -2,12 +2,14 @@ - + + + - + + - + diff --git a/src/GeomAPI/GeomAPI_Edge.cpp b/src/GeomAPI/GeomAPI_Edge.cpp index 830fbb1b1..c4504272b 100644 --- a/src/GeomAPI/GeomAPI_Edge.cpp +++ b/src/GeomAPI/GeomAPI_Edge.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include @@ -69,6 +70,18 @@ GeomAPI_Edge::GeomAPI_Edge(const std::shared_ptr& theShape) } } +void GeomAPI_Edge::vertices(std::shared_ptr& theStartVertex, + std::shared_ptr& theEndVertex) const +{ + const TopoDS_Edge& anEdge = impl(); + TopoDS_Vertex aStart, aEnd; + TopExp::Vertices(anEdge, aStart, aEnd); + theStartVertex.reset(new GeomAPI_Vertex); + theStartVertex->setImpl(new TopoDS_Vertex(aStart)); + theEndVertex.reset(new GeomAPI_Vertex); + theEndVertex->setImpl(new TopoDS_Vertex(aEnd)); +} + static Handle(Geom_Curve) baseCurve(const TopoDS_Edge& theEdge) { double aFirst, aLast; diff --git a/src/GeomAPI/GeomAPI_Edge.h b/src/GeomAPI/GeomAPI_Edge.h index 9d3a4f47b..fdf82ed6f 100644 --- a/src/GeomAPI/GeomAPI_Edge.h +++ b/src/GeomAPI/GeomAPI_Edge.h @@ -27,6 +27,7 @@ class GeomAPI_Pnt; class GeomAPI_Circ; class GeomAPI_Lin; class GeomAPI_Ellipse; +class GeomAPI_Vertex; /**\class GeomAPI_Edge * \ingroup DataModel @@ -44,6 +45,11 @@ public: GEOMAPI_EXPORT GeomAPI_Edge(const std::shared_ptr& theShape); + /// Return vertices of the edge; + GEOMAPI_EXPORT + void vertices(std::shared_ptr& theStartVertex, + std::shared_ptr& theEndVertex) const; + /// Returns \c true if edges have same underlying curve GEOMAPI_EXPORT virtual bool isSameGeometry(const std::shared_ptr theShape) const;