]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
refs #80 - Sketch base GUI: create/draw point, circle and arc
authornds <natalia.donis@opencascade.com>
Tue, 17 Jun 2014 14:33:18 +0000 (18:33 +0400)
committernds <natalia.donis@opencascade.com>
Tue, 17 Jun 2014 14:33:18 +0000 (18:33 +0400)
1. Using the GeomAPI_Lin projection/distance for a line to be used later for a lenght constraint.
2. Correct projection() in the Line
3. Append double flyout value argument to the constraint.
4. Add lenght constraint presentation and operation to create it(may be later it will be join with feature create operation)

15 files changed:
src/GeomAPI/GeomAPI_Lin2d.cpp
src/PartSet/CMakeLists.txt
src/PartSet/PartSet_FeatureLengthPrs.cpp [new file with mode: 0644]
src/PartSet/PartSet_FeatureLengthPrs.h [new file with mode: 0644]
src/PartSet/PartSet_FeatureLinePrs.cpp
src/PartSet/PartSet_Module.cpp
src/PartSet/PartSet_OperationConstraint.cpp
src/PartSet/PartSet_OperationCreateConstraint.cpp [new file with mode: 0644]
src/PartSet/PartSet_OperationCreateConstraint.h [new file with mode: 0644]
src/PartSet/PartSet_Presentation.cpp
src/PartSet/PartSet_Tools.cpp
src/PartSet/PartSet_Tools.h
src/SketchPlugin/SketchPlugin_Constraint.h
src/SketchPlugin/SketchPlugin_ConstraintLength.cpp
src/SketchPlugin/SketchPlugin_ConstraintLength.h

index 2d698c089a4c23149e1294cebacec7820a5a58ee..8eb102ae56b235f99da82eb63b629de463085271 100644 (file)
@@ -45,7 +45,7 @@ const boost::shared_ptr<GeomAPI_Pnt2d> GeomAPI_Lin2d::intersect(
   IntAna2d_AnaIntersection anInter(*MY_LIN2D, theLine->impl<gp_Lin2d>());
   if (!anInter.IsDone() || anInter.IsEmpty())
     return boost::shared_ptr<GeomAPI_Pnt2d>();
-  const gp_Pnt2d& aResult = anInter.Point(0).Value();
+  const gp_Pnt2d& aResult = anInter.Point(1).Value();
   return boost::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(aResult.X(), aResult.Y()));
 }
 
@@ -56,7 +56,7 @@ const boost::shared_ptr<GeomAPI_Pnt2d> GeomAPI_Lin2d::project(const boost::share
   const gp_XY& aPnt = thePoint->impl<gp_Pnt2d>().XY();
   double aParam = aDir.Dot(aPnt - aLoc);
 
-  gp_XY aResult = aPnt + aDir * aParam;
+  gp_XY aResult = aLoc + aDir * aParam;
   return boost::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(aResult.X(), aResult.Y()));
 }
 
