Salome HOME
updated copyright message
[modules/shaper.git] / src / PartSet / PartSet_PreviewSketchPlane.cpp
index 28b5c8491f5cf03ee865b7a0574c1af007350df9..8cfb60457045140bf1f4e87f107f3c4a8b74ae24 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2017  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
 //
 // 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 "PartSet_PreviewSketchPlane.h"
@@ -28,7 +27,8 @@
 #include <ModelAPI_CompositeFeature.h>
 #include <ModelAPI_Tools.h>
 
-#include <GeomAlgoAPI_ShapeTools.h>
+#include <GeomAPI_AISObject.h>
+#include <GeomAPI_Pnt.h>
 
 #include <XGUI_Tools.h>
 #include <XGUI_Displayer.h>
 
 #include <BRepBndLib.hxx>
 
-double maximumSize(double theXmin, double theYmin, double theZmin,
-                   double theXmax, double theYmax, double theZmax)
-{
-  double aSize = fabs(theXmax - theXmin);
-  double aSizeToCompare = fabs(theYmax - theYmin);
-  if (aSizeToCompare > aSize)
-    aSize = aSizeToCompare;
-  aSizeToCompare = fabs(theZmax - theZmin);
-  if (aSizeToCompare > aSize)
-    aSize = aSizeToCompare;
-
-  return aSize;
-}
-
 PartSet_PreviewSketchPlane::PartSet_PreviewSketchPlane()
- : mySketchDisplayed(false), myOtherSketchSize(0)
+ : myPreviewIsDisplayed(false), mySizeOfView(0), myIsUseSizeOfView(false)
 {
 }
 
-void PartSet_PreviewSketchPlane::setOtherSketchParameters(const GeomShapePtr& theOtherSketchFace)
-{
-  myOtherSketchOrigin = std::shared_ptr<GeomAPI_Pnt>();
-  myOtherSketchSize = 0;
-  if (!theOtherSketchFace)
-    return;
-
-  getShapeParameters(theOtherSketchFace, myOtherSketchOrigin, myOtherSketchSize);
-}
-
 void PartSet_PreviewSketchPlane::eraseSketchPlane(ModuleBase_IWorkshop* theWorkshop,
                                                   const bool isClearPlane)
 {
-  if (mySketchDisplayed) {
+  if (myPreviewIsDisplayed) {
     XGUI_Displayer* aDisp = XGUI_Tools::workshop(theWorkshop)->displayer();
     aDisp->eraseAIS(myPlane, false);
-    if (isClearPlane) {
-      myPlane = NULL;
-      myOrigin = NULL;
-      myNormal = NULL;
-    }
-    mySketchDisplayed = false;
+    myPreviewIsDisplayed = false;
+  }
+  if (isClearPlane) clearPlanePreview();
+}
+
+void PartSet_PreviewSketchPlane::displaySketchPlane(ModuleBase_IWorkshop* theWorkshop)
+{
+  if (myPlane.get() && (!myPreviewIsDisplayed)) {
+    XGUI_Displayer* aDisp = XGUI_Tools::workshop(theWorkshop)->displayer();
+    aDisp->displayAIS(myPlane, false/*load object in selection*/, 1/*shaded*/, false);
+    myPreviewIsDisplayed = true;
   }
 }
 
+
+void PartSet_PreviewSketchPlane::clearPlanePreview()
+{
+  myPlane = std::shared_ptr<GeomAPI_AISObject>();
+  myShape = std::shared_ptr<GeomAPI_Shape>();
+}
+
+
 void PartSet_PreviewSketchPlane::createSketchPlane(const CompositeFeaturePtr& theSketch,
                                                    ModuleBase_IWorkshop* theWorkshop)
 {
-  if (mySketchDisplayed)
-    return;
-
   // plane is visualized only if sketch plane is filled
-  std::shared_ptr<GeomAPI_Pln> aPlane = PartSet_Tools::sketchPlane(theSketch);
-  if (!aPlane.get())
+  if (!PartSet_Tools::sketchPlane(theSketch).get())
     return;
 
-  if (!myPlane) { // If planes are not created
-    std::shared_ptr<GeomDataAPI_Point> anOrigin = std::dynamic_pointer_cast<GeomDataAPI_Point>(
-        theSketch->data()->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
-    std::shared_ptr<GeomDataAPI_Dir> aNormal = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
-        theSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID()));
-
-    // Create Preview
-    // default planes parameters
-    std::shared_ptr<GeomAPI_Pnt> anOriginPnt = anOrigin->pnt();
-    double aSize = Config_PropManager::integer(SKETCH_TAB_NAME, "planes_size");
-    // another sketch parameters
-    if (myOtherSketchOrigin) {
-      anOriginPnt = myOtherSketchOrigin;
-      aSize = myOtherSketchSize;
-      setOtherSketchParameters(GeomShapePtr());
-    }
-    else {
-      // selected linear face parameters
-      AttributeSelectionPtr aSelAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>
-        (theSketch->data()->attribute(SketchPlugin_SketchEntity::EXTERNAL_ID()));
-      if (aSelAttr) {
-        std::shared_ptr<GeomAPI_Shape> aSketchExternalFace = aSelAttr->value();
-        if (aSketchExternalFace)
-          getShapeParameters(aSketchExternalFace, anOriginPnt, aSize);
-      }
-    }
-    double aSketchSize = getSketchBoundingBoxSize(theSketch, anOriginPnt);
-    if (aSketchSize > 0)
-      aSize = aSketchSize;
+  AttributeSelectionPtr aSelAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>
+    (theSketch->data()->attribute(SketchPlugin_SketchEntity::EXTERNAL_ID()));
+  if (!aSelAttr)
+    return;
 
-    myOrigin = anOriginPnt;
-    myNormal = aNormal->dir();
-    myPlane = createPreviewPlane(aSize);
-  }
+  if (myShape.get() && myShape->isSame(aSelAttr->value()) && myPlane.get())
+    return;
 
   XGUI_Displayer* aDisp = XGUI_Tools::workshop(theWorkshop)->displayer();
-  aDisp->displayAIS(myPlane, true, 1/*shaded*/, false);
-  mySketchDisplayed = true;
-}
+  if (myPreviewIsDisplayed) {
+    aDisp->eraseAIS(myPlane, false);
+  }
 
