- else if (theID == CENTER_ID() || theID == RADIUS_ID()) {
- std::string aType = std::dynamic_pointer_cast<ModelAPI_AttributeString>(
- data()->attribute(CIRCLE_TYPE()))->value();
- if (aType == CIRCLE_TYPE_THREE_POINTS())
- return;
-
- std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(CENTER_ID()));
- if (!aCenterAttr->isInitialized())
- return;
- AttributeDoublePtr aRadiusAttr =
- std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(attribute(RADIUS_ID()));
- if (!aRadiusAttr->isInitialized())
- return;
-
- // check the execute() was called and the shape was built
- if (!lastResult())
- return;
-
- data()->blockSendAttributeUpdated(true);
- std::shared_ptr<GeomDataAPI_Point2D> aFirstPnt =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(FIRST_POINT_ID()));
- std::shared_ptr<GeomDataAPI_Point2D> aSecondPnt =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(SECOND_POINT_ID()));
- std::shared_ptr<GeomDataAPI_Point2D> aThirdPnt =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(THIRD_POINT_ID()));
- double aRadius = aRadiusAttr->value();
- aFirstPnt->setValue(aCenterAttr->x() + aRadius, aCenterAttr->y());
- aSecondPnt->setValue(aCenterAttr->x(), aCenterAttr->y() + aRadius);
- aThirdPnt->setValue(aCenterAttr->x() - aRadius, aCenterAttr->y());
- data()->blockSendAttributeUpdated(false);
- }
- else if (theID == FIRST_POINT_ID() || theID == SECOND_POINT_ID() || theID == THIRD_POINT_ID()) {
- std::string aType = std::dynamic_pointer_cast<ModelAPI_AttributeString>(
- data()->attribute(CIRCLE_TYPE()))->value();
- if (aType == CIRCLE_TYPE_CENTER_AND_RADIUS())
- return;
-
- data()->blockSendAttributeUpdated(true);
-
- std::shared_ptr<GeomAPI_Pnt2d> aPoints[3];
- int aNbInitialized = 0;
- for (int i = 1; i <= 3; ++i) {
- std::shared_ptr<GeomDataAPI_Point2D> aCurPnt =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(POINT_ID(i)));
- if (aCurPnt->isInitialized())
- aPoints[aNbInitialized++] = aCurPnt->pnt();
- }
-
- std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr = std::dynamic_pointer_cast<
- GeomDataAPI_Point2D>(data()->attribute(CENTER_ID()));
- AttributeDoublePtr aRadiusAttr =
- std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(data()->attribute(RADIUS_ID()));
-
- if (aNbInitialized == 1)
- aCenterAttr->setValue(aPoints[0]->x(), aPoints[0]->y());
- else if (aNbInitialized == 2) {
- std::shared_ptr<GeomAPI_XY> aCoord =
- aPoints[0]->xy()->added(aPoints[1]->xy())->multiplied(0.5);
- double aRadius = aPoints[0]->distance(aPoints[1]) * 0.5;
- aCenterAttr->setValue(aCoord->x(), aCoord->y());
- aRadiusAttr->setValue(aRadius);
- } else {
- std::shared_ptr<GeomAPI_Pnt2d> aCenter;
- double aRadius;
- calculateCircleOnThreePoints(aPoints[0], aPoints[1], aPoints[2], aCenter, aRadius);
- if (aCenter) {
- aCenterAttr->setValue(aCenter->x(), aCenter->y());
- aRadiusAttr->setValue(aRadius);
- }
- }
-
- data()->blockSendAttributeUpdated(false);
- }
-}
-
-
-
-
-// ========== Auxiliary functions =========================
-void calculateCircleOnThreePoints(const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPnt,
- const std::shared_ptr<GeomAPI_Pnt2d>& theSecondPnt,
- const std::shared_ptr<GeomAPI_Pnt2d>& theThirdPnt,
- std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
- double& theRadius)
-{
- std::shared_ptr<GeomAPI_XY> aVec12 = theSecondPnt->xy()->decreased(theFirstPnt->xy());
- std::shared_ptr<GeomAPI_XY> aVec23 = theThirdPnt->xy()->decreased(theSecondPnt->xy());
- std::shared_ptr<GeomAPI_XY> aVec31 = theFirstPnt->xy()->decreased(theThirdPnt->xy());
- // square of parallelogram
- double aSquare2 = aVec12->cross(aVec23);
- aSquare2 *= aSquare2 * 2.0;
- if (aSquare2 < 1.e-20)
- return;
- // coefficients to calculate center
- double aCoeff1 = aVec23->dot(aVec23) / aSquare2 * aVec12->dot(aVec31->multiplied(-1.0));
- double aCoeff2 = aVec31->dot(aVec31) / aSquare2 * aVec23->dot(aVec12->multiplied(-1.0));
- double aCoeff3 = aVec12->dot(aVec12) / aSquare2 * aVec31->dot(aVec23->multiplied(-1.0));
- // center
- std::shared_ptr<GeomAPI_XY> aCenter = theFirstPnt->xy()->multiplied(aCoeff1)->added(
- theSecondPnt->xy()->multiplied(aCoeff2))->added(theThirdPnt->xy()->multiplied(aCoeff3));
- theCenter = std::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(aCenter));
- // radius
- theRadius = theFirstPnt->distance(theCenter);