+AISObjectPtr SketchPlugin_ConstraintLength::getAISObject(AISObjectPtr thePrevious)
+{
+ if (!sketch())
+ return thePrevious;
+
+ AISObjectPtr anAIS = SketcherPrs_Factory::lengthDimensionConstraint(this, sketch()->coordinatePlane(),
+ thePrevious);
+ return anAIS;
+}
+
+void SketchPlugin_ConstraintLength::move(double theDeltaX, double theDeltaY)
+{
+ std::shared_ptr<ModelAPI_Data> aData = data();
+ if (!aData->isValid())
+ return;
+
+ AttributeRefAttrPtr aLineAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+ attribute(SketchPlugin_Constraint::ENTITY_A()));
+ if (!aLineAttr || !aLineAttr->isObject())
+ return;
+ FeaturePtr aLine = ModelAPI_Feature::feature(aLineAttr->object());
+ if (!aLine || aLine->getKind() != SketchPlugin_Line::ID())
+ return;
+
+ // Recalculate a shift of flyout point in terms of local coordinates
+ std::shared_ptr<GeomAPI_XY> aDir(new GeomAPI_XY(theDeltaX, theDeltaY));
+ std::shared_ptr<GeomAPI_XY> aStartPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aLine->attribute(SketchPlugin_Line::START_ID()))->pnt()->xy();
+ std::shared_ptr<GeomAPI_XY> aEndPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aLine->attribute(SketchPlugin_Line::END_ID()))->pnt()->xy();
+ std::shared_ptr<GeomAPI_Dir2d> aLineDir(new GeomAPI_Dir2d(aEndPnt->decreased(aStartPnt)));
+ double dX = aDir->dot(aLineDir->xy());
+ double dY = -aDir->cross(aLineDir->xy());
+
+ myFlyoutUpdate = true;
+ std::shared_ptr<GeomDataAPI_Point2D> aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aData->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()));
+ aPoint->setValue(aPoint->x() + dX, aPoint->y() + dY);
+ myFlyoutUpdate = false;
+}
+
+void SketchPlugin_ConstraintLength::attributeChanged(const std::string& theID) {
+ if (theID == SketchPlugin_Constraint::ENTITY_A())
+ {
+ std::shared_ptr<ModelAPI_AttributeDouble> aValueAttr = std::dynamic_pointer_cast<
+ ModelAPI_AttributeDouble>(attribute(SketchPlugin_Constraint::VALUE()));
+ if (!aValueAttr->isInitialized()) { // only if it is not initialized, try to compute the current value
+ std::shared_ptr<GeomAPI_Pnt> aPoint1, aPoint2;
+ std::shared_ptr<GeomDataAPI_Point2D> aStartPoint, anEndPoint;
+ if (getPoints(aPoint1, aPoint2, aStartPoint, anEndPoint)) {
+ double aLength = aPoint1->distance(aPoint2);
+ aValueAttr->setValue(aLength);
+ }
+ }
+ } else if (theID == SketchPlugin_Constraint::FLYOUT_VALUE_PNT() && !myFlyoutUpdate) {
+ myFlyoutUpdate = true;
+ // Recalculate flyout point in local coordinates of the line:
+ // the X coordinate is a length of projection of the flyout point on the line
+ // the Y coordinate is a distance from the point to the line
+ std::shared_ptr<GeomDataAPI_Point2D> aFlyoutAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()));
+ AttributeRefAttrPtr aLineAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+ attribute(SketchPlugin_Constraint::ENTITY_A()));
+ if (!aLineAttr || !aLineAttr->isObject())
+ return;
+ FeaturePtr aLine = ModelAPI_Feature::feature(aLineAttr->object());
+ if (!aLine || aLine->getKind() != SketchPlugin_Line::ID())
+ return;
+
+ std::shared_ptr<GeomAPI_Pnt2d> aFlyoutPnt = aFlyoutAttr->pnt();
+ std::shared_ptr<GeomAPI_XY> aStartPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aLine->attribute(SketchPlugin_Line::START_ID()))->pnt()->xy();
+ std::shared_ptr<GeomAPI_XY> aEndPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aLine->attribute(SketchPlugin_Line::END_ID()))->pnt()->xy();
+
+ std::shared_ptr<GeomAPI_Dir2d> aLineDir(new GeomAPI_Dir2d(aEndPnt->decreased(aStartPnt)));
+ std::shared_ptr<GeomAPI_XY> aFlyoutDir = aFlyoutPnt->xy()->decreased(aStartPnt);
+ double X = aFlyoutDir->dot(aLineDir->xy());
+ double Y = -aFlyoutDir->cross(aLineDir->xy());
+ aFlyoutAttr->setValue(X, Y);
+ myFlyoutUpdate = false;
+ }
+}