Salome HOME
Updated copyright comment
[modules/shaper.git] / src / SketchPlugin / SketchPlugin_Ellipse.cpp
index df323b1674c425972a5fd4967c57130812f71fd3..fb0f18e38d35df6b6483fc8552fab1a3c38f4cfe 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2017-2019  CEA/DEN, EDF R&D
+// Copyright (C) 2017-2024  CEA, EDF
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
 
-// File:        SketchPlugin_Ellipse.cpp
-// Created:     26 April 2017
-// Author:      Artem ZHIDKOV
-
 #include <SketchPlugin_Ellipse.h>
 #include <SketchPlugin_Sketch.h>
 
 #include <GeomAlgoAPI_EdgeBuilder.h>
+
+#include <GeomAPI_Dir2d.h>
 #include <GeomAPI_Edge.h>
 #include <GeomAPI_Ellipse.h>
+#include <GeomAPI_Pnt2d.h>
+
 #include <GeomDataAPI_Point2D.h>
+
 #include <ModelAPI_AttributeDouble.h>
 #include <ModelAPI_ResultConstruction.h>
 #include <ModelAPI_Session.h>
 #include <ModelAPI_Validator.h>
 
+#include <cmath>
+
 static const double tolerance = 1e-7;
 
 
@@ -44,10 +47,22 @@ SketchPlugin_Ellipse::SketchPlugin_Ellipse()
 void SketchPlugin_Ellipse::initDerivedClassAttributes()
 {
   data()->addAttribute(CENTER_ID(), GeomDataAPI_Point2D::typeId());
-  data()->addAttribute(FOCUS_ID(), GeomDataAPI_Point2D::typeId());
+  data()->addAttribute(FIRST_FOCUS_ID(), GeomDataAPI_Point2D::typeId());
+  data()->addAttribute(SECOND_FOCUS_ID(), GeomDataAPI_Point2D::typeId());
+  data()->addAttribute(MAJOR_AXIS_START_ID(), GeomDataAPI_Point2D::typeId());
+  data()->addAttribute(MAJOR_AXIS_END_ID(), GeomDataAPI_Point2D::typeId());
+  data()->addAttribute(MINOR_AXIS_START_ID(), GeomDataAPI_Point2D::typeId());
+  data()->addAttribute(MINOR_AXIS_END_ID(), GeomDataAPI_Point2D::typeId());
   data()->addAttribute(MAJOR_RADIUS_ID(), ModelAPI_AttributeDouble::typeId());
   data()->addAttribute(MINOR_RADIUS_ID(), ModelAPI_AttributeDouble::typeId());
 
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SECOND_FOCUS_ID());
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), MAJOR_AXIS_START_ID());
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), MAJOR_AXIS_END_ID());
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), MINOR_AXIS_START_ID());
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), MINOR_AXIS_END_ID());
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), MAJOR_RADIUS_ID());
+
   data()->addAttribute(EXTERNAL_ID(), ModelAPI_AttributeSelection::typeId());
   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), EXTERNAL_ID());
 }
@@ -59,46 +74,11 @@ void SketchPlugin_Ellipse::execute()
     return;
   }
 
-  // Compute a ellipse in 3D view.
-  std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr =
-      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(CENTER_ID()));
-  std::shared_ptr<GeomDataAPI_Point2D> aFocusAttr =
-      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(FOCUS_ID()));
-  AttributeDoublePtr aMajorRadiusAttr = real(MAJOR_RADIUS_ID());
-  AttributeDoublePtr aMinorRadiusAttr = real(MINOR_RADIUS_ID());
-  if (!aCenterAttr->isInitialized() ||
-      !aFocusAttr->isInitialized() ||
-      !aMajorRadiusAttr->isInitialized() ||
-      !aMinorRadiusAttr->isInitialized()) {
-    return;
-  }
-
-  double aMajorRadius = aMajorRadiusAttr->value();
-  double aMinorRadius = aMinorRadiusAttr->value();
-  if(aMajorRadius < tolerance || aMinorRadius < tolerance) {
-    return;
-  }
-
-  // Make a visible point.
-  SketchPlugin_Sketch::createPoint2DResult(this, aSketch, CENTER_ID(), 0);
-
-  std::shared_ptr<GeomDataAPI_Dir> aNDir = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
-      aSketch->attribute(SketchPlugin_Sketch::NORM_ID()));
+  // Calculate all characteristics of the ellipse.
+  fillCharacteristicPoints();
 
   // Make a visible ellipse.
-  std::shared_ptr<GeomAPI_Pnt> aCenter(aSketch->to3D(aCenterAttr->x(), aCenterAttr->y()));
-  std::shared_ptr<GeomAPI_Pnt> aFocus(aSketch->to3D(aFocusAttr->x(), aFocusAttr->y()));
-  std::shared_ptr<GeomAPI_Dir> aNormal = aNDir->dir();
-  std::shared_ptr<GeomAPI_Dir> aMajorAxis(new GeomAPI_Dir(aFocus->x() - aCenter->x(),
-      aFocus->y() - aCenter->y(), aFocus->z() - aCenter->z()));
-
-  std::shared_ptr<GeomAPI_Shape> anEllipseShape =
-      GeomAlgoAPI_EdgeBuilder::ellipse(aCenter, aNormal, aMajorAxis, aMajorRadius, aMinorRadius);
-
-  std::shared_ptr<ModelAPI_ResultConstruction> aResult = document()->createConstruction(data(), 1);
-  aResult->setShape(anEllipseShape);
-  aResult->setIsInHistory(false);
-  setResult(aResult, 1);
+  createEllipse(aSketch, 0);
 }
 
 bool SketchPlugin_Ellipse::isFixed() {
@@ -125,7 +105,7 @@ void SketchPlugin_Ellipse::attributeChanged(const std::string& theID) {
       aCenterAttr->setValue(sketch()->to2D(anEllipse->center()));
 
       std::shared_ptr<GeomDataAPI_Point2D> aFocusAttr =
-          std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(FOCUS_ID()));
+          std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(FIRST_FOCUS_ID()));
       aFocusAttr->setValue(sketch()->to2D(anEllipse->firstFocus()));
 
       real(MAJOR_RADIUS_ID())->setValue(anEllipse->majorRadius());