index bb812080dea5ea5967af82ed346c3b5d63ba9cb0..7c38f2fa093662a36a0c612f1bc67e7340cd1892 100644 (file)
@@ -8,11 +8,13 @@ SET(PROJECT_HEADERS
        PartSet_FeatureArcPrs.h
        PartSet_FeatureCirclePrs.h
        PartSet_FeaturePrs.h
+       PartSet_FeatureLengthPrs.h
        PartSet_FeatureLinePrs.h
        PartSet_FeaturePointPrs.h
        PartSet_Listener.h
        PartSet_Module.h
        PartSet_OperationConstraint.h
+       PartSet_OperationCreateConstraint.h
        PartSet_OperationCreateFeature.h
        PartSet_OperationEditFeature.h
        PartSet_OperationSketchBase.h
@@ -26,11 +28,13 @@ SET(PROJECT_SOURCES
        PartSet_FeaturePrs.cpp
        PartSet_FeatureArcPrs.cpp
        PartSet_FeatureCirclePrs.cpp
+       PartSet_FeatureLengthPrs.cpp
        PartSet_FeatureLinePrs.cpp
        PartSet_FeaturePointPrs.cpp
        PartSet_Listener.cpp
        PartSet_Module.cpp
        PartSet_OperationConstraint.cpp
+       PartSet_OperationCreateConstraint.cpp
        PartSet_OperationCreateFeature.cpp
        PartSet_OperationEditFeature.cpp
        PartSet_OperationSketchBase.cpp
diff --git a/src/PartSet/PartSet_FeatureLengthPrs.cpp b/src/PartSet/PartSet_FeatureLengthPrs.cpp
new file mode 100644 (file)
index 0000000..944e7c5
--- /dev/null
@@ -0,0 +1,174 @@
+// File:        PartSet_FeaturePrs.h
+// Created:     16 Jun 2014
+// Author:      Natalia ERMOLAEVA
+
+#include <PartSet_FeatureLengthPrs.h>
+#include <PartSet_Tools.h>
+
+#include <SketchPlugin_Feature.h>
+#include <SketchPlugin_Sketch.h>
+#include <SketchPlugin_Line.h>
+#include <SketchPlugin_ConstraintLength.h>
+
+#include <GeomDataAPI_Point2D.h>
+#include <GeomAPI_Pnt2d.h>
+
+#include <ModelAPI_Data.h>
+#include <ModelAPI_Document.h>
+#include <ModelAPI_AttributeRefAttr.h>
+#include <ModelAPI_AttributeRefList.h>
+
+#include <Precision.hxx>
+
+using namespace std;
+
+PartSet_FeatureLengthPrs::PartSet_FeatureLengthPrs(FeaturePtr theSketch)
+: PartSet_FeaturePrs(theSketch)
+{
+}
+
+std::string PartSet_FeatureLengthPrs::getKind()
+{
+  return SKETCH_CONSTRAINT_LENGTH_KIND;
+}
+
+PartSet_SelectionMode PartSet_FeatureLengthPrs::setPoint(double theX, double theY,
+                                                         const PartSet_SelectionMode& theMode)
+{
+  PartSet_SelectionMode aMode = theMode;
+  switch (theMode)
+  {
+    case SM_FirstPoint: {
+      //PartSet_Tools::setFeaturePoint(feature(), theX, theY, CIRCLE_ATTR_CENTER);
+      //aMode = SM_SecondPoint;
+    }
+    break;
+    case SM_SecondPoint: {
+      /*boost::shared_ptr<ModelAPI_Data> aData = feature()->data();
+      boost::shared_ptr<GeomDataAPI_Point2D> aPoint = boost::dynamic_pointer_cast<GeomDataAPI_Point2D>
+                                                                  (aData->attribute(CIRCLE_ATTR_CENTER));
+      boost::shared_ptr<GeomAPI_Pnt2d> aCoordPoint(new GeomAPI_Pnt2d(theX, theY));
+      double aRadius = aCoordPoint->distance(aPoint->pnt());
+      PartSet_Tools::setFeatureValue(feature(), aRadius, CIRCLE_ATTR_RADIUS);
+
+      aMode = SM_DonePoint;*/
+   }
+    break;
+    default:
+      break;
+  }
+  return aMode;
+}
+
+std::string PartSet_FeatureLengthPrs::getAttribute(const PartSet_SelectionMode& theMode) const
+{
+  std::string aAttribute;
+  switch (theMode)
+  {
+    case SM_FirstPoint:
+      //aAttribute = CIRCLE_ATTR_CENTER;
+    break;
+    case SM_SecondPoint:
+      //aAttribute = CIRCLE_ATTR_RADIUS;
+    break;
+    default:
+    break;
+  }
+  return aAttribute;
+}
+
+PartSet_SelectionMode PartSet_FeatureLengthPrs::getNextMode(const std::string& theAttribute) const
+{
+  PartSet_SelectionMode aMode = SM_SecondPoint;
+
+  /*if (theAttribute == CIRCLE_ATTR_CENTER)
+    aMode = SM_SecondPoint;
+  else if (theAttribute == CIRCLE_ATTR_RADIUS)
+    aMode = SM_DonePoint;*/
+  return aMode;
+}
+
+void PartSet_FeatureLengthPrs::move(double theDeltaX, double theDeltaY)
+{
+  /*boost::shared_ptr<ModelAPI_Data> aData = feature()->data();
+  if (!aData->isValid())
+    return;
+
+  boost::shared_ptr<GeomDataAPI_Point2D> aPoint1 =
+        boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(CIRCLE_ATTR_CENTER));
+  aPoint1->setValue(aPoint1->x() + theDeltaX, aPoint1->y() + theDeltaY);*/
+}
+
+double PartSet_FeatureLengthPrs::distanceToPoint(FeaturePtr theFeature,
+                                                 double theX, double theY)
+{
+  /*double aDelta = 0;
+  if (!theFeature || theFeature->getKind() != getKind())
+    return aDelta;
+
+  boost::shared_ptr<ModelAPI_Data> aData = theFeature->data();
+  boost::shared_ptr<GeomDataAPI_Point2D> aPoint =
+        boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(CIRCLE_ATTR_CENTER));
+
+  boost::shared_ptr<GeomAPI_Pnt2d> aPoint2d(new GeomAPI_Pnt2d(theX, theY));
+  return aPoint->pnt()->distance(aPoint2d);*/
+  return 0;
+}
+
+boost::shared_ptr<GeomDataAPI_Point2D> PartSet_FeatureLengthPrs::findPoint(FeaturePtr theFeature,
+                                                                           double theX, double theY)
+{
+  boost::shared_ptr<GeomDataAPI_Point2D> aPoint2D;
+  /*if (!theFeature || theFeature->getKind() != getKind())
+    return aPoint2D;
+
+  boost::shared_ptr<ModelAPI_Data> aData = theFeature->data();
+  boost::shared_ptr<GeomDataAPI_Point2D> aPoint =
+        boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(CIRCLE_ATTR_CENTER));
+  if (fabs(aPoint->x() - theX) < Precision::Confusion() && fabs(aPoint->y() - theY) < Precision::Confusion() )
+    aPoint2D = aPoint;
+*/
+  return aPoint2D;
+}
+
+boost::shared_ptr<GeomDataAPI_Point2D> PartSet_FeatureLengthPrs::featurePoint
+                                                     (const PartSet_SelectionMode& theMode)
+{
+  /*std::string aPointArg;
+  switch (theMode)
+  {
+    case SM_FirstPoint:
+      aPointArg = CIRCLE_ATTR_CENTER;
+      break;
+    default:
+      break;
+  }
+  boost::shared_ptr<ModelAPI_Data> aData = feature()->data();
+  boost::shared_ptr<GeomDataAPI_Point2D> aPoint = boost::dynamic_pointer_cast<GeomDataAPI_Point2D>
+                                                              (aData->attribute(aPointArg));
+  return aPoint;
+  */
+  return boost::shared_ptr<GeomDataAPI_Point2D>();
+}
+
+void PartSet_FeatureLengthPrs::initFeature(FeaturePtr theSourceFeature)
+{
+  if (feature() && theSourceFeature && theSourceFeature->getKind() == SKETCH_LINE_KIND)
+  {
+    // set length feature
+    boost::shared_ptr<ModelAPI_Data> aData = feature()->data();
+    boost::shared_ptr<ModelAPI_AttributeRefAttr> aRef =
+          boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(aData->attribute(CONSTRAINT_ATTR_ENTITY_A));
+    aRef->setFeature(theSourceFeature);
+
+    // set length value
+    aData = theSourceFeature->data();
+    boost::shared_ptr<GeomDataAPI_Point2D> aPoint1 =
+          boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(LINE_ATTR_START));
+    boost::shared_ptr<GeomDataAPI_Point2D> aPoint2 =
+          boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(LINE_ATTR_END));
+
+    double aLenght = aPoint1->pnt()->distance(aPoint2->pnt());
+    PartSet_Tools::setFeatureValue(feature(), aLenght, CONSTRAINT_ATTR_VALUE);
+  }
+}
diff --git a/src/PartSet/PartSet_FeatureLengthPrs.h b/src/PartSet/PartSet_FeatureLengthPrs.h
new file mode 100644 (file)
index 0000000..2c39f38
--- /dev/null
@@ -0,0 +1,78 @@
+// File:        PartSet_FeatureLengthPrs.h
+// Created:     16 Jun 2014
+// Author:      Natalia ERMOLAEVA
+
+#ifndef PartSet_FeatureLengthPrs_H
+#define PartSet_FeatureLengthPrs_H
+
+#include "PartSet.h"
+
+#include "PartSet_FeaturePrs.h"
+#include "PartSet_Constants.h"
+
+class GeomDataAPI_Point2D;
+
+/*!
+ \class PartSet_FeatureLengthPrs
+ * \brief The class to define the circle feature manipulation. It is created for
+ * the feature create operation to move out the feature properties set and use one operation
+ * for any type of features.
+*/
+class PARTSET_EXPORT PartSet_FeatureLengthPrs : public PartSet_FeaturePrs
+{
+public:
+  /// Returns the feature type processed by this presentation
+  /// \return the feature kind
+  static std::string getKind();
+
+  /// Constructor
+  /// \param theSketch the sketch feature
+  PartSet_FeatureLengthPrs(FeaturePtr theSketch);
+  /// Destructor
+  virtual ~PartSet_FeatureLengthPrs() {};
+
+  /// Sets the point to the feature in an attribute depending on the selection mode
+  /// \param theX the 2D point horizontal coordinate
+  /// \param theY the 2D point vertical coordinate
+  /// \param theMode the selection mode
+  /// \return the new selection mode
+  virtual PartSet_SelectionMode setPoint(double theX, double theY,
+                                         const PartSet_SelectionMode& theMode);
+
+  /// Returns the feature attribute name for the selection mode
+  /// \param theMode the current operation selection mode. The feature attribute depends on the mode
+  virtual std::string getAttribute(const PartSet_SelectionMode& theMode) const;
+
+  /// Returns the next selection mode after the attribute
+  /// \param theAttribute the feature attribute name
+  /// \return next attribute selection mode
+  virtual PartSet_SelectionMode getNextMode(const std::string& theAttribute) const;
+
+  /// \brief Move the full feature.
+  /// \param theDeltaX the delta for X coordinate is moved
+  /// \param theDeltaY the delta for Y coordinate is moved
+  virtual void move(double theDeltaX, double theDeltaY);
+
+  /// Return the distance between the feature and the point
+  /// \param theFeature feature object
+  /// \param theX the horizontal coordinate of the point
+  /// \param theX the vertical coordinate of the point
+  virtual double distanceToPoint(FeaturePtr theFeature, double theX, double theY);
+
+  /// Find a point in the line with given coordinates
+  /// \param theFeature the line feature
+  /// \param theX the horizontal point coordinate
+  /// \param theY the vertical point coordinate
+  virtual boost::shared_ptr<GeomDataAPI_Point2D> findPoint(FeaturePtr theFeature, double theX,
+                                                           double theY);
+protected:
+  /// Returns the feature point in the selection mode position.
+  /// \param theMode the current operation selection mode. The feature attribute depends on the mode
+  virtual boost::shared_ptr<GeomDataAPI_Point2D> featurePoint(const PartSet_SelectionMode& theMode);
+
+  /// Initializes current feature by the given
+  /// \param theSourceFeature the feature, which attributes are used to initialize the current feature
+  virtual void initFeature(FeaturePtr theSourceFeature);
+};
+
+#endif
index 54af4c9737b90afa6240782dee35da4360d765ac..ae85a3d88b730f0e81ae7150f4a4e552aab6395f 100644 (file)
@@ -12,6 +12,8 @@
 #include <SketchPlugin_Constraint.h>
 
 #include <GeomDataAPI_Point2D.h>
