X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSketchPlugin%2FSketchPlugin_MacroArc.cpp;h=5bbb322358f90792c725358c6a973603614ec281;hb=b5893b0a30fac08134c24de4565cb513a43affa6;hp=42e3b1cd5b2b64cd2fb5906983587c0ce40887f0;hpb=205dad6e3d828218e87f8dc050a41cb1af7eaa65;p=modules%2Fshaper.git diff --git a/src/SketchPlugin/SketchPlugin_MacroArc.cpp b/src/SketchPlugin/SketchPlugin_MacroArc.cpp index 42e3b1cd5..5bbb32235 100644 --- a/src/SketchPlugin/SketchPlugin_MacroArc.cpp +++ b/src/SketchPlugin/SketchPlugin_MacroArc.cpp @@ -29,12 +29,15 @@ #include #include #include +#include #include #include -#include + +#include #include #include +#include // for sqrt on Linux #include @@ -50,6 +53,71 @@ static void projectPointOnCircle(AttributePoint2DPtr& thePoint, const GeomAPI_Ci thePoint->setValue(aProjection); } +static void intersectShapeAndCircle(const GeomShapePtr& theShape, + const GeomAPI_Circ2d& theCircle, + const SketchPlugin_Sketch* theSketch, + AttributePoint2DPtr& theIntersection) +{ + if (!theShape->isEdge()) + return projectPointOnCircle(theIntersection, theCircle); + + // convert shape to unbounded + std::shared_ptr anEdge(new GeomAPI_Edge(theShape)); + if (anEdge->isLine()) { + static const double HALF_SIZE = 1.e6; + std::shared_ptr aLoc = anEdge->line()->location()->xyz(); + std::shared_ptr aDir = anEdge->line()->direction()->xyz(); + + std::shared_ptr aStart( + new GeomAPI_Pnt(aLoc->added(aDir->multiplied(-HALF_SIZE)))); + std::shared_ptr aEnd( + new GeomAPI_Pnt(aLoc->added(aDir->multiplied(HALF_SIZE)))); + anEdge = GeomAlgoAPI_EdgeBuilder::line(aStart, aEnd); + } else if (anEdge->isArc()) { + std::shared_ptr aCircle = anEdge->circle(); + anEdge = GeomAlgoAPI_EdgeBuilder::lineCircle( + aCircle->center(), aCircle->normal(), aCircle->radius()); + } + + // convert 2D circle to 3D object + std::shared_ptr aCenter2d = theCircle.center(); + std::shared_ptr aCenter(theSketch->to3D(aCenter2d->x(), aCenter2d->y())); + std::shared_ptr aNDir = std::dynamic_pointer_cast( + const_cast(theSketch)->attribute(SketchPlugin_Sketch::NORM_ID())); + std::shared_ptr aNormal(new GeomAPI_Dir(aNDir->x(), aNDir->y(), aNDir->z())); + + GeomShapePtr aCircleShape = + GeomAlgoAPI_EdgeBuilder::lineCircle(aCenter, aNormal, theCircle.radius()); + + GeomShapePtr anInter = anEdge->intersect(aCircleShape); + std::shared_ptr anInterPnt; + if (!anInter) + return projectPointOnCircle(theIntersection, theCircle); + if (anInter->isVertex()) { + std::shared_ptr aVertex(new GeomAPI_Vertex(anInter)); + anInterPnt = theSketch->to2D(aVertex->point()); + } else if (anInter->isCompound()) { + double aMinDist = 1.e300; + + GeomAPI_ShapeIterator anIt(anInter); + for (; anIt.more(); anIt.next()) { + GeomShapePtr aCurrent = anIt.current(); + if (!aCurrent->isVertex()) + continue; + std::shared_ptr aVertex(new GeomAPI_Vertex(aCurrent)); + std::shared_ptr aPnt = theSketch->to2D(aVertex->point()); + double aDist = aPnt->distance(theIntersection->pnt()); + if (aDist < aMinDist) { + aMinDist = aDist; + anInterPnt = aPnt; + } + } + } + if(anInterPnt.get()) { + theIntersection->setValue(anInterPnt); + } +} + SketchPlugin_MacroArc::SketchPlugin_MacroArc() : SketchPlugin_SketchEntity(), @@ -149,12 +217,17 @@ void SketchPlugin_MacroArc::attributeChanged(const std::string& theID) } bool aWasBlocked = data()->blockSendAttributeUpdated(true); + if(myCenter.get()) { + // center attribute is used in processEvent() to set reference to reentrant arc + std::dynamic_pointer_cast(attribute(CENTER_POINT_ID())) + ->setValue(myCenter); + } real(RADIUS_ID())->setValue(aRadius); real(ANGLE_ID())->setValue(anAngle); data()->blockSendAttributeUpdated(aWasBlocked, false); } -GeomShapePtr SketchPlugin_MacroArc::getArcShape() +GeomShapePtr SketchPlugin_MacroArc::getArcShape(bool isBound) { if(!myStart.get() || !myEnd.get() || !myCenter.get()) { return GeomShapePtr(); @@ -172,9 +245,15 @@ GeomShapePtr SketchPlugin_MacroArc::getArcShape() std::dynamic_pointer_cast(aSketch->attribute(SketchPlugin_Sketch::NORM_ID())); std::shared_ptr aNormal(new GeomAPI_Dir(aNDir->x(), aNDir->y(), aNDir->z())); - GeomShapePtr anArcShape = boolean(REVERSED_ID())->value() ? - GeomAlgoAPI_EdgeBuilder::lineCircleArc(aCenter, anEnd, aStart, aNormal) - : GeomAlgoAPI_EdgeBuilder::lineCircleArc(aCenter, aStart, anEnd, aNormal); + GeomShapePtr anArcShape; + if (isBound) { + anArcShape = boolean(REVERSED_ID())->value() ? + GeomAlgoAPI_EdgeBuilder::lineCircleArc(aCenter, anEnd, aStart, aNormal) + : GeomAlgoAPI_EdgeBuilder::lineCircleArc(aCenter, aStart, anEnd, aNormal); + } else { + double aRadius = aCenter->distance(aStart); + anArcShape = GeomAlgoAPI_EdgeBuilder::lineCircle(aCenter, aNormal, aRadius); + } return anArcShape; } @@ -278,7 +357,7 @@ void SketchPlugin_MacroArc::execute() // message to init reentrant operation static Events_ID anId = SketchPlugin_MacroArcReentrantMessage::eventId(); std::shared_ptr aMessage = std::shared_ptr - (new SketchPlugin_MacroArcReentrantMessage(anId, 0)); + (new SketchPlugin_MacroArcReentrantMessage(anId, this)); std::string anEditArcType = string(EDIT_ARC_TYPE_ID())->value(); aMessage->setTypeOfCreation(!anEditArcType.empty() ? anEditArcType : anArcType); @@ -328,16 +407,33 @@ std::string SketchPlugin_MacroArc::processEvent(const std::shared_ptrsetValue(aClickedPoint); // fill reference attribute AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast( - attribute(aReferenceAttributeName)); + attribute(aReferenceAttributeName)); if (aRefAttr.get()) { - if (anAttribute.get()) + if (anAttribute.get()) { + if (!anAttribute->owner().get() || !anAttribute->owner()->data()->isValid()) { + FeaturePtr aCreatedFeature = aReentrantMessage->createdFeature(); + if (aCreatedFeature.get()) { + std::string anID = anAttribute->id(); + std::string anArcID; + if (anID == END_POINT_1_ID() || anID == END_POINT_2_ID() || + anID == END_POINT_3_ID()) + anArcID = SketchPlugin_Arc::END_ID(); + else if (anID == START_POINT_1_ID() || anID ==START_POINT_2_ID()) + anArcID = SketchPlugin_Arc::START_ID(); + else if (anID == CENTER_POINT_ID()) + anArcID = SketchPlugin_Arc::CENTER_ID(); + anAttribute = aCreatedFeature->attribute(anArcID); + } + } aRefAttr->setAttr(anAttribute); + } else if (anObject.get()) { // if presentation of previous reentrant macro arc is used, the object is invalid, // we should use result of previous feature of the message(Arc) if (!anObject->data()->isValid()) { FeaturePtr aCreatedFeature = aReentrantMessage->createdFeature(); - anObject = aCreatedFeature->lastResult(); + if (aCreatedFeature.get()) + anObject = aCreatedFeature->lastResult(); } aRefAttr->setObject(anObject); } @@ -391,9 +487,24 @@ void SketchPlugin_MacroArc::fillByCenterAndTwoPassed() GeomAPI_Circ2d aCircleForArc(myCenter, myStart); - // End point should be a projection on circle. bool aWasBlocked = data()->blockSendAttributeUpdated(true); - projectPointOnCircle(anEndPointAttr, aCircleForArc); + // check the end point is referred to another feature + GeomShapePtr aRefShape; + AttributeRefAttrPtr aEndPointRefAttr = refattr(END_POINT_REF_ID()); + if (aEndPointRefAttr && aEndPointRefAttr->isInitialized()) { + if (aEndPointRefAttr->isObject()) { + FeaturePtr aFeature = ModelAPI_Feature::feature(aEndPointRefAttr->object()); + if (aFeature) + aRefShape = aFeature->lastResult()->shape(); + } + } + if (aRefShape) { + // Calculate end point as an intersection between circle and another shape + intersectShapeAndCircle(aRefShape, aCircleForArc, sketch(), anEndPointAttr); + } else { + // End point should be a projection on circle. + projectPointOnCircle(anEndPointAttr, aCircleForArc); + } data()->blockSendAttributeUpdated(aWasBlocked, false); myEnd = anEndPointAttr->pnt(); @@ -437,18 +548,22 @@ void SketchPlugin_MacroArc::fillByThreePassedPoints() SketchPlugin_Tools::convertRefAttrToPointOrTangentCurve( refattr(PASSED_POINT_REF_ID()), aPassedPointAttr, aTangentCurve, aPassedPnt); - std::shared_ptr aPassed; - if (aTangentCurve) - aPassed = aTangentCurve; - else - aPassed = aPassedPnt; - - std::shared_ptr anAxis = SketchPlugin_Sketch::plane(sketch()); - GeomAPI_Circ2d aCircle(myStart, myEnd, aPassed, anAxis); - myCenter = aCircle.center(); - aCircle = GeomAPI_Circ2d(myCenter, myStart); + GeomAlgoAPI_Circ2dBuilder aCircBuilder(SketchPlugin_Sketch::plane(sketch())); + aCircBuilder.addPassingPoint(myStart); + aCircBuilder.addPassingPoint(myEnd); + if (aTangentCurve) { + aCircBuilder.addTangentCurve(aTangentCurve); + aCircBuilder.setClosestPoint(aPassedPointAttr->pnt()); + } else + aCircBuilder.addPassingPoint(aPassedPnt); + + std::shared_ptr aCircle = aCircBuilder.circle(); + if (!aCircle) + return; + myCenter = aCircle->center(); - recalculateReversedFlagByPassed(aCircle); + aCircle = std::shared_ptr(new GeomAPI_Circ2d(myCenter, myStart)); + recalculateReversedFlagByPassed(*aCircle); } else myCenter.reset(new GeomAPI_Pnt2d(myStart->xy()->added(myEnd->xy())->multiplied(0.5))); } @@ -497,11 +612,15 @@ void SketchPlugin_MacroArc::fillByTangentEdge() FeaturePtr aTangentFeature = ModelAPI_Feature::feature(aTangentPointAttr->owner()); std::shared_ptr aTangentShape = aTangentFeature->lastResult()->shape(); - std::shared_ptr anAxis = SketchPlugin_Sketch::plane(sketch()); - GeomAPI_Circ2d aCircle(myStart, myEnd, aTangentShape, anAxis); - myCenter = aCircle.center(); + GeomAlgoAPI_Circ2dBuilder aCircBuilder(SketchPlugin_Sketch::plane(sketch())); + aCircBuilder.addPassingPoint(myStart); + aCircBuilder.addPassingPoint(myEnd); + aCircBuilder.addTangentCurve(aTangentShape); + + std::shared_ptr aCircle = aCircBuilder.circle(); + myCenter = aCircle->center(); // rebuild circle to set start point equal to zero parameter - aCircle = GeomAPI_Circ2d(myCenter, myStart); - recalculateReversedFlagByEnd(aCircle); + aCircle = std::shared_ptr(new GeomAPI_Circ2d(myCenter, myStart)); + recalculateReversedFlagByEnd(*aCircle); }