X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2FSketchPlugin%2FSketchPlugin_MacroCircle.cpp;h=b1528ae5aaa8f6b1182fdf5a69d398e5cc6ca6b7;hb=4d139bda8e931e65bf1a63b12e6b13d26ae9b205;hp=2af73d693548bc28112927fe3e95b65152691a03;hpb=84c65dc1337015a368f160b588994d1f59a7b2f0;p=modules%2Fshaper.git diff --git a/src/SketchPlugin/SketchPlugin_MacroCircle.cpp b/src/SketchPlugin/SketchPlugin_MacroCircle.cpp index 2af73d693..b1528ae5a 100644 --- a/src/SketchPlugin/SketchPlugin_MacroCircle.cpp +++ b/src/SketchPlugin/SketchPlugin_MacroCircle.cpp @@ -1,20 +1,35 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> - -// File: SketchPlugin_MacroCircle.cpp -// Created: 26 May 2014 -// Author: Artem ZHIDKOV +// Copyright (C) 2014-2022 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 +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// 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 +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// #include "SketchPlugin_MacroCircle.h" #include "SketchPlugin_Circle.h" #include "SketchPlugin_Point.h" #include "SketchPlugin_Tools.h" +#include "SketchPlugin_MacroArcReentrantMessage.h" #include #include #include #include #include +#include #include #include @@ -23,6 +38,7 @@ #include #include +#include #include #include #include @@ -46,13 +62,15 @@ namespace { SketchPlugin_MacroCircle::SketchPlugin_MacroCircle() -: SketchPlugin_SketchEntity() +: SketchPlugin_SketchEntity(), + myRadius(0.0) { } void SketchPlugin_MacroCircle::initAttributes() { data()->addAttribute(CIRCLE_TYPE(), ModelAPI_AttributeString::typeId()); + data()->addAttribute(EDIT_CIRCLE_TYPE(), ModelAPI_AttributeString::typeId()); data()->addAttribute(CENTER_POINT_ID(), GeomDataAPI_Point2D::typeId()); data()->addAttribute(CENTER_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId()); @@ -69,99 +87,181 @@ void SketchPlugin_MacroCircle::initAttributes() data()->addAttribute(CIRCLE_RADIUS_ID(), ModelAPI_AttributeDouble::typeId()); data()->addAttribute(AUXILIARY_ID(), ModelAPI_AttributeBoolean::typeId()); + string(EDIT_CIRCLE_TYPE())->setValue(""); + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), CENTER_POINT_REF_ID()); ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), PASSED_POINT_REF_ID()); ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), FIRST_POINT_REF_ID()); ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SECOND_POINT_REF_ID()); ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), THIRD_POINT_REF_ID()); + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), EDIT_CIRCLE_TYPE()); } void SketchPlugin_MacroCircle::execute() { + FeaturePtr aCircle = createCircleFeature(); + std::string aType = string(CIRCLE_TYPE())->value(); if (aType == CIRCLE_TYPE_BY_CENTER_AND_PASSED_POINTS()) - createCircleByCenterAndPassed(); + constraintsForCircleByCenterAndPassed(aCircle); else if (aType == CIRCLE_TYPE_BY_THREE_POINTS()) - createCircleByThreePoints(); + constraintsForCircleByThreePoints(aCircle); + + // message to init reentrant operation + static Events_ID anId = SketchPlugin_MacroArcReentrantMessage::eventId(); + std::shared_ptr aMessage = std::shared_ptr + (new SketchPlugin_MacroArcReentrantMessage(anId, this)); + + std::string anEditType = string(EDIT_CIRCLE_TYPE())->value(); + aMessage->setTypeOfCreation(!anEditType.empty() ? anEditType : aType); + aMessage->setCreatedFeature(aCircle); + Events_Loop::loop()->send(aMessage); } -void SketchPlugin_MacroCircle::createCircleByCenterAndPassed() +// LCOV_EXCL_START +std::string SketchPlugin_MacroCircle::processEvent( + const std::shared_ptr& theMessage) { - // Create circle feature. - std::shared_ptr aCircle = shapeByCenterAndPassed(); - FeaturePtr aCircleFeature = createCircleFeature(aCircle); + std::string aFilledAttributeName; + std::shared_ptr aReentrantMessage = + std::dynamic_pointer_cast(theMessage); + if (aReentrantMessage.get()) { + std::string aCircleType = aReentrantMessage->typeOfCreation(); + + string(CIRCLE_TYPE())->setValue(aCircleType); + + aFilledAttributeName = CIRCLE_TYPE(); + ObjectPtr anObject = aReentrantMessage->selectedObject(); + AttributePtr anAttribute = aReentrantMessage->selectedAttribute(); + std::shared_ptr aClickedPoint = aReentrantMessage->clickedPoint(); + + if (aClickedPoint.get() && (anObject.get() || anAttribute.get())) { + std::string aReferenceAttributeName; + if (aCircleType == CIRCLE_TYPE_BY_CENTER_AND_PASSED_POINTS()) { + aFilledAttributeName = CENTER_POINT_ID(); + aReferenceAttributeName = CENTER_POINT_REF_ID(); + } + else { + aFilledAttributeName = FIRST_POINT_ID(); + aReferenceAttributeName = FIRST_POINT_REF_ID(); + } + // fill 2d point attribute + AttributePoint2DPtr aPointAttr = std::dynamic_pointer_cast( + attribute(aFilledAttributeName)); + aPointAttr->setValue(aClickedPoint); + // fill reference attribute + AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast( + attribute(aReferenceAttributeName)); + if (aRefAttr.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 == CENTER_POINT_ID()) + anArcID = SketchPlugin_Circle::CENTER_ID(); + anAttribute = aCreatedFeature->attribute(anArcID); + } + } + aRefAttr->setAttr(anAttribute); + } + else if (anObject.get()) { + // if attribute is NULL, only object is defined, it should be processed outside + // the feature because it might be an external feature, that will be + // removed/created again after restart operation + // #2468 - Crash when sketching circles successively on a repetition + aFilledAttributeName = CIRCLE_TYPE(); + } + } + } + Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED)); + } + return aFilledAttributeName; +} +// LCOV_EXCL_STOP +void SketchPlugin_MacroCircle::constraintsForCircleByCenterAndPassed(FeaturePtr theCircleFeature) +{ // Create constraints. - SketchPlugin_Tools::createConstraint(this, - CENTER_POINT_REF_ID(), - aCircleFeature->attribute(SketchPlugin_Circle::CENTER_ID()), - ObjectPtr(), - false); - SketchPlugin_Tools::createConstraint(this, - PASSED_POINT_REF_ID(), - AttributePtr(), - aCircleFeature->lastResult(), - true); + SketchPlugin_Tools::createCoincidenceOrTangency( + this, CENTER_POINT_REF_ID(), + theCircleFeature->attribute(SketchPlugin_Circle::CENTER_ID()), + ObjectPtr(), false); + SketchPlugin_Tools::createCoincidenceOrTangency( + this, PASSED_POINT_REF_ID(), AttributePtr(), + theCircleFeature->lastResult(), true); } -void SketchPlugin_MacroCircle::createCircleByThreePoints() +void SketchPlugin_MacroCircle::constraintsForCircleByThreePoints(FeaturePtr theCircleFeature) { std::string aPointRef[3] = { FIRST_POINT_REF_ID(), SECOND_POINT_REF_ID(), THIRD_POINT_REF_ID() }; - // Create circle feature. - std::shared_ptr aCircle = shapeByThreePoints(); - FeaturePtr aCircleFeature = createCircleFeature(aCircle); - ResultPtr aCircleResult = aCircleFeature->lastResult(); - // Create constraints. - for (int i = 0; i < 3; ++i) - SketchPlugin_Tools::createConstraint(this, aPointRef[i], AttributePtr(), aCircleResult, true); + ResultPtr aCircleResult = theCircleFeature->lastResult(); + for (int i = 0; i < 3; ++i) { + SketchPlugin_Tools::createCoincidenceOrTangency( + this, aPointRef[i], AttributePtr(), aCircleResult, true); + } } -FeaturePtr SketchPlugin_MacroCircle::createCircleFeature( - const std::shared_ptr& theCircle) +FeaturePtr SketchPlugin_MacroCircle::createCircleFeature() { FeaturePtr aCircleFeature = sketch()->addFeature(SketchPlugin_Circle::ID()); - std::shared_ptr aCenter = theCircle->center(); std::dynamic_pointer_cast( - aCircleFeature->attribute(SketchPlugin_Circle::CENTER_ID()))->setValue(aCenter->x(), - aCenter->y()); - aCircleFeature->real(SketchPlugin_Circle::RADIUS_ID())->setValue(theCircle->radius()); + aCircleFeature->attribute(SketchPlugin_Circle::CENTER_ID()))->setValue(myCenter->x(), + myCenter->y()); + aCircleFeature->real(SketchPlugin_Circle::RADIUS_ID())->setValue(myRadius); aCircleFeature->boolean(SketchPlugin_Circle::AUXILIARY_ID()) ->setValue(boolean(AUXILIARY_ID())->value()); aCircleFeature->execute(); return aCircleFeature; } -std::shared_ptr SketchPlugin_MacroCircle::shapeByCenterAndPassed() +void SketchPlugin_MacroCircle::fillByCenterAndPassed() { AttributePtr aCenterAttr = attribute(CENTER_POINT_ID()); AttributePtr aPassedAttr = attribute(PASSED_POINT_ID()); if (!aCenterAttr->isInitialized() || !aPassedAttr->isInitialized()) - return std::shared_ptr(); + return; - AttributeRefAttrPtr aPassedRef = refattr(PASSED_POINT_REF_ID()); // Calculate circle parameters - std::shared_ptr aCenter = - std::dynamic_pointer_cast(aCenterAttr)->pnt(); + AttributeRefAttrPtr aCenterRef = refattr(CENTER_POINT_REF_ID()); + std::shared_ptr aCenter; + std::shared_ptr aCurve; + SketchPlugin_Tools::convertRefAttrToPointOrTangentCurve( + aCenterRef, aCenterAttr, aCurve, aCenter); + if (!aCenter) + aCenter = std::dynamic_pointer_cast(aCenterAttr)->pnt(); + AttributeRefAttrPtr aPassedRef = refattr(PASSED_POINT_REF_ID()); std::shared_ptr aPassedPoint; std::shared_ptr aTangentCurve; SketchPlugin_Tools::convertRefAttrToPointOrTangentCurve( aPassedRef, aPassedAttr, aTangentCurve, aPassedPoint); // Build a circle - std::shared_ptr aCircle; + GeomAlgoAPI_Circ2dBuilder aCircBuilder(SketchPlugin_Sketch::plane(sketch())); + aCircBuilder.setCenter(aCenter); if (aTangentCurve) { - std::shared_ptr anAxis = SketchPlugin_Sketch::plane(sketch()); - aCircle = std::shared_ptr(new GeomAPI_Circ2d(aCenter, aTangentCurve, anAxis)); + aCircBuilder.addTangentCurve(aTangentCurve); + + AttributePoint2DPtr aPassedPntAttr = + std::dynamic_pointer_cast(aPassedAttr); + if (aPassedPntAttr) + aCircBuilder.setClosestPoint(aPassedPntAttr->pnt()); } else - aCircle = std::shared_ptr(new GeomAPI_Circ2d(aCenter, aPassedPoint)); - return aCircle; + aCircBuilder.addPassingPoint(aPassedPoint); + + std::shared_ptr aCircle = aCircBuilder.circle(); + if (aCircle) { + myCenter = aCircle->center(); + myRadius = aCircle->radius(); + } } -std::shared_ptr SketchPlugin_MacroCircle::shapeByThreePoints() +void SketchPlugin_MacroCircle::fillByThreePoints() { std::string aPointAttr[3] = { FIRST_POINT_ID(), SECOND_POINT_ID(), @@ -169,7 +269,9 @@ std::shared_ptr SketchPlugin_MacroCircle::shapeByThreePoints() std::string aPointRef[3] = { FIRST_POINT_REF_ID(), SECOND_POINT_REF_ID(), THIRD_POINT_REF_ID() }; - std::shared_ptr aPassedEntities[3]; + + GeomAlgoAPI_Circ2dBuilder aCircBuilder(SketchPlugin_Sketch::plane(sketch())); + for (int aPntIndex = 0; aPntIndex < 3; ++aPntIndex) { AttributePtr aPassedAttr = attribute(aPointAttr[aPntIndex]); if (!aPassedAttr->isInitialized()) @@ -183,27 +285,34 @@ std::shared_ptr SketchPlugin_MacroCircle::shapeByThreePoints() aPassedRef, aPassedAttr, aTangentCurve, aPassedPoint); if (aPassedPoint) - aPassedEntities[aPntIndex] = aPassedPoint; - else - aPassedEntities[aPntIndex] = aTangentCurve; + aCircBuilder.addPassingPoint(aPassedPoint); + else { + aCircBuilder.addTangentCurve(aTangentCurve); + AttributePoint2DPtr aPassedPointAttr = + std::dynamic_pointer_cast(aPassedAttr); + if (aPassedPointAttr) + aCircBuilder.setClosestPoint(aPassedPointAttr->pnt()); + } } - std::shared_ptr anAxis = SketchPlugin_Sketch::plane(sketch()); - std::shared_ptr aCircle = std::shared_ptr( - new GeomAPI_Circ2d(aPassedEntities[0], aPassedEntities[1], aPassedEntities[2], anAxis)); - if (!aCircle->implPtr()) - return std::shared_ptr(); - return aCircle; + std::shared_ptr aCircle = aCircBuilder.circle(); + if (aCircle) { + myCenter = aCircle->center(); + myRadius = aCircle->radius(); + } } -std::shared_ptr SketchPlugin_MacroCircle::shapeByTwoPassedPoints() +void SketchPlugin_MacroCircle::fillByTwoPassedPoints() { std::string aPointAttr[2] = { FIRST_POINT_ID(), SECOND_POINT_ID() }; std::string aPointRef[2] = { FIRST_POINT_REF_ID(), SECOND_POINT_REF_ID() }; + + GeomAlgoAPI_Circ2dBuilder aCircBuilder(SketchPlugin_Sketch::plane(sketch())); + std::shared_ptr aPassedPoints[2]; // there is possible only two passed points - std::shared_ptr aPassedEntities[3]; + bool hasTangentCurve = false; int aPntIndex = 0; for (; aPntIndex < 2; ++aPntIndex) { AttributePtr aPassedAttr = attribute(aPointAttr[aPntIndex]); @@ -218,69 +327,52 @@ std::shared_ptr SketchPlugin_MacroCircle::shapeByTwoPassedPoints aPassedRef, aPassedAttr, aTangentCurve, aPassedPoint); if (aPassedPoint) { - aPassedEntities[aPntIndex] = aPassedPoint; + aCircBuilder.addPassingPoint(aPassedPoint); aPassedPoints[aPntIndex] = aPassedPoint; } else { - aPassedEntities[aPntIndex] = aTangentCurve; + hasTangentCurve = true; + aCircBuilder.addTangentCurve(aTangentCurve); // if the circle is tangent to any curve, // the third point will be initialized by the tangent point - aPassedEntities[2] = std::dynamic_pointer_cast(aPassedAttr)->pnt(); + aCircBuilder.addPassingPoint( + std::dynamic_pointer_cast(aPassedAttr)->pnt()); } } if (aPntIndex <= 1) - return std::shared_ptr(); + return; std::shared_ptr aCircle; - if (aPassedEntities[2]) { - std::shared_ptr anAxis = SketchPlugin_Sketch::plane(sketch()); - aCircle = std::shared_ptr( - new GeomAPI_Circ2d(aPassedEntities[0], aPassedEntities[1], aPassedEntities[2], anAxis)); - } else { + + if (hasTangentCurve) + aCircle = aCircBuilder.circle(); + else { // the circle is defined by two points, calculate its parameters manually std::shared_ptr aCenter(new GeomAPI_Pnt2d( (aPassedPoints[0]->x() + aPassedPoints[1]->x()) * 0.5, (aPassedPoints[0]->y() + aPassedPoints[1]->y()) * 0.5)); aCircle = std::shared_ptr(new GeomAPI_Circ2d(aCenter, aPassedPoints[0])); } - if (!aCircle->implPtr()) - return std::shared_ptr(); - return aCircle; + + if (aCircle) { + myCenter = aCircle->center(); + myRadius = aCircle->radius(); + } } AISObjectPtr SketchPlugin_MacroCircle::getAISObject(AISObjectPtr thePrevious) { SketchPlugin_Sketch* aSketch = sketch(); - if(!aSketch) { + if(!aSketch || !myCenter || myRadius == 0) { return AISObjectPtr(); } - // Create circle on the sketch plane - std::shared_ptr aCircleOnSketch; - std::string aType = string(CIRCLE_TYPE())->value(); - if (aType == CIRCLE_TYPE_BY_CENTER_AND_PASSED_POINTS()) - aCircleOnSketch = shapeByCenterAndPassed(); - else if (aType == CIRCLE_TYPE_BY_THREE_POINTS()) { - if (attribute(THIRD_POINT_ID())->isInitialized()) - aCircleOnSketch = shapeByThreePoints(); - else - aCircleOnSketch = shapeByTwoPassedPoints(); - } - - if (!aCircleOnSketch) - return AISObjectPtr(); - - std::shared_ptr aCenter2D = aCircleOnSketch->center(); - if(!aCenter2D.get()) - return AISObjectPtr(); - double aRadius = aCircleOnSketch->radius(); - // Compute a circle in 3D view. - std::shared_ptr aCenter(aSketch->to3D(aCenter2D->x(), aCenter2D->y())); + std::shared_ptr aCenter(aSketch->to3D(myCenter->x(), myCenter->y())); std::shared_ptr aNDir = std::dynamic_pointer_cast( aSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID())); std::shared_ptr aNormal = aNDir->dir(); - GeomShapePtr aCircleShape = GeomAlgoAPI_EdgeBuilder::lineCircle(aCenter, aNormal, aRadius); + GeomShapePtr aCircleShape = GeomAlgoAPI_EdgeBuilder::lineCircle(aCenter, aNormal, myRadius); GeomShapePtr aCenterPointShape = GeomAlgoAPI_PointBuilder::vertex(aCenter); if(!aCircleShape.get() || !aCenterPointShape.get()) { return AISObjectPtr(); @@ -296,11 +388,14 @@ AISObjectPtr SketchPlugin_MacroCircle::getAISObject(AISObjectPtr thePrevious) anAIS.reset(new GeomAPI_AISObject()); } anAIS->createShape(aCompound); + + // Modify attributes + SketchPlugin_Tools::customizeFeaturePrs(anAIS, boolean(AUXILIARY_ID())->value()); + return anAIS; } void SketchPlugin_MacroCircle::attributeChanged(const std::string& theID) { - double aRadius = 0.0; // If circle type switched reset all attributes. if(theID == CIRCLE_TYPE()) { SketchPlugin_Tools::resetAttribute(this, CENTER_POINT_ID()); @@ -313,20 +408,12 @@ void SketchPlugin_MacroCircle::attributeChanged(const std::string& theID) { SketchPlugin_Tools::resetAttribute(this, SECOND_POINT_REF_ID()); SketchPlugin_Tools::resetAttribute(this, THIRD_POINT_ID()); SketchPlugin_Tools::resetAttribute(this, THIRD_POINT_REF_ID()); - } else if(theID == CENTER_POINT_ID() || theID == PASSED_POINT_ID()) { - std::shared_ptr aCenterPointAttr = - std::dynamic_pointer_cast(attribute(CENTER_POINT_ID())); - if(!aCenterPointAttr->isInitialized()) { - return; - } - std::shared_ptr aPassedPointAttr = - std::dynamic_pointer_cast(attribute(PASSED_POINT_ID())); - if(!aPassedPointAttr->isInitialized()) { - return; - } - - aRadius = aCenterPointAttr->pnt()->distance(aPassedPointAttr->pnt()); - } else if(theID == FIRST_POINT_ID() || theID == SECOND_POINT_ID() || theID == THIRD_POINT_ID()) { + } else if(theID == CENTER_POINT_ID() || theID == PASSED_POINT_ID() || + theID == CENTER_POINT_REF_ID() || theID == PASSED_POINT_REF_ID()) + fillByCenterAndPassed(); + else if(theID == FIRST_POINT_ID() || theID == FIRST_POINT_REF_ID() || + theID == SECOND_POINT_ID() || theID == SECOND_POINT_REF_ID() || + theID == THIRD_POINT_ID() || theID == THIRD_POINT_REF_ID()) { std::shared_ptr aPoints[3]; int aNbInitialized = 0; for(int i = 1; i <= 3; ++i) { @@ -336,19 +423,21 @@ void SketchPlugin_MacroCircle::attributeChanged(const std::string& theID) { aPoints[aNbInitialized++] = aCurPnt->pnt(); } - std::shared_ptr aCircle; if(aNbInitialized == 1) return; else if(aNbInitialized == 2) - aCircle = shapeByTwoPassedPoints(); + fillByTwoPassedPoints(); else - aCircle = shapeByThreePoints(); - if (aCircle) - aRadius = aCircle->radius(); + fillByThreePoints(); } AttributeDoublePtr aRadiusAttr = real(CIRCLE_RADIUS_ID()); bool aWasBlocked = data()->blockSendAttributeUpdated(true); - aRadiusAttr->setValue(aRadius); + 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); + } + aRadiusAttr->setValue(myRadius); data()->blockSendAttributeUpdated(aWasBlocked, false); }