X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSketchPlugin%2FSketchPlugin_Projection.cpp;h=afedd33e3a3fdb7f48a988a1027d4c9be05243cb;hb=cdbbde4803e9c320204d537d22af4ac7ef024962;hp=e04031fee6db7cee731dd447ce225900018759b9;hpb=d588149317acbc2bd8e6ceb00f8e82e806571775;p=modules%2Fshaper.git diff --git a/src/SketchPlugin/SketchPlugin_Projection.cpp b/src/SketchPlugin/SketchPlugin_Projection.cpp index e04031fee..afedd33e3 100644 --- a/src/SketchPlugin/SketchPlugin_Projection.cpp +++ b/src/SketchPlugin/SketchPlugin_Projection.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2019 CEA/DEN, EDF R&D +// Copyright (C) 2014-2021 CEA/DEN, EDF R&D // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -20,6 +20,8 @@ #include #include +#include +#include #include #include #include @@ -31,6 +33,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -39,6 +44,7 @@ #include +#include #include #include #include @@ -49,10 +55,17 @@ #include #include #include +#include #include static const double tolerance = 1.e-7; +static const std::string THE_KEEP_REF("true"); + +static bool isKeepReference(AttributeStringPtr theAttr) +{ + return !theAttr || !theAttr->isInitialized() || theAttr->value() == THE_KEEP_REF; +} SketchPlugin_Projection::SketchPlugin_Projection() @@ -65,6 +78,7 @@ void SketchPlugin_Projection::initDerivedClassAttributes() { data()->addAttribute(EXTERNAL_FEATURE_ID(), ModelAPI_AttributeSelection::typeId()); data()->addAttribute(PROJECTED_FEATURE_ID(), ModelAPI_AttributeRefAttr::typeId()); + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), PROJECTED_FEATURE_ID()); data()->attribute(PROJECTED_FEATURE_ID())->setIsArgument(false); data()->addAttribute(EXTERNAL_ID(), ModelAPI_AttributeSelection::typeId()); @@ -75,6 +89,22 @@ void SketchPlugin_Projection::initDerivedClassAttributes() ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), AUXILIARY_ID()); } +void SketchPlugin_Projection::initDerivedClassAttributes2() +{ + AttributePtr aKeepRefAttr = + data()->addAttribute(KEEP_REFERENCE_ID(), ModelAPI_AttributeString::typeId()); + if (!aKeepRefAttr->isInitialized()) { + std::dynamic_pointer_cast(aKeepRefAttr)->setValue(THE_KEEP_REF); + } + + data()->addAttribute(MAKE_FIXED(), ModelAPI_AttributeBoolean::typeId()); + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), MAKE_FIXED()); + + data()->addAttribute(FIXED_CONSTRAINT_ID(), ModelAPI_AttributeReference::typeId()); + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), FIXED_CONSTRAINT_ID()); + data()->attribute(FIXED_CONSTRAINT_ID())->setIsArgument(false); +} + void SketchPlugin_Projection::execute() { AttributeRefAttrPtr aRefAttr = data()->refattr(PROJECTED_FEATURE_ID()); @@ -82,7 +112,7 @@ void SketchPlugin_Projection::execute() return; FeaturePtr aProjection = ModelAPI_Feature::feature(aRefAttr->object()); - if (!lastResult().get()) { + if (isKeepReference(string(KEEP_REFERENCE_ID())) && !lastResult().get()) { bool hasProjResult = aProjection->lastResult().get() != NULL; ResultConstructionPtr aConstr = document()->createConstruction(data()); if (hasProjResult) @@ -100,6 +130,16 @@ void SketchPlugin_Projection::execute() computeProjection(EXTERNAL_FEATURE_ID()); } +bool SketchPlugin_Projection::isMacro() const +{ + if (!data() || !data()->isValid()) + return false; + + AttributeStringPtr aKeepRefAttr = + const_cast(this)->string(KEEP_REFERENCE_ID()); + return !isKeepReference(aKeepRefAttr); +} + void SketchPlugin_Projection::attributeChanged(const std::string& theID) { if ((theID == EXTERNAL_FEATURE_ID() || theID == EXTERNAL_ID()) && !myIsComputing) { @@ -145,6 +185,16 @@ static const std::set& ARC_PROJECTION() return aProj; } +static const std::set& BSPLINE_PROJECTION() +{ + static std::set aProj; + if (aProj.empty()) { + aProj.insert(SketchPlugin_BSpline::ID()); + aProj.insert(SketchPlugin_BSplinePeriodic::ID()); + } + return aProj; +} + static const std::set& possibleProjectionTypes(GeomEdgePtr theEdge, GeomVertexPtr theVertex) @@ -160,6 +210,8 @@ static const std::set& possibleProjectionTypes(GeomEdgePtr theEdge, else return ARC_PROJECTION(); } + else + return BSPLINE_PROJECTION(); } static const std::set DUMMY; return DUMMY; @@ -196,190 +248,71 @@ void SketchPlugin_Projection::computeProjection(const std::string& theID) // if the type of feature differs with already selected, remove it and create once again bool isRebuild = rebuildProjectedFeature(aProjection, aProjType); - std::shared_ptr aSketchPlane = sketch()->plane(); - ResultConstructionPtr aResult = std::dynamic_pointer_cast(lastResult()); if (!isRebuild && aResult && aResult->shape() && theID == EXTERNAL_FEATURE_ID()) { aResult->setShape(std::shared_ptr()); if (aProjection) - aProjection->selection(EXTERNAL_ID())->setValue(lastResult(), lastResult()->shape()); + aProjection->selection(EXTERNAL_ID())->setValue(ResultPtr(), GeomShapePtr()); } keepCurrentFeature(); - if (aVertex) { - std::shared_ptr aPrjPnt = aSketchPlane->project(aVertex->point()); - std::shared_ptr aPntInSketch = sketch()->to2D(aPrjPnt); + bool isProjected = false; + if (aVertex) + isProjected = projectPoint(aProjection, aVertex->point()); + else + isProjected = projectEdge(aProjection, anEdge); - rebuildProjectedFeature(aProjection, POINT_PROJECTION(), SketchPlugin_Point::ID()); + if (!isProjected) + return; // projection is not computed, stop processing - // update coordinates of projection - std::dynamic_pointer_cast( - aProjection->attribute(SketchPlugin_Point::COORD_ID()))->setValue(aPntInSketch); - } - else if (anEdge->isLine()) { - std::shared_ptr aFirst = aSketchPlane->project(anEdge->firstPoint()); - std::shared_ptr aLast = aSketchPlane->project(anEdge->lastPoint()); - - std::shared_ptr aFirstInSketch = sketch()->to2D(aFirst); - std::shared_ptr aLastInSketch = sketch()->to2D(aLast); - if (aFirstInSketch->distance(aLastInSketch) < tolerance) - return; // line is semi-orthogonal to the sketch plane - - rebuildProjectedFeature(aProjection, LINE_PROJECTION(), SketchPlugin_Line::ID()); - - // update attributes of projection - std::shared_ptr aStartPnt = std::dynamic_pointer_cast( - aProjection->attribute(SketchPlugin_Line::START_ID())); - std::shared_ptr aEndPnt = std::dynamic_pointer_cast( - aProjection->attribute(SketchPlugin_Line::END_ID())); - aStartPnt->setValue(aFirstInSketch); - aEndPnt->setValue(aLastInSketch); - } - else if (anEdge->isCircle() || anEdge->isArc() || anEdge->isEllipse()) { - GeomAlgoAPI_Projection aProjAlgo(aSketchPlane); - GeomCurvePtr aProjectedCurve = aProjAlgo.project(anEdge); - - if (aProjectedCurve->isCircle()) { - GeomAPI_Circ aCircle(aProjectedCurve); - GeomPointPtr aCenter = aSketchPlane->project(aCircle.center()); - GeomPnt2dPtr aCenterInSketch = sketch()->to2D(aCenter); - - if (aProjectedCurve->isTrimmed()) { - // ARC is a projection - rebuildProjectedFeature(aProjection, ARC_PROJECTION(), SketchPlugin_Arc::ID()); - - GeomPointPtr aFirst = aProjectedCurve->getPoint(aProjectedCurve->startParam()); - GeomPointPtr aLast = aProjectedCurve->getPoint(aProjectedCurve->endParam()); - GeomPnt2dPtr aFirstInSketch = sketch()->to2D(aSketchPlane->project(aFirst)); - GeomPnt2dPtr aLastInSketch = sketch()->to2D(aSketchPlane->project(aLast)); - - double aNormalsDot = aCircle.normal()->dot(aSketchPlane->direction()); - if (fabs(fabs(aNormalsDot) - 1.0) > tolerance) - return; // arc is not in the plane, parallel to the sketch plane - - bool isInversed = aNormalsDot < 0.; - - bool aWasBlocked = aProjection->data()->blockSendAttributeUpdated(true); - - // update attributes of projection - std::shared_ptr aCenterPnt = - std::dynamic_pointer_cast( - aProjection->attribute(SketchPlugin_Arc::CENTER_ID())); - std::shared_ptr aStartPnt = - std::dynamic_pointer_cast( - aProjection->attribute(SketchPlugin_Arc::START_ID())); - std::shared_ptr aEndPnt = - std::dynamic_pointer_cast( - aProjection->attribute(SketchPlugin_Arc::END_ID())); - aStartPnt->setValue(aFirstInSketch); - aEndPnt->setValue(aLastInSketch); - aCenterPnt->setValue(aCenterInSketch); - aProjection->boolean(SketchPlugin_Arc::REVERSED_ID())->setValue(isInversed); - - aProjection->data()->blockSendAttributeUpdated(aWasBlocked); - } - else { - // CIRCLE is a projection - rebuildProjectedFeature(aProjection, CIRCLE_ELLIPSE_PROJECTION(), - SketchPlugin_Circle::ID()); - - // update attributes of projection - std::shared_ptr aCenterPnt = - std::dynamic_pointer_cast( - aProjection->attribute(SketchPlugin_Circle::CENTER_ID())); - aCenterPnt->setValue(aCenterInSketch); - aProjection->real(SketchPlugin_Circle::RADIUS_ID())->setValue(aCircle.radius()); - } - } - else if (aProjectedCurve->isEllipse()) { - GeomAPI_Ellipse anEllipse(aProjectedCurve); - GeomPointPtr aCenter = aSketchPlane->project(anEllipse.center()); - GeomPnt2dPtr aCenterInSketch = sketch()->to2D(aCenter); - GeomPointPtr aFocus = aSketchPlane->project(anEllipse.firstFocus()); - GeomPnt2dPtr aFocusInSketch = sketch()->to2D(aFocus); - - if (aProjectedCurve->isTrimmed()) { - // ELLIPTIC ARC is a projection - rebuildProjectedFeature(aProjection, ARC_PROJECTION(), SketchPlugin_EllipticArc::ID()); - - GeomPointPtr aFirst = aProjectedCurve->getPoint(aProjectedCurve->startParam()); - GeomPointPtr aLast = aProjectedCurve->getPoint(aProjectedCurve->endParam()); - GeomPnt2dPtr aFirstInSketch = sketch()->to2D(aSketchPlane->project(aFirst)); - GeomPnt2dPtr aLastInSketch = sketch()->to2D(aSketchPlane->project(aLast)); - - double aNormalsDot = anEllipse.normal()->dot(aSketchPlane->direction()); - if (fabs(fabs(aNormalsDot) - 1.0) > tolerance) - return; // arc is not in the plane, parallel to the sketch plane - - bool isInversed = aNormalsDot < 0.; - - bool aWasBlocked = aProjection->data()->blockSendAttributeUpdated(true); - - // update attributes of projection - std::shared_ptr aCenterPnt = - std::dynamic_pointer_cast( - aProjection->attribute(SketchPlugin_EllipticArc::CENTER_ID())); - std::shared_ptr aFocusPnt = - std::dynamic_pointer_cast( - aProjection->attribute(SketchPlugin_EllipticArc::FIRST_FOCUS_ID())); - std::shared_ptr aStartPnt = - std::dynamic_pointer_cast( - aProjection->attribute(SketchPlugin_EllipticArc::START_POINT_ID())); - std::shared_ptr aEndPnt = - std::dynamic_pointer_cast( - aProjection->attribute(SketchPlugin_EllipticArc::END_POINT_ID())); - aStartPnt->setValue(aFirstInSketch); - aEndPnt->setValue(aLastInSketch); - aCenterPnt->setValue(aCenterInSketch); - aFocusPnt->setValue(aFocusInSketch); - aProjection->boolean(SketchPlugin_EllipticArc::REVERSED_ID())->setValue(isInversed); - - aProjection->data()->blockSendAttributeUpdated(aWasBlocked); - } - else { - // ELLIPSE is a projection - rebuildProjectedFeature(aProjection, CIRCLE_ELLIPSE_PROJECTION(), - SketchPlugin_Ellipse::ID()); - - // update attributes of projection - std::shared_ptr aCenterPnt = - std::dynamic_pointer_cast( - aProjection->attribute(SketchPlugin_Ellipse::CENTER_ID())); - aCenterPnt->setValue(aCenterInSketch); - std::shared_ptr aFocusPnt = - std::dynamic_pointer_cast( - aProjection->attribute(SketchPlugin_Ellipse::FIRST_FOCUS_ID())); - aFocusPnt->setValue(aFocusInSketch); - aProjection->real(SketchPlugin_Ellipse::MINOR_RADIUS_ID())->setValue( - anEllipse.minorRadius()); - } - } - else - return; - } else - return; + bool keepBackRef = isKeepReference(string(KEEP_REFERENCE_ID())); - aProjection->boolean(COPY_ID())->setValue(true); + aProjection->boolean(COPY_ID())->setValue(keepBackRef); aProjection->execute(); aRefAttr->setObject(aProjection); restoreCurrentFeature(); - if (theID == EXTERNAL_FEATURE_ID()) { - selection(EXTERNAL_ID())->selectValue(aExtFeature); + AttributeBooleanPtr aMakeFixedAttr = boolean(MAKE_FIXED()); + bool isMakeFixed = aMakeFixedAttr && aMakeFixedAttr->isInitialized() && aMakeFixedAttr->value(); - if (aResult) { - aResult->setShape(aProjection->lastResult()->shape()); - setResult(aResult); - GeomShapePtr anEmptyVal; - aProjection->selection(EXTERNAL_ID())->setValue(lastResult(), anEmptyVal); + AttributeReferencePtr aFixedConstrAttr = reference(FIXED_CONSTRAINT_ID()); + FeaturePtr aFixedConstraint; + if (aFixedConstrAttr && aFixedConstrAttr->isInitialized()) + aFixedConstraint = ModelAPI_Feature::feature(aFixedConstrAttr->value()); - static const Events_ID anEvent = Events_Loop::eventByName(EVENT_VISUAL_ATTRIBUTES); - ModelAPI_EventCreator::get()->sendUpdated(aProjection, anEvent, false); + if (keepBackRef) { + if (theID == EXTERNAL_FEATURE_ID()) { + selection(EXTERNAL_ID())->selectValue(aExtFeature); + + if (aResult) { + aResult->setShape(aProjection->lastResult()->shape()); + setResult(aResult); + GeomShapePtr anEmptyVal; + aProjection->selection(EXTERNAL_ID())->setValue(lastResult(), anEmptyVal); + } } } + else if (isMakeFixed) { + // fix the projected entity with the Fixed constraint + if (!aFixedConstraint) + aFixedConstraint = sketch()->addFeature(SketchPlugin_ConstraintRigid::ID()); + aFixedConstraint->refattr(SketchPlugin_Constraint::ENTITY_A())->setObject( + aProjection->lastResult()); + } + + + // remove Fixed constraint in case of redundance + if (aFixedConstraint && (keepBackRef || !isMakeFixed)) { + document()->removeFeature(aFixedConstraint); + aFixedConstraint = FeaturePtr(); + } + aFixedConstrAttr->setValue(aFixedConstraint); + + static const Events_ID anEvent = Events_Loop::eventByName(EVENT_VISUAL_ATTRIBUTES); + ModelAPI_EventCreator::get()->sendUpdated(aProjection, anEvent, false); } bool SketchPlugin_Projection::rebuildProjectedFeature( @@ -407,3 +340,291 @@ bool SketchPlugin_Projection::rebuildProjectedFeature( theProjection = sketch()->addFeature(theRequestedFeature); return isRebuild; } + +bool SketchPlugin_Projection::projectPoint(FeaturePtr& theProjection, const GeomPointPtr& thePoint) +{ + std::shared_ptr aSketchPlane = sketch()->plane(); + + std::shared_ptr aPrjPnt = aSketchPlane->project(thePoint); + std::shared_ptr aPntInSketch = sketch()->to2D(aPrjPnt); + + rebuildProjectedFeature(theProjection, POINT_PROJECTION(), SketchPlugin_Point::ID()); + + // update coordinates of projection + std::dynamic_pointer_cast( + theProjection->attribute(SketchPlugin_Point::COORD_ID()))->setValue(aPntInSketch); + return true; +} + +bool SketchPlugin_Projection::projectSegment(FeaturePtr& theProjection, const GeomEdgePtr& theEdge) +{ + std::shared_ptr aSketchPlane = sketch()->plane(); + + std::shared_ptr aFirst = aSketchPlane->project(theEdge->firstPoint()); + std::shared_ptr aLast = aSketchPlane->project(theEdge->lastPoint()); + + std::shared_ptr aFirstInSketch = sketch()->to2D(aFirst); + std::shared_ptr aLastInSketch = sketch()->to2D(aLast); + if (aFirstInSketch->distance(aLastInSketch) < tolerance) + return false; // line is semi-orthogonal to the sketch plane + + rebuildProjectedFeature(theProjection, LINE_PROJECTION(), SketchPlugin_Line::ID()); + + // update attributes of projection + std::shared_ptr aStartPnt = std::dynamic_pointer_cast( + theProjection->attribute(SketchPlugin_Line::START_ID())); + std::shared_ptr aEndPnt = std::dynamic_pointer_cast( + theProjection->attribute(SketchPlugin_Line::END_ID())); + aStartPnt->setValue(aFirstInSketch); + aEndPnt->setValue(aLastInSketch); + + return true; +} + +bool SketchPlugin_Projection::projectEdge(FeaturePtr& theProjection, const GeomEdgePtr& theEdge) +{ + if (theEdge->isLine()) + return projectSegment(theProjection, theEdge); + + std::shared_ptr aSketchPlane = sketch()->plane(); + + GeomAlgoAPI_Projection aProjAlgo(aSketchPlane); + GeomCurvePtr aProjectedCurve = aProjAlgo.project(theEdge); + + bool isOk = false; + if (aProjectedCurve->isCircle()) { + if (aProjectedCurve->isTrimmed()) { + // ARC is a projection + isOk = fillArc(theProjection, aProjectedCurve, aSketchPlane, theEdge); + } + else { + // CIRCLE is a projection + isOk = fillCircle(theProjection, aProjectedCurve, aSketchPlane); + } + } + else if (aProjectedCurve->isEllipse()) { + if (aProjectedCurve->isTrimmed()) { + // ELLIPTIC ARC is a projection + isOk = fillEllipticArc(theProjection, aProjectedCurve, aSketchPlane, theEdge); + } + else { + // ELLIPSE is a projection + isOk = fillEllipse(theProjection, aProjectedCurve, aSketchPlane); + } + } + else + isOk = fillBSpline(theProjection, aProjectedCurve, aSketchPlane); + + return isOk; +} + +bool SketchPlugin_Projection::fillArc(FeaturePtr& theProjection, + const GeomCurvePtr& theArc, + const GeomPlanePtr& thePlane, + const GeomEdgePtr& theOriginalEdge) +{ + rebuildProjectedFeature(theProjection, ARC_PROJECTION(), SketchPlugin_Arc::ID()); + + GeomAPI_Circ aCircle(theArc); + + double aNormalsDot = aCircle.normal()->dot(thePlane->direction()); + if (fabs(fabs(aNormalsDot) - 1.0) > tolerance) + return false; // arc is not in the plane, parallel to the sketch plane + + bool isInversed = aNormalsDot < 0.; + + GeomCirclePtr anOriginalCircle = theOriginalEdge->circle(); + if (anOriginalCircle) { + double aCirclesDot = anOriginalCircle->normal()->dot(aCircle.normal()); + if (aCirclesDot < 0.) + isInversed = !isInversed; + } + + GeomPointPtr aCenter = thePlane->project(aCircle.center()); + GeomPnt2dPtr aCenterInSketch = sketch()->to2D(aCenter); + + GeomPointPtr aFirst = theArc->getPoint(theArc->startParam()); + GeomPnt2dPtr aFirstInSketch = sketch()->to2D(thePlane->project(aFirst)); + + GeomPointPtr aLast = theArc->getPoint(theArc->endParam()); + GeomPnt2dPtr aLastInSketch = sketch()->to2D(thePlane->project(aLast)); + + bool aWasBlocked = theProjection->data()->blockSendAttributeUpdated(true); + + // update attributes of projection + std::shared_ptr aCenterPnt = + std::dynamic_pointer_cast( + theProjection->attribute(SketchPlugin_Arc::CENTER_ID())); + std::shared_ptr aStartPnt = + std::dynamic_pointer_cast( + theProjection->attribute(SketchPlugin_Arc::START_ID())); + std::shared_ptr aEndPnt = + std::dynamic_pointer_cast( + theProjection->attribute(SketchPlugin_Arc::END_ID())); + aStartPnt->setValue(aFirstInSketch); + aEndPnt->setValue(aLastInSketch); + aCenterPnt->setValue(aCenterInSketch); + theProjection->boolean(SketchPlugin_Arc::REVERSED_ID())->setValue(isInversed); + + theProjection->data()->blockSendAttributeUpdated(aWasBlocked); + return true; +} + +bool SketchPlugin_Projection::fillCircle(FeaturePtr& theProjection, + const GeomCurvePtr& theCircle, + const GeomPlanePtr& thePlane) +{ + rebuildProjectedFeature(theProjection, CIRCLE_ELLIPSE_PROJECTION(), SketchPlugin_Circle::ID()); + + GeomAPI_Circ aCircle(theCircle); + GeomPointPtr aCenter = thePlane->project(aCircle.center()); + GeomPnt2dPtr aCenterInSketch = sketch()->to2D(aCenter); + + // update attributes of projection + std::shared_ptr aCenterPnt = + std::dynamic_pointer_cast( + theProjection->attribute(SketchPlugin_Circle::CENTER_ID())); + aCenterPnt->setValue(aCenterInSketch); + theProjection->real(SketchPlugin_Circle::RADIUS_ID())->setValue(aCircle.radius()); + return true; +} + +bool SketchPlugin_Projection::fillEllipse(FeaturePtr& theProjection, + const GeomCurvePtr& theEllipse, + const GeomPlanePtr& thePlane) +{ + rebuildProjectedFeature(theProjection, CIRCLE_ELLIPSE_PROJECTION(), SketchPlugin_Ellipse::ID()); + + GeomAPI_Ellipse anEllipse(theEllipse); + GeomPointPtr aCenter = thePlane->project(anEllipse.center()); + GeomPnt2dPtr aCenterInSketch = sketch()->to2D(aCenter); + GeomPointPtr aFocus = thePlane->project(anEllipse.firstFocus()); + GeomPnt2dPtr aFocusInSketch = sketch()->to2D(aFocus); + + // update attributes of projection + std::shared_ptr aCenterPnt = + std::dynamic_pointer_cast( + theProjection->attribute(SketchPlugin_Ellipse::CENTER_ID())); + aCenterPnt->setValue(aCenterInSketch); + std::shared_ptr aFocusPnt = + std::dynamic_pointer_cast( + theProjection->attribute(SketchPlugin_Ellipse::FIRST_FOCUS_ID())); + aFocusPnt->setValue(aFocusInSketch); + theProjection->real(SketchPlugin_Ellipse::MINOR_RADIUS_ID())->setValue(anEllipse.minorRadius()); + return true; +} + +bool SketchPlugin_Projection::fillEllipticArc(FeaturePtr& theProjection, + const GeomCurvePtr& theEllipticArc, + const GeomPlanePtr& thePlane, + const GeomEdgePtr& theOriginalEdge) +{ + rebuildProjectedFeature(theProjection, ARC_PROJECTION(), SketchPlugin_EllipticArc::ID()); + + GeomAPI_Ellipse anEllipse(theEllipticArc); + + double aNormalsDot = anEllipse.normal()->dot(thePlane->direction()); + if (fabs(fabs(aNormalsDot) - 1.0) > tolerance) + return false; // arc is not in the plane, parallel to the sketch plane + + bool isInversed = aNormalsDot < 0.; + + GeomEllipsePtr anOriginalEllipse = theOriginalEdge->ellipse(); + if (anOriginalEllipse) { + double anEllipsesDot = anOriginalEllipse->normal()->dot(anEllipse.normal()); + if (anEllipsesDot < 0.) + isInversed = !isInversed; + } + + GeomPointPtr aCenter = thePlane->project(anEllipse.center()); + GeomPnt2dPtr aCenterInSketch = sketch()->to2D(aCenter); + GeomPointPtr aFocus = thePlane->project(anEllipse.firstFocus()); + GeomPnt2dPtr aFocusInSketch = sketch()->to2D(aFocus); + + GeomPointPtr aFirst = theEllipticArc->getPoint(theEllipticArc->startParam()); + GeomPnt2dPtr aFirstInSketch = sketch()->to2D(thePlane->project(aFirst)); + GeomPointPtr aLast = theEllipticArc->getPoint(theEllipticArc->endParam()); + GeomPnt2dPtr aLastInSketch = sketch()->to2D(thePlane->project(aLast)); + + bool aWasBlocked = theProjection->data()->blockSendAttributeUpdated(true); + + // update attributes of projection + std::shared_ptr aCenterPnt = + std::dynamic_pointer_cast( + theProjection->attribute(SketchPlugin_EllipticArc::CENTER_ID())); + std::shared_ptr aFocusPnt = + std::dynamic_pointer_cast( + theProjection->attribute(SketchPlugin_EllipticArc::FIRST_FOCUS_ID())); + std::shared_ptr aStartPnt = + std::dynamic_pointer_cast( + theProjection->attribute(SketchPlugin_EllipticArc::START_POINT_ID())); + std::shared_ptr aEndPnt = + std::dynamic_pointer_cast( + theProjection->attribute(SketchPlugin_EllipticArc::END_POINT_ID())); + aStartPnt->setValue(aFirstInSketch); + aEndPnt->setValue(aLastInSketch); + aCenterPnt->setValue(aCenterInSketch); + aFocusPnt->setValue(aFocusInSketch); + theProjection->boolean(SketchPlugin_EllipticArc::REVERSED_ID())->setValue(isInversed); + + theProjection->data()->blockSendAttributeUpdated(aWasBlocked); + return true; +} + +bool SketchPlugin_Projection::fillBSpline(FeaturePtr& theProjection, + const GeomCurvePtr& theCurve, + const GeomPlanePtr& /*thePlane*/) +{ + GeomAPI_BSpline aBSpline(theCurve); + + rebuildProjectedFeature(theProjection, BSPLINE_PROJECTION(), + aBSpline.isPeriodic() ? SketchPlugin_BSplinePeriodic::ID() : SketchPlugin_BSpline::ID()); + + theProjection->integer(SketchPlugin_BSpline::DEGREE_ID())->setValue(aBSpline.degree()); + + AttributePoint2DArrayPtr aPolesAttr = std::dynamic_pointer_cast( + theProjection->attribute(SketchPlugin_BSpline::POLES_ID())); + std::list aPoles = aBSpline.poles(); + aPolesAttr->setSize((int)aPoles.size()); + std::list::iterator anIt = aPoles.begin(); + for (int anIndex = 0; anIt != aPoles.end(); ++anIt, ++anIndex) { + GeomPnt2dPtr aPoleInSketch = sketch()->to2D(*anIt); + aPolesAttr->setPnt(anIndex, aPoleInSketch); + } + + AttributeDoubleArrayPtr aWeightsAttr = + theProjection->data()->realArray(SketchPlugin_BSpline::WEIGHTS_ID()); + std::list aWeights = aBSpline.weights(); + if (aWeights.empty()) { // rational B-spline + int aSize = (int)aPoles.size(); + aWeightsAttr->setSize(aSize); + for (int anIndex = 0; anIndex < aSize; ++anIndex) + aWeightsAttr->setValue(anIndex, 1.0); + } + else { // non-rational B-spline + aWeightsAttr->setSize((int)aWeights.size()); + std::list::iterator aWIt = aWeights.begin(); + for (int anIndex = 0; aWIt != aWeights.end(); ++aWIt, ++anIndex) + aWeightsAttr->setValue(anIndex, *aWIt); + } + + AttributeDoubleArrayPtr aKnotsAttr = + theProjection->data()->realArray(SketchPlugin_BSpline::KNOTS_ID()); + std::list aKnots = aBSpline.knots(); + int aSize = (int)aKnots.size(); + aKnotsAttr->setSize(aSize); + std::list::iterator aKIt = aKnots.begin(); + for (int index = 0; index < aSize; ++index, ++aKIt) + aKnotsAttr->setValue(index, *aKIt); + + AttributeIntArrayPtr aMultsAttr = + theProjection->data()->intArray(SketchPlugin_BSpline::MULTS_ID()); + std::list aMultiplicities = aBSpline.mults(); + aSize = (int)aMultiplicities.size(); + aMultsAttr->setSize(aSize); + std::list::iterator aMIt = aMultiplicities.begin(); + for (int index = 0; index < aSize; ++index, ++aMIt) + aMultsAttr->setValue(index, *aMIt); + + return true; +}