@@ -133,3 +113,92 @@ void SketchPlugin_Ellipse::attributeChanged(const std::string& theID) {
     }
   }
 }
+
+bool SketchPlugin_Ellipse::fillCharacteristicPoints()
+{
+  std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr =
+      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(CENTER_ID()));
+  std::shared_ptr<GeomDataAPI_Point2D> aFocusAttr =
+      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(FIRST_FOCUS_ID()));
+
+  AttributeDoublePtr aMinorRadiusAttr = real(MINOR_RADIUS_ID());
+
+  if (!aCenterAttr->isInitialized() ||
+      !aFocusAttr->isInitialized() ||
+      !aMinorRadiusAttr->isInitialized()) {
+    return false;
+  }
+
+  double aMinorRadius = aMinorRadiusAttr->value();
+  if (aMinorRadius < tolerance) {
+    return false;
+  }
+
+  bool aWasBlocked = data()->blockSendAttributeUpdated(true);
+  GeomPnt2dPtr aCenter2d = aCenterAttr->pnt();
+  GeomPnt2dPtr aFocus2d = aFocusAttr->pnt();
+  GeomDir2dPtr aMajorDir2d(new GeomAPI_Dir2d(aFocus2d->x() - aCenter2d->x(),
+    aFocus2d->y() - aCenter2d->y()));
+  GeomDir2dPtr aMinorDir2d(new GeomAPI_Dir2d(-aMajorDir2d->y(), aMajorDir2d->x()));
+
+  AttributeDoublePtr aMajorRadiusAttr = real(MAJOR_RADIUS_ID());
+  double aFocalDist = aCenter2d->distance(aFocus2d);
+  double aMajorRadius = sqrt(aFocalDist * aFocalDist + aMinorRadius * aMinorRadius);
+  if (!aMajorRadiusAttr->isInitialized() ||
+      fabs(aMajorRadiusAttr->value() - aMajorRadius) > tolerance)
+    aMajorRadiusAttr->setValue(aMajorRadius);
+
+  std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(SECOND_FOCUS_ID()))
+    ->setValue(2.0 * aCenter2d->x() - aFocus2d->x(), 2.0 * aCenter2d->y() - aFocus2d->y());
+  std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(MAJOR_AXIS_START_ID()))
+      ->setValue(aCenter2d->x() - aMajorDir2d->x() * aMajorRadius,
+                 aCenter2d->y() - aMajorDir2d->y() * aMajorRadius);
+  std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(MAJOR_AXIS_END_ID()))
+      ->setValue(aCenter2d->x() + aMajorDir2d->x() * aMajorRadius,
+                 aCenter2d->y() + aMajorDir2d->y() * aMajorRadius);
+  std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(MINOR_AXIS_START_ID()))
+      ->setValue(aCenter2d->x() - aMinorDir2d->x() * aMinorRadius,
+                 aCenter2d->y() - aMinorDir2d->y() * aMinorRadius);
+  std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(MINOR_AXIS_END_ID()))
+      ->setValue(aCenter2d->x() + aMinorDir2d->x() * aMinorRadius,
+                 aCenter2d->y() + aMinorDir2d->y() * aMinorRadius);
+  data()->blockSendAttributeUpdated(aWasBlocked);
+
+  return true;
+}
+
+void SketchPlugin_Ellipse::createEllipse(SketchPlugin_Sketch* theSketch, const int theResultIndex)
+{
+  // Compute a ellipse in 3D view.
+  std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr =
+    std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(CENTER_ID()));
+  std::shared_ptr<GeomDataAPI_Point2D> aFocusAttr =
+    std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(FIRST_FOCUS_ID()));
+
+  double aMajorRadius = real(MAJOR_RADIUS_ID())->value();
+  double aMinorRadius = real(MINOR_RADIUS_ID())->value();
+
+  std::shared_ptr<GeomDataAPI_Dir> aNDir = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
+    theSketch->attribute(SketchPlugin_Sketch::NORM_ID()));
+
+  GeomPointPtr aCenter(theSketch->to3D(aCenterAttr->x(), aCenterAttr->y()));
+  GeomPointPtr aFocus(theSketch->to3D(aFocusAttr->x(), aFocusAttr->y()));
+  GeomDirPtr aNormal = aNDir->dir();
+  std::shared_ptr<GeomAPI_Shape> anEllipseShape;
+  if (aFocus->distance(aCenter) > tolerance) {
+    GeomDirPtr aMajorAxis(new GeomAPI_Dir(aFocus->x() - aCenter->x(),
+        aFocus->y() - aCenter->y(), aFocus->z() - aCenter->z()));
+
+    anEllipseShape =
+        GeomAlgoAPI_EdgeBuilder::ellipse(aCenter, aNormal, aMajorAxis, aMajorRadius, aMinorRadius);
+  }
+  else {
+    // build circle instead of ellipse
+    anEllipseShape = GeomAlgoAPI_EdgeBuilder::lineCircle(aCenter, aNormal, aMajorRadius);
+  }
+
+  ResultConstructionPtr aResult = document()->createConstruction(data(), theResultIndex);
+  aResult->setShape(anEllipseShape);
+  aResult->setIsInHistory(false);
+  setResult(aResult, theResultIndex);
+}