Salome HOME
updated copyright message
[modules/shaper.git] / src / PartSet / PartSet_Tools.cpp
index fbb50228faf57290a384d347d72b2e8b0b0dffec..315abbd77907f4c240cc7c230734e82a59db0f9e 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2019  CEA/DEN, EDF R&D
+// Copyright (C) 2014-2023  CEA, EDF
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
@@ -49,6 +49,7 @@
 #include <GeomDataAPI_Point.h>
 #include <GeomDataAPI_Dir.h>
 #include <GeomDataAPI_Point2D.h>
+#include <GeomDataAPI_Point2DArray.h>
 #include <GeomAPI_Pln.h>
 #include <GeomAPI_Pnt2d.h>
 #include <GeomAPI_Pnt.h>
@@ -92,7 +93,6 @@
 #include <AIS_InteractiveObject.hxx>
 #include <StdSelect_BRepOwner.hxx>
 #include <SelectMgr_IndexedMapOfOwner.hxx>
-#include <V3d_Coordinate.hxx>
 
 #include <QMouseEvent>
 
@@ -114,15 +114,14 @@ gp_Pnt PartSet_Tools::convertClickToPoint(QPoint thePoint, Handle(V3d_View) theV
   if (theView.IsNull())
     return gp_Pnt();
 
-  V3d_Coordinate XEye, YEye, ZEye, XAt, YAt, ZAt;
-  theView->Eye(XEye, YEye, ZEye);
-
+  Standard_Real XAt, YAt, ZAt;
   theView->At(XAt, YAt, ZAt);
-  gp_Pnt EyePoint(XEye, YEye, ZEye);
   gp_Pnt AtPoint(XAt, YAt, ZAt);
 
-  gp_Vec EyeVector(EyePoint, AtPoint);
-  gp_Dir EyeDir(EyeVector);
+  double aX, aY, aZ;
+  theView->Proj(aX, aY, aZ);
+  gp_Dir EyeDir(aX, aY, aZ);
+  EyeDir.Reverse();
 
   gp_Pln PlaneOfTheView = gp_Pln(AtPoint, EyeDir);
   Standard_Real X, Y, Z;
@@ -130,9 +129,8 @@ gp_Pnt PartSet_Tools::convertClickToPoint(QPoint thePoint, Handle(V3d_View) theV
   gp_Pnt ConvertedPoint(X, Y, Z);
 
   gp_Pnt2d ConvertedPointOnPlane = ProjLib::Project(PlaneOfTheView, ConvertedPoint);
-  gp_Pnt ResultPoint = ElSLib::Value(ConvertedPointOnPlane.X(), ConvertedPointOnPlane.Y(),
+  return ElSLib::Value(ConvertedPointOnPlane.X(), ConvertedPointOnPlane.Y(),
                                      PlaneOfTheView);
-  return ResultPoint;
 }
 
 void PartSet_Tools::convertTo2D(const gp_Pnt& thePoint, FeaturePtr theSketch,
@@ -158,25 +156,27 @@ Handle(V3d_View) theView,
   gp_Vec aVec(anOriginPnt, thePoint);
 
   if (!theView.IsNull()) {
-    V3d_Coordinate XEye, YEye, ZEye, XAt, YAt, ZAt;
+    Standard_Real XEye, YEye, ZEye, XAt, YAt, ZAt;
     theView->Eye(XEye, YEye, ZEye);
 
     theView->At(XAt, YAt, ZAt);
     gp_Pnt EyePoint(XEye, YEye, ZEye);
     gp_Pnt AtPoint(XAt, YAt, ZAt);
 
-    gp_Vec anEyeVec(EyePoint, AtPoint);
-    anEyeVec.Normalize();
+    if (EyePoint.Distance(AtPoint) > gp::Resolution()) {
+      gp_Vec anEyeVec(EyePoint, AtPoint);
+      anEyeVec.Normalize();
 
-    std::shared_ptr<GeomDataAPI_Dir> aNormal = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
-        aData->attribute(SketchPlugin_Sketch::NORM_ID()));
-    gp_Vec aNormalVec(aNormal->x(), aNormal->y(), aNormal->z());
+      std::shared_ptr<GeomDataAPI_Dir> aNormal = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
+         aData->attribute(SketchPlugin_Sketch::NORM_ID()));
+      gp_Vec aNormalVec(aNormal->x(), aNormal->y(), aNormal->z());
 
-    double aDen = anEyeVec * aNormalVec;
-    double aLVec = aDen != 0 ? aVec * aNormalVec / aDen : DBL_MAX;
+      double aDen = anEyeVec * aNormalVec;
+      double aLVec = aDen != 0 ? aVec * aNormalVec / aDen : DBL_MAX;
 
-    gp_Vec aDeltaVec = anEyeVec * aLVec;
-    aVec = aVec - aDeltaVec;
+      gp_Vec aDeltaVec = anEyeVec * aLVec;
+      aVec = aVec - aDeltaVec;
+    }
   }
   theX = aVec.X() * aX->x() + aVec.Y() * aX->y() + aVec.Z() * aX->z();
   theY = aVec.X() * anY->x() + aVec.Y() * anY->y() + aVec.Z() * anY->z();
@@ -383,10 +383,13 @@ ResultPtr PartSet_Tools::createFixedObjectByExternal(
   anIntoResult->setValue(SKETCH_PROJECTION_INCLUDE_INTO_RESULT);
   aProjectionFeature->execute();
 
+  ModelAPI_ValidatorsFactory* aValidators = ModelAPI_Session::get()->validators();
+  bool isValid = aValidators->validate(aProjectionFeature);
+
   // if projection feature has not been created, exit
   AttributeRefAttrPtr aRefAttr = aProjectionFeature->data()->refattr(
     SketchPlugin_Projection::PROJECTED_FEATURE_ID());
-  if (!aRefAttr || !aRefAttr->isInitialized())
+  if (!isValid || !aRefAttr || !aRefAttr->isInitialized())
   {
     // remove external feature if the attribute is not filled
     std::set<FeaturePtr> aFeatures;
@@ -443,9 +446,9 @@ GeomShapePtr PartSet_Tools::findShapeBy2DPoint(const AttributePtr& theAttribute,
               // 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) {
+              std::pair<AttributePtr, int> aPntAttrIndex = PartSet_Tools::findAttributeBy2dPoint(
+                  anAttributeFeature, aBRepShape, aSketchMgr->activeSketch());
+              if (aPntAttrIndex.first.get() != NULL && aPntAttrIndex.first == theAttribute) {
                 aShape = std::shared_ptr<GeomAPI_Shape>(new GeomAPI_Shape);
                 aShape->setImpl(new TopoDS_Shape(aBRepShape));
                 break;
@@ -483,6 +486,24 @@ std::shared_ptr<GeomAPI_Pnt2d> PartSet_Tools::getPnt2d(QMouseEvent* theEvent,
   return std::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(aX, anY));
 }
 
+std::shared_ptr<GeomAPI_Pnt2d> PartSet_Tools::getPnt2d(const Handle(V3d_View)& theView,
+                                                       const TopoDS_Shape& theShape,
+                                                       const FeaturePtr& theSketch)
+{
+  GeomPnt2dPtr aPoint2D;
+  if (!theShape.IsNull() && theShape.ShapeType() == TopAbs_VERTEX) {
+    const TopoDS_Vertex& aVertex = TopoDS::Vertex(theShape);
+    if (!aVertex.IsNull()) {
+      // the case when the point is taken from the existing vertex
+      gp_Pnt aPoint = BRep_Tool::Pnt(aVertex);
+      double aX, aY;
+      PartSet_Tools::convertTo2D(aPoint, theSketch, theView, aX, aY);
+      aPoint2D.reset(new GeomAPI_Pnt2d(aX, aY));
+    }
+  }
+  return aPoint2D;
+}
+
 FeaturePtr findFirstCoincidenceByData(const DataPtr& theData,
                                       std::shared_ptr<GeomAPI_Pnt2d> thePoint)
 {
@@ -543,9 +564,9 @@ FeaturePtr PartSet_Tools::findFirstCoincidence(const FeaturePtr& theFeature,
   /// Find by result
   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;
+    std::list<ResultPtr>::const_iterator aResIt;
+    for (aResIt = aResults.cbegin(); aResIt != aResults.cend(); ++aResIt) {
+      ResultPtr aResult = *aResIt;
       aCoincident = findFirstCoincidenceByData(aResult->data(), thePoint);
       if (aCoincident.get())
         break;
@@ -579,8 +600,8 @@ void PartSet_Tools::findCoincidences(FeaturePtr theStartCoin, QList<FeaturePtr>&
         FeaturePtr aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
         if (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
           if (!theCoincidencies.contains(aConstrFeature)) {
-            std::shared_ptr<GeomAPI_Pnt2d> aPnt = getCoincedencePoint(aConstrFeature);
-            if (aPnt.get() && aOrig->isEqual(aPnt)) {
+            std::shared_ptr<GeomAPI_Pnt2d> aCoincPnt = getCoincedencePoint(aConstrFeature);
+            if (aCoincPnt.get() && aOrig->isEqual(aCoincPnt)) {
               findCoincidences(aConstrFeature, theList, theCoincidencies,
                 SketchPlugin_ConstraintCoincidence::ENTITY_A(), theIsAttributes);
               findCoincidences(aConstrFeature, theList, theCoincidencies,
@@ -594,9 +615,9 @@ void PartSet_Tools::findCoincidences(FeaturePtr theStartCoin, QList<FeaturePtr>&
     // Find by Results
     ResultConstructionPtr aResult = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aObj);
     if (aResult.get()) {
-      FeaturePtr aFeature = ModelAPI_Feature::feature(aPnt->object());
-      if (!theList.contains(aFeature))
-        theList.append(aFeature);
+      FeaturePtr aFeat = ModelAPI_Feature::feature(aPnt->object());
+      if (!theList.contains(aFeat))
+        theList.append(aFeat);
       theCoincidencies.append(theStartCoin);
       theIsAttributes.append(false); // point attribute on a feature
 
@@ -607,8 +628,8 @@ void PartSet_Tools::findCoincidences(FeaturePtr theStartCoin, QList<FeaturePtr>&
         FeaturePtr aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
         if (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
           if (!theCoincidencies.contains(aConstrFeature)) {
-            std::shared_ptr<GeomAPI_Pnt2d> aPnt = getCoincedencePoint(aConstrFeature);
-            if (aPnt.get() && aOrig->isEqual(aPnt)) {
+            std::shared_ptr<GeomAPI_Pnt2d> aCoincPnt = getCoincedencePoint(aConstrFeature);
+            if (aCoincPnt.get() && aOrig->isEqual(aCoincPnt)) {
               findCoincidences(aConstrFeature, theList, theCoincidencies,
                 SketchPlugin_ConstraintCoincidence::ENTITY_A(), theIsAttributes);
               findCoincidences(aConstrFeature, theList, theCoincidencies,
@@ -630,12 +651,44 @@ std::shared_ptr<GeomAPI_Pnt2d> PartSet_Tools::getCoincedencePoint(FeaturePtr the
   return aPnt;
 }
 
-AttributePtr PartSet_Tools::findAttributeBy2dPoint(ObjectPtr theObj,
-                                                   const TopoDS_Shape theShape,
-                                                   FeaturePtr theSketch)
+class PointWrapper
+{
+public:
+  PointWrapper(AttributePtr theAttribute)
+    : myPoint(std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theAttribute)),
+      myArray(std::dynamic_pointer_cast<GeomDataAPI_Point2DArray>(theAttribute))
+  {}
+
+  int size() const { return myPoint.get() ? 1 : (myArray.get() ? myArray->size() : 0); }
+
+  GeomPointPtr point(int theIndex, FeaturePtr theSketch)
+  {
+    GeomPnt2dPtr aP2d;
+    if (myPoint.get())
+      aP2d = myPoint->pnt();
+    else if (myArray.get())
+      aP2d = myArray->pnt(theIndex);
+
+    GeomPointPtr aP3d;
+    if (aP2d.get())
+      aP3d = PartSet_Tools::convertTo3D(aP2d->x(), aP2d->y(), theSketch);
+    return aP3d;
+  }
+
+  bool isArray() const { return myArray.get(); }
+
+private:
+  AttributePoint2DPtr myPoint;
+  AttributePoint2DArrayPtr myArray;
+};
+
+std::pair<AttributePtr, int> PartSet_Tools::findAttributeBy2dPoint(ObjectPtr theObj,
+                                                                   const TopoDS_Shape theShape,
+                                                                   FeaturePtr theSketch)
 {
 
   AttributePtr anAttribute;
+  int aPointIndex = -1;
   FeaturePtr aFeature = ModelAPI_Feature::feature(theObj);
   if (aFeature) {
     if (theShape.ShapeType() == TopAbs_VERTEX) {
@@ -648,29 +701,32 @@ AttributePtr PartSet_Tools::findAttributeBy2dPoint(ObjectPtr theObj,
         // find the given point in the feature attributes
         std::list<AttributePtr> anAttiributes =
           aFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
+        std::list<AttributePtr> anArrays =
+          aFeature->data()->attributes(GeomDataAPI_Point2DArray::typeId());
+        anAttiributes.insert(anAttiributes.end(), anArrays.begin(), anArrays.end());
+
         std::list<AttributePtr>::const_iterator anIt = anAttiributes.begin(),
                                                 aLast = anAttiributes.end();
         double aMinDistance = 1.e-6; // searching for point with minimal distance and < 1.e-6
         for (; anIt != aLast && !anAttribute; anIt++) {
-          std::shared_ptr<GeomDataAPI_Point2D> aCurPoint =
-            std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*anIt);
-          if (!aCurPoint->isInitialized())
-            continue;
-
-          std::shared_ptr<GeomAPI_Pnt> aPnt =
-            convertTo3D(aCurPoint->x(), aCurPoint->y(), theSketch);
-          if (aPnt) {
-            double aDistance = aPnt->distance(aValue);
-            if (aDistance < aMinDistance) {
-              anAttribute = aCurPoint;
-              aMinDistance = aPnt->distance(aValue);
+          PointWrapper aWrapper(*anIt);
+          for (int anIndex = 0, aSize = aWrapper.size(); anIndex < aSize; ++anIndex) {
+            std::shared_ptr<GeomAPI_Pnt> aPnt = aWrapper.point(anIndex, theSketch);
+            if (aPnt) {
+              double aDistance = aPnt->distance(aValue);
+              if (aDistance < aMinDistance) {
+                anAttribute = *anIt;
+                if (aWrapper.isArray())
+                  aPointIndex = anIndex;
+                aMinDistance = aPnt->distance(aValue);
+              }
             }
           }
         }
       }
     }
   }
-  return anAttribute;
+  return std::pair<AttributePtr, int>(anAttribute, aPointIndex);
 }
 
 void PartSet_Tools::sendSubFeaturesEvent(const CompositeFeaturePtr& theComposite,
@@ -679,7 +735,6 @@ void PartSet_Tools::sendSubFeaturesEvent(const CompositeFeaturePtr& theComposite
   if (!theComposite.get())
     return;
 
-  static Events_Loop* aLoop = Events_Loop::loop();
   int aNumberOfSubs = theComposite->numberOfSubs();
   for (int i = 0; i < aNumberOfSubs; i++) {
     FeaturePtr aSubFeature = theComposite->subFeature(i);
@@ -803,12 +858,10 @@ void PartSet_Tools::getDefaultColor(ObjectPtr theObject, const bool isEmptyColor
 {
   theColor.clear();
   // get default color from the preferences manager for the given result
-  if (theColor.empty()) {
-    std::string aSection, aName, aDefault;
-    theObject->colorConfigInfo(aSection, aName, aDefault);
-    if (!aSection.empty() && !aName.empty()) {
-      theColor = Config_PropManager::color(aSection, aName);
-    }
+  std::string aSection, aName, aDefault;
+  theObject->colorConfigInfo(aSection, aName, aDefault);
+  if (!aSection.empty() && !aName.empty()) {
+    theColor = Config_PropManager::color(aSection, aName);
   }
   if (!isEmptyColorValid && theColor.empty()) {
     // all AIS objects, where the color is not set, are in black.
@@ -851,3 +904,17 @@ double PartSet_Tools::getDefaultTransparency()
 {
   return Config_PropManager::integer("Visualization", "shaper_default_transparency") / 100.;
 }
+
+QCursor PartSet_Tools::getOperationCursor()
+{
+  int aId = Config_PropManager::integer(SKETCH_TAB_NAME, "operation_cursor");
+  switch (aId) {
+  case 0:
+    return QCursor(Qt::ArrowCursor);
+  case 1:
+    return QCursor(Qt::CrossCursor);
+  case 2:
+    return QCursor(Qt::PointingHandCursor);
+  }
+  return QCursor();
+}