Salome HOME
"2.11 Constraint with a point from the intersection between an outer edge and plane...
[modules/shaper.git] / src / PartSet / PartSet_Tools.cpp
old mode 100644 (file)
new mode 100755 (executable)
index f5dbff3..002f148
@@ -1,10 +1,12 @@
 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
 
-// File:        PartSet_Tools.h
+// File:        PartSet_Tools.cpp
 // Created:     28 Apr 2014
 // Author:      Natalia ERMOLAEVA
 
 #include <PartSet_Tools.h>
+#include <PartSet_Module.h>
+#include <PartSet_SketcherMgr.h>
 
 #include <ModelAPI_Data.h>
 #include <ModelAPI_AttributeDouble.h>
 #include <ModelAPI_Session.h>
 #include <ModelAPI_ResultConstruction.h>
 
+#include <SketcherPrs_Tools.h>
+
+#include <XGUI_ModuleConnector.h>
+#include <XGUI_Displayer.h>
+#include <XGUI_Workshop.h>
+#include <XGUI_SelectionMgr.h>
+#include <XGUI_Selection.h>
+
 #include <GeomDataAPI_Point.h>
 #include <GeomDataAPI_Dir.h>
 #include <GeomDataAPI_Point2D.h>
@@ -38,6 +48,7 @@
 #include <SketchPlugin_Line.h>
 #include <SketchPlugin_Point.h>
 
+#include <ModuleBase_IWorkshop.h>
 #include <ModuleBase_ViewerPrs.h>
 
 #include <V3d_View.hxx>
@@ -51,6 +62,9 @@
 #include <TopoDS.hxx>
 #include <TopoDS_Edge.hxx>
 #include <TopoDS_Vertex.hxx>
+#include <AIS_InteractiveObject.hxx>
+#include <StdSelect_BRepOwner.hxx>
+#include <SelectMgr_IndexedMapOfOwner.hxx>
 
 #ifdef _DEBUG
 #include <QDebug>
@@ -166,68 +180,6 @@ std::shared_ptr<GeomAPI_Pnt> PartSet_Tools::convertTo3D(const double theX, const
   return aPnt2d->to3D(aC->pnt(), aX->dir(), aY);
 }
 
