From 042cf84a1be87ff17acadf8c40c006b5123fe7e1 Mon Sep 17 00:00:00 2001 From: azv Date: Tue, 2 Feb 2016 12:19:01 +0300 Subject: [PATCH] Update movement of a circle --- src/GeomAPI/GeomAPI_Circ2d.cpp | 39 +++++++++++++ src/GeomAPI/GeomAPI_Circ2d.h | 6 ++ src/SketchPlugin/SketchPlugin_Circle.cpp | 73 ++++++++++-------------- src/SketchPlugin/SketchPlugin_Circle.h | 4 ++ 4 files changed, 80 insertions(+), 42 deletions(-) diff --git a/src/GeomAPI/GeomAPI_Circ2d.cpp b/src/GeomAPI/GeomAPI_Circ2d.cpp index c809e567e..a58151409 100644 --- a/src/GeomAPI/GeomAPI_Circ2d.cpp +++ b/src/GeomAPI/GeomAPI_Circ2d.cpp @@ -44,6 +44,35 @@ static gp_Circ2d* newCirc2d(const double theCenterX, const double theCenterY, return newCirc2d(theCenterX, theCenterY, aDir, aRadius); } +static gp_Circ2d* newCirc2d(const std::shared_ptr& theFirstPoint, + const std::shared_ptr& theSecondPoint, + const std::shared_ptr& theThirdPoint) +{ + gp_XY aFirstPnt(theFirstPoint->x(), theFirstPoint->y()); + gp_XY aSecondPnt(theSecondPoint->x(), theSecondPoint->y()); + gp_XY aThirdPnt(theThirdPoint->x(), theThirdPoint->y()); + + gp_XY aVec12 = aSecondPnt - aFirstPnt; + gp_XY aVec23 = aThirdPnt - aSecondPnt; + gp_XY aVec31 = aFirstPnt - aThirdPnt; + // square of parallelogram + double aSquare2 = aVec12.Crossed(aVec23); + aSquare2 *= aSquare2 * 2.0; + if (aSquare2 < 1.e-20) + return NULL; + // coefficients to calculate center + double aCoeff1 = aVec23.Dot(aVec23) / aSquare2 * aVec12.Dot(aVec31.Reversed()); + double aCoeff2 = aVec31.Dot(aVec31) / aSquare2 * aVec23.Dot(aVec12.Reversed()); + double aCoeff3 = aVec12.Dot(aVec12) / aSquare2 * aVec31.Dot(aVec23.Reversed()); + // center + gp_XY aCenter = aFirstPnt * aCoeff1 + aSecondPnt * aCoeff2 + aThirdPnt * aCoeff3; + // radius + double aRadius = (aFirstPnt - aCenter).Modulus(); + + gp_Dir2d aDir(aFirstPnt - aCenter); + return newCirc2d(aCenter.X(), aCenter.Y(), aDir, aRadius); +} + GeomAPI_Circ2d::GeomAPI_Circ2d(const std::shared_ptr& theCenter, const std::shared_ptr& theCirclePoint) : GeomAPI_Interface( @@ -56,7 +85,13 @@ GeomAPI_Circ2d::GeomAPI_Circ2d(const std::shared_ptr& theCenter, : GeomAPI_Interface( newCirc2d(theCenter->x(), theCenter->y(), theDir->impl(), theRadius)) { +} +GeomAPI_Circ2d::GeomAPI_Circ2d(const std::shared_ptr& theFirstPoint, + const std::shared_ptr& theSecondPoint, + const std::shared_ptr& theThirdPoint) + : GeomAPI_Interface(newCirc2d(theFirstPoint, theSecondPoint, theThirdPoint)) +{ } const std::shared_ptr GeomAPI_Circ2d::project( @@ -89,12 +124,16 @@ const std::shared_ptr GeomAPI_Circ2d::project( const std::shared_ptr GeomAPI_Circ2d::center() const { + if (!MY_CIRC2D) + return std::shared_ptr(); const gp_Pnt2d& aCenter = MY_CIRC2D->Location(); return std::shared_ptr(new GeomAPI_Pnt2d(aCenter.X(), aCenter.Y())); } double GeomAPI_Circ2d::radius() const { + if (!MY_CIRC2D) + return 0.0; return MY_CIRC2D->Radius(); } diff --git a/src/GeomAPI/GeomAPI_Circ2d.h b/src/GeomAPI/GeomAPI_Circ2d.h index 478c9986a..d6ad5c755 100644 --- a/src/GeomAPI/GeomAPI_Circ2d.h +++ b/src/GeomAPI/GeomAPI_Circ2d.h @@ -31,6 +31,12 @@ class GeomAPI_Circ2d : public GeomAPI_Interface GeomAPI_Circ2d(const std::shared_ptr& theCenter, const std::shared_ptr& theDir, double theRadius); + /// Creation of circle defined by three points lying on it + GEOMAPI_EXPORT + GeomAPI_Circ2d(const std::shared_ptr& theFirstPoint, + const std::shared_ptr& theSecondPoint, + const std::shared_ptr& theThirdPoint); + /// Return center of the circle GEOMAPI_EXPORT const std::shared_ptr center() const; diff --git a/src/SketchPlugin/SketchPlugin_Circle.cpp b/src/SketchPlugin/SketchPlugin_Circle.cpp index 858c2e7ef..ea819628e 100644 --- a/src/SketchPlugin/SketchPlugin_Circle.cpp +++ b/src/SketchPlugin/SketchPlugin_Circle.cpp @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -68,12 +69,6 @@ namespace { } } -static void calculateCircleOnThreePoints(const std::shared_ptr& theFirstPnt, - const std::shared_ptr& theSecondPnt, - const std::shared_ptr& theThirdPnt, - std::shared_ptr& theCenter, - double& theRadius); - SketchPlugin_Circle::SketchPlugin_Circle() : SketchPlugin_SketchEntity() @@ -134,7 +129,7 @@ void SketchPlugin_Circle::execute() AISObjectPtr SketchPlugin_Circle::getAISObject(AISObjectPtr thePrevious) { SketchPlugin_Sketch* aSketch = sketch(); - if (aSketch) { + if (aSketch && !isFeatureValid()) { // compute a circle point in 3D view std::shared_ptr aCenterAttr = std::dynamic_pointer_cast< GeomDataAPI_Point2D>(data()->attribute(CENTER_ID())); @@ -171,15 +166,37 @@ AISObjectPtr SketchPlugin_Circle::getAISObject(AISObjectPtr thePrevious) return AISObjectPtr(); } +bool SketchPlugin_Circle::isFeatureValid() +{ + std::shared_ptr aCenter = + std::dynamic_pointer_cast(attribute(CENTER_ID())); + std::shared_ptr aFirstPnt = + std::dynamic_pointer_cast(attribute(FIRST_POINT_ID())); + std::shared_ptr aSecondPnt = + std::dynamic_pointer_cast(attribute(SECOND_POINT_ID())); + std::shared_ptr aThirdPnt = + std::dynamic_pointer_cast(attribute(THIRD_POINT_ID())); + + return aCenter->isInitialized() && aFirstPnt->isInitialized() && + aSecondPnt->isInitialized() && aThirdPnt->isInitialized(); +} + void SketchPlugin_Circle::move(double theDeltaX, double theDeltaY) { std::shared_ptr aData = data(); if (!aData->isValid()) return; - std::shared_ptr aPoint1 = std::dynamic_pointer_cast( + std::shared_ptr aPoint = std::dynamic_pointer_cast( aData->attribute(CENTER_ID())); - aPoint1->move(theDeltaX, theDeltaY); + aPoint->move(theDeltaX, theDeltaY); + + aPoint = std::dynamic_pointer_cast(aData->attribute(FIRST_POINT_ID())); + aPoint->move(theDeltaX, theDeltaY); + aPoint = std::dynamic_pointer_cast(aData->attribute(SECOND_POINT_ID())); + aPoint->move(theDeltaX, theDeltaY); + aPoint = std::dynamic_pointer_cast(aData->attribute(THIRD_POINT_ID())); + aPoint->move(theDeltaX, theDeltaY); } bool SketchPlugin_Circle::isFixed() { @@ -263,10 +280,12 @@ void SketchPlugin_Circle::attributeChanged(const std::string& theID) { aCenterAttr->setValue(aCoord->x(), aCoord->y()); aRadiusAttr->setValue(aRadius); } else { - std::shared_ptr aCenter; - double aRadius; - calculateCircleOnThreePoints(aPoints[0], aPoints[1], aPoints[2], aCenter, aRadius); + std::shared_ptr aCircle( + new GeomAPI_Circ2d(aPoints[0], aPoints[1], aPoints[2])); + + std::shared_ptr aCenter = aCircle->center(); if (aCenter) { + double aRadius = aCircle->radius(); aCenterAttr->setValue(aCenter->x(), aCenter->y()); aRadiusAttr->setValue(aRadius); } @@ -275,33 +294,3 @@ void SketchPlugin_Circle::attributeChanged(const std::string& theID) { data()->blockSendAttributeUpdated(false); } } - - - - -// ========== Auxiliary functions ========================= -void calculateCircleOnThreePoints(const std::shared_ptr& theFirstPnt, - const std::shared_ptr& theSecondPnt, - const std::shared_ptr& theThirdPnt, - std::shared_ptr& theCenter, - double& theRadius) -{ - std::shared_ptr aVec12 = theSecondPnt->xy()->decreased(theFirstPnt->xy()); - std::shared_ptr aVec23 = theThirdPnt->xy()->decreased(theSecondPnt->xy()); - std::shared_ptr 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 aCenter = theFirstPnt->xy()->multiplied(aCoeff1)->added( - theSecondPnt->xy()->multiplied(aCoeff2))->added(theThirdPnt->xy()->multiplied(aCoeff3)); - theCenter = std::shared_ptr(new GeomAPI_Pnt2d(aCenter)); - // radius - theRadius = theFirstPnt->distance(theCenter); -} diff --git a/src/SketchPlugin/SketchPlugin_Circle.h b/src/SketchPlugin/SketchPlugin_Circle.h index fe0ca3a42..daf4d2651 100644 --- a/src/SketchPlugin/SketchPlugin_Circle.h +++ b/src/SketchPlugin/SketchPlugin_Circle.h @@ -76,6 +76,10 @@ class SketchPlugin_Circle : public SketchPlugin_SketchEntity, public GeomAPI_IPr protected: /// \brief Initializes attributes of derived class. virtual void initDerivedClassAttributes(); + +private: + /// Returns true if all obligatory attributes are initialized + bool isFeatureValid(); }; #endif -- 2.39.2