Salome HOME
Issue #1303 Reordering menu items: Sketch action enable state
[modules/shaper.git] / src / SketcherPrs / SketcherPrs_Angle.cpp
index 8603dd444b790c0801d15a8dcc34b0db2bd56a87..d4264233e472f6088a1919de3b5682e1d3df9cb1 100644 (file)
@@ -6,6 +6,7 @@
 
 #include "SketcherPrs_Angle.h"
 #include "SketcherPrs_Tools.h"
+#include "SketcherPrs_DimensionStyleListener.h"
 
 #include <SketchPlugin_ConstraintAngle.h>
 #include <SketchPlugin_Constraint.h>
 
 #include <ModelAPI_AttributeRefAttr.h>
 #include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeInteger.h>
 
 #include <TopExp.hxx>
 #include <BRep_Tool.hxx>
 
+#include <Events_Error.h>
+
 #define PI 3.1415926535897932
 
 IMPLEMENT_STANDARD_HANDLE(SketcherPrs_Angle, AIS_AngleDimension);
 IMPLEMENT_STANDARD_RTTIEXT(SketcherPrs_Angle, AIS_AngleDimension);
 
-
 SketcherPrs_Angle::SketcherPrs_Angle(ModelAPI_Feature* theConstraint, 
                                      const std::shared_ptr<GeomAPI_Ax3>& thePlane)
 : AIS_AngleDimension(gp_Pnt(0,0,0), gp_Pnt(1,0,0), gp_Pnt(0,1,0)), myConstraint(theConstraint), myPlane(thePlane)
@@ -40,30 +43,36 @@ SketcherPrs_Angle::SketcherPrs_Angle(ModelAPI_Feature* theConstraint,
   
   SetDimensionAspect(myAspect);
   SetSelToleranceForText2d(SketcherPrs_Tools::getDefaultTextHeight());
+
+  myStyleListener = new SketcherPrs_DimensionStyleListener();
 }
 
-void SketcherPrs_Angle::Compute(const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
-                                const Handle(Prs3d_Presentation)& thePresentation, 
-                                const Standard_Integer theMode)
+SketcherPrs_Angle::~SketcherPrs_Angle()
 {
-  DataPtr aData = myConstraint->data();
+  delete myStyleListener;
+}
+
+bool SketcherPrs_Angle::IsReadyToDisplay(ModelAPI_Feature* theConstraint,
+                                         const std::shared_ptr<GeomAPI_Ax3>&/* thePlane*/)
+{
+  bool aReadyToDisplay = false;
+
+  DataPtr aData = theConstraint->data();
 
   // Flyout point
   std::shared_ptr<GeomDataAPI_Point2D> aFlyoutAttr = 
     std::dynamic_pointer_cast<GeomDataAPI_Point2D>
     (aData->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()));
   if (!aFlyoutAttr->isInitialized())
-    return; // can not create a good presentation
-
-  std::shared_ptr<GeomAPI_Pnt> aFlyoutPnt = myPlane->to3D(aFlyoutAttr->x(), aFlyoutAttr->y());
+    return aReadyToDisplay; // can not create a good presentation
 
   AttributeRefAttrPtr anAttr1 = aData->refattr(SketchPlugin_Constraint::ENTITY_A());
   if (!anAttr1->isInitialized())
-    return;
+    return aReadyToDisplay;
 
   AttributeRefAttrPtr anAttr2 = aData->refattr(SketchPlugin_Constraint::ENTITY_B());
   if (!anAttr2->isInitialized())
-    return;
+    return aReadyToDisplay;
 
   // Get angle edges
   ObjectPtr aObj1 = anAttr1->object();
