]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Task 2.3. Sketch Point created by intersectionPoints
authorazv <azv@opencascade.com>
Thu, 24 May 2018 10:47:35 +0000 (13:47 +0300)
committerazv <azv@opencascade.com>
Thu, 24 May 2018 10:47:35 +0000 (13:47 +0300)
Finalize Intersection feature

13 files changed:
src/GeomAPI/GeomAPI_Edge.cpp
src/SketchAPI/SketchAPI_IntersectionPoint.cpp
src/SketchAPI/SketchAPI_IntersectionPoint.h
src/SketchAPI/SketchAPI_Sketch.cpp
src/SketchAPI/SketchAPI_Sketch.h
src/SketchPlugin/CMakeLists.txt
src/SketchPlugin/SketchPlugin_IntersectionPoint.cpp
src/SketchPlugin/SketchPlugin_IntersectionPoint.h
src/SketchPlugin/SketchPlugin_Validators.cpp
src/SketchPlugin/Test/TestIntersectionChangeEdge.py [new file with mode: 0644]
src/SketchPlugin/Test/TestIntersectionWithCircle.py [new file with mode: 0644]
src/SketchPlugin/Test/TestIntersectionWithLine.py [new file with mode: 0644]
src/SketchPlugin/Test/TestIntersectionWithSpline.py [new file with mode: 0644]

index 242b6809e42011df66e3468fcc1a2d41fc19066d..b5d0de4b673c35ad38c0d532e3b8cbf8df7d87b3 100644 (file)
@@ -34,6 +34,7 @@
 #include <TopoDS.hxx>
 #include <BRep_Builder.hxx>
 #include <BRep_Tool.hxx>
+#include <ElCLib.hxx>
 #include <Geom_Curve.hxx>
 #include <Geom_Line.hxx>
 #include <Geom_Circle.hxx>