+#include <GeomAPI_Lin2d.h>
+#include <GeomAPI_Pnt2d.h>
 
 #include <ModelAPI_Data.h>
 #include <ModelAPI_Document.h>
@@ -122,20 +124,36 @@ void PartSet_FeatureLinePrs::projectPointOnLine(FeaturePtr theFeature,
                                                 const gp_Pnt& thePoint, Handle(V3d_View) theView,
                                                 double& theX, double& theY)
 {
-  if (theFeature) {
+  if (theFeature && theFeature->getKind() == getKind()) {
     double X0, X1, X2, X3;
     double Y0, Y1, Y2, Y3;
     getLinePoint(theFeature, LINE_ATTR_START, X2, Y2);
     getLinePoint(theFeature, LINE_ATTR_END, X3, Y3);
-    PartSet_Tools::convertTo2D(thePoint, sketch(), theView, X1, Y1);
 
+    PartSet_Tools::convertTo2D(thePoint, sketch(), theView, X1, Y1);
+    boost::shared_ptr<GeomAPI_Pnt2d> aPoint = boost::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(X1, Y1));
+    boost::shared_ptr<GeomAPI_Lin2d> aFeatureLin = boost::shared_ptr<GeomAPI_Lin2d>
+                                                         (new GeomAPI_Lin2d(X2, Y2, X3, Y3));
     switch (theMode) {
-      case SM_FirstPoint:
-        PartSet_Tools::projectPointOnLine(X2, Y2, X3, Y3, X1, Y1, theX, theY);
+      case SM_FirstPoint: {
+        boost::shared_ptr<GeomAPI_Pnt2d> aResult = aFeatureLin->project(aPoint);
+        theX = aResult->x();
+        theY = aResult->y();
+      }
       break;
       case SM_SecondPoint: {
         getLinePoint(feature(), LINE_ATTR_START, X0, Y0);
-        PartSet_Tools::intersectLines(X0, Y0, X1, Y1, X2, Y2, X3, Y3, theX, theY);
+        boost::shared_ptr<GeomAPI_Lin2d> aCurrentLin = boost::shared_ptr<GeomAPI_Lin2d>
+                                                           (new GeomAPI_Lin2d(X0, Y0, X1, Y1));
+        boost::shared_ptr<GeomAPI_Pnt2d> aResult = aFeatureLin->intersect(aCurrentLin);
+        boost::shared_ptr<GeomAPI_Pnt2d> aPoint0 = boost::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(X0, Y0));
+        if (aResult->distance(aPoint0) < Precision::Confusion()) { // the start point is nearest to the line
+          // if the first point of a line belongs to the given line
+          // we need to project the second point on the same line
+          aResult = aFeatureLin->project(aPoint);
+        }
+        theX = aResult->x();
+        theY = aResult->y();
       }
       break;
       default:
@@ -157,9 +175,16 @@ double PartSet_FeatureLinePrs::distanceToPoint(FeaturePtr theFeature,
   boost::shared_ptr<GeomDataAPI_Point2D> aPoint2 =
         boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(LINE_ATTR_END));
 
-  double aX, anY;
-  PartSet_Tools::projectPointOnLine(aPoint1->x(), aPoint1->y(), aPoint2->x(), aPoint2->y(), theX, theY, aX, anY);
-  aDelta = gp_Pnt(theX, theY, 0).Distance(gp_Pnt(aX, anY, 0));
+  GeomAPI_Lin2d aLin2d(aPoint1->x(), aPoint1->y(), aPoint2->x(), aPoint2->y());
+  boost::shared_ptr<GeomAPI_Pnt2d> aPoint = boost::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(theX, theY));
+
+  if (false/*projection*/) { // TODO: if it has not been necessary, remove this block
+    boost::shared_ptr<GeomAPI_Pnt2d> aResult = aLin2d.project(aPoint);
+    aDelta = aResult->distance(aPoint);
+  }
+  else { // distance
+    aDelta = aLin2d.distance(aPoint);
+  }
 
   return aDelta;
 }