@@ -72,43 +81,116 @@ void SketcherPrs_Angle::Compute(const Handle(PrsMgr_PresentationManager3d)& theP
   std::shared_ptr<GeomAPI_Shape> aShape1 = SketcherPrs_Tools::getShape(aObj1);
   std::shared_ptr<GeomAPI_Shape> aShape2 = SketcherPrs_Tools::getShape(aObj2);
 
-  if (!aShape1 && !aShape2)
-    return;
+  aReadyToDisplay = aShape1.get() && aShape2.get();
+  return aReadyToDisplay;
+}
+
+void SketcherPrs_Angle::Compute(const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
+                                const Handle(Prs3d_Presentation)& thePresentation, 
+                                const Standard_Integer theMode)
+{
+  DataPtr aData = myConstraint->data();
+
+  if (!IsReadyToDisplay(myConstraint, myPlane)) {
+    Events_Error::throwException("An empty AIS presentation: SketcherPrs_Angle");
+    return; // can not create a good presentation
+  }
+
+  std::shared_ptr<ModelAPI_AttributeInteger> aTypeAttr = std::dynamic_pointer_cast<
+      ModelAPI_AttributeInteger>(aData->attribute(SketchPlugin_ConstraintAngle::TYPE_ID()));
+  SketcherPrs_Tools::AngleType anAngleType = (SketcherPrs_Tools::AngleType)(aTypeAttr->value());
+
+  AttributeRefAttrPtr anAttr1 = aData->refattr(SketchPlugin_Constraint::ENTITY_A());
+  AttributeRefAttrPtr anAttr2 = aData->refattr(SketchPlugin_Constraint::ENTITY_B());
+
+  // Get angle edges
+  ObjectPtr aObj1 = anAttr1->object();
+  ObjectPtr aObj2 = anAttr2->object();
+
+  std::shared_ptr<GeomAPI_Shape> aShape1 = SketcherPrs_Tools::getShape(aObj1);
+  std::shared_ptr<GeomAPI_Shape> aShape2 = SketcherPrs_Tools::getShape(aObj2);
 
   TopoDS_Shape aTEdge1 = aShape1->impl<TopoDS_Shape>();
   TopoDS_Shape aTEdge2 = aShape2->impl<TopoDS_Shape>();
 
   TopoDS_Edge aEdge1 = TopoDS::Edge(aTEdge1);
   TopoDS_Edge aEdge2 = TopoDS::Edge(aTEdge2);
-  SetMeasuredGeometry(aEdge1, aEdge2);
-
-  // Compute intersection point
-  TopoDS_Vertex aV1, aV2;
-  TopExp::Vertices(aEdge1, aV1, aV2);
-  gp_Pnt aPnt1 = BRep_Tool::Pnt(aV1);
-  gp_Pnt aPnt2 = BRep_Tool::Pnt(aV2);
-  std::shared_ptr<GeomAPI_Lin> aL1(new GeomAPI_Lin(aPnt1.X(), aPnt1.Y(), aPnt1.Z(),
-                                                   aPnt2.X(), aPnt2.Y(), aPnt2.Z()));
-  TopExp::Vertices(aEdge2, aV1, aV2);
-  aPnt1 = BRep_Tool::Pnt(aV1);
-  aPnt2 = BRep_Tool::Pnt(aV2);
-  std::shared_ptr<GeomAPI_Lin> aL2(new GeomAPI_Lin(aPnt1.X(), aPnt1.Y(), aPnt1.Z(),
-                                                   aPnt2.X(), aPnt2.Y(), aPnt2.Z()));
-
-  std::shared_ptr<GeomAPI_Pnt> aInter = aL1->intersect(aL2);
-  gp_Pnt aCenter = aInter->impl<gp_Pnt>();
-
-  gp_Pnt aFLyPnt(aFlyoutPnt->x(), aFlyoutPnt->y(), aFlyoutPnt->z());
-  double aDist = aCenter.Distance(aFLyPnt);
+
+  double aDist = -1;
+
+  switch (anAngleType) {
+    case SketcherPrs_Tools::ANGLE_DIRECT: {
+      SetArrowVisible(Standard_False/*first*/, Standard_True/*second*/);
+      /*
+      std::shared_ptr<GeomAPI_Edge> anEdge1 = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(aShape1));
+      std::shared_ptr<GeomAPI_Edge> anEdge2 = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(aShape2));
+
+      std::shared_ptr<GeomAPI_Lin> aLin1 = anEdge1->line();
+      std::shared_ptr<GeomAPI_Lin> aLin2 = anEdge2->line();
+
+      std::shared_ptr<GeomAPI_Pnt> aCenterPnt = aLin1->intersect(aLin2);
+      std::shared_ptr<GeomAPI_Dir> aDir1 = aLin1->direction();
+      std::shared_ptr<GeomAPI_Dir> aDir2 = aLin2->direction();
+
+      const gp_Pnt& aCenterPoint = aCenterPnt->impl<gp_Pnt>();
+
+      const gp_Dir& aDirection1 = aDir1->impl<gp_Dir>();
+      const gp_Dir& aDirection2 = aDir2->impl<gp_Dir>();
+
+      gp_Pnt aFirstPoint  = aCenterPoint.Translated (gp_Vec (aDirection1));
+      gp_Pnt aSecondPoint = aCenterPoint.Translated (gp_Vec (aDirection2));
+
+      SetMeasuredGeometry(aFirstPoint, aCenterPoint, aSecondPoint);*/
+      SetMeasuredGeometry(aEdge1, aEdge2, Standard_False);
+      bool isReversedPlanes = isAnglePlaneReversedToSketchPlane();
+      SetAngleReversed(!isReversedPlanes);
+    }
+    break;
+    case SketcherPrs_Tools::ANGLE_COMPLEMENTARY: {
+      SetArrowVisible(Standard_True/*first*/, Standard_False/*second*/);
+      // to calculate center, first and end points
+      SetAngleReversed(false);
+      SetMeasuredGeometry(aEdge1, aEdge2, Standard_False);
+      /// the first point will be moved, so it is necessary to find distance
+      /// after applying initial parameters of geometry but before correcting them
+      /// for the current type of angle(complementary)
+      aDist = calculateDistanceToFlyoutPoint();
+      /// invert the first edge according to the angle center
+      gp_Pnt aCenter = CenterPoint();
+      gp_Pnt aFirst = FirstPoint();
+      gp_Pnt aSecond = SecondPoint();
+      double anEdge1Length = aCenter.Distance(aFirst);
+      aFirst = aCenter.Translated (gp_Vec(aCenter, aFirst).Normalized() * (-anEdge1Length));
+      anEdge1Length = aCenter.Distance(aFirst);
+
+      SetMeasuredGeometry(aFirst, aCenter, aSecond);
+    }
+    break;
+    case SketcherPrs_Tools::ANGLE_BACKWARD: {
+      SetArrowVisible(Standard_False/*first*/, Standard_True/*second*/);
+
+      SetMeasuredGeometry(aEdge1, aEdge2, Standard_False);
+      bool isReversedPlanes = isAnglePlaneReversedToSketchPlane();
+      SetAngleReversed(isReversedPlanes);
+    }
+    break;
+    default:
+      break;
+  }
+  if (aDist < 0) /// it was not calculated yet
+    aDist = calculateDistanceToFlyoutPoint();
   SetFlyout(aDist);
 
   // Angle value is in degrees
-  AttributeDoublePtr aVal = aData->real(SketchPlugin_Constraint::VALUE());
-  SetCustomValue(aVal->value() * PI / 180.0);
+  AttributeDoublePtr aVal = aData->real(SketchPlugin_ConstraintAngle::ANGLE_VALUE_ID());
+  SetCustomValue(aVal->value());
 
   myAspect->SetExtensionSize(myAspect->ArrowAspect()->Length());
   myAspect->SetArrowTailSize(myAspect->ArrowAspect()->Length());
 
+  SketcherPrs_Tools::setDisplaySpecialSymbol(this, aVal->usedParameters().size() > 0);
+  myStyleListener->updateDimensions(this, aVal);
+
   AIS_AngleDimension::Compute(thePresentationManager, thePresentation, theMode);
 }
 