-void PartSet_PreviewSketchPlane::updatePlaneSize(const CompositeFeaturePtr& theSketch,
-                                                 ModuleBase_IWorkshop* theWorkshop)
-{
-  std::shared_ptr<GeomAPI_Pnt> anOriginPnt;
-  double aSize = getSketchBoundingBoxSize(theSketch, anOriginPnt);
-  if (aSize <= 0)
-    return;
-  myOrigin = anOriginPnt;
-  createPreviewPlane(aSize);
-}
+  // Create Preview
+  // selected linear face parameters
+  myShape = aSelAttr->value();
+  // this case is needed by constructing sketch on a plane, where result shape is equal
+  // to context result, therefore value() returns NULL and we should use shape of context.
+  if (!myShape.get() && aSelAttr->context().get())
+    myShape = aSelAttr->context()->shape();
 
-AISObjectPtr PartSet_PreviewSketchPlane::createPreviewPlane(double theSize)
-{
-  std::vector<int> aYZRGB(3, 0);
-#ifdef SET_PLANES_COLOR_IN_PREFERENCES
-    aYZRGB = Config_PropManager::color("Visualization", "yz_plane_color");
-#else
-    aYZRGB[0] = 225;
-#endif
-    int aR[] = {aYZRGB[0], aYZRGB[1], aYZRGB[2]};
+  if (!myShape.get()) {
+    // Create Preview for default planes
+    std::shared_ptr<GeomDataAPI_Point> anOrigin = std::dynamic_pointer_cast<GeomDataAPI_Point>(
+        theSketch->data()->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
+    std::shared_ptr<GeomDataAPI_Dir> aNormal = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
+        theSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID()));
 
-  std::shared_ptr<GeomAPI_Shape> aFace =
-    GeomAlgoAPI_FaceBuilder::squareFace(myOrigin, myNormal, theSize);
+    double aFaceSize = myIsUseSizeOfView ? mySizeOfView
+      : Config_PropManager::real(SKETCH_TAB_NAME, "planes_size");
+    if (aFaceSize <= Precision::Confusion())
+      aFaceSize = 200;   // Set default value
 
-  if (myPlane.get()) {
-    myPlane->createShape(aFace);
-    return myPlane;
+    myShape = GeomAlgoAPI_FaceBuilder::squareFace(
+      myViewCentralPoint.get() ? myViewCentralPoint : anOrigin->pnt(), aNormal->dir(), aFaceSize);
   }
-  else {
-    AISObjectPtr aAIS = AISObjectPtr(new GeomAPI_AISObject());
-    aAIS->createShape(aFace);
-    std::vector<int> aColor = Config_PropManager::color("Visualization", "sketch_preview_plane");
-    if (aColor.size() == 3)
-      aAIS->setColor(aColor[0], aColor[1], aColor[2]);
-    aAIS->setTransparensy(0.8);
-
-    int aDispMode = 1; // shading
-    Handle(AIS_InteractiveObject) anAISIO = aAIS->impl<Handle(AIS_InteractiveObject)>();
-    if (!anAISIO.IsNull()) {
-      anAISIO->Attributes()->SetFaceBoundaryDraw( Standard_True );
-      anAISIO->SetDisplayMode(aDispMode);
+  else if (myIsUseSizeOfView && (mySizeOfView > 0)) {
+    std::shared_ptr<GeomAPI_Face> aFace(new GeomAPI_Face(myShape));
+    std::shared_ptr<GeomAPI_Pln> aPlane = aFace->getPlane();
+    if (aPlane.get()) {
+      double anA, aB, aC, aD;
+      aPlane->coefficients(anA, aB, aC, aD);
+      std::shared_ptr<GeomAPI_Dir> aNormDir(new GeomAPI_Dir(anA, aB, aC));
+      std::shared_ptr<GeomAPI_XYZ> aCoords = aNormDir->xyz();
+      std::shared_ptr<GeomAPI_XYZ> aZero(new GeomAPI_XYZ(0, 0, 0));
+      aCoords = aCoords->multiplied(-aD * aCoords->distance(aZero));
+      std::shared_ptr<GeomAPI_Pnt> anOrigPnt(new GeomAPI_Pnt(aCoords));
+      myShape = GeomAlgoAPI_FaceBuilder::squareFace(
+        myViewCentralPoint.get() ? myViewCentralPoint : anOrigPnt, aNormDir, mySizeOfView);
     }
-    return aAIS;
   }
+  myPlane = createPreviewPlane();
+
+  aDisp->displayAIS(myPlane, false/*load object in selection*/, 1/*shaded*/, false);
+  myPreviewIsDisplayed = true;
 }
 
-void PartSet_PreviewSketchPlane::getShapeParameters(const GeomShapePtr& theShape,
-                                                    std::shared_ptr<GeomAPI_Pnt>& theOrigin,
-                                                    double& theSize)
+double maximumSize(double theXmin, double theYmin, double theZmin,
+                   double theXmax, double theYmax, double theZmax)
 {
-  theOrigin = GeomAlgoAPI_ShapeTools::centreOfMass(theShape);
-
-  // Create rectangular face close to the selected
-  double aXmin, anYmin, aZmin, aXmax, anYmax, aZmax;
-  theShape->computeSize(aXmin, anYmin, aZmin, aXmax, anYmax, aZmax);
+  double aSize = fabs(theXmax - theXmin);
+  double aSizeToCompare = fabs(theYmax - theYmin);
+  if (aSizeToCompare > aSize)
+    aSize = aSizeToCompare;
+  aSizeToCompare = fabs(theZmax - theZmin);
+  if (aSizeToCompare > aSize)
+    aSize = aSizeToCompare;
 
-  theSize = maximumSize(aXmin, anYmin, aZmin, aXmax, anYmax, aZmax);
+  return aSize;
 }
 
-double PartSet_PreviewSketchPlane::getSketchBoundingBoxSize(
-                                 const std::shared_ptr<ModelAPI_CompositeFeature>& theSketch,
-                                 std::shared_ptr<GeomAPI_Pnt>& theCentralPnt)
+bool PartSet_PreviewSketchPlane::getDefaultSizeOfView(
+  const CompositeFeaturePtr& theSketch, double& theSizeOfView,
+  std::shared_ptr<GeomAPI_Pnt>& theCentralPnt)
 {
-  if (!theSketch.get() || theSketch->numberOfSubs() == 0)
-    return 0;
+  if (!PartSet_Tools::sketchPlane(theSketch).get())
+    return false;
+
+  AttributeSelectionPtr aSelAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>
+    (theSketch->data()->attribute(SketchPlugin_SketchEntity::EXTERNAL_ID()));
+  if (aSelAttr) {
+    myShape = aSelAttr->value();
+    // this case is needed by constructing sketch on a plane, where result shape is equal
+    // to context result, therefore value() returns NULL and we should use shape of context.
+    if (!myShape.get() && aSelAttr->context().get())
+      myShape = aSelAttr->context()->shape();
+  }
+
+  if (myShape.get())
+    return false;
 
   Bnd_Box aBox;
-  for (int aSubFeatureId = 0; aSubFeatureId < theSketch->numberOfSubs(); aSubFeatureId++) {
+  int aNumberOfSubs = theSketch->numberOfSubs();
+  for (int aSubFeatureId = 0; aSubFeatureId < aNumberOfSubs; aSubFeatureId++) {
     FeaturePtr aFeature = theSketch->subFeature(aSubFeatureId);
     if (!aFeature.get())
       continue;
@@ -228,12 +199,46 @@ double PartSet_PreviewSketchPlane::getSketchBoundingBoxSize(
   double aXmin, aXmax, anYmin, anYmax, aZmin, aZmax;
   aBox.Get(aXmin, anYmin, aZmin, aXmax, anYmax, aZmax);
 
-  double aSize = maximumSize(aXmin, anYmin, aZmin, aXmax, anYmax, aZmax);
-  if (aSize > 0) {
+  theSizeOfView = maximumSize(aXmin, anYmin, aZmin, aXmax, anYmax, aZmax);
+  if (theSizeOfView > 0) {
     gp_Pnt aCentre(aXmax-fabs(aXmax-aXmin)/2., anYmax-fabs(anYmax-anYmin)/2.,
                    aZmax - fabs(aZmax-aZmin)/2.);
     theCentralPnt = std::shared_ptr<GeomAPI_Pnt>(new GeomAPI_Pnt(aCentre.X(), aCentre.Y(),
                                                                  aCentre.Z()));
   }
-  return aSize;
-}
\ No newline at end of file
+  return true;
+}
+
+void PartSet_PreviewSketchPlane::setSizeOfView(double theSizeOfView, bool isUseSizeOfView,
+  const std::shared_ptr<GeomAPI_Pnt>& theCentralPoint)
+{
+  mySizeOfView = theSizeOfView;
+  myIsUseSizeOfView = isUseSizeOfView;
+
+  myViewCentralPoint = theCentralPoint;
+}
+
+AISObjectPtr PartSet_PreviewSketchPlane::createPreviewPlane()
+{
+  if (myPlane.get()) {
+    myPlane->createShape(myShape);
+    return myPlane;
+  }
+  else {
+    AISObjectPtr aAIS = AISObjectPtr(new GeomAPI_AISObject());
+    aAIS->createShape(myShape);
+    std::vector<int> aColor = Config_PropManager::color("Visualization", "sketch_preview_plane");
+    if (aColor.size() == 3)
+      aAIS->setColor(aColor[0], aColor[1], aColor[2]);
+    aAIS->setTransparensy(0.8);
+
+    int aDispMode = 1; // shading
+    Handle(AIS_InteractiveObject) anAISIO = aAIS->impl<Handle(AIS_InteractiveObject)>();
+    if (!anAISIO.IsNull()) {
+      //anAISIO->SetInfiniteState(Standard_True);
+      anAISIO->Attributes()->SetFaceBoundaryDraw( Standard_True );
+      anAISIO->SetDisplayMode(aDispMode);
+    }
+    return aAIS;
+  }
+}