Salome HOME
FIx for the issue #2399 : optimization of the Intersection feature results (better...
[modules/shaper.git] / src / SketchPlugin / SketchPlugin_Tools.cpp
index 7af4e9af143df71707fe878f76cca26b35123b27..d0c13c069755c25c0da3ddd7a209373cad34b87d 100644 (file)
@@ -1,8 +1,22 @@
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
-
-// File:        SketchPlugin_Tools.cpp
-// Created:     07 July 2015
-// Author:      Sergey POKHODENKO
+// Copyright (C) 2014-2017  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>
+//
 
 #include "SketchPlugin_Tools.h"
 
 #include <GeomDataAPI_Point.h>
 #include <GeomDataAPI_Point2D.h>
 
+#ifdef DEBUG_TRIM
+#include <iostream>
+#endif
+
 namespace SketchPlugin_Tools {
 
 void clearExpressions(AttributeDoublePtr theAttribute)
@@ -75,9 +93,23 @@ std::shared_ptr<GeomAPI_Pnt2d> getCoincidencePoint(const FeaturePtr theStartCoin
   return aPnt;
 }
 
+std::set<FeaturePtr> findCoincidentConstraints(const FeaturePtr& theFeature)
+{
+  std::set<FeaturePtr> aCoincident;
+  const std::set<AttributePtr>& aRefsList = theFeature->data()->refsToMe();
+  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())
+      aCoincident.insert(aConstrFeature);
+  }
+  return aCoincident;
+}
+
 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) {
@@ -89,28 +121,146 @@ void findCoincidences(const FeaturePtr theStartCoin,
     if(aOrig.get() == NULL) {
       return;
     }
-    theList.insert(aObj);
-    const std::set<AttributePtr>& aRefsList = aObj->data()->refsToMe();
-    std::set<AttributePtr>::const_iterator aIt;
-    for(aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
-      std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
-      FeaturePtr aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
-      if(aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
-        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);
-        }
+    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, theIsAttrOnly);
+        findCoincidences(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_B(),
+                         theList, theIsAttrOnly);
       }
     }
   }
 }
 
-void createConstraint(SketchPlugin_Feature* theFeature,
-                      const std::string& theId,
-                      const AttributePtr theAttr,
-                      const ObjectPtr theObject,
-                      const bool theIsCanBeTangent)
+std::set<FeaturePtr> findFeaturesCoincidentToPoint(const AttributePoint2DPtr& thePoint)
+{
+  std::set<FeaturePtr> aCoincidentFeatures;
+
+  FeaturePtr anOwner = ModelAPI_Feature::feature(thePoint->owner());
+  aCoincidentFeatures.insert(anOwner);
+
+  std::set<FeaturePtr> aCoincidences = findCoincidentConstraints(anOwner);
+  std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
+  for (; aCIt != aCoincidences.end(); ++aCIt) {
+    bool isPointUsedInCoincidence = false;
+    AttributeRefAttrPtr anOtherCoincidentAttr;
+    for (int i = 0; i < CONSTRAINT_ATTR_SIZE; ++i) {
+      AttributeRefAttrPtr aRefAttr = (*aCIt)->refattr(SketchPlugin_Constraint::ATTRIBUTE(i));
+      if (!aRefAttr)
+        continue;
+      if (!aRefAttr->isObject() && aRefAttr->attr() == thePoint)
+        isPointUsedInCoincidence = true;
+      else
+        anOtherCoincidentAttr = aRefAttr;
+    }
+
+    if (isPointUsedInCoincidence) {
+      ObjectPtr anObj;
+      if (anOtherCoincidentAttr->isObject())
+        anObj = anOtherCoincidentAttr->object();
+      else
+        anObj = anOtherCoincidentAttr->attr()->owner();
+      aCoincidentFeatures.insert(ModelAPI_Feature::feature(anObj));
+    }
+  }
+
+  return aCoincidentFeatures;
+}
+
+// Container for point-point coincidences.
+// Useful to find points coincident to a given point.
+class CoincidentPoints
+{
+public:
+  void addCoincidence(const AttributePoint2DPtr& thePoint1,
+                      const AttributePoint2DPtr& thePoint2 = AttributePoint2DPtr())
+  {
+    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);
+    } else if (aFound2 == myCoincidentPoints.end()) {
+      if (thePoint2)
+        aFound1->insert(thePoint2);
+    } else {
+      aFound1->insert(aFound2->begin(), aFound2->end());
+      myCoincidentPoints.erase(aFound2);
+    }
+  }
+
+  std::set<AttributePoint2DPtr> coincidentPoints(const AttributePoint2DPtr& thePoint)
+  {
+    std::list< std::set<AttributePoint2DPtr> >::iterator aFound = find(thePoint);
+    if (aFound == myCoincidentPoints.end())
+      return std::set<AttributePoint2DPtr>();
+    return *aFound;
+  }
+
+private:
+  std::list< std::set<AttributePoint2DPtr> >::iterator find(const AttributePoint2DPtr& thePoint)
+  {
+    std::list< std::set<AttributePoint2DPtr> >::iterator aSeek = myCoincidentPoints.begin();
+    for (; aSeek != myCoincidentPoints.end(); ++aSeek)
+      if (aSeek->find(thePoint) != aSeek->end())
+        return aSeek;
+    return myCoincidentPoints.end();
+  }
+
+private:
+  std::list< std::set<AttributePoint2DPtr> > myCoincidentPoints;
+};
+
+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);
+}
+
+void resetAttribute(SketchPlugin_Feature* theFeature,
+                    const std::string& theId)
+{
+  AttributePtr anAttr = theFeature->attribute(theId);
+  if(anAttr.get()) {
+    anAttr->reset();
+  }
+}
+
+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()) {
@@ -145,4 +295,99 @@ void createConstraint(SketchPlugin_Feature* theFeature,
     }
   }
 }
+
+void convertRefAttrToPointOrTangentCurve(const AttributeRefAttrPtr&      theRefAttr,
+                                         const AttributePtr&             theDefaultAttr,
+                                         std::shared_ptr<GeomAPI_Shape>& theTangentCurve,
+                                         std::shared_ptr<GeomAPI_Pnt2d>& thePassingPoint)
+{
+  AttributePtr anAttr = theDefaultAttr;
+  if (theRefAttr->isObject()) {
+    FeaturePtr aTgFeature = ModelAPI_Feature::feature(theRefAttr->object());
+    if (aTgFeature) {
+      if (aTgFeature->getKind() != SketchPlugin_Point::ID()) {
+        theTangentCurve = aTgFeature->lastResult()->shape();
+        return;
+      }
+      anAttr = aTgFeature->attribute(SketchPlugin_Point::COORD_ID());
+    }
+  } else
+    anAttr = theRefAttr->attr();
+
+  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;
+}
+
 } // namespace SketchPlugin_Tools