From 3c9bfdce3bd7cef0b5e5a23277acd064fb760af8 Mon Sep 17 00:00:00 2001 From: rraphael Date: Mon, 18 Jan 2021 17:10:03 +0100 Subject: [PATCH] rectangle feature: complete rectangle type by center and end points --- src/PythonAPI/Test/TestAddRectangle.py | 45 +++++ src/SketchAPI/SketchAPI_MacroRectangle.cpp | 26 ++- src/SketchAPI/SketchAPI_MacroRectangle.h | 16 +- src/SketchAPI/SketchAPI_Rectangle.cpp | 71 ++++--- src/SketchAPI/SketchAPI_Rectangle.h | 19 +- src/SketchAPI/SketchAPI_Sketch.cpp | 23 +-- src/SketchAPI/SketchAPI_Sketch.h | 16 +- .../SketchPlugin_MacroRectangle.cpp | 97 +++++---- .../SketchPlugin_MacroRectangle.h | 27 +-- src/SketchPlugin/SketchPlugin_Rectangle.cpp | 188 ++++++++++++++---- src/SketchPlugin/SketchPlugin_Rectangle.h | 31 ++- src/SketchPlugin/plugin-Sketch.xml | 16 +- 12 files changed, 396 insertions(+), 179 deletions(-) create mode 100644 src/PythonAPI/Test/TestAddRectangle.py diff --git a/src/PythonAPI/Test/TestAddRectangle.py b/src/PythonAPI/Test/TestAddRectangle.py new file mode 100644 index 000000000..d22cc3a03 --- /dev/null +++ b/src/PythonAPI/Test/TestAddRectangle.py @@ -0,0 +1,45 @@ +# Copyright (C) 2014-2020 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 +# + +from salome.shaper import model +from salome.shaper import geom + +model.begin() +partSet = model.moduleDocument() +part = model.addPart(partSet).document() + +sketch = model.addSketch(part, model.defaultPlane("XOY")) + +# rectangles from start and end points +rectangle_1 = sketch.addRectangle(0, 0, 50, 50) + +startPoint = geom.Pnt2d(50, 50) +endPoint = geom.Pnt2d(100, 100) +rectangle_2 = sketch.addRectangle(startPoint, endPoint) + +# rectangles from center and end points -> add a True argument +centerPoint = geom.Pnt2d(100, 100) +endPoint2 = geom.Pnt2d(120, 75) +rectangle_3 = sketch.addRectangle(centerPoint, endPoint2, True) +rectangle_4 = sketch.addRectangle(10, 5, 25, 75, True) + +model.end() + + +assert(model.checkPythonDump()) diff --git a/src/SketchAPI/SketchAPI_MacroRectangle.cpp b/src/SketchAPI/SketchAPI_MacroRectangle.cpp index d2614f452..a619aefd2 100644 --- a/src/SketchAPI/SketchAPI_MacroRectangle.cpp +++ b/src/SketchAPI/SketchAPI_MacroRectangle.cpp @@ -39,12 +39,12 @@ SketchAPI_MacroRectangle::SketchAPI_MacroRectangle(const std::shared_ptr& theFeature, const std::shared_ptr& theStartPoint, - const std::shared_ptr& theSecondPoint, bool isSecondPointCenter): + const std::shared_ptr& theSecondPoint, bool isFirstPointCenter): SketchAPI_SketchEntity(theFeature) { if(initialize()) { - if(isSecondPointCenter) - setByStartAndCenterPoints(theStartPoint, theSecondPoint); + if(isFirstPointCenter) + setByCenterAndEndPoints(theStartPoint, theSecondPoint); else setByStartAndEndPoints(theStartPoint, theSecondPoint); } @@ -91,20 +91,18 @@ void SketchAPI_MacroRectangle::setByStartAndEndPoints(const std::shared_ptr& theStartPoint, - const std::shared_ptr& theCenterPoint){ - fillAttribute(SketchPlugin_MacroRectangle::START_END_POINT_TYPE_ID(), rectangleType()); - fillAttribute(theStartPoint, startPoint2()); +void SketchAPI_MacroRectangle::setByCenterAndEndPoints(const std::shared_ptr& theCenterPoint, const std::shared_ptr& theEndPoint){ + fillAttribute(SketchPlugin_MacroRectangle::CENTER_END_POINT_TYPE_ID(), rectangleType()); + fillAttribute(theEndPoint, endPoint2()); fillAttribute(theCenterPoint, centerPoint()); execute(); diff --git a/src/SketchAPI/SketchAPI_MacroRectangle.h b/src/SketchAPI/SketchAPI_MacroRectangle.h index 773c849d1..c7d2c165e 100644 --- a/src/SketchAPI/SketchAPI_MacroRectangle.h +++ b/src/SketchAPI/SketchAPI_MacroRectangle.h @@ -42,13 +42,13 @@ public: double theStartX, double theStartY, double theSecondX, - double theSecondY, bool isSecondPointCenter = false); + double theSecondY, bool isFirstPointCenter = false); /// Constructor with values. SKETCHAPI_EXPORT SketchAPI_MacroRectangle(const std::shared_ptr& theFeature, const std::shared_ptr& theStartPoint, - const std::shared_ptr& theSecondPoint, bool isSecondPointCenter = false); + const std::shared_ptr& theSecondPoint, bool isFirstPointCenter = false); /// Destructor. @@ -56,13 +56,13 @@ public: virtual ~SketchAPI_MacroRectangle(); INTERFACE_5(SketchPlugin_MacroRectangle::ID(), - rectangleType, SketchPlugin_MacroRectangle::TYPE_ID(), + rectangleType, SketchPlugin_MacroRectangle::RECTANGLE_TYPE_ID(), ModelAPI_AttributeString, /** Rectangle type */, startPoint1, SketchPlugin_MacroRectangle::START1_ID(), GeomDataAPI_Point2D, /** Start point 1 */, endPoint1, SketchPlugin_MacroRectangle::END1_ID(), GeomDataAPI_Point2D, /** End point 1 */, - startPoint2, SketchPlugin_MacroRectangle::START2_ID(), + endPoint2, SketchPlugin_MacroRectangle::END2_ID(), GeomDataAPI_Point2D, /** First point 2 */, centerPoint, SketchPlugin_MacroRectangle::CENTER_ID(), GeomDataAPI_Point2D, /** Center point */) @@ -80,12 +80,12 @@ private: const std::shared_ptr& theEndPoint); /// Set by start and center points. - void setByStartAndCenterPoints(double theStartX, double theStartY, - double theCenterX, double theCenterY); + void setByCenterAndEndPoints(double theCenterX, double theCenterY, + double theEndX, double theEndY); /// Set by start and center points. - void setByStartAndCenterPoints(const std::shared_ptr& theStartPoint, - const std::shared_ptr& theCenterPoint); + void setByCenterAndEndPoints(const std::shared_ptr& theCenterPoint, + const std::shared_ptr& theEndPoint); }; /// Pointer on Rectangle object. diff --git a/src/SketchAPI/SketchAPI_Rectangle.cpp b/src/SketchAPI/SketchAPI_Rectangle.cpp index f9ee374e5..e40b501d2 100644 --- a/src/SketchAPI/SketchAPI_Rectangle.cpp +++ b/src/SketchAPI/SketchAPI_Rectangle.cpp @@ -33,24 +33,22 @@ SketchAPI_Rectangle::SketchAPI_Rectangle( initialize(); } -SketchAPI_Rectangle::SketchAPI_Rectangle( - const std::shared_ptr & theFeature, - double theX1, double theY1, double theX2, double theY2) +SketchAPI_Rectangle::SketchAPI_Rectangle(const std::shared_ptr & theFeature, + double theX1, double theY1, double theX2, double theY2, bool isFirstPointCenter) : SketchAPI_SketchEntity(theFeature) { if (initialize()) { - setByCoordinates(theX1, theY1, theX2, theY2); + setByCoordinates(theX1, theY1, theX2, theY2, isFirstPointCenter); } } -SketchAPI_Rectangle::SketchAPI_Rectangle( - const std::shared_ptr & theFeature, - const std::shared_ptr & theStartPoint, - const std::shared_ptr & theEndPoint) +SketchAPI_Rectangle::SketchAPI_Rectangle(const std::shared_ptr & theFeature, + const std::shared_ptr & theFirstPoint, + const std::shared_ptr & theEndPoint, bool isFirstPointCenter) : SketchAPI_SketchEntity(theFeature) { if (initialize()) { - setByPoints(theStartPoint, theEndPoint); + setByPoints(theFirstPoint, theEndPoint, isFirstPointCenter); } } @@ -60,22 +58,37 @@ SketchAPI_Rectangle::~SketchAPI_Rectangle() //-------------------------------------------------------------------------------------- void SketchAPI_Rectangle::setByCoordinates( - double theX1, double theY1, double theX2, double theY2) -{ - fillAttribute(startPoint(), theX1, theY1); - fillAttribute(endPoint(), theX2, theY2); + double theX1, double theY1, double theX2, double theY2, bool isFirstPointCenter) +{ + if(isFirstPointCenter){ + fillAttribute(centerPoint(), theX1, theY1); + double xStart = 2.0*theX1 - theX2; + double yStart = 2.0*theY1 - theY2; + fillAttribute(startPoint(), xStart, yStart); + } + else + fillAttribute(startPoint(), theX1, theY1); - execute(); + fillAttribute(endPoint(), theX2, theY2); + execute(true); } -void SketchAPI_Rectangle::setByPoints( - const std::shared_ptr & theStartPoint, - const std::shared_ptr & theEndPoint) -{ - fillAttribute(theStartPoint, startPoint()); - fillAttribute(theEndPoint, endPoint()); +void SketchAPI_Rectangle::setByPoints(const std::shared_ptr & theFirstPoint, + const std::shared_ptr & theSecondPoint, bool isFirstPointCenter) +{ + if(isFirstPointCenter){ + fillAttribute(theFirstPoint, centerPoint()); + double xStart = 2.0*theFirstPoint->x() - theSecondPoint->x(); + double yStart = 2.0*theFirstPoint->y() - theSecondPoint->y(); - execute(); + std::shared_ptr theStartPoint = std::make_shared(xStart, yStart); + fillAttribute(theStartPoint, startPoint()); + } + else + fillAttribute(theFirstPoint, startPoint()); + + fillAttribute(theSecondPoint, endPoint()); + execute(true); } //-------------------------------------------------------------------------------------- @@ -94,7 +107,7 @@ std::list > SketchAPI_Rectangle::lines() void SketchAPI_Rectangle::dump(ModelHighAPI_Dumper& theDumper) const { - FeaturePtr aBase = feature(); + FeaturePtr aBase = feature(); /// do not dump sub-features eg: lines and lines constraints AttributeRefListPtr noToDumpList = aBase->reflist(SketchPlugin_Rectangle::NOT_TO_DUMP_LIST_ID()); @@ -107,15 +120,17 @@ void SketchAPI_Rectangle::dump(ModelHighAPI_Dumper& theDumper) const const std::string& aSketchName = theDumper.parentName(aBase); - AttributeSelectionPtr anExternal = aBase->selection(SketchPlugin_SketchEntity::EXTERNAL_ID()); - if (anExternal->context()) { - // rectangle is external - theDumper << aBase << " = " << aSketchName << ".addRectangle(" << anExternal << ")" << std::endl; - } else { + FeaturePtr aCenterPointFeature = std::dynamic_pointer_cast(aBase->refattr(SketchPlugin_Rectangle::CENTER_REF_ID())->object()); + if(aCenterPointFeature){ + // rectangle has center + theDumper << aBase << " = " << aSketchName << ".addRectangle(" + << startPoint() << ", " << centerPoint() << ", 1)" << std::endl; + } + else // rectangle given by start and end points theDumper << aBase << " = " << aSketchName << ".addRectangle(" << startPoint() << ", " << endPoint() << ")" << std::endl; - } + // dump "auxiliary" flag if necessary SketchAPI_SketchEntity::dump(theDumper); diff --git a/src/SketchAPI/SketchAPI_Rectangle.h b/src/SketchAPI/SketchAPI_Rectangle.h index a1e6fea6b..b2fd70670 100644 --- a/src/SketchAPI/SketchAPI_Rectangle.h +++ b/src/SketchAPI/SketchAPI_Rectangle.h @@ -42,30 +42,31 @@ public: /// Constructor with values SKETCHAPI_EXPORT SketchAPI_Rectangle(const std::shared_ptr & theFeature, - double theX1, double theY1, double theX2, double theY2); + double theX1, double theY1, double theX2, double theY2, bool isFirstPointCenter = false); /// Constructor with values SKETCHAPI_EXPORT SketchAPI_Rectangle(const std::shared_ptr & theFeature, - const std::shared_ptr & theStartPoint, - const std::shared_ptr & theEndPoint); + const std::shared_ptr & theFirstPoint, + const std::shared_ptr & theEndPoint, bool isFirstPointCenter = false); /// Destructor SKETCHAPI_EXPORT virtual ~SketchAPI_Rectangle(); - INTERFACE_3(SketchPlugin_Rectangle::ID(), + INTERFACE_4(SketchPlugin_Rectangle::ID(), startPoint, SketchPlugin_Rectangle::START_ID(), GeomDataAPI_Point2D, /** Start point */, - endPoint, SketchPlugin_Rectangle::END_ID(), GeomDataAPI_Point2D, /** End point */, - linesList, SketchPlugin_Rectangle::LINES_LIST_ID(), ModelAPI_AttributeRefList, /** Lines list */ + endPoint, SketchPlugin_Rectangle::END_ID(), GeomDataAPI_Point2D, /** End point */, + centerPoint, SketchPlugin_Rectangle::CENTER_ID(), GeomDataAPI_Point2D, /** Center point */, + linesList, SketchPlugin_Rectangle::LINES_LIST_ID(), ModelAPI_AttributeRefList, /** Lines list */ ) /// Set by coordinates SKETCHAPI_EXPORT - void setByCoordinates(double theX1, double theY1, double theX2, double theY2); + void setByCoordinates(double theX1, double theY1, double theX2, double theY2, bool isFirstPointCenter); /// Set by points SKETCHAPI_EXPORT - void setByPoints(const std::shared_ptr & theStartPoint, - const std::shared_ptr & theEndPoint); + void setByPoints(const std::shared_ptr & theFirstPoint, + const std::shared_ptr & theSecondPoint, bool isFirstPointCenter); /// List of lines composing rectangle SKETCHAPI_EXPORT std::list > lines() const; diff --git a/src/SketchAPI/SketchAPI_Sketch.cpp b/src/SketchAPI/SketchAPI_Sketch.cpp index db60b1826..910beca82 100644 --- a/src/SketchAPI/SketchAPI_Sketch.cpp +++ b/src/SketchAPI/SketchAPI_Sketch.cpp @@ -67,7 +67,6 @@ #include "SketchAPI_MacroCircle.h" #include "SketchAPI_MacroEllipse.h" #include "SketchAPI_MacroEllipticArc.h" -#include "SketchAPI_MacroRectangle.h" #include "SketchAPI_Mirror.h" #include "SketchAPI_Offset.h" #include "SketchAPI_Point.h" @@ -425,23 +424,23 @@ std::shared_ptr SketchAPI_Sketch::addRectangle( compositeFeature()->addFeature(SketchAPI_Rectangle::ID()); return RectanglePtr(new SketchAPI_Rectangle(aFeature, theStartPoint, theEndPoint)); } -/* -std::shared_ptr SketchAPI_Sketch::addRectangle( - double theX1, double theY1, double theX2, double theY2, bool thePoint2IsCenter) + +std::shared_ptr SketchAPI_Sketch::addRectangle( + double theX1, double theY1, double theX2, double theY2, bool isFirstPointCenter) { std::shared_ptr aFeature = - compositeFeature()->addFeature(SketchAPI_MacroRectangle::ID()); - return MacroRectanglePtr(new SketchAPI_MacroRectangle(aFeature, theX1, theY1, theX2, theY2, thePoint2IsCenter)); + compositeFeature()->addFeature(SketchAPI_Rectangle::ID()); + return RectanglePtr(new SketchAPI_Rectangle(aFeature, theX1, theY1, theX2, theY2, isFirstPointCenter)); } -std::shared_ptr SketchAPI_Sketch::addRectangle( - const std::shared_ptr & theStartPoint, - const std::shared_ptr & theEndPoint, bool theEndPointIsCenter) +std::shared_ptr SketchAPI_Sketch::addRectangle( + const std::shared_ptr & theFirstPoint, + const std::shared_ptr & theEndPoint, bool isFirstPointCenter) { std::shared_ptr aFeature = - compositeFeature()->addFeature(SketchAPI_MacroRectangle::ID()); - return MacroRectanglePtr(new SketchAPI_MacroRectangle(aFeature, theStartPoint, theEndPoint, theEndPointIsCenter)); + compositeFeature()->addFeature(SketchAPI_Rectangle::ID()); + return RectanglePtr(new SketchAPI_Rectangle(aFeature, theFirstPoint, theEndPoint, isFirstPointCenter)); } -*/ + //-------------------------------------------------------------------------------------- std::shared_ptr SketchAPI_Sketch::addCircle(double theCenterX, double theCenterY, diff --git a/src/SketchAPI/SketchAPI_Sketch.h b/src/SketchAPI/SketchAPI_Sketch.h index d26472f28..3f77ba084 100644 --- a/src/SketchAPI/SketchAPI_Sketch.h +++ b/src/SketchAPI/SketchAPI_Sketch.h @@ -56,7 +56,7 @@ class SketchAPI_Projection; class SketchAPI_Rectangle; class SketchAPI_Rotation; class SketchAPI_Translation; -class SketchAPI_MacroRectangle; + //-------------------------------------------------------------------------------------- typedef std::pair, ModelHighAPI_RefAttr> PointOrReference; //-------------------------------------------------------------------------------------- @@ -180,15 +180,15 @@ public: const std::shared_ptr & theStartPoint, const std::shared_ptr & theEndPoint); /// Add rectangle - /*SKETCHAPI_EXPORT - std::shared_ptr addRectangle( - double theX1, double theY1, double theX2, double theY2, bool thePoint2IsCenter); + SKETCHAPI_EXPORT + std::shared_ptr addRectangle( + double theX1, double theY1, double theX2, double theY2, bool isFirstPointCenter); /// Add rectangle SKETCHAPI_EXPORT - std::shared_ptr addRectangle( - const std::shared_ptr & theStartPoint, - const std::shared_ptr & theEndPoint, bool theEndPointIsCenter); -*/ + std::shared_ptr addRectangle( + const std::shared_ptr & theFirstPoint, + const std::shared_ptr & theEndPoint, bool isFirstPointCenter); + /// Add circle SKETCHAPI_EXPORT std::shared_ptr addCircle( diff --git a/src/SketchPlugin/SketchPlugin_MacroRectangle.cpp b/src/SketchPlugin/SketchPlugin_MacroRectangle.cpp index fae735f63..cd3a06c26 100644 --- a/src/SketchPlugin/SketchPlugin_MacroRectangle.cpp +++ b/src/SketchPlugin/SketchPlugin_MacroRectangle.cpp @@ -31,6 +31,8 @@ #include #include #include +#include + #include #include #include @@ -43,65 +45,68 @@ const double tolerance = 1e-7; SketchPlugin_MacroRectangle::SketchPlugin_MacroRectangle() - : SketchPlugin_SketchEntity() + : SketchPlugin_SketchEntity(), myHasCenterPoint(false) { } void SketchPlugin_MacroRectangle::initAttributes() { data()->addAttribute(AUXILIARY_ID(), ModelAPI_AttributeBoolean::typeId()); - data()->addAttribute(START1_ID(), GeomDataAPI_Point2D::typeId()); data()->addAttribute(END1_ID(), GeomDataAPI_Point2D::typeId()); - - data()->addAttribute(START2_ID(), GeomDataAPI_Point2D::typeId()); + data()->addAttribute(END2_ID(), GeomDataAPI_Point2D::typeId()); data()->addAttribute(CENTER_ID(), GeomDataAPI_Point2D::typeId()); + data()->addAttribute(RECTANGLE_TYPE_ID(), ModelAPI_AttributeString::typeId()); + data()->addAttribute(EDIT_RECTANGLE_TYPE_ID(), ModelAPI_AttributeString::typeId()); + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), EDIT_RECTANGLE_TYPE_ID()); - data()->addAttribute(TYPE_ID(), ModelAPI_AttributeString::typeId()); - data()->addAttribute(EDIT_TYPE_ID(), ModelAPI_AttributeString::typeId()); - - string(EDIT_TYPE_ID())->setValue(""); - ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), EDIT_TYPE_ID()); + string(EDIT_RECTANGLE_TYPE_ID())->setValue(""); } -void SketchPlugin_MacroRectangle::startPoint() +void SketchPlugin_MacroRectangle::endPoint() { - std::shared_ptr aStartPoint; - if(string(TYPE_ID())->value() == START_END_POINT_TYPE_ID()) - aStartPoint = std::dynamic_pointer_cast(data()->attribute(START1_ID())); + std::shared_ptr aEndPoint; + if(string(RECTANGLE_TYPE_ID())->value() == START_END_POINT_TYPE_ID()) + aEndPoint = std::dynamic_pointer_cast(data()->attribute(END1_ID())); else - aStartPoint = std::dynamic_pointer_cast(data()->attribute(START2_ID())); - if(aStartPoint->isInitialized()) - myStartPoint = std::make_shared(aStartPoint->x(), aStartPoint->y()); + aEndPoint = std::dynamic_pointer_cast(data()->attribute(END2_ID())); + if(aEndPoint->isInitialized()) + myEndPoint = std::make_shared(aEndPoint->x(), aEndPoint->y()); else - myStartPoint.reset(); + myEndPoint.reset(); } -void SketchPlugin_MacroRectangle::endPoint() +void SketchPlugin_MacroRectangle::startPoint() { - if(string(TYPE_ID())->value() == START_END_POINT_TYPE_ID()) + if(string(RECTANGLE_TYPE_ID())->value() == START_END_POINT_TYPE_ID()) { - std::shared_ptr aEndPoint = - std::dynamic_pointer_cast(data()->attribute(END1_ID())); - if(aEndPoint->isInitialized()) - myEndPoint = std::make_shared(aEndPoint->x(), aEndPoint->y()); + std::shared_ptr aStartPoint = + std::dynamic_pointer_cast(data()->attribute(START1_ID())); + if(aStartPoint->isInitialized()) + myStartPoint = std::make_shared(aStartPoint->x(), aStartPoint->y()); else - myEndPoint.reset(); + myStartPoint.reset(); } else { /// Compute end point as the symmetric of start point w.r.t. center - std::shared_ptr aStartPoint = - std::dynamic_pointer_cast(data()->attribute(START2_ID())); + std::shared_ptr aEndPoint = + std::dynamic_pointer_cast(data()->attribute(END2_ID())); std::shared_ptr aCenterPoint = std::dynamic_pointer_cast(data()->attribute(CENTER_ID())); - double xEnd = 2.0*aCenterPoint->x() - aStartPoint->x(); - double yEnd = 2.0*aCenterPoint->y() - aStartPoint->y(); - if(aStartPoint ->isInitialized() && aCenterPoint->isInitialized()) - myEndPoint = std::make_shared(xEnd, yEnd); + if(aCenterPoint->isInitialized()) + { + myCenterPoint = std::make_shared(aCenterPoint->x(), aCenterPoint->y()); + myHasCenterPoint = true; + } + double xStart = 2.0*aCenterPoint->x() - aEndPoint->x(); + double yStart = 2.0*aCenterPoint->y() - aEndPoint->y(); + + if(aEndPoint->isInitialized() && aCenterPoint->isInitialized()) + myStartPoint = std::make_shared(xStart, yStart); else - myEndPoint.reset(); + myStartPoint.reset(); } } @@ -112,12 +117,23 @@ void SketchPlugin_MacroRectangle::execute() if(!myStartPoint || !myEndPoint || !aSketch) { return ; } + // Wait all constraints being created, then send update events + static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED); + bool isUpdateFlushed = Events_Loop::loop()->isFlushed(anUpdateEvent); + if (isUpdateFlushed) + Events_Loop::loop()->setFlushed(anUpdateEvent, false); /// create a rectangle sketch FeaturePtr myRectangleFeature = aSketch->addFeature(SketchPlugin_Rectangle::ID()); if(!myRectangleFeature) return; + if(myHasCenterPoint){ + std::dynamic_pointer_cast( + myRectangleFeature->attribute(SketchPlugin_Rectangle::CENTER_ID()))->setValue(myCenterPoint->x(), + myCenterPoint->y()); + } + std::dynamic_pointer_cast( myRectangleFeature->attribute(SketchPlugin_Rectangle::START_ID()))->setValue(myStartPoint->x(), myStartPoint->y()); @@ -128,18 +144,22 @@ void SketchPlugin_MacroRectangle::execute() myRectangleFeature->boolean(SketchPlugin_Rectangle::AUXILIARY_ID()) ->setValue(boolean(AUXILIARY_ID())->value()); myRectangleFeature->execute(); + + /// Send events to update the sub-features by the solver. + if (isUpdateFlushed) + Events_Loop::loop()->setFlushed(anUpdateEvent, true); } void SketchPlugin_MacroRectangle::attributeChanged(const std::string& theID) { - if(theID == TYPE_ID()) { + if(theID == RECTANGLE_TYPE_ID()) { SketchPlugin_Tools::resetAttribute(this, START1_ID()); SketchPlugin_Tools::resetAttribute(this, END1_ID()); SketchPlugin_Tools::resetAttribute(this, CENTER_ID()); - SketchPlugin_Tools::resetAttribute(this, START2_ID()); + SketchPlugin_Tools::resetAttribute(this, END2_ID()); } else if (theID == START1_ID() || theID == END1_ID() || - theID == START2_ID() || theID == CENTER_ID()) + theID == END2_ID() || theID == CENTER_ID()) { // update points startPoint(); @@ -183,13 +203,13 @@ AISObjectPtr SketchPlugin_MacroRectangle::getAISObject(AISObjectPtr thePrevious) } } - if(string(TYPE_ID())->value() == START_CENTER_POINT_TYPE_ID()){ - /// draw a line start->center + if(string(RECTANGLE_TYPE_ID())->value() == CENTER_END_POINT_TYPE_ID()){ + /// draw a line center->end std::shared_ptr aCenterPoint = std::dynamic_pointer_cast(data()->attribute(CENTER_ID())); - std::shared_ptr theStart(aSketch->to3D(myStartPoint->x(), myStartPoint->y())); - std::shared_ptr theEnd(aSketch->to3D(aCenterPoint->x(), aCenterPoint->y())); + std::shared_ptr theEnd(aSketch->to3D(myEndPoint->x(), myEndPoint->y())); + std::shared_ptr theStart(aSketch->to3D(aCenterPoint->x(), aCenterPoint->y())); GeomShapePtr aLine = GeomAlgoAPI_EdgeBuilder::line(theStart, theEnd); if(aLine) aShapes.push_back(aLine); @@ -209,3 +229,4 @@ AISObjectPtr SketchPlugin_MacroRectangle::getAISObject(AISObjectPtr thePrevious) return anAIS; } + diff --git a/src/SketchPlugin/SketchPlugin_MacroRectangle.h b/src/SketchPlugin/SketchPlugin_MacroRectangle.h index fc196f98f..46208f862 100644 --- a/src/SketchPlugin/SketchPlugin_MacroRectangle.h +++ b/src/SketchPlugin/SketchPlugin_MacroRectangle.h @@ -30,7 +30,8 @@ class GeomAPI_Pnt2d; * \ingroup Plugins * \brief Feature for creation of the new Rectangle in Sketch. */ -class SketchPlugin_MacroRectangle: public SketchPlugin_SketchEntity, public GeomAPI_IPresentable +class SketchPlugin_MacroRectangle: public SketchPlugin_SketchEntity, + public GeomAPI_IPresentable { public: /// Rectangle feature kind @@ -40,13 +41,13 @@ public: return ID; } - inline static const std::string& TYPE_ID() + inline static const std::string& RECTANGLE_TYPE_ID() { static const std::string ID("rectangle_type"); return ID; } - inline static const std::string& EDIT_TYPE_ID() + inline static const std::string& EDIT_RECTANGLE_TYPE_ID() { static const std::string ID("edit_rectangle_type"); return ID; @@ -58,9 +59,9 @@ public: return ID; } - inline static const std::string& START_CENTER_POINT_TYPE_ID() + inline static const std::string& CENTER_END_POINT_TYPE_ID() { - static const std::string ID("rectangle_type_by_start_and_center_points"); + static const std::string ID("rectangle_type_by_center_and_end_points"); return ID; } @@ -69,7 +70,8 @@ public: { static const std::string ID("rectangle_start_point1"); return ID; - } + } + /// 2D point - end point of the Rectangle inline static const std::string& END1_ID() { @@ -77,18 +79,18 @@ public: return ID; } /// 2D point - start point of the second Rectangle type - inline static const std::string& START2_ID() + inline static const std::string& END2_ID() { - static const std::string ID("rectangle_start_point2"); + static const std::string ID("rectangle_end_point2"); return ID; } - /// 2D point - center point of the second Rectangle type + /// 2D point - center point of the second Rectangle type inline static const std::string& CENTER_ID() { static const std::string ID("rectangle_center_point"); return ID; - } + } /// Returns the kind of a feature SKETCHPLUGIN_EXPORT virtual const std::string& getKind() @@ -97,7 +99,7 @@ public: return MY_KIND; } - /// Called on change of any argument-attribute of this object + /// Called on change of any argument-attribute of this object SKETCHPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID); /// Creates a new part document if needed @@ -120,7 +122,8 @@ private: std::shared_ptr myStartPoint; std::shared_ptr myEndPoint; - + std::shared_ptr myCenterPoint; + bool myHasCenterPoint; void startPoint(); void endPoint(); FeaturePtr createRectangle(); diff --git a/src/SketchPlugin/SketchPlugin_Rectangle.cpp b/src/SketchPlugin/SketchPlugin_Rectangle.cpp index 3933f997c..0518bdd33 100644 --- a/src/SketchPlugin/SketchPlugin_Rectangle.cpp +++ b/src/SketchPlugin/SketchPlugin_Rectangle.cpp @@ -19,23 +19,25 @@ #include "SketchPlugin_Rectangle.h" #include "SketchPlugin_Sketch.h" -#include #include #include #include -#include #include #include #include #include #include +#include +#include #include #include #include +#include #include + const double tolerance = 1e-7; @@ -44,24 +46,35 @@ SketchPlugin_Rectangle::SketchPlugin_Rectangle() { } + void SketchPlugin_Rectangle::initDerivedClassAttributes() { + data()->addAttribute(AUXILIARY_ID(), ModelAPI_AttributeBoolean::typeId()); data()->addAttribute(START_ID(), GeomDataAPI_Point2D::typeId()); data()->addAttribute(END_ID(), GeomDataAPI_Point2D::typeId()); - data()->addAttribute(EXTERNAL_ID(), ModelAPI_AttributeSelection::typeId()); - ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), EXTERNAL_ID()); + data()->addAttribute(CENTER_ID(), GeomDataAPI_Point2D::typeId()); + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), CENTER_ID()); + data()->addAttribute(CENTER_REF_ID(), ModelAPI_AttributeRefAttr::typeId()); + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), CENTER_REF_ID()); data()->addAttribute(LINES_LIST_ID(), ModelAPI_AttributeRefList::typeId()); ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), LINES_LIST_ID()); + data()->addAttribute(DIAGONAL_LIST_ID(), ModelAPI_AttributeRefList::typeId()); + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), DIAGONAL_LIST_ID()); data()->addAttribute(ISHV_LIST_ID(), ModelAPI_AttributeIntArray::typeId()); - + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), ISHV_LIST_ID()); data()->addAttribute(NOT_TO_DUMP_LIST_ID(), ModelAPI_AttributeRefList::typeId()); ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), NOT_TO_DUMP_LIST_ID()); +} - AttributeIntArrayPtr isHVList = intArray(ISHV_LIST_ID()); - isHVList->setSize(4, false); - for(int i = 0; i< 4;) - isHVList->setValue(i++, 0, false); - } +namespace { + static const std::pair cornerToDiagonalLinePoints[4] + = { + {0, SketchPlugin_Line::START_ID()}, + {1, SketchPlugin_Line::START_ID()}, + {0, SketchPlugin_Line::END_ID()}, + {1, SketchPlugin_Line::END_ID()} + }; +} void SketchPlugin_Rectangle::updateLines() { @@ -73,14 +86,17 @@ void SketchPlugin_Rectangle::updateLines() std::shared_ptr aEndPoint = std::dynamic_pointer_cast(data()->attribute(END_ID())); - double xMin = std::min(aStartPoint->x(), aEndPoint->x()); - double xMax = std::max(aStartPoint->x(), aEndPoint->x()); - double yMin = std::min(aStartPoint->y(), aEndPoint->y()); - double yMax = std::max(aStartPoint->y(), aEndPoint->y()); - std::vector aX = {xMin, xMax, xMax, xMin}; - std::vector aY = {yMin, yMin, yMax, yMax}; + double aXStart = aStartPoint->x(); + double aYStart = aStartPoint->y(); + double aXEnd = aEndPoint->x(); + double aYEnd = aEndPoint->y(); + + std::vector aX = {aXStart, aXStart, aXEnd, aXEnd}; + std::vector aY = {aYStart, aYEnd, aYEnd, aYStart}; bool anAuxiliary = data()->boolean(AUXILIARY_ID())->value(); + AttributeRefListPtr aDiagonalList = reflist(DIAGONAL_LIST_ID()); + /// Update coordinates of rectangle lines for(unsigned i = 0; i < aNbLines; i++) @@ -90,9 +106,37 @@ void SketchPlugin_Rectangle::updateLines() std::dynamic_pointer_cast(aLine->attribute(SketchPlugin_Line::START_ID())); std::shared_ptr aLineEnd = std::dynamic_pointer_cast(aLine->attribute(SketchPlugin_Line::END_ID())); - aLineStart->setValue(aX[i], aY[i]); - aLineEnd->setValue(aX[(i+1)%4], aY[(i+1)%4]); + aLineStart->setValue(aX[(i+3)%4], aY[(i+3)%4]); + aLineEnd->setValue(aX[i], aY[i]); aLine->data()->boolean(AUXILIARY_ID())->setValue(anAuxiliary); + /// Cooordinates of diagonals + if(aDiagonalList->size()) + { + auto aDiagonalPoint = cornerToDiagonalLinePoints[i]; + FeaturePtr aDiagonal = std::dynamic_pointer_cast(aDiagonalList->object(aDiagonalPoint.first)); + std::dynamic_pointer_cast(aDiagonal->attribute(aDiagonalPoint.second))->setValue(aX[(i+3)%4], aY[(i+3)%4]); + } + } +} + +void SketchPlugin_Rectangle::updateStartPoint() +{ + /// Retrieving list of already created lines + AttributeRefListPtr aLinesList = reflist(LINES_LIST_ID()); + unsigned aNbLines = aLinesList->size(); + std::shared_ptr aStartPoint = + std::dynamic_pointer_cast(data()->attribute(START_ID())); + + double aXStart = aStartPoint->x(); + double aYStart = aStartPoint->y(); + + /// Update coordinates of rectangle lines + for(unsigned i = 0; i < aNbLines; i++) + { + FeaturePtr aLine = std::dynamic_pointer_cast(aLinesList->object(i)); + std::shared_ptr aLineStart = + std::dynamic_pointer_cast(aLine->attribute(SketchPlugin_Line::END_ID())); + aLineStart->setValue(aXStart, aYStart); } } @@ -118,6 +162,7 @@ void SketchPlugin_Rectangle::execute() unsigned aNbLines = aLinesList->size(); AttributeIntArrayPtr isHVList = intArray(ISHV_LIST_ID()); AttributeRefListPtr aNotToDumpList = reflist(NOT_TO_DUMP_LIST_ID()); + AttributeRefListPtr aDiagonalList = reflist(DIAGONAL_LIST_ID()); if(aNbLines == 1) { @@ -128,8 +173,35 @@ void SketchPlugin_Rectangle::execute() aLinesList->append(aLine); aNotToDumpList->append(aLine); } + updateLines(); + aNbLines = aLinesList->size(); + FeaturePtr aCenterPointFeature; + + if(aDiagonalList->size()) + { + /// compute diagonals intersection point + std::shared_ptr aCenterAttr = + std::dynamic_pointer_cast(data()->attribute(CENTER_ID())); + + aCenterPointFeature = aSketch->addFeature(SketchPlugin_Point::ID()); + aNotToDumpList->append(aCenterPointFeature); + AttributePoint2DPtr aCoord = std::dynamic_pointer_cast( + aCenterPointFeature->attribute(SketchPlugin_Point::COORD_ID())); + aCoord->setValue(aCenterAttr->x(), aCenterAttr->y()); + aCenterPointFeature->boolean(SketchPlugin_Point::AUXILIARY_ID())->setValue(true); + refattr(CENTER_REF_ID())->setObject(aCenterPointFeature); + + for(int i = 0; i < 2; i++) + { + FeaturePtr aDiagonal = std::dynamic_pointer_cast(aDiagonalList->object(i)); + FeaturePtr aConstraint = SketchPlugin_Tools::createConstraintAttrObject(aSketch, SketchPlugin_ConstraintCoincidenceInternal::ID(), + aCoord, aDiagonal); + aNotToDumpList->append(aConstraint); + } + } + /// Create constraints to keep the rectangle for( unsigned i = 0; i < aNbLines; i++) { @@ -137,19 +209,34 @@ void SketchPlugin_Rectangle::execute() /// connect neighbor lines by coincidence unsigned iPrev = (i+3)%4; FeaturePtr aPrevLine = std::dynamic_pointer_cast(aLinesList->object(iPrev)); - FeaturePtr aCoincidence = aSketch->addFeature(SketchPlugin_ConstraintCoincidence::ID()); - aNotToDumpList->append(aCoincidence); - AttributeRefAttrPtr aRefAttrA = aCoincidence->refattr(SketchPlugin_ConstraintCoincidence::ENTITY_A()); - AttributeRefAttrPtr aRefAttrB = aCoincidence->refattr(SketchPlugin_ConstraintCoincidence::ENTITY_B()); - aRefAttrA->setAttr(aPrevLine->attribute(SketchPlugin_Line::END_ID())); - aRefAttrB->setAttr(aLine->attribute(SketchPlugin_Line::START_ID())); + FeaturePtr aConstraint = SketchPlugin_Tools::createConstraintAttrAttr(aSketch, SketchPlugin_ConstraintCoincidence::ID(), + aPrevLine->attribute(SketchPlugin_Line::END_ID()), + aLine->attribute(SketchPlugin_Line::START_ID())); + aNotToDumpList->append(aConstraint); + + /// case of rectangle created from its center + if(aDiagonalList->size()) + { + auto aDiagonalPoint = cornerToDiagonalLinePoints[i]; + FeaturePtr aDiagonal = std::dynamic_pointer_cast(aDiagonalList->object(aDiagonalPoint.first)); + FeaturePtr aConstraint = SketchPlugin_Tools::createConstraintAttrAttr(aSketch, SketchPlugin_ConstraintCoincidenceInternal::ID(), + aDiagonal->attribute(aDiagonalPoint.second), + aLine->attribute(SketchPlugin_Line::START_ID())); + aNotToDumpList->append(aConstraint); + } } - /// Update coordinates of created lines updateLines(); } /// Add horizontal and vertical constraint for the lines which already have result + if(isHVList->size() == 0) + { + isHVList->setSize(4, false); + for(int i = 0; i< 4;) + isHVList->setValue(i++, 0, false); + } + for(unsigned i = 0; i< aNbLines; i++) { if(isHVList->value(i)) @@ -163,7 +250,7 @@ void SketchPlugin_Rectangle::execute() aHVName = SketchPlugin_ConstraintVertical::ID(); FeaturePtr aHVConstraint = aSketch->addFeature(aHVName); aNotToDumpList->append(aHVConstraint); - AttributeRefAttrPtr aRefAttrA = aHVConstraint->refattr(SketchPlugin_ConstraintCoincidence::ENTITY_A()); + AttributeRefAttrPtr aRefAttrA = aHVConstraint->refattr(SketchPlugin_Constraint::ENTITY_A()); aRefAttrA->setObject(aLine->lastResult()); isHVList->setValue(i, 1, false); } @@ -175,8 +262,7 @@ void SketchPlugin_Rectangle::execute() return; } - // store results. - + /// store results. GeomShapePtr aRectangleShape; ListOfShape aSubs; @@ -189,25 +275,36 @@ void SketchPlugin_Rectangle::execute() aSubs.push_back(aLineResult->shape()); } - aRectangleShape = aSubs.empty() ? GeomShapePtr() : GeomAlgoAPI_CompoundBuilder::compound(aSubs); + for(int i = 0; i< aDiagonalList->size(); i++) + { + FeaturePtr aDiagonal = std::dynamic_pointer_cast(aDiagonalList->object(i)); + ResultPtr aDiagonalResult = aDiagonal->lastResult(); + if(!aDiagonalResult.get()) + continue; + aSubs.push_back(aDiagonalResult->shape()); + } + FeaturePtr aCenterPointFeature = std::dynamic_pointer_cast(refattr(CENTER_REF_ID())->object()); + if(aCenterPointFeature) + { + ResultPtr aCenterResult = aCenterPointFeature->lastResult(); + if(aCenterResult.get()) + aSubs.push_back(aCenterResult->shape()); + } + + aRectangleShape = aSubs.empty() ? GeomShapePtr() : GeomAlgoAPI_CompoundBuilder::compound(aSubs); std::shared_ptr aResult = document()->createConstruction(data(), 0); aResult->setShape(aRectangleShape); aResult->setIsInHistory(false); setResult(aResult, 1); } - -bool SketchPlugin_Rectangle::isFixed() { - return data()->selection(EXTERNAL_ID())->context().get() != NULL; -} - void SketchPlugin_Rectangle::attributeChanged(const std::string& theID) { if (theID == START_ID() || theID == END_ID()) { AttributeRefListPtr aLinesList = reflist(LINES_LIST_ID()); - AttributeRefListPtr aNotToDumpList = reflist(NOT_TO_DUMP_LIST_ID()); + AttributeRefListPtr aNotToDumpList = reflist(NOT_TO_DUMP_LIST_ID()); unsigned aNbLines = aLinesList->size(); if(aNbLines == 0) { @@ -219,16 +316,33 @@ void SketchPlugin_Rectangle::attributeChanged(const std::string& theID) FeaturePtr aLine = aSketch->addFeature(SketchPlugin_Line::ID()); aLinesList->append(aLine); aNotToDumpList->append(aLine); - } + /// if rectangle has center, add 2 iagonals + std::shared_ptr aCenterAttr = + std::dynamic_pointer_cast(data()->attribute(CENTER_ID())); + if(aCenterAttr->isInitialized()) + { + AttributeRefListPtr aDiagonalList = reflist(DIAGONAL_LIST_ID()); + for(int i = 0; i < 2; i++) + { + FeaturePtr aDiagonalLine = aSketch->addFeature(SketchPlugin_Line::ID()); + aDiagonalLine->boolean(SketchPlugin_Point::AUXILIARY_ID())->setValue(true); + aDiagonalList->append(aDiagonalLine); + aNotToDumpList->append(aDiagonalLine); + } + } + } std::shared_ptr aStartPoint = std::dynamic_pointer_cast(data()->attribute(START_ID())); std::shared_ptr aEndPoint = std::dynamic_pointer_cast(data()->attribute(END_ID())); if (aStartPoint->isInitialized() && aEndPoint->isInitialized()) - updateLines(); + updateLines(); + else + updateStartPoint(); } + if (theID == AUXILIARY_ID()) { bool anAuxiliary = data()->boolean(AUXILIARY_ID())->value(); diff --git a/src/SketchPlugin/SketchPlugin_Rectangle.h b/src/SketchPlugin/SketchPlugin_Rectangle.h index 7d3e2f464..72bef0d6a 100644 --- a/src/SketchPlugin/SketchPlugin_Rectangle.h +++ b/src/SketchPlugin/SketchPlugin_Rectangle.h @@ -22,14 +22,12 @@ #include "SketchPlugin.h" #include "SketchPlugin_SketchEntity.h" -#include "SketchPlugin_Sketch.h" /**\class SketchPlugin_Rectangle * \ingroup Plugins * \brief Feature for creation of the new Rectangle in Sketch. */ class SketchPlugin_Rectangle: public SketchPlugin_SketchEntity - { public: /// Rectangle feature kind @@ -53,10 +51,31 @@ class SketchPlugin_Rectangle: public SketchPlugin_SketchEntity return ID; } + /// 2D point - center point of the Rectangle + inline static const std::string& CENTER_ID() + { + static const std::string ID("rectangle_center_point"); + return ID; + } + + /// 2D point - center point of the Rectangle + inline static const std::string& CENTER_REF_ID() + { + static const std::string ID("rectangle_center_point_ref"); + return ID; + } + /// 2D point - list of Rectangle lines inline static const std::string& LINES_LIST_ID() { - static const std::string ID("RectangleList"); + static const std::string ID("RectangleLinesList"); + return ID; + } + + /// 2D point - list of Diagonal lines + inline static const std::string& DIAGONAL_LIST_ID() + { + static const std::string ID("RectangleDiagonalLinesList"); return ID; } @@ -79,8 +98,8 @@ class SketchPlugin_Rectangle: public SketchPlugin_SketchEntity return MY_KIND; } - /// Returns true is sketch element is under the rigid constraint - SKETCHPLUGIN_EXPORT virtual bool isFixed(); + SKETCHPLUGIN_EXPORT virtual bool isMacro() const + { return true;} /// Called on change of any argument-attribute of this object SKETCHPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID); @@ -98,6 +117,8 @@ protected: private: /// \brief updateLines crates lines from start and en points void updateLines(); + void updateStartPoint(); }; + #endif diff --git a/src/SketchPlugin/plugin-Sketch.xml b/src/SketchPlugin/plugin-Sketch.xml index ea64ddfe7..813607e51 100644 --- a/src/SketchPlugin/plugin-Sketch.xml +++ b/src/SketchPlugin/plugin-Sketch.xml @@ -101,20 +101,20 @@ enable_value="enable_by_preferences"/> - - + title="Center and end points"> - + +