@@ -299,6 +300,14 @@ void GeomAPI_Edge::intersectWithPlane(const std::shared_ptr<GeomAPI_Pln> thePlan
     if (aIntersect.IsDone() && (aIntersect.NbPoints() > 0)) {
       gp_Pnt aPnt;
       for (int i = 1; i <= aIntersect.NbPoints(); i++) {
+        // check the parameter of intersection in the edge range
+        aIntersect.Parameters(i, A, B, C);
+        if (aCurve->IsPeriodic())
+          C = ElCLib::InPeriod(C, aFirst, aFirst + aCurve->Period());
+        if (C < aFirst - Precision::PConfusion() || C > aLast + Precision::PConfusion())
+          continue;
+
+        // obtain intersection point
         aPnt = aIntersect.Point(i);
         std::shared_ptr<GeomAPI_Pnt> aPntPtr(new GeomAPI_Pnt(aPnt.X(), aPnt.Y(), aPnt.Z()));
         theResult.push_back(aPntPtr);
index aa5e3c0a5bb10671f2a935ef930e82782700644b..ff689965c69a9c76e49d76cc311f43505f41009d 100644 (file)
@@ -19,6 +19,9 @@
 //
 
 #include "SketchAPI_IntersectionPoint.h"
+#include "SketchAPI_Point.h"
+//--------------------------------------------------------------------------------------
+#include <SketchPlugin_Point.h>
 //--------------------------------------------------------------------------------------
 #include <GeomAPI_Pnt2d.h>
 //--------------------------------------------------------------------------------------
@@ -39,7 +42,7 @@ SketchAPI_IntersectionPoint::SketchAPI_IntersectionPoint(
 : SketchAPI_SketchEntity(theFeature)
 {
   if (initialize()) {
-    setByExternalLine(theExternal);
+    setByExternalEdge(theExternal);
   }
 }
 
@@ -49,7 +52,7 @@ SketchAPI_IntersectionPoint::SketchAPI_IntersectionPoint(
 : SketchAPI_SketchEntity(theFeature)
 {
   if (initialize()) {
-    setByExternalLineName(theExternalName);
+    setByExternalEdgeName(theExternalName);
   }
 }
 
@@ -59,20 +62,48 @@ SketchAPI_IntersectionPoint::~SketchAPI_IntersectionPoint()
 }
 
 //--------------------------------------------------------------------------------------
-void SketchAPI_IntersectionPoint::setByExternalLine(const ModelHighAPI_Selection & theExternalLine)
+void SketchAPI_IntersectionPoint::setByExternalEdge(const ModelHighAPI_Selection & theExternalLine)
 {
   fillAttribute(theExternalLine, externalFeature());
 
   execute();
 }
 
-void SketchAPI_IntersectionPoint::setByExternalLineName(const std::string & theExternalLineName)
+void SketchAPI_IntersectionPoint::setByExternalEdgeName(const std::string & theExternalLineName)
 {
   fillAttribute(ModelHighAPI_Selection("EDGE", theExternalLineName), externalFeature());
 
   execute();
 }
 
+void SketchAPI_IntersectionPoint::setIncludeToResult(bool theKeepResult)
+{
+  fillAttribute(theKeepResult, includeToResult());
+  execute(true);
+}
+
+//--------------------------------------------------------------------------------------
+
+std::list<std::shared_ptr<SketchAPI_SketchEntity> >
+SketchAPI_IntersectionPoint::intersectionPoints() const
+{
+  std::list<std::shared_ptr<SketchAPI_SketchEntity> > anEntities;
+
+  std::list<ObjectPtr> anIntersections =
+      feature()->reflist(SketchPlugin_IntersectionPoint::INTERSECTION_POINTS_ID())->list();
+  for (std::list<ObjectPtr>::iterator anIt = anIntersections.begin();
+       anIt != anIntersections.end(); ++anIt) {
+    FeaturePtr aFeature = ModelAPI_Feature::feature(*anIt);
+    if (aFeature && aFeature->getKind() == SketchPlugin_Point::ID())
+    {
+      std::shared_ptr<SketchAPI_SketchEntity> anEnt(new SketchAPI_Point(aFeature));
+      anEntities.push_back(anEnt);
+    }
+  }
+
+  return anEntities;
+}
+
 //--------------------------------------------------------------------------------------
 
 void SketchAPI_IntersectionPoint::dump(ModelHighAPI_Dumper& theDumper) const
@@ -80,9 +111,21 @@ void SketchAPI_IntersectionPoint::dump(ModelHighAPI_Dumper& theDumper) const
   FeaturePtr aBase = feature();
   const std::string& aSketchName = theDumper.parentName(aBase);
 
-  AttributeSelectionPtr aLine = externalFeature();
-  theDumper << aBase << " = " <<
-    aSketchName << ".addIntersectionPoint(" << aLine << ")" << std::endl;
+  AttributeSelectionPtr anExternal = externalFeature();
+  AttributeBooleanPtr isIncludeToRes = includeToResult();
+  theDumper << aBase << " = " << aSketchName << ".addIntersectionPoint("
+            << anExternal << ", " << isIncludeToRes << ")" << std::endl;
   // dump "auxiliary" flag if necessary
   SketchAPI_SketchEntity::dump(theDumper);
+
+  // Dump variables for a list of intersected points
+  theDumper << "[";
+  std::list<std::shared_ptr<SketchAPI_SketchEntity> > aList = intersectionPoints();
+  std::list<std::shared_ptr<SketchAPI_SketchEntity> >::const_iterator anIt = aList.begin();
+  for (; anIt != aList.end(); ++anIt) {
+    if (anIt != aList.begin())
+      theDumper << ", ";
+    theDumper << (*anIt)->feature();
+  }
+  theDumper << "] = " << theDumper.name(aBase) << ".intersectionPoints()" << std::endl;
 }
index ba0ef3825e7b6104689210716cfd1184f52143f8..cc1b4e947a107f780ff058eec33d5acc77ee5f7d 100644 (file)
@@ -52,9 +52,7 @@ public:
   SKETCHAPI_EXPORT
   virtual ~SketchAPI_IntersectionPoint();
 
-  INTERFACE_4(SketchPlugin_IntersectionPoint::ID(),
-              coordinates, SketchPlugin_IntersectionPoint::COORD_ID(),
-              GeomDataAPI_Point2D, /** IntersectionPoint coordinates */,
+  INTERFACE_3(SketchPlugin_IntersectionPoint::ID(),
               externalFeature, SketchPlugin_IntersectionPoint::EXTERNAL_FEATURE_ID(),
               ModelAPI_AttributeSelection, /** External edge */,
               external, SketchPlugin_IntersectionPoint::EXTERNAL_ID(),
@@ -65,11 +63,19 @@ public:
 
   /// Set by external
   SKETCHAPI_EXPORT
-  void setByExternalLine(const ModelHighAPI_Selection & theExternalLine);
+  void setByExternalEdge(const ModelHighAPI_Selection & theExternaEdge);
 
   /// Set by external name
   SKETCHAPI_EXPORT
-  void setByExternalLineName(const std::string & theExternalLineName);
+  void setByExternalEdgeName(const std::string & theExternalEdgeName);
+
+  /// Set flag to include projection to result or not
+  SKETCHAPI_EXPORT
+  void setIncludeToResult(bool theKeepResult);
+
+  /// Returns created intersection points
+  SKETCHAPI_EXPORT
+  std::list<std::shared_ptr<SketchAPI_SketchEntity> > intersectionPoints() const;
 
   /// Dump wrapped feature
   SKETCHAPI_EXPORT
index 2e38d2d33f3b9c4c083430daf437e576989d1087..24be396bf39a2a109d11bd5f4d90d51b82b03e9a 100644 (file)
@@ -235,18 +235,24 @@ std::shared_ptr<SketchAPI_Point> SketchAPI_Sketch::addPoint(const std::string &
 
 //--------------------------------------------------------------------------------------
 std::shared_ptr<SketchAPI_IntersectionPoint> SketchAPI_Sketch::addIntersectionPoint(
-    const ModelHighAPI_Selection & theExternal)
+    const ModelHighAPI_Selection & theExternal,
+    bool theKeepResult)
 {
   std::shared_ptr<ModelAPI_Feature> aFeature =
     compositeFeature()->addFeature(SketchPlugin_IntersectionPoint::ID());
-  return IntersectionPointPtr(new SketchAPI_IntersectionPoint(aFeature, theExternal));
+  IntersectionPointPtr anIntersection(new SketchAPI_IntersectionPoint(aFeature, theExternal));
+  anIntersection->setIncludeToResult(theKeepResult);
+  return anIntersection;
 }
 std::shared_ptr<SketchAPI_IntersectionPoint> SketchAPI_Sketch::addIntersectionPoint(
-    const std::string & theExternalName)
+    const std::string & theExternalName,
+    bool theKeepResult)
 {
   std::shared_ptr<ModelAPI_Feature> aFeature =
     compositeFeature()->addFeature(SketchPlugin_IntersectionPoint::ID());
-  return IntersectionPointPtr(new SketchAPI_IntersectionPoint(aFeature, theExternalName));
+  IntersectionPointPtr anIntersection(new SketchAPI_IntersectionPoint(aFeature, theExternalName));
+  anIntersection->setIncludeToResult(theKeepResult);
+  return anIntersection;
 }
 
 //--------------------------------------------------------------------------------------
index 5e7d902e8f6bc6b03528d2d883dc450c7b36ee06..aa58dc89edab2ea9fe68955450764eaa9dacf1e6 100644 (file)
@@ -125,11 +125,13 @@ public:
   /// Add intersection point
   SKETCHAPI_EXPORT
   std::shared_ptr<SketchAPI_IntersectionPoint>
-    addIntersectionPoint(const ModelHighAPI_Selection & theExternal);
+    addIntersectionPoint(const ModelHighAPI_Selection & theExternal,
+                         bool theKeepResult = false);
   /// Add point
   SKETCHAPI_EXPORT
   std::shared_ptr<SketchAPI_IntersectionPoint>
-    addIntersectionPoint(const std::string & theExternalName);
+    addIntersectionPoint(const std::string & theExternalName,
+                         bool theKeepResult = false);
 
   /// Add line
   SKETCHAPI_EXPORT
index 4fa4f8c0fa0f068aa86d00609488ba6aabafce61..47550e2d55bd8d24b1f500f0b1fc2b6c4686f883 100644 (file)
@@ -232,6 +232,10 @@ ADD_UNIT_TESTS(TestSketchPointLine.py
                TestDistanceSignedVsUnsigned05.py
                TestSignedDistancePointPoint.py
                TestSignedDistancePointLine.py
+               TestIntersectionWithLine.py
+               TestIntersectionWithCircle.py
+               TestIntersectionWithSpline.py
+               TestIntersectionChangeType.py
                Test2273.py
                Test2280.py
                Test2287.py
index ceb800a58a6957d3d08f53dcc799979ba601a1e1..e4feff995637bff85554d14d5fc107634cd3f6b0 100644 (file)
 //
 
 #include "SketchPlugin_IntersectionPoint.h"
+#include "SketchPlugin_Point.h"
 
 #include <ModelAPI_AttributeSelection.h>
+#include <ModelAPI_AttributeRefList.h>
+#include <ModelAPI_ResultConstruction.h>
 #include <ModelAPI_Session.h>
+#include <ModelAPI_Tools.h>
 #include <ModelAPI_Validator.h>
 
 #include <GeomAPI_Edge.h>
 #include <GeomAPI_Lin.h>
+#include <GeomAPI_Pnt2d.h>
 #include <GeomDataAPI_Point2D.h>
 
 SketchPlugin_IntersectionPoint::SketchPlugin_IntersectionPoint()
-  : SketchPlugin_Point()
+  : SketchPlugin_SketchEntity(),
+    myIsComputing(false)
 {
 }
 
 void SketchPlugin_IntersectionPoint::initDerivedClassAttributes()
 {
   data()->addAttribute(EXTERNAL_FEATURE_ID(), ModelAPI_AttributeSelection::typeId());
+  data()->addAttribute(INTERSECTION_POINTS_ID(), ModelAPI_AttributeRefList::typeId());
+  data()->attribute(INTERSECTION_POINTS_ID())->setIsArgument(false);
+
   data()->addAttribute(INCLUDE_INTO_RESULT(), ModelAPI_AttributeBoolean::typeId());
 
-  SketchPlugin_Point::initDerivedClassAttributes();
+  data()->addAttribute(EXTERNAL_ID(), ModelAPI_AttributeSelection::typeId());
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), EXTERNAL_ID());
 
   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), AUXILIARY_ID());
 }
 
 void SketchPlugin_IntersectionPoint::execute()
 {
-  SketchPlugin_Sketch* aSketch = sketch();
-  if (aSketch) {
-    computePoint();
-    SketchPlugin_Point::execute();
+  AttributeRefListPtr anIntersectionsList = reflist(INTERSECTION_POINTS_ID());
+  if (!anIntersectionsList || !anIntersectionsList->isInitialized())
+    return; // no intersections
 
-    // set this feature as external
-    data()->selection(EXTERNAL_ID())->setValue(lastResult(), lastResult()->shape());
-  }
+  computePoint(EXTERNAL_FEATURE_ID());
 }
 
 void SketchPlugin_IntersectionPoint::attributeChanged(const std::string& theID)
 {
-  if (theID == EXTERNAL_FEATURE_ID()) {
-    // compute intersection between line and sketch plane
-    computePoint();
-  }
+  // compute intersection between line and sketch plane
+  computePoint(theID);
 }
 
-void SketchPlugin_IntersectionPoint::computePoint()
+void SketchPlugin_IntersectionPoint::computePoint(const std::string& theID)
 {
-  AttributeSelectionPtr aLineAttr =
-      std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(attribute(EXTERNAL_FEATURE_ID()));
-
-  std::shared_ptr<GeomAPI_Edge> anEdge;
-  if(aLineAttr && aLineAttr->value() && aLineAttr->value()->isEdge()) {
-    anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(aLineAttr->value()));
-  } else if(aLineAttr->context() && aLineAttr->context()->shape() &&
-            aLineAttr->context()->shape()->isEdge()) {
-    anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(aLineAttr->context()->shape()));
-  }
-  if(!anEdge.get())
+  if (theID != EXTERNAL_FEATURE_ID() && theID != EXTERNAL_ID())
     return;
 
