X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2FSketchPlugin%2FSketchPlugin_EllipticArc.cpp;h=5b8b109e0da138311ee30446dd82cd4d8032abe6;hb=4cb749258f33b7de231da5bb50140407c0599d30;hp=3bc24f1ccee81a5aeaf4f8c2db99d444f84c0ee8;hpb=d2026409659dfa0a142d1b018b3cec5d94932a7a;p=modules%2Fshaper.git diff --git a/src/SketchPlugin/SketchPlugin_EllipticArc.cpp b/src/SketchPlugin/SketchPlugin_EllipticArc.cpp index 3bc24f1cc..5b8b109e0 100644 --- a/src/SketchPlugin/SketchPlugin_EllipticArc.cpp +++ b/src/SketchPlugin/SketchPlugin_EllipticArc.cpp @@ -25,7 +25,9 @@ #include #include #include +#include #include +#include #include @@ -37,10 +39,13 @@ #include static const double tolerance = 1e-7; +static const double paramTolerance = 1.e-4; +static const double PI = 3.141592653589793238463; SketchPlugin_EllipticArc::SketchPlugin_EllipticArc() -: SketchPlugin_SketchEntity() + : SketchPlugin_SketchEntity(), + myParamDelta(0.0) { } @@ -102,29 +107,63 @@ void SketchPlugin_EllipticArc::attributeChanged(const std::string& theID) { } // update arguments due to the selection value if (aSelection && !aSelection->isNull() && aSelection->isEdge()) { - std::shared_ptr anEdge( new GeomAPI_Edge(aSelection)); + std::shared_ptr anEdge(new GeomAPI_Edge(aSelection)); std::shared_ptr anEllipse = anEdge->ellipse(); + bool aWasBlocked = data()->blockSendAttributeUpdated(true); std::shared_ptr aCenterAttr = - std::dynamic_pointer_cast(attribute(CENTER_ID())); + std::dynamic_pointer_cast(attribute(CENTER_ID())); aCenterAttr->setValue(sketch()->to2D(anEllipse->center())); std::shared_ptr aFocusAttr = - std::dynamic_pointer_cast(attribute(FIRST_FOCUS_ID())); + std::dynamic_pointer_cast(attribute(FIRST_FOCUS_ID())); aFocusAttr->setValue(sketch()->to2D(anEllipse->firstFocus())); std::shared_ptr aStartAttr = - std::dynamic_pointer_cast(attribute(START_POINT_ID())); + std::dynamic_pointer_cast(attribute(START_POINT_ID())); aStartAttr->setValue(sketch()->to2D(anEdge->firstPoint())); std::shared_ptr aEndAttr = - std::dynamic_pointer_cast(attribute(END_POINT_ID())); + std::dynamic_pointer_cast(attribute(END_POINT_ID())); aEndAttr->setValue(sketch()->to2D(anEdge->lastPoint())); real(MAJOR_RADIUS_ID())->setValue(anEllipse->majorRadius()); real(MINOR_RADIUS_ID())->setValue(anEllipse->minorRadius()); + + double aStartParam, aMidParam, aEndParam; + anEllipse->parameter(anEdge->firstPoint(), tolerance, aStartParam); + anEllipse->parameter(anEdge->middlePoint(), tolerance, aMidParam); + anEllipse->parameter(anEdge->lastPoint(), tolerance, aEndParam); + if (aEndParam < aStartParam) + aEndParam += 2.0 * PI; + if (aMidParam < aStartParam) + aMidParam += 2.0 * PI; + boolean(REVERSED_ID())->setValue(aMidParam > aEndParam); + + data()->blockSendAttributeUpdated(aWasBlocked, false); + + fillCharacteristicPoints(); } } + else if (theID == CENTER_ID() || theID == FIRST_FOCUS_ID() || + theID == START_POINT_ID() || theID == END_POINT_ID()) + fillCharacteristicPoints(); + else if (theID == REVERSED_ID() && myParamDelta == 0.0) + myParamDelta = 2.0 * PI; +} + +static void calculateRadii(const GeomPnt2dPtr& theCenter, + const GeomPnt2dPtr& theFocus, + const GeomPnt2dPtr& thePassed, + double& theMajorRadius, + double& theMinorRadius) +{ + GeomPnt2dPtr aSecondFocus(new GeomAPI_Pnt2d( + theCenter->xy()->multiplied(2.0)->decreased(theFocus->xy()))); + theMajorRadius = 0.5 * (thePassed->distance(theFocus) + thePassed->distance(aSecondFocus)); + + double aFocalDist = theCenter->distance(theFocus); + theMinorRadius = sqrt(theMajorRadius * theMajorRadius - aFocalDist * aFocalDist); } bool SketchPlugin_EllipticArc::fillCharacteristicPoints() @@ -133,47 +172,74 @@ bool SketchPlugin_EllipticArc::fillCharacteristicPoints() std::dynamic_pointer_cast(data()->attribute(CENTER_ID())); std::shared_ptr aFocusAttr = std::dynamic_pointer_cast(data()->attribute(FIRST_FOCUS_ID())); - - AttributeDoublePtr aMinorRadiusAttr = real(MINOR_RADIUS_ID()); + std::shared_ptr aStartPointAttr = + std::dynamic_pointer_cast(data()->attribute(START_POINT_ID())); + std::shared_ptr aEndPointAttr = + std::dynamic_pointer_cast(data()->attribute(END_POINT_ID())); if (!aCenterAttr->isInitialized() || !aFocusAttr->isInitialized() || - !aMinorRadiusAttr->isInitialized()) { - return false; - } - - double aMinorRadius = aMinorRadiusAttr->value(); - if (aMinorRadius < tolerance) { + !aStartPointAttr->isInitialized()) { return false; } - data()->blockSendAttributeUpdated(true); GeomPnt2dPtr aCenter2d = aCenterAttr->pnt(); GeomPnt2dPtr aFocus2d = aFocusAttr->pnt(); + GeomPnt2dPtr aStart2d = aStartPointAttr->pnt(); + + double aMajorRadius = 0.0, aMinorRadius = 0.0; + calculateRadii(aCenter2d, aFocus2d, aStart2d, aMajorRadius, aMinorRadius); + if (aMinorRadius < tolerance * aMajorRadius) + return false; + + bool aWasBlocked = data()->blockSendAttributeUpdated(true); + real(MAJOR_RADIUS_ID())->setValue(aMajorRadius); + real(MINOR_RADIUS_ID())->setValue(aMinorRadius); + GeomDir2dPtr aMajorDir2d(new GeomAPI_Dir2d(aFocus2d->x() - aCenter2d->x(), - aFocus2d->y() - aCenter2d->y())); + aFocus2d->y() - aCenter2d->y())); GeomDir2dPtr aMinorDir2d(new GeomAPI_Dir2d(-aMajorDir2d->y(), aMajorDir2d->x())); - AttributeDoublePtr aMajorRadiusAttr = real(MAJOR_RADIUS_ID()); - double aFocalDist = aCenter2d->distance(aFocus2d); - double aMajorRadius = sqrt(aFocalDist * aFocalDist + aMinorRadius * aMinorRadius); - aMajorRadiusAttr->setValue(aMajorRadius); - std::dynamic_pointer_cast(attribute(SECOND_FOCUS_ID())) ->setValue(2.0 * aCenter2d->x() - aFocus2d->x(), 2.0 * aCenter2d->y() - aFocus2d->y()); std::dynamic_pointer_cast(attribute(MAJOR_AXIS_START_ID())) - ->setValue(aCenter2d->x() - aMajorDir2d->x() * aMajorRadius, - aCenter2d->y() - aMajorDir2d->y() * aMajorRadius); + ->setValue(aCenter2d->x() - aMajorDir2d->x() * aMajorRadius, + aCenter2d->y() - aMajorDir2d->y() * aMajorRadius); std::dynamic_pointer_cast(attribute(MAJOR_AXIS_END_ID())) - ->setValue(aCenter2d->x() + aMajorDir2d->x() * aMajorRadius, - aCenter2d->y() + aMajorDir2d->y() * aMajorRadius); + ->setValue(aCenter2d->x() + aMajorDir2d->x() * aMajorRadius, + aCenter2d->y() + aMajorDir2d->y() * aMajorRadius); std::dynamic_pointer_cast(attribute(MINOR_AXIS_START_ID())) - ->setValue(aCenter2d->x() - aMinorDir2d->x() * aMinorRadius, - aCenter2d->y() - aMinorDir2d->y() * aMinorRadius); + ->setValue(aCenter2d->x() - aMinorDir2d->x() * aMinorRadius, + aCenter2d->y() - aMinorDir2d->y() * aMinorRadius); std::dynamic_pointer_cast(attribute(MINOR_AXIS_END_ID())) - ->setValue(aCenter2d->x() + aMinorDir2d->x() * aMinorRadius, - aCenter2d->y() + aMinorDir2d->y() * aMinorRadius); - data()->blockSendAttributeUpdated(false); + ->setValue(aCenter2d->x() + aMinorDir2d->x() * aMinorRadius, + aCenter2d->y() + aMinorDir2d->y() * aMinorRadius); + + if (aEndPointAttr->isInitialized()) { + // recalculate REVERSED flag + std::shared_ptr anEllipseForArc( + new GeomAPI_Ellipse2d(aCenter2d, aMajorDir2d, aMajorRadius, aMinorRadius)); + GeomPnt2dPtr anEnd = aEndPointAttr->pnt(); + std::shared_ptr aProjection = anEllipseForArc->project(anEnd); + double aParamStart = 0.0, aParamEnd = 0.0; + if (aProjection && anEnd->distance(aProjection) <= tolerance && + anEllipseForArc->parameter(anEnd, paramTolerance, aParamEnd)) { + // do not recalculate REVERSED flag if the arc is not consistent + anEllipseForArc->parameter(aStart2d, paramTolerance, aParamStart); + aParamEnd -= aParamStart; + + if (myParamDelta >= 0.0 && myParamDelta <= PI * 0.5 && + aParamEnd < 0.0 && aParamEnd >= -PI * 0.5) { + boolean(REVERSED_ID())->setValue(true); + } + else if (myParamDelta <= 0.0 && myParamDelta >= -PI * 0.5 && + aParamEnd > 0.0 && aParamEnd <= PI * 0.5) { + boolean(REVERSED_ID())->setValue(false); + } + myParamDelta = aParamEnd; + } + } + data()->blockSendAttributeUpdated(aWasBlocked, false); return true; } @@ -207,6 +273,8 @@ void SketchPlugin_EllipticArc::createEllipticArc(SketchPlugin_Sketch* theSketch) GeomPointPtr aStartPnt(theSketch->to3D(aStartAttr->x(), aStartAttr->y())); GeomPointPtr aEndPnt(theSketch->to3D(aEndAttr->x(), aEndAttr->y())); + if (boolean(REVERSED_ID())->value()) + std::swap(aStartPnt, aEndPnt); anEllipseShape = GeomAlgoAPI_EdgeBuilder::ellipticArc(aCenter, aNormal, aMajorAxis, aMajorRadius, aMinorRadius, aStartPnt, aEndPnt);