-ObjectPtr PartSet_Tools::nearestFeature(QPoint thePoint, Handle_V3d_View theView,
-                                        FeaturePtr theSketch,
-                                        const QList<ModuleBase_ViewerPrs>& theSelected,
-                                        const QList<ModuleBase_ViewerPrs>& theHighlighted)
-{
-  // firstly it finds the feature in the list of highlight
-  ObjectPtr aDeltaObject  = nearestFeature(thePoint, theView, theSketch, theHighlighted);
-  if (!aDeltaObject)
-    // secondly it finds the feature in the list of selected objects
-    aDeltaObject  = nearestFeature(thePoint, theView, theSketch, theSelected);
-
-  return aDeltaObject;
-}
-
-ObjectPtr PartSet_Tools::nearestFeature(QPoint thePoint, Handle_V3d_View theView,
-                                        FeaturePtr theSketch,
-                                        const QList<ModuleBase_ViewerPrs>& thePresentations)
-{
-  ObjectPtr aDeltaObject;
-
-  CompositeFeaturePtr aSketch = 
-      std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theSketch);
-  // 1. find it in the selected list by the selected point
-  if (!aDeltaObject) {
-    double aX, anY;
-    gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(thePoint, theView);
-    PartSet_Tools::convertTo2D(aPoint, theSketch, theView, aX, anY);
-
-    FeaturePtr aFeature;
-    double aMinDelta = -1;
-    ModuleBase_ViewerPrs aPrs;
-    foreach (ModuleBase_ViewerPrs aPrs, thePresentations) {
-      if (!aPrs.object())
-        continue;
-      FeaturePtr aFeature = ModelAPI_Feature::feature(aPrs.object());
-      std::shared_ptr<SketchPlugin_Feature> aSketchFeature = std::dynamic_pointer_cast<
-          SketchPlugin_Feature>(aFeature);
-      if (!aSketchFeature || !aSketch->isSub(aSketchFeature))
-        continue;
-
-      double aDelta = aSketchFeature->distanceToPoint(
-          std::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(aX, anY)));
-      if (aMinDelta < 0 || aMinDelta > aDelta) {
-        aMinDelta = aDelta;
-        // TODO aDeltaObject = aPrs.result();
-      }
-    }
-  }
-  // 2. if the object is not found, returns the first selected sketch feature
-  if (!aDeltaObject && thePresentations.size() > 0) {
-    // there can be some highlighted objects, e.g. a result of boolean operation and a sketch point
-    foreach (ModuleBase_ViewerPrs aPrs, thePresentations) {
-      if (!aPrs.object())
-        continue;
-      FeaturePtr aFeature = ModelAPI_Feature::feature(aPrs.object());
-      if (aFeature && aSketch->isSub(aFeature))
-        aDeltaObject = aPrs.object();
-    }
-  }
-  return aDeltaObject;
-}
-
 std::shared_ptr<ModelAPI_Document> PartSet_Tools::document()
 {
   return ModelAPI_Session::get()->moduleDocument();
@@ -380,7 +332,7 @@ void PartSet_Tools::setConstraints(CompositeFeaturePtr theSketch, FeaturePtr the
       new GeomAPI_Pnt2d(theClickedX, theClickedY));
   for (; anIt != aLast; anIt++) {
     FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(*anIt);
-    if (theFeature == aFeature)
+    if (!aFeature.get() || theFeature == aFeature)
       continue;
     // find the given point in the feature attributes
     anAttiributes = aFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
@@ -468,8 +420,9 @@ ResultPtr PartSet_Tools::findFixedObjectByExternal(const TopoDS_Shape& theShape,
 }
 
 ResultPtr PartSet_Tools::createFixedObjectByExternal(const TopoDS_Shape& theShape, 
-                                                 const ObjectPtr& theObject, 
-                                                 CompositeFeaturePtr theSketch)
+                                                     const ObjectPtr& theObject, 
+                                                     CompositeFeaturePtr theSketch,
+                                                     const bool theTemporary)
 {
   if (theShape.ShapeType() == TopAbs_EDGE) {
     Standard_Real aStart, aEnd;
@@ -478,12 +431,44 @@ ResultPtr PartSet_Tools::createFixedObjectByExternal(const TopoDS_Shape& theShap
 
     Handle(Geom_Curve) aCurve = BRep_Tool::Curve(TopoDS::Edge(theShape), aStart, aEnd);
     GeomAdaptor_Curve aAdaptor(aCurve);
+    std::shared_ptr<GeomAPI_Edge> anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge);
+    anEdge->setImpl(new TopoDS_Shape(theShape));
     if (aAdaptor.GetType() == GeomAbs_Line) {
       // Create line
       aMyFeature = theSketch->addFeature(SketchPlugin_Line::ID());
+      if (!theObject.get()) {
+        // There is no selected result
+        std::shared_ptr<GeomAPI_Pnt> aPnt1 = anEdge->firstPoint();
+        std::shared_ptr<GeomAPI_Pnt> aPnt2 = anEdge->lastPoint();
+        std::shared_ptr<GeomAPI_Pnt2d> aPnt2d1 = convertTo2D(theSketch, aPnt1);
+        std::shared_ptr<GeomAPI_Pnt2d> aPnt2d2 = convertTo2D(theSketch, aPnt2);
+
+        std::shared_ptr<ModelAPI_Data> aData = aMyFeature->data();
+        std::shared_ptr<GeomDataAPI_Point2D> aPoint1 = 
+          std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(SketchPlugin_Line::START_ID()));
+        std::shared_ptr<GeomDataAPI_Point2D> aPoint2 = 
+          std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(SketchPlugin_Line::END_ID()));
+
+        aPoint1->setValue(aPnt2d1);
+        aPoint2->setValue(aPnt2d2);
+
+        // If this is an axis then its name has to be changed correspondently
+        std::string aSuffix = "";
+        bool aXdir = fabs(aPnt1->x() - aPnt2->x()) > Precision::Confusion();
+        bool aYdir = fabs(aPnt1->y() - aPnt2->y()) > Precision::Confusion();
+        bool aZdir = fabs(aPnt1->z() - aPnt2->z()) > Precision::Confusion();
+        if (aXdir && (!aYdir) && (!aZdir))
+          aSuffix = "X";
+        else if ((!aXdir) && aYdir && (!aZdir))
+          aSuffix = "Y";
+        else if ((!aXdir) && (!aYdir) && aZdir)
+          aSuffix = "Z";
+        if (aSuffix.length() > 0)
+          aData->setName("Axis_" + aSuffix);
+        aMyFeature->execute();
+
+      }
     } else if (aAdaptor.GetType() == GeomAbs_Circle) {
-      std::shared_ptr<GeomAPI_Edge> anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge);
-      anEdge->setImpl(new TopoDS_Shape(theShape));
       if (anEdge->isArc()) {
         // Create arc
         aMyFeature = theSketch->addFeature(SketchPlugin_Arc::ID());
@@ -500,19 +485,22 @@ ResultPtr PartSet_Tools::createFixedObjectByExternal(const TopoDS_Shape& theShap
         (aData->attribute(SketchPlugin_SketchEntity::EXTERNAL_ID()));
 
       ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
-      if (anAttr && aRes) {
+      if (!aRes.get()) {
+        aRes = aMyFeature->firstResult();
+      }
+      if (anAttr.get() && aRes.get()) {
         std::shared_ptr<GeomAPI_Shape> anEdge(new GeomAPI_Shape);
         anEdge->setImpl(new TopoDS_Shape(theShape));
 
         anAttr->setValue(aRes, anEdge);
-
-        aMyFeature->execute();
-
-        // fix this edge
-        FeaturePtr aFix = theSketch->addFeature(SketchPlugin_ConstraintRigid::ID());
-        aFix->data()->refattr(SketchPlugin_Constraint::ENTITY_A())->
-          setObject(aMyFeature->lastResult());
-
+        //if (!theTemporary) {
+          aMyFeature->execute();
+
+          // fix this edge
+          FeaturePtr aFix = theSketch->addFeature(SketchPlugin_ConstraintRigid::ID());
+          aFix->data()->refattr(SketchPlugin_Constraint::ENTITY_A())->
+            setObject(aMyFeature->lastResult());
+        //}
         return aMyFeature->lastResult();
       }
     }
@@ -527,18 +515,41 @@ ResultPtr PartSet_Tools::createFixedObjectByExternal(const TopoDS_Shape& theShap
         (aData->attribute(SketchPlugin_SketchEntity::EXTERNAL_ID()));
 
       ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
-      if (anAttr && aRes) {
+      if (!aRes.get()) {
+        // If the point is selected not from Result object
+        std::shared_ptr<GeomAPI_Shape> aShape = 
+          std::shared_ptr<GeomAPI_Shape>(new GeomAPI_Shape());
+        aShape->setImpl(new TopoDS_Shape(theShape));
+
+        std::shared_ptr<GeomAPI_Vertex> aVertex = 
+          std::shared_ptr<GeomAPI_Vertex>(new GeomAPI_Vertex(aShape));
+        std::shared_ptr<GeomAPI_Pnt> aPnt = aVertex->point();
+
+        std::shared_ptr<GeomAPI_Pnt2d> aPnt2d = convertTo2D(theSketch, aPnt);
+        std::shared_ptr<GeomDataAPI_Point2D> aPoint = 
+          std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(SketchPlugin_Point::COORD_ID()));
+        aPoint->setValue(aPnt2d);
+        if ((aPnt->x() < Precision::Confusion()) && 
+            (aPnt->y() < Precision::Confusion()) &&
+            (aPnt->z() < Precision::Confusion()))
+          aData->setName("Origin");
+
+        aMyFeature->execute();
+        aRes = aMyFeature->firstResult();
+      }
+      if (anAttr.get() && aRes.get()) {
         std::shared_ptr<GeomAPI_Shape> aVert(new GeomAPI_Shape);
         aVert->setImpl(new TopoDS_Shape(theShape));
 
         anAttr->setValue(aRes, aVert);
-        aMyFeature->execute();
-
-        // fix this edge
-        FeaturePtr aFix = theSketch->addFeature(SketchPlugin_ConstraintRigid::ID());
-        aFix->data()->refattr(SketchPlugin_Constraint::ENTITY_A())->
-          setObject(aMyFeature->lastResult());
-
+        //if (theTemporary) {
+          aMyFeature->execute();
+
+          // fix this edge
+          FeaturePtr aFix = theSketch->addFeature(SketchPlugin_ConstraintRigid::ID());
+          aFix->data()->refattr(SketchPlugin_Constraint::ENTITY_A())->
+            setObject(aMyFeature->lastResult());
+        //}
         return aMyFeature->lastResult();
       }
     }
@@ -632,6 +643,199 @@ bool PartSet_Tools::hasVertexShape(const ModuleBase_ViewerPrs& thePrs, FeaturePt
   return aHasVertex;
 }
 
+GeomShapePtr PartSet_Tools::findShapeBy2DPoint(const AttributePtr& theAttribute,
+                                               ModuleBase_IWorkshop* theWorkshop)
+{
+  // 1. find an attribute value in attribute reference attribute value
+  GeomShapePtr aShape;
+  AttributeRefAttrPtr aRefAttr =
+    std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
+  if (aRefAttr) {
+    if (!aRefAttr->isObject()) {
+      AttributePtr theAttribute = aRefAttr->attr();
+      if (theAttribute.get()) {
+        XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(theWorkshop);
+        XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
+
+        // 2. find visualized vertices of the attribute and if the attribute of the vertex is
+        // the same, return it
+        FeaturePtr anAttributeFeature = ModelAPI_Feature::feature(theAttribute->owner());
+        // 2.1 get visualized results of the feature
+        const std::list<ResultPtr>& aResList = anAttributeFeature->results();
+        std::list<ResultPtr>::const_iterator anIt = aResList.begin(), aLast = aResList.end();
+        for (; anIt != aLast; anIt++) {
+          AISObjectPtr aAISObj = aDisplayer->getAISObject(*anIt);
+          if (aAISObj.get() != NULL) {
+            Handle(AIS_InteractiveObject) anAISIO = aAISObj->impl<Handle(AIS_InteractiveObject)>();
+            // 2.2 find selected owners of a visualizedd object
+            SelectMgr_IndexedMapOfOwner aSelectedOwners;
+            aConnector->workshop()->selector()->selection()->entityOwners(anAISIO, aSelectedOwners);
+            for (Standard_Integer i = 1, n = aSelectedOwners.Extent(); i <= n; i++) {
+              Handle(SelectMgr_EntityOwner) anOwner = aSelectedOwners(i);
+              if (!anOwner.IsNull()) {
+                Handle(StdSelect_BRepOwner) aBRepOwner = Handle(StdSelect_BRepOwner)::DownCast(anOwner);
+                if (!aBRepOwner.IsNull() && aBRepOwner->HasShape()) {
+                  const TopoDS_Shape& aBRepShape = aBRepOwner->Shape();
+                  if (aBRepShape.ShapeType() == TopAbs_VERTEX) {
+                    // 2.3 if the owner is vertex and an attribute of the vertex is equal to the initial
+                    // attribute, returns the shape
+                    PartSet_Module* aModule = dynamic_cast<PartSet_Module*>(theWorkshop->module());
+                    PartSet_SketcherMgr* aSketchMgr = aModule->sketchMgr();
+                    AttributePtr aPntAttr = PartSet_Tools::findAttributeBy2dPoint(anAttributeFeature,
+                                                             aBRepShape, aSketchMgr->activeSketch());
+                    if (aPntAttr.get() != NULL && aPntAttr == theAttribute) {
+                      aShape = std::shared_ptr<GeomAPI_Shape>(new GeomAPI_Shape);
+                      aShape->setImpl(new TopoDS_Shape(aBRepShape));
+                      break;
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  return aShape;
+}
+
+std::shared_ptr<GeomAPI_Pnt2d> PartSet_Tools::getPoint(std::shared_ptr<ModelAPI_Feature>& theFeature,
+                                                       const std::string& theAttribute)
+{
+  std::shared_ptr<GeomDataAPI_Point2D> aPointAttr;
+
+  if (!theFeature->data())
+    return std::shared_ptr<GeomAPI_Pnt2d>();
+
+  FeaturePtr aFeature;
+  std::shared_ptr<ModelAPI_AttributeRefAttr> anAttr = std::dynamic_pointer_cast<
+      ModelAPI_AttributeRefAttr>(theFeature->data()->attribute(theAttribute));
+  if (!anAttr)
+    return std::shared_ptr<GeomAPI_Pnt2d>();
+
+  aFeature = ModelAPI_Feature::feature(anAttr->object());
+
+  if (aFeature && aFeature->getKind() == SketchPlugin_Point::ID())
+    aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+        aFeature->data()->attribute(SketchPlugin_Point::COORD_ID()));
+
+  else if (anAttr->attr()) {
+    aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr->attr());
+  }
+  if (aPointAttr.get() != NULL)
+    return aPointAttr->pnt();
+  return std::shared_ptr<GeomAPI_Pnt2d>();
+}
+
+FeaturePtr findFirstCoincidenceByData(const DataPtr& theData, std::shared_ptr<GeomAPI_Pnt2d> thePoint)
+{
+  FeaturePtr aCoincident;
+
+  const std::set<AttributePtr>& aRefsList = theData->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> a2dPnt = 
+        PartSet_Tools::getPoint(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_A());
+      if (a2dPnt.get() && thePoint->isEqual(a2dPnt)) { 
+        aCoincident = aConstrFeature;
+        break;
+      } else {
+        a2dPnt = PartSet_Tools::getPoint(aConstrFeature,
+                                          SketchPlugin_ConstraintCoincidence::ENTITY_B());
+        if (a2dPnt.get() && thePoint->isEqual(a2dPnt)) { 
+          aCoincident = aConstrFeature;
+          break;
+        }
+      }
+    }
+  }
+  return aCoincident;
+}
+
+FeaturePtr PartSet_Tools::findFirstCoincidence(const FeaturePtr& theFeature,
+                                               std::shared_ptr<GeomAPI_Pnt2d> thePoint,
+                                               const bool theSearchInResults)
+{
+  FeaturePtr aCoincident;
+  if (theFeature.get() == NULL)
+    return aCoincident;
+
+  const std::set<AttributePtr>& aRefsList = theFeature->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> a2dPnt = 
+        PartSet_Tools::getPoint(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_A());
+      if (a2dPnt.get() && thePoint->isEqual(a2dPnt)) { 
+        aCoincident = aConstrFeature;
+        break;
+      } else {
+        a2dPnt = PartSet_Tools::getPoint(aConstrFeature,
+                                          SketchPlugin_ConstraintCoincidence::ENTITY_B());
+        if (a2dPnt.get() && thePoint->isEqual(a2dPnt)) { 
+          aCoincident = aConstrFeature;
+          break;
+        }
+      }
+    }
+  }
+  if (theSearchInResults) {
+    if (!aCoincident.get()) {
+      std::list<ResultPtr> aResults = theFeature->results();
+      std::list<ResultPtr>::const_iterator aIt;
+      for (aIt = aResults.cbegin(); aIt != aResults.cend(); ++aIt) {
+        ResultPtr aResult = *aIt;
+        aCoincident = findFirstCoincidenceByData(aResult->data(), thePoint);
+        if (aCoincident.get())
+          break;
+      }
+    }
+  }
+  return aCoincident;
+}
+
+void PartSet_Tools::findCoincidences(FeaturePtr theStartCoin, QList<FeaturePtr>& theList,
+                                     std::string theAttr)
+{
+  AttributeRefAttrPtr aPnt = theStartCoin->refattr(theAttr);
+  if (!aPnt) return;
+  FeaturePtr aObj = ModelAPI_Feature::feature(aPnt->object());
+  if (!theList.contains(aObj)) {
+    std::shared_ptr<GeomAPI_Pnt2d> aOrig = getCoincedencePoint(theStartCoin);
+    if (aOrig.get() == NULL)
+      return;
+    theList.append(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 = getCoincedencePoint(aConstrFeature);
+        if (aPnt.get() && aOrig->isEqual(aPnt)) {
+          findCoincidences(aConstrFeature, theList, SketchPlugin_ConstraintCoincidence::ENTITY_A());
+          findCoincidences(aConstrFeature, theList, SketchPlugin_ConstraintCoincidence::ENTITY_B());
+        }
+      }
+    }
+  }
+}
+
+std::shared_ptr<GeomAPI_Pnt2d> PartSet_Tools::getCoincedencePoint(FeaturePtr theStartCoin)
+{
+  std::shared_ptr<GeomAPI_Pnt2d> aPnt = SketcherPrs_Tools::getPoint(theStartCoin.get(), 
+                                                                    SketchPlugin_Constraint::ENTITY_A());
+  if (aPnt.get() == NULL)
+    aPnt = SketcherPrs_Tools::getPoint(theStartCoin.get(), SketchPlugin_Constraint::ENTITY_B());
+  return aPnt;
+}
+
 AttributePtr PartSet_Tools::findAttributeBy2dPoint(ObjectPtr theObj, 
                                                    const TopoDS_Shape theShape, 
                                                    FeaturePtr theSketch)