Salome HOME
Change icons for chamfer
[modules/shaper.git] / src / SketchPlugin / SketchPlugin_Tools.cpp
index 8a119c199dfd39797a52e233c3a2cbb75e4e765c..4f55be24d485ffb1d9997890f99f5da42e708fcd 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+// Copyright (C) 2014-2019  CEA/DEN, EDF R&D
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
 //
 // You should have received a copy of the GNU Lesser General Public
 // License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 //
-// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
 
 #include "SketchPlugin_Tools.h"
 
 #include "SketchPlugin_ConstraintCoincidence.h"
+#include "SketchPlugin_ConstraintLength.h"
 #include "SketchPlugin_ConstraintTangent.h"
+#include "SketchPlugin_Line.h"
 #include "SketchPlugin_Point.h"
 #include "SketchPlugin_SketchEntity.h"
 
 
 #include <ModelAPI_AttributeDouble.h>
 
+#include <GeomAPI_Dir2d.h>
+#include <GeomAPI_Pnt2d.h>
+#include <GeomAPI_XY.h>
+
 #include <GeomDataAPI_Point.h>
 #include <GeomDataAPI_Point2D.h>
 
+#ifdef DEBUG_TRIM
+#include <iostream>
+#endif
+
 namespace SketchPlugin_Tools {
 
 void clearExpressions(AttributeDoublePtr theAttribute)
@@ -95,7 +105,7 @@ std::set<FeaturePtr> findCoincidentConstraints(const FeaturePtr& theFeature)
   std::set<AttributePtr>::const_iterator aIt;
   for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
     FeaturePtr aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>((*aIt)->owner());
-    if (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID())
+    if (aConstrFeature && aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID())
       aCoincident.insert(aConstrFeature);
   }
   return aCoincident;