-  std::shared_ptr<GeomAPI_Lin> aLine = anEdge->line();
-  std::shared_ptr<GeomAPI_Pln> aSketchPlane = sketch()->plane();
-
-  std::shared_ptr<GeomAPI_Pnt> anIntersection = aSketchPlane->intersect(aLine);
-  if (!anIntersection)
+  if (myIsComputing)
     return;
+  myIsComputing = true;
+
+  AttributeSelectionPtr anExternalFeature = selection(EXTERNAL_FEATURE_ID());
+
+  GeomShapePtr aShape;
+  GeomEdgePtr anEdge;
+  if (anExternalFeature)
+    aShape = anExternalFeature->value();
+  if (!aShape && anExternalFeature->context())
+    aShape = anExternalFeature->context()->shape();
+  if (aShape && aShape->isEdge())
+    anEdge = GeomEdgePtr(new GeomAPI_Edge(aShape));
+
+  if (anEdge) {
+    std::shared_ptr<GeomAPI_Pln> aSketchPlane = sketch()->plane();
+
+    std::list<GeomPointPtr> anIntersectionsPoints;
+    anEdge->intersectWithPlane(aSketchPlane, anIntersectionsPoints);
+
+    AttributeRefListPtr anIntersectionsList = reflist(INTERSECTION_POINTS_ID());
+    std::list<ObjectPtr> anExistentIntersections = anIntersectionsList->list();
+    std::list<ObjectPtr>::const_iterator aExistInterIt = anExistentIntersections.begin();
 
-  std::shared_ptr<GeomDataAPI_Point2D> aCoordAttr =
-      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(COORD_ID()));
-  aCoordAttr->setValue(sketch()->to2D(anIntersection));
+    const std::list<ResultPtr>& aResults = results();
+    std::list<ResultPtr>::const_iterator aResIt = aResults.begin();
+
+    int aResultIndex = 0;
+    for (std::list<GeomPointPtr>::iterator aPntIt = anIntersectionsPoints.begin();
+         aPntIt != anIntersectionsPoints.end(); ++aPntIt, ++aResultIndex) {
+      std::shared_ptr<SketchPlugin_Point> aCurSketchPoint;
+      ResultConstructionPtr aCurResult;
+      if (aExistInterIt == anExistentIntersections.end()) {
+        // create new point and result
+        aCurSketchPoint = std::dynamic_pointer_cast<SketchPlugin_Point>(
+          sketch()->addFeature(SketchPlugin_Point::ID()));
+        aCurSketchPoint->boolean(COPY_ID())->setValue(true);
+        anIntersectionsList->append(aCurSketchPoint);
+
+        aCurResult = document()->createConstruction(data(), aResultIndex);
+        aCurResult->setIsInHistory(false);
+        aCurResult->setDisplayed(false);
+      }
+      else {
+        // update existent result point
+        aCurSketchPoint = std::dynamic_pointer_cast<SketchPlugin_Point>(*aExistInterIt);
+        aCurResult = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aResIt);
+        aCurResult->setShape(std::shared_ptr<GeomAPI_Edge>());
+
+        ++aExistInterIt;
+        ++aResIt;
+      }
+
+      // update coordinates of intersection
+      GeomPnt2dPtr aPointInSketch = sketch()->to2D(*aPntIt);
+      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+        aCurSketchPoint->attribute(SketchPlugin_Point::COORD_ID()))->setValue(aPointInSketch);
+      aCurSketchPoint->execute();
+
+      // update result
+      aCurResult->setShape(aCurSketchPoint->lastResult()->shape());
+      setResult(aCurResult, aResultIndex);
+
+      // make intersection point external
+      GeomShapePtr anEmptyVal;
+      aCurSketchPoint->selection(EXTERNAL_ID())->setValue(aCurResult, anEmptyVal);
+    }
+
+    // remove rest results from previous pass
+    removeResults(aResultIndex);
+    std::set<FeaturePtr> aFeaturesToBeRemoved;
+    for (; aExistInterIt != anExistentIntersections.end(); ++aExistInterIt) {
+      aFeaturesToBeRemoved.insert(ModelAPI_Feature::feature(*aExistInterIt));
+      anIntersectionsList->removeLast();
+    }
+    ModelAPI_Tools::removeFeaturesAndReferences(aFeaturesToBeRemoved);
+
+    if (theID != EXTERNAL_ID())
+      selection(EXTERNAL_ID())->selectValue(anExternalFeature);
+  }
+  myIsComputing = false;
 }
index ab0dcd6fc5d6b0075930d49c92592138c08b330d..2ddebd6b1fa044eeccae4a100f35727b5b5eacac 100644 (file)
 #ifndef SketchPlugin_IntersectionPoint_H_
 #define SketchPlugin_IntersectionPoint_H_
 
