]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Task 3.3 Build/Edge and Build/Wire on a whole Sketch (issue #3083)
authorazv <azv@opencascade.com>
Fri, 29 Nov 2019 09:24:15 +0000 (12:24 +0300)
committerazv <azv@opencascade.com>
Tue, 3 Dec 2019 09:51:36 +0000 (12:51 +0300)
31 files changed:
src/BuildAPI/BuildAPI_Edge.cpp
src/BuildAPI/BuildAPI_Edge.h
src/BuildAPI/BuildAPI_Wire.cpp
src/BuildAPI/BuildAPI_Wire.h
src/BuildPlugin/BuildPlugin_Edge.cpp
src/BuildPlugin/BuildPlugin_Edge.h
src/BuildPlugin/BuildPlugin_Validators.cpp
src/BuildPlugin/BuildPlugin_Wire.cpp
src/BuildPlugin/BuildPlugin_Wire.h
src/BuildPlugin/CMakeLists.txt
src/BuildPlugin/Test/TestEdge.py
src/BuildPlugin/Test/TestEdge_WholeSketch_1.py [new file with mode: 0644]
src/BuildPlugin/Test/TestEdge_WholeSketch_2.py [new file with mode: 0644]
src/BuildPlugin/Test/TestEdge_WholeSketch_3.py [new file with mode: 0644]
src/BuildPlugin/Test/TestEdge_WholeSketch_4.py [new file with mode: 0644]
src/BuildPlugin/Test/TestWire.py
src/BuildPlugin/Test/TestWire_WholeSketch_1.py [new file with mode: 0644]
src/BuildPlugin/Test/TestWire_WholeSketch_2.py [new file with mode: 0644]
src/BuildPlugin/Test/TestWire_WholeSketch_3.py [new file with mode: 0644]
src/BuildPlugin/Test/TestWire_WholeSketch_4.py [new file with mode: 0644]
src/BuildPlugin/Test/TestWire_WholeSketch_5.py [new file with mode: 0644]
src/BuildPlugin/Test/TestWire_WholeSketch_6.py [new file with mode: 0644]
src/BuildPlugin/doc/edgeFeature.rst
src/BuildPlugin/doc/images/Edge.png
src/BuildPlugin/doc/images/Wire.png
src/BuildPlugin/doc/vertexFeature.rst
src/BuildPlugin/doc/wireFeature.rst
src/BuildPlugin/edge_widget.xml
src/BuildPlugin/wire_widget.xml
src/GeomAPI/GeomAPI_Edge.cpp
src/GeomAPI/GeomAPI_Edge.h

index 3371f01eaf109912c91fd67a226bd60af4a7191d..e0816f8331c741a1caec81a995f4add6bffe6f89 100644 (file)
@@ -31,11 +31,13 @@ BuildAPI_Edge::BuildAPI_Edge(const std::shared_ptr<ModelAPI_Feature>& theFeature
 
 //==================================================================================================
 BuildAPI_Edge::BuildAPI_Edge(const std::shared_ptr<ModelAPI_Feature>& theFeature,
-                             const std::list<ModelHighAPI_Selection>& theBaseObjects)
+                             const std::list<ModelHighAPI_Selection>& 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<ModelAPI_Document>& thePart,
-                const std::list<ModelHighAPI_Selection>& theBaseObjects)
+                const std::list<ModelHighAPI_Selection>& theBaseObjects,
+                const bool theComputeIntersections)
 {
   std::shared_ptr<ModelAPI_Feature> 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<ModelAPI_Document>& thePart,
index 11a7fa90210d6a424a649fa964899287c22a325e..e6a7e46d760cd398f57fed8be3c9f4457194c93d 100644 (file)
@@ -42,7 +42,8 @@ public:
   /// Constructor with values.
   BUILDAPI_EXPORT
   explicit BuildAPI_Edge(const std::shared_ptr<ModelAPI_Feature>& theFeature,
-                         const std::list<ModelHighAPI_Selection>& theBaseObjects);
+                         const std::list<ModelHighAPI_Selection>& 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<BuildAPI_Edge> EdgePtr;
 /// \brief Create Edge feature.
 BUILDAPI_EXPORT
 EdgePtr addEdge(const std::shared_ptr<ModelAPI_Document>& thePart,
-                const std::list<ModelHighAPI_Selection>& theBaseObjects);
+                const std::list<ModelHighAPI_Selection>& theBaseObjects,
+                const bool theComputeIntersection = false);
 /// \ingroup CPPHighAPI
 /// \brief Create Edge feature.
 BUILDAPI_EXPORT