@@ -137,3 +219,38 @@ void SketcherPrs_Angle::ComputeSelection(const Handle(SelectMgr_Selection)& aSel
   }
   AIS_AngleDimension::ComputeSelection(aSelection, aMode);
 }
+
+bool SketcherPrs_Angle::isAnglePlaneReversedToSketchPlane()
+{
+  bool aReversed = false;
+  if (!myPlane.get())
+    return aReversed;
+
+  gp_Pln aPlane = GetPlane();
+  gp_Dir aDir = aPlane.Axis().Direction();
+  double aDot = myPlane->normal()->dot(
+                std::shared_ptr<GeomAPI_Dir>(new GeomAPI_Dir(aDir.X(), aDir.Y(), aDir.Z())));
+  return aDot < 0;
+}
+
+double SketcherPrs_Angle::calculateDistanceToFlyoutPoint()
+{
+  const gp_Pnt& aCenter = CenterPoint();
+  const gp_Pnt& aFirst = FirstPoint();
+  const gp_Pnt& aSecond = SecondPoint();
+
+  // Flyout point
+  DataPtr aData = myConstraint->data();
+  std::shared_ptr<GeomDataAPI_Point2D> aFlyoutAttr = 
+                              std::dynamic_pointer_cast<GeomDataAPI_Point2D>
+                              (aData->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()));
+  std::shared_ptr<GeomAPI_Pnt> aFlyoutPnt = myPlane->to3D(aFlyoutAttr->x(), aFlyoutAttr->y());
+
+  gp_Dir aBisector((aFirst.XYZ() + aSecond.XYZ()) * 0.5 - aCenter.XYZ());
+  gp_Pnt aFlyPnt(aFlyoutPnt->x(), aFlyoutPnt->y(), aFlyoutPnt->z());
+  gp_XYZ aFlyDir = aFlyPnt.XYZ() - aCenter.XYZ();
+  double aDistance = aFlyDir.Dot(aBisector.XYZ());
+  // make a positive distance in order to AIS angle presentation is not reversed
+  aDistance = fabs(aDistance);
+  return aDistance;
+}