-#include "SketchPlugin_Point.h"
+#include "SketchPlugin_SketchEntity.h"
 
 /**\class SketchPlugin_IntersectionPoint
  * \ingroup Plugins
  * \brief Feature for creation of external point as an intersection
  *        between external edge and a plane of the sketch.
  */
-class SketchPlugin_IntersectionPoint : public SketchPlugin_Point
+class SketchPlugin_IntersectionPoint : public SketchPlugin_SketchEntity
 {
 public:
   /// Point feature kind
@@ -50,6 +50,12 @@ public:
     return MY_FEATURE_ID;
   }
 
+  static const std::string& INTERSECTION_POINTS_ID()
+  {
+    static std::string MY_INTERSECTIONS_ID("IntersectionPoints");
+    return MY_INTERSECTIONS_ID;
+  }
+
   static const std::string& INCLUDE_INTO_RESULT()
   {
     static std::string MY_INCLUDE("IncludeToResult");
@@ -80,7 +86,9 @@ protected:
 
 private:
   /// \brief Find intersection between a line and a sketch plane
-  void computePoint();
+  void computePoint(const std::string& theID);
+
+  bool myIsComputing;
 };
 
 #endif
index 0dce7c4fe454aa8240bca588a467ee402468b67a..c003dd7eda119e37eee5dc8e23d82926115a41e9 100755 (executable)
@@ -801,27 +801,25 @@ bool SketchPlugin_IntersectionValidator::isValid(const AttributePtr& theAttribut
     theError.arg(theAttribute->attributeType());
     return false;
   }
-  AttributeSelectionPtr aLineAttr =
-                       std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
+  AttributeSelectionPtr anExternalAttr =
+      std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
   std::shared_ptr<GeomAPI_Edge> anEdge;
-  if(aLineAttr && aLineAttr->value() && aLineAttr->value()->isEdge()) {
-    anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(aLineAttr->value()));
-  } else if(aLineAttr->context() &&
-            aLineAttr->context()->shape() && aLineAttr->context()->shape()->isEdge()) {
-    anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(aLineAttr->context()->shape()));
+  if (anExternalAttr && anExternalAttr->value() && anExternalAttr->value()->isEdge()) {
+    anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(anExternalAttr->value()));
+  } else if(anExternalAttr->context() && anExternalAttr->context()->shape() &&
+            anExternalAttr->context()->shape()->isEdge()) {
+    anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(anExternalAttr->context()->shape()));
   }
 