index 69c68be456a41276cedec0da4e09edd495713355..ffd58d48af7f160d6c63e3223ce3110078fec084 100644 (file)
@@ -31,10 +31,12 @@ BuildAPI_Wire::BuildAPI_Wire(const std::shared_ptr<ModelAPI_Feature>& theFeature
 
 //==================================================================================================
 BuildAPI_Wire::BuildAPI_Wire(const std::shared_ptr<ModelAPI_Feature>& theFeature,
-                             const std::list<ModelHighAPI_Selection>& theBaseObjects)
+                             const std::list<ModelHighAPI_Selection>& 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<ModelAPI_Document>& thePart,
-                const std::list<ModelHighAPI_Selection>& theBaseObjects)
+                const std::list<ModelHighAPI_Selection>& theBaseObjects,
+                const bool theComputeIntersections)
 {
   std::shared_ptr<ModelAPI_Feature> aFeature = thePart->addFeature(BuildAPI_Wire::ID());
-  return WirePtr(new BuildAPI_Wire(aFeature, theBaseObjects));
+  return WirePtr(new BuildAPI_Wire(aFeature, theBaseObjects, theComputeIntersections));
 }
index 4934943d7b3c8abab6fd0b8a6c370598e02938ab..86e78837b4015dc7ce8d50b45b579cd729c704d2 100644 (file)
@@ -42,15 +42,18 @@ public:
   /// Constructor with values.
   BUILDAPI_EXPORT
   explicit BuildAPI_Wire(const std::shared_ptr<ModelAPI_Feature>& theFeature,
-                         const std::list<ModelHighAPI_Selection>& theBaseObjects);
+                         const std::list<ModelHighAPI_Selection>& 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<BuildAPI_Wire> WirePtr;
 /// \brief Create Wire feature.
 BUILDAPI_EXPORT
 WirePtr addWire(const std::shared_ptr<ModelAPI_Document>& thePart,
-                const std::list<ModelHighAPI_Selection>& theBaseObjects);
+                const std::list<ModelHighAPI_Selection>& theBaseObjects,
+                const bool theComputeIntersections = false);
 
 #endif // BuildAPI_Wire_H_
index 0f85ae3e443842129b491d6e11ee39ea6ccaa76e..2a07d390c2088ce7b1c922f82b50954c29fd0275 100644 (file)
 
 #include "BuildPlugin_Edge.h"
 
+#include <ModelAPI_AttributeBoolean.h>
 #include <ModelAPI_AttributeSelectionList.h>
 #include <ModelAPI_AttributeString.h>
 #include <ModelAPI_ResultBody.h>
 #include <ModelAPI_Session.h>
 #include <ModelAPI_Validator.h>
 
+#include <GeomAlgoAPI_CompoundBuilder.h>
 #include <GeomAlgoAPI_Copy.h>
 #include <GeomAlgoAPI_EdgeBuilder.h>
+#include <GeomAlgoAPI_MakeShapeList.h>
+#include <GeomAlgoAPI_Partition.h>
 #include <GeomAlgoAPI_Tools.h>
 
 #include <GeomAPI_Edge.h>
@@ -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<GeomAlgoAPI_Partition> 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<GeomShapePtr, GeomAPI_Shape::Comparator> 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<GeomAlgoAPI_Copy> aCopyAlgo(new GeomAlgoAPI_Copy(anEdge));
 
+    std::shared_ptr<GeomAlgoAPI_MakeShapeList> 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;
   }
index 27f1665ba0eb3f0da9ff5510a13cfc5f3725b20f..af142f55b02ad9f95261259ea14a20dc699a8273 100644 (file)
@@ -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();
 
