- // update the points in accordance to the changed point changes
- if (theID == END_ID() && !myEndUpdate) {
- myEndUpdate = true;
- // compute and change the arc end point
- std::shared_ptr<GeomAPI_Circ2d> aCircleForArc(
- new GeomAPI_Circ2d(aCenterAttr->pnt(), aStartAttr->pnt()));
- std::shared_ptr<GeomAPI_Pnt2d> aProjection = aCircleForArc->project(anEndAttr->pnt());
- if (aProjection && anEndAttr->pnt()->distance(aProjection) > tolerance)
- anEndAttr->setValue(aProjection);
- myEndUpdate = false;
- } else if (theID == START_ID() && !myStartUpdate) {
- myStartUpdate = true;
- // compute and change the arc end point
- std::shared_ptr<GeomAPI_Circ2d> aCircleForArc(
- new GeomAPI_Circ2d(aCenterAttr->pnt(), anEndAttr->pnt()));
- std::shared_ptr<GeomAPI_Pnt2d> aProjection = aCircleForArc->project(aStartAttr->pnt());
- if (aProjection && aStartAttr->pnt()->distance(aProjection) > tolerance)
- aStartAttr->setValue(aProjection);
- myStartUpdate = false;
- } else if (theID == CENTER_ID() && !myEndUpdate) {
- myEndUpdate = true;
- // compute and change the arc end point
- std::shared_ptr<GeomAPI_Circ2d> aCircleForArc(
- new GeomAPI_Circ2d(aCenterAttr->pnt(), aStartAttr->pnt()));
- std::shared_ptr<GeomAPI_Pnt2d> aProjection = aCircleForArc->project(anEndAttr->pnt());
- if (aProjection && anEndAttr->pnt()->distance(aProjection) > tolerance)
- anEndAttr->setValue(aProjection);
- myEndUpdate = false;
+ // The second condition for unability to move external segments anywhere.
+ if(theID == EXTERNAL_ID() || isFixed()) {
+ std::shared_ptr<GeomAPI_Shape> aSelection = data()->selection(EXTERNAL_ID())->value();
+ if(!aSelection) {
+ // empty shape in selection shows that the shape is equal to context
+ ResultPtr anExtRes = selection(EXTERNAL_ID())->context();
+ if(anExtRes) {
+ aSelection = anExtRes->shape();
+ }
+ }
+ // update arguments due to the selection value
+ if(aSelection && !aSelection->isNull() && aSelection->isEdge()) {
+ std::shared_ptr<GeomAPI_Edge> anEdge( new GeomAPI_Edge(aSelection));
+ std::shared_ptr<GeomAPI_Circ> aCirc = anEdge->circle();
+ if(aCirc.get()) {
+ bool aWasBlocked = data()->blockSendAttributeUpdated(true);
+ aCenterAttr->setValue(sketch()->to2D(aCirc->center()));
+ aStartAttr->setValue(sketch()->to2D(anEdge->firstPoint()));
+ anEndAttr->setValue(sketch()->to2D(anEdge->lastPoint()));
+ data()->blockSendAttributeUpdated(aWasBlocked, false);
+
+ std::shared_ptr<GeomAPI_Circ2d> aCircle2d =
+ std::shared_ptr<GeomAPI_Circ2d>(new GeomAPI_Circ2d(aCenterAttr->pnt(),
+ aStartAttr->pnt()));
+
+ double anEndParam = 0.0;
+ aCircle2d->parameter(anEndAttr->pnt(), paramTolerance, anEndParam);
+ myParamBefore = anEndParam;
+
+ double aMidParam = anEndParam / 2.0;
+ std::shared_ptr<GeomAPI_Pnt2d> aMidPnt2d;
+ aCircle2d->D0(aMidParam, aMidPnt2d);
+ std::shared_ptr<GeomAPI_Pnt> aMinPnt = sketch()->to3D(aMidPnt2d->x(), aMidPnt2d->y());
+ double aStartParam = 0.0;
+ aCirc->parameter(anEdge->firstPoint(), paramTolerance, aStartParam);
+ aCirc->parameter(aMinPnt, paramTolerance, aMidParam);
+ aCirc->parameter(anEdge->lastPoint(), paramTolerance, anEndParam);
+
+ // adjust period
+ anEndParam -= aStartParam;
+ aMidParam -= aStartParam;
+ if (anEndParam < 0.0)
+ anEndParam += 2.0 * PI;
+ if (aMidParam < 0.0)
+ aMidParam += 2.0 * PI;
+
+ aWasBlocked = data()->blockSendAttributeUpdated(true);
+ if(aMidParam < anEndParam) {
+ setReversed(false);
+ } else {
+ setReversed(true);
+ }
+ data()->blockSendAttributeUpdated(aWasBlocked, false);
+ }
+ }
+ } else if(theID == CENTER_ID() || theID == START_ID() || theID == END_ID()) {
+ if(!aCenterAttr->isInitialized()
+ || !aStartAttr->isInitialized()
+ || !anEndAttr->isInitialized()) {
+ return;
+ }
+ std::shared_ptr<GeomAPI_Pnt2d> aCenter = aCenterAttr->pnt();
+ std::shared_ptr<GeomAPI_Pnt2d> aStart = aStartAttr->pnt();
+ std::shared_ptr<GeomAPI_Pnt2d> anEnd = anEndAttr->pnt();
+ double aRadius = aCenter->distance(aStart);
+ if (aRadius < tolerance)
+ return;
+ std::shared_ptr<GeomAPI_Circ2d> aCircleForArc(new GeomAPI_Circ2d(aCenter, aStart));
+
+ // Do not recalculate REVERSED flag if the arc is not consistent
+ std::shared_ptr<GeomAPI_Pnt2d> aProjection = aCircleForArc->project(anEnd);
+ if (aProjection && anEnd->distance(aProjection) <= tolerance) {
+ double aParameterNew = 0.0;
+ if(aCircleForArc->parameter(anEnd, paramTolerance, aParameterNew)) {
+ bool aWasBlocked = data()->blockSendAttributeUpdated(true);
+ if(myParamBefore <= PI / 2.0 && aParameterNew >= PI * 1.5) {
+ if(!boolean(REVERSED_ID())->value()) {
+ boolean(REVERSED_ID())->setValue(true);
+ }
+ } else if(myParamBefore >= PI * 1.5 && aParameterNew <= PI / 2.0) {
+ if(boolean(REVERSED_ID())->value()) {
+ boolean(REVERSED_ID())->setValue(false);
+ }
+ }
+ data()->blockSendAttributeUpdated(aWasBlocked, false);
+ }
+ if (fabs(aParameterNew) < paramTolerance ||
+ fabs(aParameterNew - 2.0 * PI) < paramTolerance)
+ aParameterNew = 2.0 * PI;
+ myParamBefore = aParameterNew;
+ }
+ }
+
+ double aRadius = 0;
+ double anAngle = 0;
+ if(aCenterAttr->isInitialized() && aStartAttr->isInitialized()) {
+ aRadius = aCenterAttr->pnt()->distance(aStartAttr->pnt());
+ if(anEndAttr->isInitialized()) {
+ if(aStartAttr->pnt()->isEqual(anEndAttr->pnt())) {
+ anAngle = 360;
+ } else {
+ GeomAPI_Circ2d aCircleForArc(aCenterAttr->pnt(), aStartAttr->pnt());
+ double aStartParam, anEndParam;
+ aCircleForArc.parameter(aStartAttr->pnt(), paramTolerance, aStartParam);
+ aCircleForArc.parameter(anEndAttr->pnt(), paramTolerance, anEndParam);
+ anAngle = (anEndParam - aStartParam) / PI * 180.0;
+ if(isReversed()) anAngle = 360.0 - anAngle;
+ }
+ }