index f33b67a13d65d735f3206f13858b0df0066a9f84..8b683a16905500449d12ac6c067d8844d33caeeb 100644 (file)
@@ -3,6 +3,7 @@
 #include <PartSet_OperationCreateFeature.h>
 #include <PartSet_OperationEditFeature.h>
 #include <PartSet_OperationConstraint.h>
+#include <PartSet_OperationCreateConstraint.h>
 #include <ModuleBase_Operation.h>
 #include <ModuleBase_OperationDescription.h>
 #include <ModuleBase_WidgetFactory.h>
@@ -327,6 +328,8 @@ ModuleBase_Operation* PartSet_Module::createOperation(const std::string& theCmdI
       anOperation = new PartSet_OperationCreateFeature(theCmdId.c_str(), this, aSketch);
     else if (theCmdId == PartSet_OperationEditFeature::Type())
       anOperation = new PartSet_OperationEditFeature(theCmdId.c_str(), this, aSketch);
+    else if (PartSet_OperationCreateConstraint::canProcessKind(theCmdId))
+      anOperation = new PartSet_OperationCreateConstraint(theCmdId.c_str(), this, aSketch);
     else if (theCmdId == PartSet_OperationConstraint::Type())
       anOperation = new PartSet_OperationConstraint(theCmdId.c_str(), this, aSketch);
   }