@@ -103,7 +113,8 @@ std::set<FeaturePtr> findCoincidentConstraints(const FeaturePtr& theFeature)
 
 void findCoincidences(const FeaturePtr theStartCoin,
                       const std::string& theAttr,
-                      std::set<FeaturePtr>& theList)
+                      std::set<FeaturePtr>& theList,
+                      const bool theIsAttrOnly)
 {
   AttributeRefAttrPtr aPnt = theStartCoin->refattr(theAttr);
   if(!aPnt) {
@@ -115,15 +126,19 @@ void findCoincidences(const FeaturePtr theStartCoin,
     if(aOrig.get() == NULL) {
       return;
     }
-    theList.insert(aObj);
+    if(!theIsAttrOnly || !aPnt->isObject()) {
+      theList.insert(aObj);
+    }
     std::set<FeaturePtr> aCoincidences = findCoincidentConstraints(aObj);
     std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
     for (; aCIt != aCoincidences.end(); ++aCIt) {
       FeaturePtr aConstrFeature = *aCIt;
       std::shared_ptr<GeomAPI_Pnt2d> aPnt = getCoincidencePoint(aConstrFeature);
       if(aPnt.get() && aOrig->isEqual(aPnt)) {
-        findCoincidences(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_A(), theList);
-        findCoincidences(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_B(), theList);
+        findCoincidences(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_A(),
+                         theList, theIsAttrOnly);
+        findCoincidences(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_B(),
+                         theList, theIsAttrOnly);
       }
     }
   }
@@ -175,11 +190,14 @@ public:
     std::list< std::set<AttributePoint2DPtr> >::iterator aFound1 = find(thePoint1);
     std::list< std::set<AttributePoint2DPtr> >::iterator aFound2 = find(thePoint2);
     if (aFound1 == myCoincidentPoints.end()) {
-      std::set<AttributePoint2DPtr> aNewSet;
-      aNewSet.insert(thePoint1);
-      if (thePoint2)
-        aNewSet.insert(thePoint2);
-      myCoincidentPoints.push_back(aNewSet);
+      if (aFound2 == myCoincidentPoints.end()) {
+        std::set<AttributePoint2DPtr> aNewSet;
+        aNewSet.insert(thePoint1);
+        if (thePoint2)
+          aNewSet.insert(thePoint2);
+        myCoincidentPoints.push_back(aNewSet);
+      } else
+        aFound2->insert(thePoint1);
     } else if (aFound2 == myCoincidentPoints.end()) {
       if (thePoint2)
         aFound1->insert(thePoint2);
@@ -191,6 +209,8 @@ public:
 
   std::set<AttributePoint2DPtr> coincidentPoints(const AttributePoint2DPtr& thePoint)
   {
+    collectCoincidentPoints(thePoint);
+
     std::list< std::set<AttributePoint2DPtr> >::iterator aFound = find(thePoint);
     if (aFound == myCoincidentPoints.end())
       return std::set<AttributePoint2DPtr>();
@@ -198,6 +218,55 @@ public:
   }
 
 private:
+  void coincidences(const FeaturePtr& theFeature,
+                    std::set<FeaturePtr>& theCoincidences) const
+  {
+    // iterate through coincideces for the given feature
+    std::set<FeaturePtr> aCoincidences = SketchPlugin_Tools::findCoincidentConstraints(theFeature);
+    std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
+    for (; aCIt != aCoincidences.end(); ++aCIt)
+    {
+      if (theCoincidences.find(*aCIt) != theCoincidences.end())
+        continue; // already processed
+      theCoincidences.insert(*aCIt);
+      // iterate on coincident attributes
+      for (int i = 0, aPtInd = 0; i < CONSTRAINT_ATTR_SIZE; ++i) {
+        AttributeRefAttrPtr aRefAttr = (*aCIt)->refattr(SketchPlugin_Constraint::ATTRIBUTE(i));
+        if (aRefAttr && !aRefAttr->isObject())
+        {
+          FeaturePtr anOwner = ModelAPI_Feature::feature(aRefAttr->attr()->owner());
+          if (anOwner != theFeature)
+            coincidences(anOwner, theCoincidences);
+        }
+      }
+    }
+  }
+
+  // Iteratively search points coincident to the given point
+  // (two points may be coincident through the third point)
+  void collectCoincidentPoints(const AttributePoint2DPtr& thePoint)
+  {
+    AttributePoint2DPtr aPoints[2];
+
+    FeaturePtr anOwner = ModelAPI_Feature::feature(thePoint->owner());
+    std::set<FeaturePtr> aCoincidences;
+    coincidences(anOwner, aCoincidences);
+
+    std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
+    for (; aCIt != aCoincidences.end(); ++aCIt) {
+      aPoints[0] = AttributePoint2DPtr();
+      aPoints[1] = AttributePoint2DPtr();
+      for (int i = 0, aPtInd = 0; i < CONSTRAINT_ATTR_SIZE; ++i) {
+        AttributeRefAttrPtr aRefAttr = (*aCIt)->refattr(SketchPlugin_Constraint::ATTRIBUTE(i));
+        if (aRefAttr && !aRefAttr->isObject())
+          aPoints[aPtInd++] = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aRefAttr->attr());
+      }
+
+      if (aPoints[0] && aPoints[1])
+        addCoincidence(aPoints[0], aPoints[1]);
+    }
+  }
+
   std::list< std::set<AttributePoint2DPtr> >::iterator find(const AttributePoint2DPtr& thePoint)
   {
     std::list< std::set<AttributePoint2DPtr> >::iterator aSeek = myCoincidentPoints.begin();
@@ -214,26 +283,6 @@ private:
 std::set<AttributePoint2DPtr> findPointsCoincidentToPoint(const AttributePoint2DPtr& thePoint)
 {
   CoincidentPoints aCoincidentPoints;
-  AttributePoint2DPtr aPoints[2];
-
-  FeaturePtr anOwner = ModelAPI_Feature::feature(thePoint->owner());
-  std::set<FeaturePtr> aCoincidences = findCoincidentConstraints(anOwner);
-  std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
-  for (; aCIt != aCoincidences.end(); ++aCIt) {
-    aPoints[0] = AttributePoint2DPtr();
-    aPoints[1] = AttributePoint2DPtr();
-    for (int i = 0, aPtInd = 0; i < CONSTRAINT_ATTR_SIZE; ++i) {
-      AttributeRefAttrPtr aRefAttr = (*aCIt)->refattr(SketchPlugin_Constraint::ATTRIBUTE(i));
-      if (!aRefAttr)
-        continue;
-      if (!aRefAttr->isObject())
-        aPoints[aPtInd++] = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aRefAttr->attr());
-    }
-
-    if (aPoints[0])
-      aCoincidentPoints.addCoincidence(aPoints[0], aPoints[1]);
-  }
-
   return aCoincidentPoints.coincidentPoints(thePoint);
 }
 
@@ -246,11 +295,11 @@ void resetAttribute(SketchPlugin_Feature* theFeature,
   }
 }
 
-void createConstraint(SketchPlugin_Feature* theFeature,
-                      const std::string& theId,
-                      const AttributePtr theAttr,
-                      const ObjectPtr theObject,
-                      const bool theIsCanBeTangent)
+void createCoincidenceOrTangency(SketchPlugin_Feature* theFeature,
+                                 const std::string& theId,
+                                 const AttributePtr theAttr,
+                                 const ObjectPtr theObject,
+                                 const bool theIsCanBeTangent)
 {
   AttributeRefAttrPtr aRefAttr = theFeature->refattr(theId);
   if(aRefAttr.get() && aRefAttr->isInitialized()) {
@@ -307,4 +356,108 @@ void convertRefAttrToPointOrTangentCurve(const AttributeRefAttrPtr&      theRefA
   thePassingPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr)->pnt();
 }
 
+
+FeaturePtr createConstraintAttrAttr(SketchPlugin_Sketch* theSketch,
+                                    const std::string& theConstraintId,
+                                    const AttributePtr& theFirstAttribute,
+                                    const AttributePtr& theSecondAttribute)
+{
+  FeaturePtr aConstraint = theSketch->addFeature(theConstraintId);
+  AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+                                 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
+  aRefAttr->setAttr(theFirstAttribute);
+
+  aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+                                 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
+  aRefAttr->setAttr(theSecondAttribute);
+
+#if defined(DEBUG_TRIM) || defined(DEBUG_SPLIT)
+  std::cout << "<createConstraint to attribute> :"
+            << " first attribute - " << theFirstAttribute->id()
+            << " second attribute - " << theSecondAttribute->id()
+            << std::endl;
+#endif
+
+  return aConstraint;
+}
+
+FeaturePtr createConstraintAttrObject(SketchPlugin_Sketch* theSketch,
+                                      const std::string& theConstraintId,
+                                      const AttributePtr& theFirstAttribute,
+                                      const ObjectPtr& theSecondObject)
+{
+  FeaturePtr aConstraint = theSketch->addFeature(theConstraintId);
+  AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+                                 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
+  aRefAttr->setAttr(theFirstAttribute);
+
+  aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+                                 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
+  aRefAttr->setObject(theSecondObject);
+
+#if defined(DEBUG_TRIM) || defined(DEBUG_SPLIT)
+  std::cout << "<createConstraint to attribute> :"
+            << " first attribute - " << theFirstAttribute->id()
+            << " second object - " << ModelAPI_Feature::feature(theSecondObject)->getKind()
+            << std::endl;
+#endif
+
+  return aConstraint;
+}
+
+FeaturePtr createConstraintObjectObject(SketchPlugin_Sketch* theSketch,
+                                        const std::string& theConstraintId,
+                                        const ObjectPtr& theFirstObject,
+                                        const ObjectPtr& theSecondObject)
+{
+  FeaturePtr aConstraint = theSketch->addFeature(theConstraintId);
+  AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+                                 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
+  aRefAttr->setObject(theFirstObject);
+
+  aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+                                 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
+  aRefAttr->setObject(theSecondObject);
+
+#if defined(DEBUG_TRIM) || defined(DEBUG_SPLIT)
+  std::cout << "<createConstraint to attribute> :"
+            << " first object - " << ModelAPI_Feature::feature(theFirstObject)->getKind()
+            << " second object - " << ModelAPI_Feature::feature(theSecondObject)->getKind()
+            << std::endl;
+#endif
+
+  return aConstraint;
+}
+
+GeomPnt2dPtr flyoutPointCoordinates(const ConstraintPtr& theConstraint)
+{
+  // currently process Length constraints only
+  if (theConstraint->getKind() != SketchPlugin_ConstraintLength::ID())
+    return GeomPnt2dPtr();
+
+  AttributeRefAttrPtr aLineAttr = theConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
+  if (!aLineAttr || !aLineAttr->isObject())
+    return GeomPnt2dPtr();
+  FeaturePtr aLine = ModelAPI_Feature::feature(aLineAttr->object());
+  if (!aLine || aLine->getKind() != SketchPlugin_Line::ID())
+    return GeomPnt2dPtr();
+
+  std::shared_ptr<GeomAPI_XY> aStartPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+      aLine->attribute(SketchPlugin_Line::START_ID()))->pnt()->xy();
+  std::shared_ptr<GeomAPI_XY> aEndPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+      aLine->attribute(SketchPlugin_Line::END_ID()))->pnt()->xy();
+
+  std::shared_ptr<GeomDataAPI_Point2D> aFlyoutAttr =
+      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+      theConstraint->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()));
+  std::shared_ptr<GeomAPI_Pnt2d> aFltPnt = aFlyoutAttr->pnt();
+
+  std::shared_ptr<GeomAPI_Dir2d> aLineDir(new GeomAPI_Dir2d(aEndPnt->decreased(aStartPnt)));
+
+  double X = aStartPnt->x() + aFltPnt->x() * aLineDir->x() - aFltPnt->y() * aLineDir->y();
+  double Y = aStartPnt->y() + aFltPnt->x() * aLineDir->y() + aFltPnt->y() * aLineDir->x();
+
+  return GeomPnt2dPtr(new GeomAPI_Pnt2d(X, Y));
+}
+
 } // namespace SketchPlugin_Tools