X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSketchPlugin%2FSketchPlugin_Projection.cpp;h=afedd33e3a3fdb7f48a988a1027d4c9be05243cb;hb=eed8986352c64d13fe05eed6c42c36902ddddf52;hp=59f4cd6fbe1aa198e05cad420e386294b2608b44;hpb=aa7ce8bd36a44173fd76fefa189d8b6123d76ad2;p=modules%2Fshaper.git diff --git a/src/SketchPlugin/SketchPlugin_Projection.cpp b/src/SketchPlugin/SketchPlugin_Projection.cpp index 59f4cd6fb..afedd33e3 100644 --- a/src/SketchPlugin/SketchPlugin_Projection.cpp +++ b/src/SketchPlugin/SketchPlugin_Projection.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2017 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 @@ -12,16 +12,19 @@ // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // -// See http://www.salome-platform.org/ or -// email : webmaster.salome@opencascade.com +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // #include #include +#include +#include #include +#include +#include #include #include #include @@ -30,23 +33,40 @@ #include #include #include +#include +#include +#include #include #include #include #include +#include +#include + +#include #include #include +#include #include #include #include #include #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() : SketchPlugin_SketchEntity(), @@ -58,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()); @@ -68,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()); @@ -75,14 +112,17 @@ void SketchPlugin_Projection::execute() return; FeaturePtr aProjection = ModelAPI_Feature::feature(aRefAttr->object()); - if (!lastResult().get() && aProjection->lastResult().get()) { + if (isKeepReference(string(KEEP_REFERENCE_ID())) && !lastResult().get()) { + bool hasProjResult = aProjection->lastResult().get() != NULL; ResultConstructionPtr aConstr = document()->createConstruction(data()); - aConstr->setShape(aProjection->lastResult()->shape()); + if (hasProjResult) + aConstr->setShape(aProjection->lastResult()->shape()); aConstr->setIsInHistory(false); aConstr->setDisplayed(false); setResult(aConstr); - aProjection->selection(EXTERNAL_ID())->setValue(lastResult(), lastResult()->shape()); + if (hasProjResult) + aProjection->selection(EXTERNAL_ID())->setValue(lastResult(), lastResult()->shape()); } // is sketch plane is changed (issue 1791), attribute of projection is not changed, but @@ -90,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) { @@ -99,21 +149,72 @@ void SketchPlugin_Projection::attributeChanged(const std::string& theID) } } -static bool isValidProjectionType(FeaturePtr theProjection, - GeomEdgePtr theEdge, - GeomVertexPtr theVertex) +static const std::set& POINT_PROJECTION() +{ + static std::set aProj; + if (aProj.empty()) + aProj.insert(SketchPlugin_Point::ID()); + return aProj; +} + +static const std::set& LINE_PROJECTION() +{ + static std::set aProj; + if (aProj.empty()) + aProj.insert(SketchPlugin_Line::ID()); + return aProj; +} + +static const std::set& CIRCLE_ELLIPSE_PROJECTION() +{ + static std::set aProj; + if (aProj.empty()) { + aProj.insert(SketchPlugin_Circle::ID()); + aProj.insert(SketchPlugin_Ellipse::ID()); + } + return aProj; +} + +static const std::set& ARC_PROJECTION() +{ + static std::set aProj; + if (aProj.empty()) { + aProj.insert(SketchPlugin_Arc::ID()); + aProj.insert(SketchPlugin_EllipticArc::ID()); + } + 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) { - if (theVertex && theProjection->getKind() == SketchPlugin_Point::ID()) - return true; + if (theVertex) + return POINT_PROJECTION(); if (theEdge) { - if (theEdge->isLine() && theProjection->getKind() == SketchPlugin_Line::ID()) - return true; - else if (theEdge->isCircle() && theProjection->getKind() == SketchPlugin_Circle::ID()) - return true; - else if (theEdge->isArc() && theProjection->getKind() == SketchPlugin_Arc::ID()) - return true; + if (theEdge->isLine()) + return LINE_PROJECTION(); + else if (theEdge->isCircle() || theEdge->isArc() || theEdge->isEllipse()) { + if (theEdge->isClosed()) + return CIRCLE_ELLIPSE_PROJECTION(); + else + return ARC_PROJECTION(); + } + else + return BSPLINE_PROJECTION(); } - return false; + static const std::set DUMMY; + return DUMMY; } void SketchPlugin_Projection::computeProjection(const std::string& theID) @@ -137,129 +238,393 @@ void SketchPlugin_Projection::computeProjection(const std::string& theID) if (!anEdge && !aVertex) return; + const std::set& aProjType = possibleProjectionTypes(anEdge, aVertex); + AttributeRefAttrPtr aRefAttr = data()->refattr(PROJECTED_FEATURE_ID()); FeaturePtr aProjection; if (aRefAttr && aRefAttr->isInitialized()) aProjection = ModelAPI_Feature::feature(aRefAttr->object()); // if the type of feature differs with already selected, remove it and create once again - bool hasPrevProj = aProjection.get() != 0; - if (hasPrevProj && !isValidProjectionType(aProjection, anEdge, aVertex)) { + bool isRebuild = rebuildProjectedFeature(aProjection, aProjType); + + 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(ResultPtr(), GeomShapePtr()); + } + + keepCurrentFeature(); + + bool isProjected = false; + if (aVertex) + isProjected = projectPoint(aProjection, aVertex->point()); + else + isProjected = projectEdge(aProjection, anEdge); + + if (!isProjected) + return; // projection is not computed, stop processing + + bool keepBackRef = isKeepReference(string(KEEP_REFERENCE_ID())); + + aProjection->boolean(COPY_ID())->setValue(keepBackRef); + aProjection->execute(); + aRefAttr->setObject(aProjection); + + restoreCurrentFeature(); + + AttributeBooleanPtr aMakeFixedAttr = boolean(MAKE_FIXED()); + bool isMakeFixed = aMakeFixedAttr && aMakeFixedAttr->isInitialized() && aMakeFixedAttr->value(); + + AttributeReferencePtr aFixedConstrAttr = reference(FIXED_CONSTRAINT_ID()); + FeaturePtr aFixedConstraint; + if (aFixedConstrAttr && aFixedConstrAttr->isInitialized()) + aFixedConstraint = ModelAPI_Feature::feature(aFixedConstrAttr->value()); + + 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( + FeaturePtr& theProjection, + const std::set& theSupportedTypes, + const std::string& theRequestedFeature) +{ + bool isRebuild = false; + if (theProjection && + (theSupportedTypes.find(theProjection->getKind()) == theSupportedTypes.end() || + (!theRequestedFeature.empty() && theProjection->getKind() != theRequestedFeature))) { DocumentPtr aDoc = sketch()->document(); + AttributeRefAttrPtr aRefAttr = data()->refattr(PROJECTED_FEATURE_ID()); aRefAttr->setObject(data()->owner()); // to not remove of this remove reference to aProjection std::set aFeaturesToBeRemoved; - aFeaturesToBeRemoved.insert(aProjection); + aFeaturesToBeRemoved.insert(theProjection); ModelAPI_Tools::removeFeaturesAndReferences(aFeaturesToBeRemoved); - aProjection = FeaturePtr(); - aRefAttr->setObject(aProjection); - hasPrevProj = false; + theProjection = FeaturePtr(); + aRefAttr->setObject(theProjection); + isRebuild = true; } + if (!theProjection && !theRequestedFeature.empty()) + theProjection = sketch()->addFeature(theRequestedFeature); + return isRebuild; +} + +bool SketchPlugin_Projection::projectPoint(FeaturePtr& theProjection, const GeomPointPtr& thePoint) +{ std::shared_ptr aSketchPlane = sketch()->plane(); - ResultConstructionPtr aResult = - std::dynamic_pointer_cast(lastResult()); - if (aResult && aResult->shape() && theID == EXTERNAL_FEATURE_ID()) { - aResult->setShape(std::shared_ptr()); - aProjection->selection(EXTERNAL_ID())->setValue(lastResult(), lastResult()->shape()); - } + 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()); - if (aVertex) { - std::shared_ptr aPrjPnt = aSketchPlane->project(aVertex->point()); - std::shared_ptr aPntInSketch = sketch()->to2D(aPrjPnt); + 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(); - if (!hasPrevProj) - aProjection = sketch()->addFeature(SketchPlugin_Point::ID()); + GeomAlgoAPI_Projection aProjAlgo(aSketchPlane); + GeomCurvePtr aProjectedCurve = aProjAlgo.project(theEdge); - // update coordinates of projection - std::dynamic_pointer_cast( - aProjection->attribute(SketchPlugin_Point::COORD_ID()))->setValue(aPntInSketch); + 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 (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 - - if (!hasPrevProj) - aProjection = sketch()->addFeature(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 (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 if (anEdge->isCircle()) { - std::shared_ptr aCircle = anEdge->circle(); - double aRadius = aCircle->radius(); + else + isOk = fillBSpline(theProjection, aProjectedCurve, aSketchPlane); - std::shared_ptr aCenter = aSketchPlane->project(aCircle->center()); - std::shared_ptr aCenterInSketch = sketch()->to2D(aCenter); + return isOk; +} - if (!hasPrevProj) - aProjection = sketch()->addFeature(SketchPlugin_Circle::ID()); +bool SketchPlugin_Projection::fillArc(FeaturePtr& theProjection, + const GeomCurvePtr& theArc, + const GeomPlanePtr& thePlane, + const GeomEdgePtr& theOriginalEdge) +{ + rebuildProjectedFeature(theProjection, ARC_PROJECTION(), SketchPlugin_Arc::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(aRadius); + 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; } - else if (anEdge->isArc()) { - 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); - std::shared_ptr aCircle = anEdge->circle(); - std::shared_ptr aCenter = aSketchPlane->project(aCircle->center()); - std::shared_ptr aCenterInSketch = sketch()->to2D(aCenter); + GeomPointPtr aCenter = thePlane->project(aCircle.center()); + GeomPnt2dPtr aCenterInSketch = sketch()->to2D(aCenter); - bool isInversed = aCircle->normal()->dot(aSketchPlane->direction()) < 0.; + GeomPointPtr aFirst = theArc->getPoint(theArc->startParam()); + GeomPnt2dPtr aFirstInSketch = sketch()->to2D(thePlane->project(aFirst)); - if (!hasPrevProj) - aProjection = sketch()->addFeature(SketchPlugin_Arc::ID()); + GeomPointPtr aLast = theArc->getPoint(theArc->endParam()); + GeomPnt2dPtr aLastInSketch = sketch()->to2D(thePlane->project(aLast)); - bool aWasBlocked = aProjection->data()->blockSendAttributeUpdated(true); + bool aWasBlocked = theProjection->data()->blockSendAttributeUpdated(true); - // update attributes of projection - std::shared_ptr aCenterPnt = + // update attributes of projection + std::shared_ptr aCenterPnt = std::dynamic_pointer_cast( - aProjection->attribute(SketchPlugin_Arc::CENTER_ID())); - std::shared_ptr aStartPnt = + theProjection->attribute(SketchPlugin_Arc::CENTER_ID())); + std::shared_ptr aStartPnt = std::dynamic_pointer_cast( - aProjection->attribute(SketchPlugin_Arc::START_ID())); - std::shared_ptr aEndPnt = + theProjection->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, false); - } else - return; + 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; +} - aProjection->boolean(COPY_ID())->setValue(true); - aProjection->execute(); - aRefAttr->setObject(aProjection); +bool SketchPlugin_Projection::fillCircle(FeaturePtr& theProjection, + const GeomCurvePtr& theCircle, + const GeomPlanePtr& thePlane) +{ + rebuildProjectedFeature(theProjection, CIRCLE_ELLIPSE_PROJECTION(), SketchPlugin_Circle::ID()); - if (theID == EXTERNAL_FEATURE_ID()) { - selection(EXTERNAL_ID())->selectValue(aExtFeature); + GeomAPI_Circ aCircle(theCircle); + GeomPointPtr aCenter = thePlane->project(aCircle.center()); + GeomPnt2dPtr aCenterInSketch = sketch()->to2D(aCenter); - if (aResult) { - aResult->setShape(aProjection->lastResult()->shape()); - setResult(aResult); - aProjection->selection(EXTERNAL_ID())->setValue(lastResult(), NULL); - } + // 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; }