index 447f7a4d30b34bb094e5d087dc81876a627b4c3a..3a96b309a914e48be00cf398f2d283e0a2a90d25 100644 (file)
@@ -79,23 +79,7 @@ void PartSet_OperationConstraint::mouseReleased(QMouseEvent* theEvent, Handle(V3
                                                 const std::list<XGUI_ViewerPrs>& theSelected,
                                                 const std::list<XGUI_ViewerPrs>& /*theHighlighted*/)
 {
-  /*if (myPointSelectionMode == SM_DonePoint)
-  {
-    // if the point creation is finished, the next mouse release should commit the modification
-    // the next release can happens by double click in the viewer
-    commit();
-    restartOperation(PartSet_OperationConstraint::Type(), feature());
-    return;
-  }
-
-  double aX, anY;
-
-  bool isFoundPoint = false;
-  gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), theView);
-*/
   if (theSelected.empty()) {
-    //PartSet_Tools::convertTo2D(aPoint, sketch(), theView, aX, anY);
-    //isFoundPoint = true;
   }
   else {
     XGUI_ViewerPrs aPrs = theSelected.front();
@@ -104,100 +88,11 @@ void PartSet_OperationConstraint::mouseReleased(QMouseEvent* theEvent, Handle(V3
     setFeature(aFeature);
     setValue(120);
     flushUpdated();
-
-    /*const TopoDS_Shape& aShape = aPrs.shape();
-    if (!aShape.IsNull()) // the point is selected
-    {
-      if (aShape.ShapeType() == TopAbs_VERTEX) {
-        const TopoDS_Vertex& aVertex = TopoDS::Vertex(aShape);
-        if (!aVertex.IsNull()) {
-          aPoint = BRep_Tool::Pnt(aVertex);
-          PartSet_Tools::convertTo2D(aPoint, sketch(), theView, aX, anY);
-          isFoundPoint = true;
-
-          setConstraints(aX, anY);
-        }
-      }
-      else if (aShape.ShapeType() == TopAbs_EDGE) // the line is selected
-      {
-        FeaturePtr aFeature = aPrs.feature();
-        if (aFeature) {
-          double X0, X1, X2, X3;
-          double Y0, Y1, Y2, Y3;
-          PartSet_Tools::getLinePoint(aFeature, LINE_ATTR_START, X2, Y2);
-          PartSet_Tools::getLinePoint(aFeature, LINE_ATTR_END, X3, Y3);
-          PartSet_Tools::convertTo2D(aPoint, sketch(), theView, X1, Y1);
-
-          switch (myPointSelectionMode) {
-            case SM_FirstPoint:
-              PartSet_Tools::projectPointOnLine(X2, Y2, X3, Y3, X1, Y1, aX, anY);
-            break;
-            case SM_SecondPoint: {
-              PartSet_Tools::getLinePoint(feature(), LINE_ATTR_START, X0, Y0);
-              PartSet_Tools::intersectLines(X0, Y0, X1, Y1, X2, Y2, X3, Y3, aX, anY);
-            }
-            break;
-            default:
-            break;
-          }
-          isFoundPoint = true;
-        }
-      }
-    }*/
   }
-
-  /*switch (myPointSelectionMode)
-  {
-    case SM_FirstPoint: {
-      setLinePoint(feature(), aX, anY, LINE_ATTR_START);
-      setLinePoint(feature(), aX, anY, LINE_ATTR_END);
-      flushUpdated();
-
-      //setPointSelectionMode(SM_SecondPoint);
-    }
-    break;
-    case SM_SecondPoint: {
-      setLinePoint(feature(), aX, anY, LINE_ATTR_END);
-      flushUpdated();
-
-      //setPointSelectionMode(SM_DonePoint);
-   }
-    break;
-    default:
-      break;
-  }*/
 }
 
 void PartSet_OperationConstraint::mouseMoved(QMouseEvent* theEvent, Handle(V3d_View) theView)
 {
-/*  switch (myPointSelectionMode)
-  {
-    case SM_FirstPoint: {
-      double aX, anY;
-      gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), theView);
-      PartSet_Tools::convertTo2D(aPoint, sketch(), theView, aX, anY);
-      setLinePoint(feature(), aX, anY, LINE_ATTR_START);
-      setLinePoint(feature(), aX, anY, LINE_ATTR_END);
-      flushUpdated();
-      emit focusActivated(LINE_ATTR_START);
-    }
-    break;
-    case SM_SecondPoint:
-    {
-      gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), theView);
-      setLinePoint(aPoint, theView, LINE_ATTR_END);
-      flushUpdated();
-      emit focusActivated(LINE_ATTR_END);
-    }
-    break;
-    case SM_DonePoint:
-    {
-      commit();
-      restartOperation(PartSet_OperationConstraint::Type(), feature());
-    }
-    default:
-      break;
-  }*/
 }
 
 void PartSet_OperationConstraint::startOperation()
diff --git a/src/PartSet/PartSet_OperationCreateConstraint.cpp b/src/PartSet/PartSet_OperationCreateConstraint.cpp
new file mode 100644 (file)
index 0000000..a648c82
--- /dev/null
@@ -0,0 +1,239 @@
+// File:        PartSet_OperationCreateConstraint.h
+// Created:     20 Apr 2014
+// Author:      Natalia ERMOLAEVA
+
+#include <PartSet_OperationCreateConstraint.h>
+
+#include <PartSet_Tools.h>
+#include <PartSet_OperationSketch.h>
+#include <PartSet_FeaturePointPrs.h>
+#include <PartSet_FeatureLinePrs.h>
+#include <PartSet_FeatureCirclePrs.h>
+#include <PartSet_FeatureArcPrs.h>
+
+#include <SketchPlugin_Feature.h>
+#include <SketchPlugin_Point.h>
+#include <SketchPlugin_Line.h>
+#include <SketchPlugin_Circle.h>
+#include <SketchPlugin_Arc.h>
+
+#include <SketchPlugin_ConstraintLength.h>
+
+#include <ModuleBase_OperationDescription.h>
+
+#include <XGUI_ViewerPrs.h>
+#include <XGUI_Constants.h>
+
+#include <V3d_View.hxx>
+#include <TopoDS_Vertex.hxx>
+#include <TopoDS.hxx>
+#include <BRep_Tool.hxx>
+
+#ifdef _DEBUG
+#include <QDebug>
+#endif
+
+#include <QMouseEvent>
+
+using namespace std;
+
+PartSet_OperationCreateConstraint::PartSet_OperationCreateConstraint(const QString& theId,
+                                                               QObject* theParent,
+                                                               FeaturePtr theFeature)
+: PartSet_OperationSketchBase(theId, theParent),
+  myPointSelectionMode(SM_FirstPoint)
+{
+  std::string aKind = theId.toStdString();
+  myFeaturePrs = PartSet_Tools::createFeaturePrs(aKind, theFeature);
+}
+
+PartSet_OperationCreateConstraint::~PartSet_OperationCreateConstraint()
+{
+}
+
+bool PartSet_OperationCreateConstraint::canProcessKind(const std::string& theId)
+{
+  return /*theId == SKETCH_LINE_KIND || theId == SKETCH_POINT_KIND || theId == SKETCH_CIRCLE_KIND ||
+         theId == SKETCH_ARC_KIND || */theId == SKETCH_CONSTRAINT_LENGTH_KIND;
+}
+
+bool PartSet_OperationCreateConstraint::canBeCommitted() const
+{
+  return myPointSelectionMode == SM_DonePoint;
+}
+
+bool PartSet_OperationCreateConstraint::isGranted(ModuleBase_IOperation* theOperation) const
+{
+  return theOperation->getDescription()->operationId().toStdString() == PartSet_OperationSketch::Type();
+}
+
+std::list<int> PartSet_OperationCreateConstraint::getSelectionModes(FeaturePtr theFeature) const
+{
+  std::list<int> aModes;
+  if (theFeature != feature())
+    aModes = PartSet_OperationSketchBase::getSelectionModes(theFeature);
+  return aModes;
+}
+
+void PartSet_OperationCreateConstraint::init(FeaturePtr theFeature,
+                                       const std::list<XGUI_ViewerPrs>& /*theSelected*/,
+                                       const std::list<XGUI_ViewerPrs>& /*theHighlighted*/)
+{
+  if (!theFeature || theFeature->getKind() != SKETCH_LINE_KIND)
+    return;
+  myInitFeature = theFeature;
+}
+
+FeaturePtr PartSet_OperationCreateConstraint::sketch() const
+{
+  return myFeaturePrs->sketch();
+}
+
+void PartSet_OperationCreateConstraint::mouseReleased(QMouseEvent* theEvent, Handle(V3d_View) theView,
+                                                const std::list<XGUI_ViewerPrs>& theSelected,
+                                                const std::list<XGUI_ViewerPrs>& /*theHighlighted*/)
+{
+  if (theSelected.empty()) {
+
+  }
+  else {
+    XGUI_ViewerPrs aPrs = theSelected.front();
+    FeaturePtr aFeature = aPrs.feature();
+
+    myFeaturePrs->init(feature(), aFeature);
+    flushUpdated();
+  }
+}
+
+void PartSet_OperationCreateConstraint::mouseMoved(QMouseEvent* theEvent, Handle(V3d_View) theView)
+{
+  switch (myPointSelectionMode)
+  {
+    case SM_FirstPoint:
+    case SM_SecondPoint:
+    case SM_ThirdPoint:
+    {
+      double aX, anY;
+      gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), theView);
+      PartSet_Tools::convertTo2D(aPoint, sketch(), theView, aX, anY);
+      /*if (myPointSelectionMode == SM_ThirdPoint) {
+        if (feature()->getKind() == SKETCH_ARC_KIND) {
+          boost::shared_ptr<PartSet_FeatureArcPrs> anArcPrs =
+                                 boost::dynamic_pointer_cast<PartSet_FeatureArcPrs>(myFeaturePrs);
+          if (anArcPrs) {
+            anArcPrs->projectPointOnArc(aPoint, theView, aX, anY);
+          }
+        }
+      }*/
+      myFeaturePrs->setPoint(aX, anY, myPointSelectionMode);
+
+      flushUpdated();
+      emit focusActivated(myFeaturePrs->getAttribute(myPointSelectionMode));
+    }
+    break;
+    case SM_DonePoint:
+    {
+      commit();
+      restartOperation(feature()->getKind(), feature());
+    }
+    default:
+      break;
+  }
+}
+
+void PartSet_OperationCreateConstraint::keyReleased(std::string theName, QKeyEvent* theEvent)
+{
+  int aKeyType = theEvent->key();
+  // the second point should be activated by any modification in the property panel
+  if (!theName.empty() /*&& aKeyType == Qt::Key_Return*/)
+  {
+    setPointSelectionMode(myFeaturePrs->getNextMode(theName), false);
+  }
+  keyReleased(theEvent->key());
+}
+
+void PartSet_OperationCreateConstraint::keyReleased(const int theKey)
+{
+  switch (theKey) {
+    case Qt::Key_Return: {
+      if (myPointSelectionMode == SM_DonePoint)
+      {
+        commit();
+        // it start a new line creation at a free point
+        restartOperation(feature()->getKind(), FeaturePtr()/*feature()*/);
+      }
+      //else
+      //  abort();
+      //restartOperation(feature()->getKind(), FeaturePtr());
+    }
+    break;
+    case Qt::Key_Escape: {
+      if (myPointSelectionMode == SM_DonePoint)
+      {
+        commit();
+      }
+      else
+      {
+        abort();
+      }
+    }
+    default:
+    break;
+  }
+}
+
+void PartSet_OperationCreateConstraint::startOperation()
+{
+  PartSet_OperationSketchBase::startOperation();
+  setPointSelectionMode(!myInitFeature ? SM_FirstPoint : SM_SecondPoint);
+
+  emit multiSelectionEnabled(false);
+}
+
+void PartSet_OperationCreateConstraint::abortOperation()
+{
+  emit featureConstructed(feature(), FM_Hide);
+  PartSet_OperationSketchBase::abortOperation();
+}
+
+void PartSet_OperationCreateConstraint::stopOperation()
+{
+  PartSet_OperationSketchBase::stopOperation();
+  emit multiSelectionEnabled(true);
+}
+
+void PartSet_OperationCreateConstraint::afterCommitOperation()
+{
+  PartSet_OperationSketchBase::afterCommitOperation();  
+  emit featureConstructed(feature(), FM_Deactivation);
+}
+
+FeaturePtr PartSet_OperationCreateConstraint::createFeature(const bool theFlushMessage)
+{
+  FeaturePtr aNewFeature = ModuleBase_Operation::createFeature(false);
+  if (sketch()) {
+    boost::shared_ptr<SketchPlugin_Feature> aFeature = 
+                           boost::dynamic_pointer_cast<SketchPlugin_Feature>(sketch());
+
+    aFeature->addSub(aNewFeature);
+  }
+  myFeaturePrs->init(aNewFeature, myInitFeature);
+
+  emit featureConstructed(aNewFeature, FM_Activation);
+  if (theFlushMessage)
+    flushCreated();
+  return aNewFeature;
+}
+
+void PartSet_OperationCreateConstraint::setPointSelectionMode(const PartSet_SelectionMode& theMode,
+                                                           const bool isToEmitSignal)
+{
+  myPointSelectionMode = theMode;
+  if (isToEmitSignal) {
+    std::string aName = myFeaturePrs->getAttribute(theMode);
+    if (aName.empty() && theMode == SM_DonePoint) {
+      aName = XGUI::PROP_PANEL_OK;
+    }
+    emit focusActivated(aName);
+  }
+}
diff --git a/src/PartSet/PartSet_OperationCreateConstraint.h b/src/PartSet/PartSet_OperationCreateConstraint.h
new file mode 100644 (file)
index 0000000..9e09ad7
--- /dev/null
@@ -0,0 +1,124 @@
+// File:        PartSet_OperationCreateConstraint.h
+// Created:     20 Apr 2014
+// Author:      Natalia ERMOLAEVA
+
+#ifndef PartSet_OperationCreateConstraint_H
+#define PartSet_OperationCreateConstraint_H
+
+#include "PartSet.h"
+
+#include <PartSet_OperationSketchBase.h>
+#include <PartSet_Constants.h>
+
+#include <QObject>
+
+class PartSet_FeaturePrs;
+class GeomDataAPI_Point2D;
+class QMouseEvent;
+class QKeyEvent;
+
+/*!
+ \class PartSet_OperationCreateConstraint
+ * \brief The operation for the sketch feature creation
+*/
+class PARTSET_EXPORT PartSet_OperationCreateConstraint : public PartSet_OperationSketchBase
+{
+  Q_OBJECT
+
+public:
+  /// Returns true if the feature with the given kind can be created by this operation
+  /// \param theId the feature kind
+  /// \return the boolean result
+  static bool canProcessKind(const std::string& theId);
+
+public:
+  /// Constructor
+  /// \param theId the feature identifier
+  /// \param theParent the operation parent
+  /// \param theSketch the parent feature
+  PartSet_OperationCreateConstraint(const QString& theId, QObject* theParent,
+                                 FeaturePtr theSketch);
+  /// Destructor
+  virtual ~PartSet_OperationCreateConstraint();
+
+  /// Verifies whether this operator can be commited.
+  /// \return Returns TRUE if current operation can be committed, e.g. all parameters are filled
+  virtual bool canBeCommitted() const;
+
+  /// Returns that this operator can be started above already running one.
+   /// The runned operation should be the sketch feature modified operation
+  /// \param theOperation the previous running operation
+  virtual bool isGranted(ModuleBase_IOperation* theOperation) const;
+
+  /// Returns the operation local selection mode
+  /// \param theFeature the feature object to get the selection mode
+  /// \return the selection mode
+  virtual std::list<int> getSelectionModes(FeaturePtr theFeature) const;
+
+  /// Initializes some fields accorging to the feature
+  /// \param theSelected the list of selected presentations
+  /// \param theHighlighted the list of highlighted presentations
+  virtual void init(FeaturePtr theFeature,
+                    const std::list<XGUI_ViewerPrs>& theSelected,
+                    const std::list<XGUI_ViewerPrs>& theHighlighted);
+
+  /// Returns the operation sketch feature
+  /// \returns the sketch instance
+  virtual FeaturePtr sketch() const;
+
+  /// Gives the current selected objects to be processed by the operation
+  /// \param theEvent the mouse event
+  /// \param theView a viewer to have the viewer the eye position
+  /// \param theSelected the list of selected presentations
+  /// \param theHighlighted the list of highlighted presentations
+ virtual void mouseReleased(QMouseEvent* theEvent, Handle_V3d_View theView,
+                            const std::list<XGUI_ViewerPrs>& theSelected,
+                            const std::list<XGUI_ViewerPrs>& theHighlighted);
+  /// Gives the current mouse point in the viewer
+  /// \param thePoint a point clicked in the viewer
+  /// \param theEvent the mouse event
+  virtual void mouseMoved(QMouseEvent* theEvent, Handle_V3d_View theView);
+  /// Processes the key pressed in the view
+  /// \param theKey a key value
+  virtual void keyReleased(const int theKey);
+
+  virtual void keyReleased(std::string theName, QKeyEvent* theEvent);
+
+protected:
+  /// \brief Virtual method called when operation is started
+  /// Virtual method called when operation started (see start() method for more description)
+  /// After the parent operation body perform, set sketch feature to the created line feature
+  virtual void startOperation();
+
+  /// Virtual method called when operation aborted (see abort() method for more description)
+  /// Before the feature is aborted, it should be hidden from the viewer
+  virtual void abortOperation();
+
+  /// Virtual method called when operation stopped - committed or aborted.
+  /// Restore the multi selection state
+  virtual void stopOperation();
+
+  /// Virtual method called after operation committed (see commit() method for more description)
+  virtual void afterCommitOperation();
+
+  /// Creates an operation new feature
+  /// In addition to the default realization it appends the created line feature to
+  /// the sketch feature
+  /// \param theFlushMessage the flag whether the create message should be flushed
+  /// \returns the created feature
+  virtual FeaturePtr createFeature(const bool theFlushMessage = true);
+
+protected:
+  ///< Set the point selection mode. Emit signal about focus change if necessary.
+  /// \param theMode a new selection mode
+  /// \param isToEmitSignal the neccessity to emit signal
+  void setPointSelectionMode(const PartSet_SelectionMode& theMode,
+                             const bool isToEmitSignal = true);
+
+private:
+  boost::shared_ptr<PartSet_FeaturePrs> myFeaturePrs; ///< the feature presentation
+  FeaturePtr myInitFeature; ///< the initial feature
+  PartSet_SelectionMode myPointSelectionMode; ///< point selection mode
+};
+
+#endif
index 28d9ce3d188b20419ecef62cde02d78a1fcd8fd2..18fcce5f8cec21dac97e03d4666089dc137ff4d2 100644 (file)
@@ -7,6 +7,7 @@
 
 #include <ModelAPI_Feature.h>
 #include <ModelAPI_Data.h>
+#include <ModelAPI_AttributeDouble.h>
 
 #include <GeomDataAPI_Point.h>
 #include <GeomDataAPI_Point2D.h>
@@ -101,6 +102,10 @@ Handle(AIS_InteractiveObject) PartSet_Presentation::createSketchConstraintLength
   if (!aFeature || aFeature->getKind() != SKETCH_LINE_KIND)
     return thePrevPrs;
 
+  boost::shared_ptr<ModelAPI_AttributeDouble> aFlyoutAttr = 
+          boost::dynamic_pointer_cast<ModelAPI_AttributeDouble>(aData->attribute(CONSTRAINT_ATTR_FLYOUT_VALUE));
+  double aFlyout = aFlyoutAttr->value();
+
   aData = aFeature->data();
   if (!aData->isValid())
     return thePrevPrs;
@@ -134,7 +139,7 @@ Handle(AIS_InteractiveObject) PartSet_Presentation::createSketchConstraintLength
       aLenDim->SetDisplayUnits (aDimDlg->GetUnits ());
     }*/
     aLenDim->SetDimensionAspect (anAspect);