-  if (!anEdge || !anEdge->isLine()) {
-    theError = "The attribute %1 should be a line";
+  if (!anEdge) {
+    theError = "The attribute %1 should be an edge";
     theError.arg(theAttribute->id());
     return false;
   }
 
-  std::shared_ptr<GeomAPI_Dir> aLineDir = anEdge->line()->direction();
-
   // find a sketch
   std::shared_ptr<SketchPlugin_Sketch> aSketch;
-  std::set<AttributePtr> aRefs = aLineAttr->owner()->data()->refsToMe();
+  std::set<AttributePtr> aRefs = anExternalAttr->owner()->data()->refsToMe();
   std::set<AttributePtr>::const_iterator anIt = aRefs.begin();
   for (; anIt != aRefs.end(); ++anIt) {
     CompositeFeaturePtr aComp =
@@ -836,9 +834,16 @@ bool SketchPlugin_IntersectionValidator::isValid(const AttributePtr& theAttribut
     return false;
   }
 
+  // check the edge is intersected with sketch plane
   std::shared_ptr<GeomAPI_Pln> aPlane = aSketch->plane();
-  std::shared_ptr<GeomAPI_Dir> aNormal = aPlane->direction();
-  return fabs(aNormal->dot(aLineDir)) > tolerance * tolerance;
+
+  std::list<GeomPointPtr> anIntersectionsPoints;
+  anEdge->intersectWithPlane(aPlane, anIntersectionsPoints);
+  if (anIntersectionsPoints.empty()) {
+    theError = "The edge is not intersected with sketch plane";
+    return false;
+  }
+  return true;
 }
 
 bool SketchPlugin_SplitValidator::isValid(const AttributePtr& theAttribute,
diff --git a/src/SketchPlugin/Test/TestIntersectionChangeEdge.py b/src/SketchPlugin/Test/TestIntersectionChangeEdge.py
new file mode 100644 (file)
index 0000000..f328df9
--- /dev/null
@@ -0,0 +1,111 @@
+## Copyright (C) 2018-20xx  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<mailto:webmaster.salome@opencascade.com>
+##
+
+"""
+    TestIntersectionChangeEdge.py
+    Unit test of SketchPlugin_IntersectionPoint class
+"""
+
+from SketchAPI import *
+
+from salome.shaper import model
+
+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"))
+SketchArc_1 = Sketch_1.addArc(0, 0, 13.75, -26.66341125962693, -24.98309575119448, 16.60857991180005, False)
+SketchArc_2 = Sketch_1.addArc(0, 0, 53.75, -26.66341125962693, -53.75, -26.66341125962693, False)
+SketchLine_1 = Sketch_1.addLine(13.75, -26.66341125962693, 53.75, -26.66341125962693)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchArc_1.startPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchArc_2.startPoint(), SketchLine_1.endPoint())
+SketchLine_2 = Sketch_1.addLine(-24.98309575119448, 16.60857991180005, -53.75, -26.66341125962693)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchArc_2.endPoint(), SketchLine_2.endPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchArc_2.center(), SketchArc_1.center())
+SketchConstraintTangent_1 = Sketch_1.setTangent(SketchLine_2.result(), SketchArc_1.results()[1])
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_1.result())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchArc_1.results()[1], 30)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchConstraintCoincidence_7 = Sketch_1.setCoincident(SketchArc_2.center(), SketchAPI_Point(SketchPoint_1).coordinates())
+SketchConstraintRadius_2 = Sketch_1.setRadius(SketchArc_2.results()[1], 60)
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_1.result(), 40)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchArc_1_2r-SketchArc_2_2f-SketchLine_1f-SketchLine_2r")], model.selection(), 50, 50)
+Filling_1 = model.addFilling(Part_1_doc, [model.selection("EDGE", "Extrusion_1_1/Generated_Face_4&Extrusion_1_1/From_Face_1"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_3&Extrusion_1_1/To_Face_1")])
+Plane_4 = model.addPlane(Part_1_doc, model.selection("EDGE", "Extrusion_1_1/Generated_Face_4&Extrusion_1_1/To_Face_1"), model.selection("VERTEX", "Extrusion_1_1/Generated_Face_2&Extrusion_1_1/Generated_Face_1&Extrusion_1_1/From_Face_1"), False)
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Plane_1"))
+SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "Sketch_1/Vertex-SketchArc_1-SketchArc_2-SketchProjection_1-SketchPoint_1"), False)
+SketchPoint_2 = SketchProjection_2.createdFeature()
+SketchLine_3 = Sketch_2.addLine(-70, 60, 70, 60)
+SketchLine_4 = Sketch_2.addLine(70, 60, 70, -60)
+SketchLine_5 = Sketch_2.addLine(70, -60, -70, -60)
+SketchLine_6 = Sketch_2.addLine(-70, -60, -70, 60)
+SketchConstraintCoincidence_8 = Sketch_2.setCoincident(SketchLine_6.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_9 = Sketch_2.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintCoincidence_10 = Sketch_2.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchConstraintCoincidence_11 = Sketch_2.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchConstraintHorizontal_2 = Sketch_2.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_1 = Sketch_2.setVertical(SketchLine_4.result())
+SketchConstraintHorizontal_3 = Sketch_2.setHorizontal(SketchLine_5.result())
+SketchConstraintVertical_2 = Sketch_2.setVertical(SketchLine_6.result())
+SketchConstraintDistance_1 = Sketch_2.setDistance(SketchAPI_Point(SketchPoint_2).coordinates(), SketchLine_5.result(), 60, True)
+SketchConstraintDistance_2 = Sketch_2.setDistance(SketchAPI_Point(SketchPoint_2).coordinates(), SketchLine_3.result(), 60, True)
+SketchConstraintDistance_3 = Sketch_2.setDistance(SketchAPI_Point(SketchPoint_2).coordinates(), SketchLine_4.result(), 70, True)
+SketchConstraintDistance_4 = Sketch_2.setDistance(SketchAPI_Point(SketchPoint_2).coordinates(), SketchLine_6.result(), 70, True)
+model.do()
+Face_1 = model.addFace(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_3r-SketchLine_4r-SketchLine_5r-SketchLine_6r")])
+Intersection_1 = model.addIntersection(Part_1_doc, [model.selection("FACE", "Filling_1_1")], [model.selection("FACE", "Face_1_1")])
+
+# set different edges used for intersection and check reference data: number of intersection points and their coordinates
+REF_DATA = [("Sketch_1/Edge-SketchArc_1_2", 1, [[30, 0]]),
+            ("Sketch_1/Edge-SketchLine_2", 1, [[-36.024358588836, 0]]),
+            ("Sketch_1/Edge-SketchArc_2_2", 2, [[60, 0], [-60, 0]]),
+            ("Sketch_1/Edge-SketchLine_1", 0, []),
+            ("Extrusion_1_1/Generated_Face_1&Extrusion_1_1/To_Face_1", 1, [[30, 50]]),
+            ("Extrusion_1_1/Generated_Face_2&Extrusion_1_1/To_Face_1", 1, [[-36.024358588836, 50]]),
+            ("Extrusion_1_1/Generated_Face_3&Extrusion_1_1/To_Face_1", 2, [[60, 50], [-60, 50]]),
+            ("Extrusion_1_1/Generated_Face_4&Extrusion_1_1/To_Face_1", 0, []),
+            ("Intersection_1_1", 2, [[-0.0515933488223, -11.6181750315], [41.6438615258, -11.6181750315]])]
+TOLERANCE = 1.e-7
+
+Sketch_3 = model.addSketch(Part_1_doc, model.defaultPlane("XOZ"))
+SketchIntersectionPoint_1 = Sketch_3.addIntersectionPoint(model.selection("EDGE", "Intersection_1_1"), True)
+model.do()
+
+for ref in REF_DATA:
+    SketchIntersectionPoint_1.setByExternalEdgeName(ref[0])
+    aPoints = SketchIntersectionPoint_1.intersectionPoints()
+    assert(len(aPoints) == ref[1]), "Intersection with edge {} produce {} points, expected {}".format(ref[0], aPoints.size(), ref[1])
+    # check coordinates
+    ind = 0
+    for p in aPoints:
+        pnt = SketchAPI_Point(p)
+        delta = (pnt.coordinates().x() - ref[2][ind][0])**2 + (pnt.coordinates().y() - ref[2][ind][1])**2
+        assert(delta < TOLERANCE * TOLERANCE), "Wrong coordinates of intersection with edge {}: ({}, {}) != expected ({}, {})".format(ref[0], pnt.coordinates().x(), pnt.coordinates().y(), ref[2][ind][0], ref[2][ind][1])
+        ind += 1
+model.do()
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/SketchPlugin/Test/TestIntersectionWithCircle.py b/src/SketchPlugin/Test/TestIntersectionWithCircle.py
new file mode 100644 (file)
index 0000000..47237e8
--- /dev/null
@@ -0,0 +1,158 @@
+## Copyright (C) 2018-20xx  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<mailto:webmaster.salome@opencascade.com>
+##
+
+"""
+    TestIntersectionWithCircle.py
+    Unit test of SketchPlugin_IntersectionPoint class
+"""
+
+from GeomAPI import *
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+ParamD = model.addParameter(Part_1_doc, "D", "12")
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(21.25834261322606, 21.25834261322606, 0, 0)
+SketchLine_2 = Sketch_1.addLine(0, 0, 50, -4.088404617988313e-023)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(50, -4.088404617988313e-023, 50, 50)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchLine_4 = Sketch_1.addLine(50, 50, 28.74165738677394, 28.74165738677394)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchAPI_Point(SketchPoint_1).coordinates())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_2.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_3.result())
+SketchConstraintCollinear_1 = Sketch_1.setCollinear(SketchLine_4.result(), SketchLine_1.result())
+SketchConstraintEqual_1 = Sketch_1.setEqual(SketchLine_2.result(), SketchLine_3.result())
+SketchConstraintEqual_2 = Sketch_1.setEqual(SketchLine_1.result(), SketchLine_4.result())
+SketchArc_1 = Sketch_1.addArc(31, 19, 21.25834261322606, 21.25834261322606, 28.74165738677394, 28.74165738677394, False)
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchArc_1.startPoint())
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchArc_1.endPoint())
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_2.result(), 50)
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchArc_1.results()[1], 10)
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchArc_1.center(), SketchLine_2.result(), 19, True)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1f-SketchLine_2f-SketchLine_3f-SketchLine_4f-SketchArc_1_2r")], model.selection(), 10, 0)
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face_4"), "D", True)
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Plane_1"))
+SketchIntersectionPoint_1 = Sketch_2.addIntersectionPoint(model.selection("EDGE", "Extrusion_1_1/Generated_Face_1&Extrusion_1_1/To_Face_1"), True)
+SketchIntersectionPoint_1.result().setName("SketchIntersectionPoint_1")
+[SketchPoint_2, SketchPoint_3] = SketchIntersectionPoint_1.intersectionPoints()
+SketchCircle_1 = Sketch_2.addCircle(38.14142842854285, 10, 1)
+SketchConstraintCoincidence_7 = Sketch_2.setCoincident(SketchCircle_1.center(), SketchAPI_Point(SketchPoint_2).coordinates())
+SketchConstraintRadius_2 = Sketch_2.setRadius(SketchCircle_1.results()[1], 1)
+SketchLine_5 = Sketch_2.addLine(23.85857157145715, 10.5, 23.85857157145715, 5)
+SketchLine_6 = Sketch_2.addLine(22.85857157145715, 6, 22.85857157145715, 10.5)
+SketchLine_7 = Sketch_2.addLine(22.85857157145715, 10.5, 23.85857157145715, 10.5)
+SketchConstraintCoincidence_8 = Sketch_2.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint())
+SketchConstraintCoincidence_9 = Sketch_2.setCoincident(SketchLine_5.startPoint(), SketchLine_7.endPoint())
+SketchConstraintCoincidence_10 = Sketch_2.setCoincident(SketchAPI_Point(SketchPoint_3).coordinates(), SketchLine_5.result())
+SketchConstraintVertical_2 = Sketch_2.setVertical(SketchLine_5.result())
+SketchConstraintVertical_3 = Sketch_2.setVertical(SketchLine_6.result())
+SketchConstraintHorizontal_2 = Sketch_2.setHorizontal(SketchLine_7.result())
+SketchConstraintDistanceHorizontal_1 = Sketch_2.setHorizontalDistance(SketchLine_6.endPoint(), SketchLine_5.startPoint(), 1)
+SketchConstraintDistanceVertical_1 = Sketch_2.setVerticalDistance(SketchLine_5.startPoint(), SketchAPI_Point(SketchPoint_3).coordinates(), 0.5)
+SketchArc_2 = Sketch_2.addArc(23.85857157145715, 6, 23.85857157145715, 5, 22.85857157145715, 6, True)
+SketchConstraintCoincidence_11 = Sketch_2.setCoincident(SketchLine_5.result(), SketchArc_2.center())
+SketchConstraintCoincidence_12 = Sketch_2.setCoincident(SketchLine_5.endPoint(), SketchArc_2.startPoint())
+SketchConstraintCoincidence_13 = Sketch_2.setCoincident(SketchArc_2.endPoint(), SketchLine_6.startPoint())
+SketchConstraintDistanceVertical_2 = Sketch_2.setVerticalDistance(SketchAPI_Point(SketchPoint_3).coordinates(), SketchArc_2.startPoint(), 5)
+SketchConstraintTangent_1 = Sketch_2.setTangent(SketchArc_2.results()[1], SketchLine_6.result())
+model.do()
+RevolutionCut_1 = model.addRevolutionCut(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_5r-SketchLine_6r-SketchLine_7r-SketchArc_2_2f")], model.selection("EDGE", "Sketch_2/Edge-SketchLine_5"), 360, 0, [model.selection("SOLID", "Extrusion_1_1")])
+ExtrusionCut_1 = model.addExtrusionCut(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchCircle_1_2f")], model.selection(), 5, 5, [model.selection("SOLID", "RevolutionCut_1_1")])
+model.do()
+
+assert(SketchIntersectionPoint_1.feature().results().size() == 2)
+
+model.testNbResults(ExtrusionCut_1, 1)
+model.testNbSubResults(ExtrusionCut_1, [0])
+model.testNbSubShapes(ExtrusionCut_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(ExtrusionCut_1, GeomAPI_Shape.FACE, [13])
+model.testNbSubShapes(ExtrusionCut_1, GeomAPI_Shape.EDGE, [66])
+model.testNbSubShapes(ExtrusionCut_1, GeomAPI_Shape.VERTEX, [132])
+model.testResultsVolumes(ExtrusionCut_1, [9451.611727849665840039961040020])
+
+# change parameter and check intersection validity
+ParamD.setValue(15)
+model.do();
+
+assert(SketchIntersectionPoint_1.feature().results().size() == 2)
+
+model.testNbResults(ExtrusionCut_1, 1)
+model.testNbSubResults(ExtrusionCut_1, [0])
+model.testNbSubShapes(ExtrusionCut_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(ExtrusionCut_1, GeomAPI_Shape.FACE, [14])
+model.testNbSubShapes(ExtrusionCut_1, GeomAPI_Shape.EDGE, [74])
+model.testNbSubShapes(ExtrusionCut_1, GeomAPI_Shape.VERTEX, [148])
+model.testResultsVolumes(ExtrusionCut_1, [9451.152473626798382611013948917])
+
+# change parameter and check intersection validity
+ParamD.setValue(19)
+model.do();
+
+assert(SketchIntersectionPoint_1.feature().results().size() == 2)
+
+model.testNbResults(ExtrusionCut_1, 1)
+model.testNbSubResults(ExtrusionCut_1, [0])
+model.testNbSubShapes(ExtrusionCut_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(ExtrusionCut_1, GeomAPI_Shape.FACE, [14])
+model.testNbSubShapes(ExtrusionCut_1, GeomAPI_Shape.EDGE, [74])
+model.testNbSubShapes(ExtrusionCut_1, GeomAPI_Shape.VERTEX, [148])
+model.testResultsVolumes(ExtrusionCut_1, [9448.046243665688962209969758987])
+
+# change parameter and check intersection validity
+ParamD.setValue(23)
+model.do();
+
+assert(SketchIntersectionPoint_1.feature().results().size() == 1)
+
+model.testNbResults(ExtrusionCut_1, 1)
+model.testNbSubResults(ExtrusionCut_1, [0])
+model.testNbSubShapes(ExtrusionCut_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(ExtrusionCut_1, GeomAPI_Shape.FACE, [10])
+model.testNbSubShapes(ExtrusionCut_1, GeomAPI_Shape.EDGE, [50])
+model.testNbSubShapes(ExtrusionCut_1, GeomAPI_Shape.VERTEX, [100])
+model.testResultsVolumes(ExtrusionCut_1, [9458.635858820198336616158485413])
+
+# change parameter and check intersection validity
+ParamD.setValue(29)
+model.do();
+
+assert(SketchIntersectionPoint_1.feature().results().size() == 1)
+
+model.testNbResults(ExtrusionCut_1, 1)
+model.testNbSubResults(ExtrusionCut_1, [0])
+model.testNbSubShapes(ExtrusionCut_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(ExtrusionCut_1, GeomAPI_Shape.FACE, [9])
+model.testNbSubShapes(ExtrusionCut_1, GeomAPI_Shape.EDGE, [42])
+model.testNbSubShapes(ExtrusionCut_1, GeomAPI_Shape.VERTEX, [84])
+model.testResultsVolumes(ExtrusionCut_1, [9463.846034357124153757467865944])
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/SketchPlugin/Test/TestIntersectionWithLine.py b/src/SketchPlugin/Test/TestIntersectionWithLine.py
new file mode 100644 (file)
index 0000000..a6b163c
--- /dev/null
@@ -0,0 +1,130 @@
+## Copyright (C) 2018-20xx  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<mailto:webmaster.salome@opencascade.com>
+##
+
+"""
+    TestIntersectionWithLine.py
+    Unit test of SketchPlugin_IntersectionPoint class
+"""
+
+from GeomAPI import *
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+ParamD = model.addParameter(Part_1_doc, "D", "40")
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(0, 0, 50, 0)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchPoint_1.result())
+SketchLine_2 = Sketch_1.addLine(50, 0, 50, 10)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(50, 10, 40, 10)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchLine_4 = Sketch_1.addLine(40, 10, 40, 30)
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchLine_5 = Sketch_1.addLine(40, 30, 50, 30)
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchLine_6 = Sketch_1.addLine(50, 30, 50, 40)
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchLine_7 = Sketch_1.addLine(50, 40, 0, 50)
+SketchConstraintCoincidence_7 = Sketch_1.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint())
+SketchLine_8 = Sketch_1.addLine(0, 50, 0, 0)
+SketchConstraintCoincidence_8 = Sketch_1.setCoincident(SketchLine_7.endPoint(), SketchLine_8.startPoint())
+SketchConstraintCoincidence_9 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_8.endPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchConstraintHorizontal_3 = Sketch_1.setHorizontal(SketchLine_5.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result())
+SketchConstraintVertical_3 = Sketch_1.setVertical(SketchLine_8.result())
+SketchConstraintCollinear_1 = Sketch_1.setCollinear(SketchLine_2.result(), SketchLine_6.result())
+SketchConstraintEqual_1 = Sketch_1.setEqual(SketchLine_2.result(), SketchLine_6.result())
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_1.result(), 50)
+SketchConstraintLength_2 = Sketch_1.setLength(SketchLine_8.result(), 50)
+SketchConstraintLength_3 = Sketch_1.setLength(SketchLine_2.result(), 10)
+SketchConstraintDistanceHorizontal_1 = Sketch_1.setHorizontalDistance(SketchLine_1.startPoint(), SketchLine_4.startPoint(), "D")
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchLine_1.endPoint(), SketchLine_7.startPoint(), 40, True)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1f-SketchLine_2f-SketchLine_3f-SketchLine_4f-SketchLine_5f-SketchLine_6f-SketchLine_7f-SketchLine_8f")], model.selection(), 10, 0)
+ExtrusionCut_1 = model.addExtrusionCut(Part_1_doc, [], model.selection(), 5, 5, [model.selection("SOLID", "Extrusion_1_1")])
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face_5"))
+SketchIntersectionPoint_1 = Sketch_2.addIntersectionPoint(model.selection("EDGE", "Extrusion_1_1/Generated_Face_2&Extrusion_1_1/To_Face_1"))
+[SketchPoint_2] = SketchIntersectionPoint_1.intersectionPoints()
+SketchCircle_1 = Sketch_2.addCircle(40, 10, 5)
+SketchConstraintCoincidence_10 = Sketch_2.setCoincident(SketchAPI_Point(SketchPoint_2).coordinates(), SketchCircle_1.center())
+SketchConstraintRadius_1 = Sketch_2.setRadius(SketchCircle_1.results()[1], 5)
+ExtrusionCut_1.setNestedSketch(Sketch_2)
+model.do()
+
+assert(SketchIntersectionPoint_1.feature().results().empty() == False)
+
+model.testNbResults(ExtrusionCut_1, 1)
+model.testNbSubResults(ExtrusionCut_1, [0])
+model.testNbSubShapes(ExtrusionCut_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(ExtrusionCut_1, GeomAPI_Shape.FACE, [13])
+model.testNbSubShapes(ExtrusionCut_1, GeomAPI_Shape.EDGE, [66])
+model.testNbSubShapes(ExtrusionCut_1, GeomAPI_Shape.VERTEX, [132])
+model.testResultsVolumes(ExtrusionCut_1, [20303.650459150881943060085177422])
+
+# change parameter and check intersection validity
+ParamD.setValue(35)
+model.do();
+
+assert(SketchIntersectionPoint_1.feature().results().empty() == False)
+
+model.testNbResults(ExtrusionCut_1, 1)
+model.testNbSubResults(ExtrusionCut_1, [0])
+model.testNbSubShapes(ExtrusionCut_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(ExtrusionCut_1, GeomAPI_Shape.FACE, [13])
+model.testNbSubShapes(ExtrusionCut_1, GeomAPI_Shape.EDGE, [66])
+model.testNbSubShapes(ExtrusionCut_1, GeomAPI_Shape.VERTEX, [132])
+model.testResultsVolumes(ExtrusionCut_1, [19303.650459150881943060085177422])
+
+# change parameter and check the intersection is not valid now
+ParamD.setValue(60)
+model.do();
+assert(SketchIntersectionPoint_1.feature().results().empty() == True)
+
+# change parameter to initial value and check intersection validity
+ParamD.setValue(40)
+model.do();
+# coincidence of circle center and intersection point is lost on previous step, restore it
+[SketchPoint_2] = SketchIntersectionPoint_1.intersectionPoints()
+Sketch_2.setCoincident(SketchAPI_Point(SketchPoint_2).coordinates(), SketchCircle_1.center())
+model.do()
+
+assert(SketchIntersectionPoint_1.feature().results().empty() == False)
+
+model.testNbResults(ExtrusionCut_1, 1)
+model.testNbSubResults(ExtrusionCut_1, [0])
+model.testNbSubShapes(ExtrusionCut_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(ExtrusionCut_1, GeomAPI_Shape.FACE, [13])
+model.testNbSubShapes(ExtrusionCut_1, GeomAPI_Shape.EDGE, [66])
+model.testNbSubShapes(ExtrusionCut_1, GeomAPI_Shape.VERTEX, [132])
+model.testResultsVolumes(ExtrusionCut_1, [20303.650459150881943060085177422])
+
+model.end()
+
+assert(model.checkPythonDump())
diff --git a/src/SketchPlugin/Test/TestIntersectionWithSpline.py b/src/SketchPlugin/Test/TestIntersectionWithSpline.py
new file mode 100644 (file)
index 0000000..9fffb54
--- /dev/null
@@ -0,0 +1,151 @@
+## Copyright (C) 2018-20xx  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<mailto:webmaster.salome@opencascade.com>
+##
+
+"""
+    TestIntersectionWithSpline.py
+    Unit test of SketchPlugin_IntersectionPoint class
+"""
+
+from GeomAPI import *
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+ParamD = model.addParameter(Part_1_doc, "D", "5")
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchArc_1 = Sketch_1.addArc(-20, 0, -12.51615726667241, -49.43674845641531, -67.51615726667241, 15.56325154358469, False)
+SketchLine_1 = Sketch_1.addLine(-67.51615726667241, 15.56325154358469, -12.51615726667241, 15.56325154358469)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchLine_1.startPoint())
+SketchLine_2 = Sketch_1.addLine(-12.51615726667241, 15.56325154358469, -12.51615726667241, -49.43674845641531)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchArc_1.startPoint(), SketchLine_2.endPoint())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchProjection_1 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OX"), False)
+SketchLine_3 = SketchProjection_1.createdFeature()
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchArc_1.center(), SketchLine_3.result())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchArc_1.results()[1], 50)
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_2.result(), 65)
+SketchConstraintDistanceHorizontal_1 = Sketch_1.setHorizontalDistance(SketchArc_1.center(), SketchAPI_Line(SketchLine_3).startPoint(), 20)
+SketchConstraintLength_2 = Sketch_1.setLength(SketchLine_1.result(), 55)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchArc_1_2f-SketchLine_1f-SketchLine_2f")], model.selection(), 25, 25)
+Filling_1 = model.addFilling(Part_1_doc, [model.selection("EDGE", "Extrusion_1_1/Generated_Face_1&Extrusion_1_1/From_Face_1"), model.selection("EDGE", "Extrusion_1_1/Generated_Face_3&Extrusion_1_1/To_Face_1")])
+Face_1 = model.addFace(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchArc_1_2f-SketchLine_1f-SketchLine_2f")])
+Intersection_1 = model.addIntersection(Part_1_doc, [model.selection("FACE", "Filling_1_1")], [model.selection("FACE", "Face_1_1")])
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_4 = Sketch_2.addLine(-34.11217447219568, 40, 20, -37.28019411294778)
+SketchLine_5 = Sketch_2.addLine(20, -37.28019411294778, 20, 40)
+SketchConstraintCoincidence_5 = Sketch_2.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchLine_6 = Sketch_2.addLine(20, 40, -34.11217447219568, 40)
+SketchConstraintCoincidence_6 = Sketch_2.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchConstraintCoincidence_7 = Sketch_2.setCoincident(SketchLine_4.startPoint(), SketchLine_6.endPoint())
+SketchConstraintVertical_2 = Sketch_2.setVertical(SketchLine_5.result())
+SketchConstraintHorizontal_2 = Sketch_2.setHorizontal(SketchLine_6.result())
+SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_2.createdFeature()
+SketchConstraintDistance_1 = Sketch_2.setDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_5.result(), 20, True)
+SketchConstraintDistance_2 = Sketch_2.setDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_6.result(), 40, True)
+SketchConstraintDistance_3 = Sketch_2.setDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_4.result(), "D", True)
+SketchConstraintAngle_1 = Sketch_2.setAngle(SketchLine_5.result(), SketchLine_4.result(), 35)
+model.do()
+Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_4f-SketchLine_5f-SketchLine_6f")], model.selection(), 10, 10)
+ExtrusionFuse_1 = model.addExtrusionFuse(Part_1_doc, [], model.selection(), 10, 0, [model.selection("SOLID", "Extrusion_2_1")])
+Sketch_3 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_2_1/Generated_Face_3"))
+SketchIntersectionPoint_1 = Sketch_3.addIntersectionPoint(model.selection("EDGE", "Intersection_1_1"), False)
+[SketchPoint_2, SketchPoint_3] = SketchIntersectionPoint_1.intersectionPoints()
+SketchCircle_1 = Sketch_3.addCircle(-33.22640570408476, 0, 5)
+SketchConstraintCoincidence_8 = Sketch_3.setCoincident(SketchCircle_1.center(), SketchAPI_Point(SketchPoint_2).coordinates())
+SketchCircle_2 = Sketch_3.addCircle(21.47998214403209, 0, 5)
+SketchConstraintCoincidence_9 = Sketch_3.setCoincident(SketchCircle_2.center(), SketchAPI_Point(SketchPoint_3).coordinates())
+SketchConstraintEqual_1 = Sketch_3.setEqual(SketchCircle_1.results()[1], SketchCircle_2.results()[1])
+SketchConstraintRadius_2 = Sketch_3.setRadius(SketchCircle_1.results()[1], 5)
+ExtrusionFuse_1.setNestedSketch(Sketch_3)
+model.do()
+
+assert(SketchIntersectionPoint_1.feature().results().size() == 2)
+
+model.testNbResults(ExtrusionFuse_1, 1)
+model.testNbSubResults(ExtrusionFuse_1, [0])
+model.testNbSubShapes(ExtrusionFuse_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(ExtrusionFuse_1, GeomAPI_Shape.FACE, [9])
+model.testNbSubShapes(ExtrusionFuse_1, GeomAPI_Shape.EDGE, [30])
+model.testNbSubShapes(ExtrusionFuse_1, GeomAPI_Shape.VERTEX, [60])
+model.testResultsVolumes(ExtrusionFuse_1, [43388.789797644698410294950008392])
+
+# change parameter and check intersection validity
+ParamD.setValue(15)
+model.do();
+
+assert(SketchIntersectionPoint_1.feature().results().size() == 2)
+
+model.testNbResults(ExtrusionFuse_1, 1)
+model.testNbSubResults(ExtrusionFuse_1, [0])
+model.testNbSubShapes(ExtrusionFuse_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(ExtrusionFuse_1, GeomAPI_Shape.FACE, [9])
+model.testNbSubShapes(ExtrusionFuse_1, GeomAPI_Shape.EDGE, [30])
+model.testNbSubShapes(ExtrusionFuse_1, GeomAPI_Shape.VERTEX, [60])
+model.testResultsVolumes(ExtrusionFuse_1, [64385.484780074148147832602262497])
+
+# change parameter and check single intersection
+ParamD.setValue(25)
+model.do();
+
+assert(SketchIntersectionPoint_1.feature().results().size() == 1)
+
+model.testNbResults(ExtrusionFuse_1, 1)
+model.testNbSubResults(ExtrusionFuse_1, [1])
+model.testNbSubShapes(ExtrusionFuse_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(ExtrusionFuse_1, GeomAPI_Shape.FACE, [11])
+model.testNbSubShapes(ExtrusionFuse_1, GeomAPI_Shape.EDGE, [42])
+model.testNbSubShapes(ExtrusionFuse_1, GeomAPI_Shape.VERTEX, [84])
+model.testResultsVolumes(ExtrusionFuse_1, [89224.362837261898675933480262756])
+
+# change parameter and check intersection is NOT valid now
+ParamD.setValue(50)
+model.do();
+
+assert(SketchIntersectionPoint_1.feature().results().empty())
+
+# revert parameter to original value and reset coincidences
+ParamD.setValue(5)
+model.do()
+[SketchPoint_2, SketchPoint_3] = SketchIntersectionPoint_1.intersectionPoints()
+SketchConstraintCoincidence_8 = Sketch_3.setCoincident(SketchCircle_1.center(), SketchAPI_Point(SketchPoint_2).coordinates())
+SketchConstraintCoincidence_9 = Sketch_3.setCoincident(SketchCircle_2.center(), SketchAPI_Point(SketchPoint_3).coordinates())
+model.do()
+
+assert(SketchIntersectionPoint_1.feature().results().size() == 2)
+
+model.testNbResults(ExtrusionFuse_1, 1)
+model.testNbSubResults(ExtrusionFuse_1, [0])
+model.testNbSubShapes(ExtrusionFuse_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(ExtrusionFuse_1, GeomAPI_Shape.FACE, [9])
+model.testNbSubShapes(ExtrusionFuse_1, GeomAPI_Shape.EDGE, [30])
+model.testNbSubShapes(ExtrusionFuse_1, GeomAPI_Shape.VERTEX, [60])
+model.testResultsVolumes(ExtrusionFuse_1, [43388.789797644698410294950008392])
+
+model.end()
+
+assert(model.checkPythonDump())