X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSketchPlugin%2FSketchPlugin_Projection.cpp;h=79eb675ca240ca273480dd8d6d4c92ed3b8f08d9;hb=da65953fac478d8e87f89b294c3344f1b4250258;hp=0d40b618130d79109470f4f7ad9ef8d9f099180f;hpb=c4eab94a20a0d93100549a210582d46409fec1cc;p=modules%2Fshaper.git diff --git a/src/SketchPlugin/SketchPlugin_Projection.cpp b/src/SketchPlugin/SketchPlugin_Projection.cpp index 0d40b6181..79eb675ca 100644 --- a/src/SketchPlugin/SketchPlugin_Projection.cpp +++ b/src/SketchPlugin/SketchPlugin_Projection.cpp @@ -21,6 +21,8 @@ #include #include +#include +#include #include #include #include @@ -36,11 +38,13 @@ #include #include +#include #include #include #include #include #include +#include #include #include @@ -101,21 +105,60 @@ void SketchPlugin_Projection::attributeChanged(const std::string& theID) } } -static bool isValidProjectionType(FeaturePtr theProjection, - GeomEdgePtr theEdge, - GeomVertexPtr theVertex) +static const std::set& POINT_PROJECTION() { - if (theVertex && theProjection->getKind() == SketchPlugin_Point::ID()) - return true; + 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& possibleProjectionTypes(GeomEdgePtr theEdge, + GeomVertexPtr theVertex) +{ + 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(); + } } - return false; + static const std::set DUMMY; + return DUMMY; } void SketchPlugin_Projection::computeProjection(const std::string& theID) @@ -139,41 +182,33 @@ 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)) { - DocumentPtr aDoc = sketch()->document(); - - aRefAttr->setObject(data()->owner()); // to not remove of this remove reference to aProjection - std::set aFeaturesToBeRemoved; - aFeaturesToBeRemoved.insert(aProjection); - ModelAPI_Tools::removeFeaturesAndReferences(aFeaturesToBeRemoved); - aProjection = FeaturePtr(); - aRefAttr->setObject(aProjection); - hasPrevProj = false; - } + bool isRebuild = rebuildProjectedFeature(aProjection, aProjType); std::shared_ptr aSketchPlane = sketch()->plane(); ResultConstructionPtr aResult = std::dynamic_pointer_cast(lastResult()); - if (aResult && aResult->shape() && theID == EXTERNAL_FEATURE_ID()) { + if (!isRebuild && aResult && aResult->shape() && theID == EXTERNAL_FEATURE_ID()) { aResult->setShape(std::shared_ptr()); if (aProjection) aProjection->selection(EXTERNAL_ID())->setValue(lastResult(), lastResult()->shape()); } + keepCurrentFeature(); + if (aVertex) { std::shared_ptr aPrjPnt = aSketchPlane->project(aVertex->point()); std::shared_ptr aPntInSketch = sketch()->to2D(aPrjPnt); - if (!hasPrevProj) - aProjection = sketch()->addFeature(SketchPlugin_Point::ID()); + rebuildProjectedFeature(aProjection, POINT_PROJECTION(), SketchPlugin_Point::ID()); // update coordinates of projection std::dynamic_pointer_cast( @@ -188,8 +223,7 @@ void SketchPlugin_Projection::computeProjection(const std::string& theID) if (aFirstInSketch->distance(aLastInSketch) < tolerance) return; // line is semi-orthogonal to the sketch plane - if (!hasPrevProj) - aProjection = sketch()->addFeature(SketchPlugin_Line::ID()); + rebuildProjectedFeature(aProjection, LINE_PROJECTION(), SketchPlugin_Line::ID()); // update attributes of projection std::shared_ptr aStartPnt = std::dynamic_pointer_cast( @@ -199,64 +233,127 @@ void SketchPlugin_Projection::computeProjection(const std::string& theID) aStartPnt->setValue(aFirstInSketch); aEndPnt->setValue(aLastInSketch); } - else if (anEdge->isCircle()) { - std::shared_ptr aCircle = anEdge->circle(); - double aRadius = aCircle->radius(); - - double aNormalsDot = aCircle->normal()->dot(aSketchPlane->direction()); - if (fabs(fabs(aNormalsDot) - 1.0) > tolerance) - return; // circle is not in the plane, parallel to the sketch plane - - std::shared_ptr aCenter = aSketchPlane->project(aCircle->center()); - std::shared_ptr aCenterInSketch = sketch()->to2D(aCenter); - - if (!hasPrevProj) - aProjection = sketch()->addFeature(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(aRadius); - } - 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); - - 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.; - - if (!hasPrevProj) - aProjection = sketch()->addFeature(SketchPlugin_Arc::ID()); - - 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 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; @@ -264,6 +361,8 @@ void SketchPlugin_Projection::computeProjection(const std::string& theID) aProjection->execute(); aRefAttr->setObject(aProjection); + restoreCurrentFeature(); + if (theID == EXTERNAL_FEATURE_ID()) { selection(EXTERNAL_ID())->selectValue(aExtFeature); @@ -275,3 +374,29 @@ void SketchPlugin_Projection::computeProjection(const std::string& theID) } } } + +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(theProjection); + ModelAPI_Tools::removeFeaturesAndReferences(aFeaturesToBeRemoved); + theProjection = FeaturePtr(); + aRefAttr->setObject(theProjection); + isRebuild = true; + } + + if (!theProjection && !theRequestedFeature.empty()) + theProjection = sketch()->addFeature(theRequestedFeature); + return isRebuild; +}