-    aLenDim->SetFlyout(12);
+    aLenDim->SetFlyout(aFlyout);
 
     anAIS = aLenDim;
   }
index 3e965280a5c77f8643787045fbe6cdce93f53a14..615f79a281f62e8e36e5947137acd59c3ed7101a 100644 (file)
@@ -25,6 +25,8 @@
 #include <PartSet_FeatureCirclePrs.h>
 #include <PartSet_FeatureArcPrs.h>
 
+#include <PartSet_FeatureLengthPrs.h>
+
 #include <XGUI_ViewerPrs.h>
 
 #include <V3d_View.hxx>
@@ -134,47 +136,6 @@ void PartSet_Tools::convertTo3D(const double theX, const double theY,
   thePoint = gp_Pnt(aPoint->x(), aPoint->y(), aPoint->z());
 }
 
-void PartSet_Tools::intersectLines(double theX0, double theY0, double theX1, double theY1,
-                                   double theX2, double theY2, double theX3, double theY3,
-                                   double& theX, double& theY)
-{
-  double aV1 = theX1 - theX0, aV2 = theY1 - theY0;
-  double aW1 = theX3 - theX2, aW2 = theY3 - theY2;
-
-  double aT2 = 0;
-  if (aV1  != 0 && aV2 != 0)
-    aT2 = (( theY2 - theY0 )/aV2 - ( theX2 - theX0 )/aV1) / ( aW1/aV1 - aW2/aV2 );
-  else
-    aT2 = DBL_MAX;
-
-  theX  = theX2 + aT2*aW1;
-  theY = theY2 + aT2*aW2;
-
-  // the coordinates of two lines are on the common line
-  //It is not possible to use Precision::Confusion(), because it is e-0.8, but V is sometimes e-6
-  Standard_Real aPrec = PRECISION_TOLERANCE;
-  if (fabs(theX - theX0) < aPrec && fabs(theY - theY0) < aPrec) {
-    projectPointOnLine(theX2, theY2, theX3, theY3, theX1, theY1, theX, theY);    
-  }
-}
-
-void PartSet_Tools::projectPointOnLine(double theX1, double theY1, double theX2, double theY2,
-                                       double thePointX, double thePointY, double& theX, double& theY)
-{
-  theX = theY = 0;
-
-  Handle(Geom_Line) aLine = new Geom_Line(gp_Pnt(theX1, theY1, 0),
-                                     gp_Dir(gp_Vec(gp_Pnt(theX1, theY1, 0), gp_Pnt(theX2, theY2, 0))));
-  GeomAPI_ProjectPointOnCurve aProj(gp_Pnt(thePointX, thePointY, 0), aLine);
-
-  Standard_Integer aNbPoint = aProj.NbPoints();
-  if (aNbPoint > 0) {
-    gp_Pnt aPoint = aProj.Point(1);
-    theX = aPoint.X();
-    theY = aPoint.Y();
-  }
-}
-
 boost::shared_ptr<PartSet_FeaturePrs> PartSet_Tools::createFeaturePrs(const std::string& theKind,
                                                                       FeaturePtr theSketch,
                                                                       FeaturePtr theFeature)