index 761fc6fa542c9acea0db48d56dfd66b820fe782e..aef6b7fc8828430feb890998dc6e01a765c6b10d 100644 (file)
@@ -116,12 +116,6 @@ bool BuildPlugin_ValidatorBaseForWire::isValid(const std::shared_ptr<ModelAPI_Fe
                                                Events_InfoMessage& theError) const
 {
   // Get attribute.
-  if(theArguments.size() != 1) {
-    std::string aMsg = "Error: BuildPlugin_ValidatorBaseForWire should be used only "
-                       "with 1 parameter (ID of base objects list).";
-    Events_InfoMessage("BuildPlugin_Validators", aMsg).send();
-    return false;
-  }
   AttributeSelectionListPtr aSelectionList = theFeature->selectionList(theArguments.front());
   if(!aSelectionList.get()) {
     theError = "Empty attribute \"%1\".";
@@ -129,25 +123,53 @@ bool BuildPlugin_ValidatorBaseForWire::isValid(const std::shared_ptr<ModelAPI_Fe
     return false;
   }
 
+  GeomAPI_Shape::ShapeType aShapeType = GeomAPI_Shape::shapeTypeByStr(theArguments.back());
 
   // Collect base shapes.
   ListOfShape aListOfShapes;
   for(int anIndex = 0; anIndex < aSelectionList->size(); ++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;
index 4fe602e84c29c5c4f0dfb3a8c3369b6cdf07c726..c7caa85812a46170e654e5298e309f35a53b494e 100644 (file)
 
 #include "BuildPlugin_Wire.h"
 
+#include <ModelAPI_AttributeBoolean.h>
 #include <ModelAPI_AttributeSelectionList.h>
 #include <ModelAPI_ResultBody.h>
 #include <ModelAPI_ResultConstruction.h>
+#include <ModelAPI_Session.h>
+#include <ModelAPI_Validator.h>
 
 #include <Events_InfoMessage.h>
 
 #include <GeomAPI_PlanarEdges.h>
 #include <GeomAPI_ShapeExplorer.h>
+#include <GeomAPI_Vertex.h>
 
-#include <GeomAlgoAPI_ShapeTools.h>
+#include <GeomAlgoAPI_MakeShapeList.h>
+#include <GeomAlgoAPI_PaveFiller.h>
+#include <GeomAlgoAPI_SketchBuilder.h>
+#include <GeomAlgoAPI_Tools.h>
 #include <GeomAlgoAPI_WireBuilder.h>
 
+#include <SketchPlugin_Sketch.h>
+
 #include <algorithm>
 
+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<FeaturePtr, GeomShapePtr> > 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<GeomAPI_PlanarEdges> aSketchShape =
+          std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(aShape);
+      if (aSketchShape) {
+        FeaturePtr aSketchFeature = ModelAPI_Feature::feature(aSelection->context());
+        aSketches.push_back(std::pair<FeaturePtr, GeomShapePtr>(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<GeomAPI_Edge> 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<GeomAPI_Edge> 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<std::pair<FeaturePtr, GeomShapePtr> >::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<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;
+}
index c0b873174344e4f7db5054ec5a276bfdc26c9d9d..5677bebb3275b228583941a23d5e9181a0c14502 100644 (file)
@@ -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()
   {
index e8a4e470fc671d0f50fbbc7d0141b70504e8e7c3..2954b05c7f0cb94b7601731bcbd92103982f4172 100644 (file)
@@ -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
index 83d163b5ee8294165367bcc39dace57b9495eecf..2e194941ff4a3dccf497325820f1ea2118536b9f 100644 (file)
@@ -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 (file)
index 0000000..aa7a9aa
--- /dev/null
@@ -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 (file)
index 0000000..8558502
--- /dev/null
@@ -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 (file)
index 0000000..c725d12
--- /dev/null
@@ -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 (file)
index 0000000..8ddd0ab
--- /dev/null
@@ -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())
index 0bbbbce8fefbae0c8b8572f4b646ef490eddb5c0..fc4734adc5eb577d63ae5c9ec251f71849764313 100644 (file)
@@ -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 (file)
index 0000000..e64e662
--- /dev/null
@@ -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 (file)
index 0000000..e5db2e1
--- /dev/null
@@ -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 (file)
index 0000000..bbc4dac
--- /dev/null
@@ -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 (file)
index 0000000..fee5553
--- /dev/null
@@ -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 (file)
index 0000000..0a07779
--- /dev/null
@@ -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 (file)
index 0000000..94f7c7a
--- /dev/null
@@ -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())
index a94a22020fe68a429c1a2f4df03ca590e0abd896..2dbc68c5e24571cc085680502d07cb79e4db6bf2 100644 (file)
@@ -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
index 4eaf230b39b01c4c6c147321e7f946c1619d2446..9ca142f3a9dfb2a66b420f462443469aae9fdee8 100644 (file)
Binary files a/src/BuildPlugin/doc/images/Edge.png and b/src/BuildPlugin/doc/images/Edge.png differ
index 13ada63fbd5ec2962753526e686494277c0c3655..3248c8c0360d537ed47d344e7b5cd387c6edd79b 100644 (file)
Binary files a/src/BuildPlugin/doc/images/Wire.png and b/src/BuildPlugin/doc/images/Wire.png differ
index 370588cef49f4a098c7a811d5109ec2c1aaf47d5..e27d3025f0589f06768ee5d3d5691a923be04a8c 100644 (file)
@@ -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.
index 32d03e58fe62f36773f649833cc24c97f68ca754..1b9ba515a7af4737cfe1a70c67be7fe587d3678c 100644 (file)
@@ -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
index f7ff1144731a23fb064600ec8dc04b8d9e7a32b3..0433b9bb9d2e3b9aa3fbfeef6ea8d01e6ffa517e 100644 (file)
@@ -2,12 +2,14 @@
   <toolbox id="creation_method">
     <box id="by_segments" title="By segments" icon="icons/Build/edge_by_segments_32x32.png">
       <multi_selector id="base_objects"
-                      label="Edges:"
+                      label="Edges or sketches:"
                       tooltip="Select edges on sketch or edges objects."
                       shape_types="edges"
                       concealment="true">
-        <validator id="BuildPlugin_ValidatorBaseForBuild" parameters="edge"/>
+        <validator id="BuildPlugin_ValidatorBaseForBuild" parameters="edge,compound"/>
       </multi_selector>
+      <boolvalue id="intersect" label="Compute intersections" tooltip="Divide sketch edges in intersection points." default="false"/>
+      <validator id="BuildPlugin_ValidatorBaseForWire" parameters="base_objects,edge"/>
     </box>
     <box id="by_points" title="By two points" icon="icons/Build/edge_by_points_32x32.png">
       <shape_selector id="first_point"
index 96067ebe6d9917d26bfda0e59bbfe7d2ddea87bc..d0fca7a69c0bbf5717e402e4399b7a8b92b2f60f 100644 (file)
@@ -4,11 +4,12 @@
                   tooltip="Select edges on sketch, edges or wires objects."
                   shape_types="edges wires"
                   concealment="true">
-    <validator id="BuildPlugin_ValidatorBaseForBuild" parameters="edge,wire"/>
+    <validator id="BuildPlugin_ValidatorBaseForBuild" parameters="edge,wire,compound"/>
   </multi_selector>
+  <boolvalue id="intersect" label="Compute intersections" tooltip="Divide sketch edges in intersection points." default="false"/>
   <action id="add_contour"
           label="Add contour"
           tooltip="Adds to the list of segments other segments of the sketcher
                    connected to the already selected ones to create a closed contour."/>
-  <validator id="BuildPlugin_ValidatorBaseForWire" parameters="base_objects"/>
+  <validator id="BuildPlugin_ValidatorBaseForWire" parameters="base_objects,wire"/>
 </source>
index 830fbb1b1ceac2fa867ea85ac0b3011820cc7814..c4504272b3ccbea972eb5606d69f5288aab6da0a 100644 (file)
@@ -25,6 +25,7 @@
 #include<GeomAPI_Lin.h>
 #include<GeomAPI_Ax2.h>
 #include<GeomAPI_Ellipse.h>
+#include<GeomAPI_Vertex.h>
 
 #include <BRepAdaptor_Curve.hxx>
 
@@ -69,6 +70,18 @@ GeomAPI_Edge::GeomAPI_Edge(const std::shared_ptr<GeomAPI_Shape>& theShape)
   }
 }
 
+void GeomAPI_Edge::vertices(std::shared_ptr<GeomAPI_Vertex>& theStartVertex,
+                            std::shared_ptr<GeomAPI_Vertex>& theEndVertex) const
+{
+  const TopoDS_Edge& anEdge = impl<TopoDS_Edge>();
+  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;
index 9d3a4f47b9ae1fe26df16c724cd795a5386c2d27..fdf82ed6fb57954343676c3969fa3805791f44a1 100644 (file)
@@ -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<GeomAPI_Shape>& theShape);
 
+  /// Return vertices of the edge;
+  GEOMAPI_EXPORT
+  void vertices(std::shared_ptr<GeomAPI_Vertex>& theStartVertex,
+                std::shared_ptr<GeomAPI_Vertex>& theEndVertex) const;
+
   /// Returns \c true if edges have same underlying curve
   GEOMAPI_EXPORT
   virtual bool isSameGeometry(const std::shared_ptr<GeomAPI_Shape> theShape) const;