@@ -193,6 +154,9 @@ boost::shared_ptr<PartSet_FeaturePrs> PartSet_Tools::createFeaturePrs(const std:
   else if (theKind == PartSet_FeatureArcPrs::getKind()) {
     aFeaturePrs = boost::shared_ptr<PartSet_FeaturePrs>(new PartSet_FeatureArcPrs(theSketch));
   }
+  else if (theKind == PartSet_FeatureLengthPrs::getKind()) {
+    aFeaturePrs = boost::shared_ptr<PartSet_FeaturePrs>(new PartSet_FeatureLengthPrs(theSketch));
+  }
 
   if (theFeature && aFeaturePrs)
     aFeaturePrs->init(theFeature, FeaturePtr());
index fff206b6f166b4da4d9bc475607f467180b87310..a3de5e0f259d3ae76304d538877ad4dc5893776e 100644 (file)
@@ -50,32 +50,6 @@ public:
   static void convertTo3D(const double theX, const double theY, FeaturePtr theSketch,
                           gp_Pnt& thePoint);
 
-  /// Returns the point of intersection of the two lines, the first is (v0, v1), the second is (v2, v3),
-  /// where vi - {xi,yi}. If the v0 is on the second line, the result is a projection of the v1 to this line
-  /// \param theX0 the horizontal coordinate of 0 point
-  /// \param theY0 the vertical coordinate of 0 point
-  /// \param theX1 the horizontal coordinate of 1 point
-  /// \param theY1 the vertical coordinate of 1 point
-  /// \param theX2 the horizontal coordinate of 2 point
-  /// \param theY2 the vertical coordinate of 2 point
-  /// \param theX3 the horizontal coordinate of 3 point
-  /// \param theY3 the vertical coordinate of 3 point
-  /// \param theX the output horizontal coordinate of the intersection point
-  /// \param theY the outpup vertical coordinate of the intersection point
-  static void intersectLines(double theX0, double theY0, double theX1, double theY1,
-                             double theX2, double theY2, double theX3, double theY3,
-                             double& theX, double& theY);
-
-  /// Returns the coordinates of projection of the point to the line
-  /// \param thePointX the projected point horizontal coordinate
-  /// \param thePointY the projected point vertictal coordinate
-  /// \param theX1 the horizontal coordinate of the first line point
-  /// \param theY1 the vertical coordinate of the first line point
-  /// \param theX2 the horizontal coordinate of the second line point
-  /// \param theY2 the vertical coordinate of the second line point
-  static void projectPointOnLine(double theX1, double theY1, double theX2, double theY2,
-                                 double thePointX, double thePointY, double& theX, double& theY);
-
   /// Creates the feature presentation
   /// \param theKind a feature kind
   /// \param theSketch the sketch of the feature
index b4e8bcca6aac2b5496e6e547cbd8e37651ed7654..08dc621c70cc342be1b7be4df2dc41dba79a3dd9 100644 (file)
@@ -26,6 +26,8 @@
  */
 /// The value parameter for the constraint
 const std::string CONSTRAINT_ATTR_VALUE("ConstraintValue");
+/// The value parameter for the constraint
+const std::string CONSTRAINT_ATTR_FLYOUT_VALUE("ConstraintFlyoutValue");
 /// First entity for the constraint
 const std::string CONSTRAINT_ATTR_ENTITY_A("ConstraintEntityA");
 /// Second entity for the constraint
index 07a86905e3693e016a3a35ecee6bbe4ca59419f1..b5fe8fca3e3d126c2b837017d352ced5e515f2e1 100644 (file)
@@ -14,6 +14,7 @@ SketchPlugin_ConstraintLength::SketchPlugin_ConstraintLength()
 void SketchPlugin_ConstraintLength::initAttributes()
 {
   data()->addAttribute(CONSTRAINT_ATTR_VALUE,    ModelAPI_AttributeDouble::type());
+  data()->addAttribute(CONSTRAINT_ATTR_FLYOUT_VALUE, ModelAPI_AttributeDouble::type());
   data()->addAttribute(CONSTRAINT_ATTR_ENTITY_A, ModelAPI_AttributeRefAttr::type());
 }
 
index bc614e137ad3bf22c24931359d5763635e762cf4..57a5dbcc61af88b4a4ec1708c7112a382c765835 100644 (file)
@@ -18,7 +18,8 @@ const std::string SKETCH_CONSTRAINT_LENGTH_KIND("SketchConstraintLength");
  *  \brief Feature for creation of a new constraint which defines a length of a line segment
  *
  *  These constraint has two attributes:
- *  CONSTRAINT_ATTR_VALUE (length) and CONSTRAINT_ATTR_ENTITY_A (segment)
+ *  CONSTRAINT_ATTR_VALUE (length) and CONSTRAINT_ATTR_ENTITY_A (segment),
+ *  CONSTRAINT_ATTR_FLYOUT_VALUE (distance of a constraints handle)
  */
 class SketchPlugin_ConstraintLength: public SketchPlugin_Constraint
 {