From: azv Date: Thu, 27 Apr 2017 04:47:33 +0000 (+0300) Subject: Task 2.1. Creation of ellipses and arcs of ellipse. X-Git-Tag: V_2.7.1.1~3^2~14 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=a299eecbf62594492e777394588e4cf2e6ba11c3;p=modules%2Fshaper.git Task 2.1. Creation of ellipses and arcs of ellipse. Sketch feature Ellipse has been implemented from skratch --- diff --git a/src/GeomAPI/CMakeLists.txt b/src/GeomAPI/CMakeLists.txt index d76e17b78..ca8d2855c 100644 --- a/src/GeomAPI/CMakeLists.txt +++ b/src/GeomAPI/CMakeLists.txt @@ -38,7 +38,8 @@ SET(PROJECT_HEADERS GeomAPI_Trsf.h GeomAPI_Angle2d.h GeomAPI_Wire.h - GeomAPI_Ellipse.h + GeomAPI_Ellipse.h + GeomAPI_Ellipse2d.h ) SET(PROJECT_SOURCES @@ -73,7 +74,8 @@ SET(PROJECT_SOURCES GeomAPI_Trsf.cpp GeomAPI_Angle2d.cpp GeomAPI_Wire.cpp - GeomAPI_Ellipse.cpp + GeomAPI_Ellipse.cpp + GeomAPI_Ellipse2d.cpp ) SET(PROJECT_LIBRARIES diff --git a/src/GeomAPI/GeomAPI_Ellipse.cpp b/src/GeomAPI/GeomAPI_Ellipse.cpp index 1eae6445f..2d47a5a6f 100644 --- a/src/GeomAPI/GeomAPI_Ellipse.cpp +++ b/src/GeomAPI/GeomAPI_Ellipse.cpp @@ -18,6 +18,12 @@ GeomAPI_Ellipse::GeomAPI_Ellipse(const std::shared_ptr& theAx2, { } +std::shared_ptr GeomAPI_Ellipse::center() const +{ + const gp_Pnt& aCenter = MY_ELIPS->Location(); + return std::shared_ptr(new GeomAPI_Pnt(aCenter.X(), aCenter.Y(), aCenter.Z())); +} + GeomPointPtr GeomAPI_Ellipse::firstFocus() const { const gp_Pnt& aFirst = MY_ELIPS->Focus1(); diff --git a/src/GeomAPI/GeomAPI_Ellipse.h b/src/GeomAPI/GeomAPI_Ellipse.h index a855e189b..d201d127a 100644 --- a/src/GeomAPI/GeomAPI_Ellipse.h +++ b/src/GeomAPI/GeomAPI_Ellipse.h @@ -35,10 +35,13 @@ public: GEOMAPI_EXPORT GeomAPI_Ellipse(const std::shared_ptr& theAx2, double theMajorRadius, double theMinorRadius); - /// Returns first center of the ellipse + /// Returns center of the ellipse + GEOMAPI_EXPORT std::shared_ptr center() const; + + /// Returns first focus of the ellipse GEOMAPI_EXPORT std::shared_ptr firstFocus() const; - /// Returns second center of the ellipse + /// Returns second focus of the ellipse GEOMAPI_EXPORT std::shared_ptr secondFocus() const; /// Returns minor radius of the ellipse diff --git a/src/GeomAPI/GeomAPI_Ellipse2d.cpp b/src/GeomAPI/GeomAPI_Ellipse2d.cpp new file mode 100644 index 000000000..eca8f4a8e --- /dev/null +++ b/src/GeomAPI/GeomAPI_Ellipse2d.cpp @@ -0,0 +1,97 @@ +// Copyright (C) 2017-20xx CEA/DEN, EDF R&D + +// File: GeomAPI_Ellipse2d.cpp +// Created: 26 April 2017 +// Author: Artem ZHIDKOV + +#include +#include +#include + +#include +#include +#include + +#define MY_ELLIPSE implPtr() + +static gp_Elips2d* newEllipse(const gp_Pnt2d& theCenter, + const gp_Dir2d& theXAxis, + const double theMajorRadius, + const double theMinorRadius) +{ + if (theMajorRadius < theMinorRadius - Precision::Confusion()) { + return newEllipse(theCenter, gp_Dir2d(-theXAxis.Y(), theXAxis.X()), + theMinorRadius, theMajorRadius); + } + + gp_Ax22d anAxis(theCenter, theXAxis); + return new gp_Elips2d(anAxis, theMajorRadius, theMinorRadius); +} + +static gp_Elips2d* newEllipse(const std::shared_ptr& theCenter, + const std::shared_ptr& theAxisPoint, + const std::shared_ptr& thePassingPoint) +{ + const gp_Pnt2d& aCenter = theCenter->impl(); + const gp_Pnt2d& anAxisPnt = theAxisPoint->impl(); + const gp_Pnt2d& aPassedPnt = thePassingPoint->impl(); + + gp_Dir2d aXAxis(anAxisPnt.XY() - aCenter.XY()); + double aMajorRadius = anAxisPnt.Distance(aCenter); + + gp_XY aPassedDir = aPassedPnt.XY() - aCenter.XY(); + + double X = aPassedDir.Dot(aXAxis.XY()) / aMajorRadius; + if (Abs(X) > 1.0 - Precision::Confusion()) + return 0; // ellipse cannot be created for such parameters + + double Y = aPassedDir.CrossMagnitude(aXAxis.XY()); + double aMinorRadius = Y / Sqrt(1. - X * X); + + return newEllipse(aCenter, aXAxis, aMajorRadius, aMinorRadius); +} + + +GeomAPI_Ellipse2d::GeomAPI_Ellipse2d(const std::shared_ptr& theCenter, + const std::shared_ptr& theXAxis, + const double theMajorRadius, + const double theMinorRadius) + : GeomAPI_Interface(newEllipse(theCenter->impl(), theXAxis->impl(), + theMajorRadius, theMinorRadius)) +{ +} + +GeomAPI_Ellipse2d::GeomAPI_Ellipse2d(const std::shared_ptr& theCenter, + const std::shared_ptr& theAxisPoint, + const std::shared_ptr& thePassingPoint) + : GeomAPI_Interface(newEllipse(theCenter, theAxisPoint, thePassingPoint)) +{ +} + +std::shared_ptr GeomAPI_Ellipse2d::center() const +{ + const gp_Pnt2d& aCenter = MY_ELLIPSE->Location(); + return std::shared_ptr(new GeomAPI_Pnt2d(aCenter.X(), aCenter.Y())); +} + +std::shared_ptr GeomAPI_Ellipse2d::firstFocus() const +{ + const gp_Pnt2d& aFirst = MY_ELLIPSE->Focus1(); + return std::shared_ptr(new GeomAPI_Pnt2d(aFirst.X(), aFirst.Y())); +} + +std::shared_ptr GeomAPI_Ellipse2d::secondFocus() const +{ + const gp_Pnt2d& aSecond = MY_ELLIPSE->Focus2(); + return std::shared_ptr(new GeomAPI_Pnt2d(aSecond.X(), aSecond.Y())); +} + +double GeomAPI_Ellipse2d::minorRadius() const +{ + return MY_ELLIPSE->MinorRadius(); +} + +double GeomAPI_Ellipse2d::majorRadius() const +{ + return MY_ELLIPSE->MajorRadius(); +} diff --git a/src/GeomAPI/GeomAPI_Ellipse2d.h b/src/GeomAPI/GeomAPI_Ellipse2d.h new file mode 100644 index 000000000..293c95649 --- /dev/null +++ b/src/GeomAPI/GeomAPI_Ellipse2d.h @@ -0,0 +1,51 @@ +// Copyright (C) 2017-20xx CEA/DEN, EDF R&D + +// File: GeomAPI_Ellipse2d.h +// Created: 26 April 2017 +// Author: Artem ZHIDKOV + +#ifndef GeomAPI_Ellipse2d_H_ +#define GeomAPI_Ellipse2d_H_ + +#include + +class GeomAPI_Pnt2d; +class GeomAPI_Dir2d; + +/**\class GeomAPI_Ellipse2d + * \ingroup DataModel + * \brief Ellipse in 2D + */ +class GeomAPI_Ellipse2d : public GeomAPI_Interface +{ +public: + /// \brief Constructs ellipse by center, X-axis and given radii + GEOMAPI_EXPORT GeomAPI_Ellipse2d(const std::shared_ptr& theCenter, + const std::shared_ptr& theXAxis, + const double theMajorRadius, + const double theMinorRadius); + + /// \brief Constructs ellipse by center and two points lying on the ellipse: + /// first of them defines an axis of the ellipse + /// and another is just placed on the ellipse. + GEOMAPI_EXPORT GeomAPI_Ellipse2d(const std::shared_ptr& theCenter, + const std::shared_ptr& theAxisPoint, + const std::shared_ptr& thePassingPoint); + + /// Returns center of the ellipse + GEOMAPI_EXPORT std::shared_ptr center() const; + + /// Returns first focus of the ellipse + GEOMAPI_EXPORT std::shared_ptr firstFocus() const; + + /// Returns second focus of the ellipse + GEOMAPI_EXPORT std::shared_ptr secondFocus() const; + + /// Returns minor radius of the ellipse + GEOMAPI_EXPORT double minorRadius() const; + + /// Returns major radius of the ellipse + GEOMAPI_EXPORT double majorRadius() const; +}; + +#endif diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_EdgeBuilder.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_EdgeBuilder.cpp index a1ada3eca..b10bbf736 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_EdgeBuilder.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_EdgeBuilder.cpp @@ -5,20 +5,21 @@ // Author: Mikhail PONIKAROV #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 +#include std::shared_ptr GeomAlgoAPI_EdgeBuilder::line( std::shared_ptr theStart, std::shared_ptr theEnd) @@ -208,3 +209,23 @@ std::shared_ptr GeomAlgoAPI_EdgeBuilder::lineCircleArc( } return aRes; } + +std::shared_ptr GeomAlgoAPI_EdgeBuilder::ellipse( + const std::shared_ptr& theCenter, + const std::shared_ptr& theNormal, + const std::shared_ptr& theMajorAxis, + const double theMajorRadius, + const double theMinorRadius) +{ + const gp_Pnt& aCenter = theCenter->impl(); + const gp_Dir& aNormal = theNormal->impl(); + const gp_Dir& aMajorAxis = theMajorAxis->impl(); + + gp_Elips anEllipse(gp_Ax2(aCenter, aNormal, aMajorAxis), theMajorRadius, theMinorRadius); + + BRepBuilderAPI_MakeEdge anEdgeBuilder(anEllipse); + std::shared_ptr aRes(new GeomAPI_Edge); + TopoDS_Edge anEdge = anEdgeBuilder.Edge(); + aRes->setImpl(new TopoDS_Shape(anEdge)); + return aRes; +} diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_EdgeBuilder.h b/src/GeomAlgoAPI/GeomAlgoAPI_EdgeBuilder.h index a781ce219..a77693e51 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_EdgeBuilder.h +++ b/src/GeomAlgoAPI/GeomAlgoAPI_EdgeBuilder.h @@ -58,6 +58,13 @@ class GEOMALGOAPI_EXPORT GeomAlgoAPI_EdgeBuilder std::shared_ptr theStartPoint, std::shared_ptr theEndPoint, std::shared_ptr theNormal); + + /// Creates elliptic edge + static std::shared_ptr ellipse(const std::shared_ptr& theCenter, + const std::shared_ptr& theNormal, + const std::shared_ptr& theMajorAxis, + const double theMajorRadius, + const double theMinorRadius); }; #endif diff --git a/src/SketchPlugin/CMakeLists.txt b/src/SketchPlugin/CMakeLists.txt index 3f8723de7..010ee47f9 100644 --- a/src/SketchPlugin/CMakeLists.txt +++ b/src/SketchPlugin/CMakeLists.txt @@ -14,7 +14,6 @@ SET(PROJECT_HEADERS SketchPlugin_ConstraintCollinear.h SketchPlugin_ConstraintDistance.h SketchPlugin_ConstraintEqual.h - SketchPlugin_Fillet.h SketchPlugin_ConstraintHorizontal.h SketchPlugin_ConstraintLength.h SketchPlugin_ConstraintMiddle.h @@ -26,13 +25,16 @@ SET(PROJECT_HEADERS SketchPlugin_ConstraintSplit.h SketchPlugin_ConstraintTangent.h SketchPlugin_ConstraintVertical.h + SketchPlugin_Ellipse.h SketchPlugin_ExternalValidator.h SketchPlugin_Feature.h + SketchPlugin_Fillet.h SketchPlugin_IntersectionPoint.h SketchPlugin_Line.h SketchPlugin_MacroArc.h SketchPlugin_MacroArcReentrantMessage.h SketchPlugin_MacroCircle.h + SketchPlugin_MacroEllipse.h SketchPlugin_MultiRotation.h SketchPlugin_MultiTranslation.h SketchPlugin_Plugin.h @@ -55,7 +57,6 @@ SET(PROJECT_SOURCES SketchPlugin_ConstraintCollinear.cpp SketchPlugin_ConstraintDistance.cpp SketchPlugin_ConstraintEqual.cpp - SketchPlugin_Fillet.cpp SketchPlugin_ConstraintHorizontal.cpp SketchPlugin_ConstraintLength.cpp SketchPlugin_ConstraintMiddle.cpp @@ -67,12 +68,15 @@ SET(PROJECT_SOURCES SketchPlugin_ConstraintSplit.cpp SketchPlugin_ConstraintTangent.cpp SketchPlugin_ConstraintVertical.cpp + SketchPlugin_Ellipse.cpp SketchPlugin_ExternalValidator.cpp SketchPlugin_Feature.cpp + SketchPlugin_Fillet.cpp SketchPlugin_IntersectionPoint.cpp SketchPlugin_Line.cpp SketchPlugin_MacroArc.cpp SketchPlugin_MacroCircle.cpp + SketchPlugin_MacroEllipse.cpp SketchPlugin_MultiRotation.cpp SketchPlugin_MultiTranslation.cpp SketchPlugin_Plugin.cpp diff --git a/src/SketchPlugin/SketchPlugin_Ellipse.cpp b/src/SketchPlugin/SketchPlugin_Ellipse.cpp new file mode 100644 index 000000000..2317e0575 --- /dev/null +++ b/src/SketchPlugin/SketchPlugin_Ellipse.cpp @@ -0,0 +1,132 @@ +// Copyright (C) 2017-20xx CEA/DEN, EDF R&D --> + +// File: SketchPlugin_Ellipse.cpp +// Created: 26 April 2017 +// Author: Artem ZHIDKOV + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +static const double tolerance = 1e-7; + + +SketchPlugin_Ellipse::SketchPlugin_Ellipse() +: SketchPlugin_SketchEntity() +{ +} + +void SketchPlugin_Ellipse::initDerivedClassAttributes() +{ + data()->addAttribute(CENTER_ID(), GeomDataAPI_Point2D::typeId()); + data()->addAttribute(FOCUS_ID(), GeomDataAPI_Point2D::typeId()); + data()->addAttribute(MAJOR_RADIUS_ID(), ModelAPI_AttributeDouble::typeId()); + data()->addAttribute(MINOR_RADIUS_ID(), ModelAPI_AttributeDouble::typeId()); + + data()->addAttribute(EXTERNAL_ID(), ModelAPI_AttributeSelection::typeId()); + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), EXTERNAL_ID()); +} + +void SketchPlugin_Ellipse::execute() +{ + SketchPlugin_Sketch* aSketch = sketch(); + if(!aSketch) { + return; + } + + // Compute a ellipse in 3D view. + std::shared_ptr aCenterAttr = + std::dynamic_pointer_cast(data()->attribute(CENTER_ID())); + std::shared_ptr aFocusAttr = + std::dynamic_pointer_cast(data()->attribute(FOCUS_ID())); + AttributeDoublePtr aMajorRadiusAttr = real(MAJOR_RADIUS_ID()); + AttributeDoublePtr aMinorRadiusAttr = real(MINOR_RADIUS_ID()); + if (!aCenterAttr->isInitialized() || + !aFocusAttr->isInitialized() || + !aMajorRadiusAttr->isInitialized() || + !aMinorRadiusAttr->isInitialized()) { + return; + } + + double aMajorRadius = aMajorRadiusAttr->value(); + double aMinorRadius = aMinorRadiusAttr->value(); + if(aMajorRadius < tolerance || aMinorRadius < tolerance) { + return; + } + + // Make a visible point. + SketchPlugin_Sketch::createPoint2DResult(this, aSketch, CENTER_ID(), 0); + + std::shared_ptr aNDir = std::dynamic_pointer_cast( + aSketch->attribute(SketchPlugin_Sketch::NORM_ID())); + + // Make a visible ellipse. + std::shared_ptr aCenter(aSketch->to3D(aCenterAttr->x(), aCenterAttr->y())); + std::shared_ptr aFocus(aSketch->to3D(aFocusAttr->x(), aFocusAttr->y())); + std::shared_ptr aNormal = aNDir->dir(); + std::shared_ptr aMajorAxis(new GeomAPI_Dir(aFocus->x() - aCenter->x(), + aFocus->y() - aCenter->y(), aFocus->z() - aCenter->z())); + + std::shared_ptr anEllipseShape = + GeomAlgoAPI_EdgeBuilder::ellipse(aCenter, aNormal, aMajorAxis, aMajorRadius, aMinorRadius); + + std::shared_ptr aResult = document()->createConstruction(data(), 1); + aResult->setShape(anEllipseShape); + aResult->setIsInHistory(false); + setResult(aResult, 1); +} + +void SketchPlugin_Ellipse::move(double theDeltaX, double theDeltaY) +{ + std::shared_ptr aData = data(); + if(!aData->isValid()) { + return; + } + + std::shared_ptr aPoint = std::dynamic_pointer_cast( + aData->attribute(CENTER_ID())); + if(aPoint->isInitialized()) { + aPoint->move(theDeltaX, theDeltaY); + } +} + +bool SketchPlugin_Ellipse::isFixed() { + return data()->selection(EXTERNAL_ID())->context().get() != NULL; +} + +void SketchPlugin_Ellipse::attributeChanged(const std::string& theID) { + // the second condition for unability to move external segments anywhere + if (theID == EXTERNAL_ID() || isFixed()) { + std::shared_ptr aSelection = data()->selection(EXTERNAL_ID())->value(); + if (!aSelection) { + // empty shape in selection shows that the shape is equal to context + ResultPtr anExtRes = selection(EXTERNAL_ID())->context(); + if (anExtRes) + aSelection = anExtRes->shape(); + } + // update arguments due to the selection value + if (aSelection && !aSelection->isNull() && aSelection->isEdge()) { + std::shared_ptr anEdge( new GeomAPI_Edge(aSelection)); + std::shared_ptr anEllipse = anEdge->ellipse(); + + std::shared_ptr aCenterAttr = + std::dynamic_pointer_cast(attribute(CENTER_ID())); + aCenterAttr->setValue(sketch()->to2D(anEllipse->center())); + + std::shared_ptr aFocusAttr = + std::dynamic_pointer_cast(attribute(FOCUS_ID())); + aFocusAttr->setValue(sketch()->to2D(anEllipse->firstFocus())); + + real(MAJOR_RADIUS_ID())->setValue(anEllipse->majorRadius()); + real(MINOR_RADIUS_ID())->setValue(anEllipse->minorRadius()); + } + } +} diff --git a/src/SketchPlugin/SketchPlugin_Ellipse.h b/src/SketchPlugin/SketchPlugin_Ellipse.h new file mode 100644 index 000000000..287a1a54a --- /dev/null +++ b/src/SketchPlugin/SketchPlugin_Ellipse.h @@ -0,0 +1,84 @@ +// Copyright (C) 2017-20xx CEA/DEN, EDF R&D --> + +// File: SketchPlugin_Ellipse.h +// Created: 26 April 2017 +// Author: Artem ZHIDKOV + +#ifndef SketchPlugin_Ellipse_H_ +#define SketchPlugin_Ellipse_H_ + +#include +#include + +/**\class SketchPlugin_Ellipse + * \ingroup Plugins + * \brief Feature for creation of the new ellipse in Sketch. + */ +class SketchPlugin_Ellipse: public SketchPlugin_SketchEntity +{ + public: + /// Ellipse feature kind + inline static const std::string& ID() + { + static const std::string ID("SketchEllipse"); + return ID; + } + + /// 2D point - center of the ellipse + inline static const std::string& CENTER_ID() + { + static const std::string ID("ellipse_center"); + return ID; + } + + /// 2D point - focus of the ellipse + inline static const std::string& FOCUS_ID() + { + static const std::string ID("ellipse_focus"); + return ID; + } + + /// Major radius of the ellipse + inline static const std::string& MAJOR_RADIUS_ID() + { + static const std::string ID("ellipse_major_radius"); + return ID; + } + + /// Minor radius of the ellipse + inline static const std::string& MINOR_RADIUS_ID() + { + static const std::string ID("ellipse_minor_radius"); + return ID; + } + + /// Returns the kind of a feature + SKETCHPLUGIN_EXPORT virtual const std::string& getKind() + { + static std::string MY_KIND = SketchPlugin_Ellipse::ID(); + return MY_KIND; + } + + /// Returns true is sketch element is under the rigid constraint + SKETCHPLUGIN_EXPORT virtual bool isFixed(); + + /// 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 + SKETCHPLUGIN_EXPORT virtual void execute(); + + /// Moves the feature + /// \param theDeltaX the delta for X coordinate is moved + /// \param theDeltaY the delta for Y coordinate is moved + SKETCHPLUGIN_EXPORT virtual void move(const double theDeltaX, const double theDeltaY); + + /// Use plugin manager for features creation + SketchPlugin_Ellipse(); + +protected: + /// \brief Initializes attributes of derived class. + virtual void initDerivedClassAttributes(); +}; + +#endif diff --git a/src/SketchPlugin/SketchPlugin_MacroCircle.cpp b/src/SketchPlugin/SketchPlugin_MacroCircle.cpp index 3af61c721..6b24fc725 100644 --- a/src/SketchPlugin/SketchPlugin_MacroCircle.cpp +++ b/src/SketchPlugin/SketchPlugin_MacroCircle.cpp @@ -373,7 +373,6 @@ AISObjectPtr SketchPlugin_MacroCircle::getAISObject(AISObjectPtr thePrevious) } 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()); diff --git a/src/SketchPlugin/SketchPlugin_MacroEllipse.cpp b/src/SketchPlugin/SketchPlugin_MacroEllipse.cpp new file mode 100644 index 000000000..77a04c978 --- /dev/null +++ b/src/SketchPlugin/SketchPlugin_MacroEllipse.cpp @@ -0,0 +1,243 @@ +// Copyright (C) 2017-20xx CEA/DEN, EDF R&D --> + +// File: SketchPlugin_MacroEllipse.cpp +// Created: 26 April 2017 +// Author: Artem ZHIDKOV + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include + + +SketchPlugin_MacroEllipse::SketchPlugin_MacroEllipse() +: SketchPlugin_SketchEntity(), + myMajorRadius(0.0), + myMinorRadius(0.0) +{ +} + +void SketchPlugin_MacroEllipse::initAttributes() +{ + data()->addAttribute(CENTER_POINT_ID(), GeomDataAPI_Point2D::typeId()); + data()->addAttribute(CENTER_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId()); + data()->addAttribute(MAJOR_AXIS_POINT_ID(), GeomDataAPI_Point2D::typeId()); + data()->addAttribute(MAJOR_AXIS_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId()); + data()->addAttribute(PASSED_POINT_ID(), GeomDataAPI_Point2D::typeId()); + data()->addAttribute(PASSED_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId()); + + data()->addAttribute(MAJOR_RADIUS_ID(), ModelAPI_AttributeDouble::typeId()); + data()->addAttribute(MINOR_RADIUS_ID(), ModelAPI_AttributeDouble::typeId()); + data()->addAttribute(AUXILIARY_ID(), ModelAPI_AttributeBoolean::typeId()); + + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), CENTER_POINT_REF_ID()); + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), MAJOR_AXIS_POINT_REF_ID()); + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), PASSED_POINT_REF_ID()); +} + +void SketchPlugin_MacroEllipse::execute() +{ + FeaturePtr anEllipse = createEllipseFeature(); + constraintsForEllipse(anEllipse); + + // message to init reentrant operation + static Events_ID anId = ModelAPI_EventReentrantMessage::eventId(); + ReentrantMessagePtr aMessage(new ModelAPI_EventReentrantMessage(anId, this)); + aMessage->setCreatedFeature(anEllipse); + Events_Loop::loop()->send(aMessage); +} + +void SketchPlugin_MacroEllipse::attributeChanged(const std::string& theID) +{ + static const int NB_POINTS = 3; + std::string aPointAttrName[NB_POINTS] = { CENTER_POINT_ID(), + MAJOR_AXIS_POINT_ID(), + PASSED_POINT_ID() }; + std::string aPointRefName[NB_POINTS] = { CENTER_POINT_REF_ID(), + MAJOR_AXIS_POINT_REF_ID(), + PASSED_POINT_REF_ID() }; + + int aNbInitialized = 0; + std::shared_ptr anEllipsePoints[NB_POINTS]; + + for (int aPntIndex = 0; aPntIndex < NB_POINTS; ++aPntIndex) { + AttributePtr aPointAttr = attribute(aPointAttrName[aPntIndex]); + if (!aPointAttr->isInitialized()) + continue; + + AttributeRefAttrPtr aPointRef = refattr(aPointRefName[aPntIndex]); + // calculate ellipse parameters + std::shared_ptr aPassedPoint; + std::shared_ptr aTangentCurve; + SketchPlugin_Tools::convertRefAttrToPointOrTangentCurve( + aPointRef, aPointAttr, aTangentCurve, aPassedPoint); + + anEllipsePoints[aNbInitialized++] = aPassedPoint; + } + + std::shared_ptr anEllipse; + if (aNbInitialized == 2) { + std::shared_ptr aXDir(new GeomAPI_Dir2d( + anEllipsePoints[1]->x() - anEllipsePoints[0]->x(), + anEllipsePoints[1]->y() - anEllipsePoints[0]->y())); + double aMajorRad = anEllipsePoints[1]->distance(anEllipsePoints[0]); + anEllipse = std::shared_ptr( + new GeomAPI_Ellipse2d(anEllipsePoints[0], aXDir, aMajorRad, 0.5 * aMajorRad)); + } else if (aNbInitialized == 3) { + anEllipse = std::shared_ptr( + new GeomAPI_Ellipse2d(anEllipsePoints[0], anEllipsePoints[1], anEllipsePoints[2])); + } + + if (!anEllipse || anEllipse->implPtr() == 0) + return; + + myCenter = anEllipse->center(); + myFocus = anEllipse->firstFocus(); + myMajorRadius = anEllipse->majorRadius(); + myMinorRadius = anEllipse->minorRadius(); + + AttributeDoublePtr aMajorRadiusAttr = real(MAJOR_RADIUS_ID()); + AttributeDoublePtr aMinorRadiusAttr = real(MINOR_RADIUS_ID()); + + bool aWasBlocked = data()->blockSendAttributeUpdated(true); + // center attribute is used in processEvent() to set reference to reentrant arc + std::dynamic_pointer_cast(attribute(CENTER_POINT_ID()))->setValue(myCenter); + aMajorRadiusAttr->setValue(myMajorRadius); + aMinorRadiusAttr->setValue(myMinorRadius); + data()->blockSendAttributeUpdated(aWasBlocked, false); +} + +std::string SketchPlugin_MacroEllipse::processEvent( + const std::shared_ptr& theMessage) +{ + std::string aFilledAttributeName; + + ReentrantMessagePtr aReentrantMessage = + std::dynamic_pointer_cast(theMessage); + if (aReentrantMessage) { + FeaturePtr aCreatedFeature = aReentrantMessage->createdFeature(); + ObjectPtr anObject = aReentrantMessage->selectedObject(); + AttributePtr anAttribute = aReentrantMessage->selectedAttribute(); + std::shared_ptr aClickedPoint = aReentrantMessage->clickedPoint(); + + if (aClickedPoint && (anObject || anAttribute)) { + aFilledAttributeName = CENTER_POINT_ID(); + std::string aReferenceAttributeName = CENTER_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 (anAttribute) { + if (!anAttribute->owner() || !anAttribute->owner()->data()->isValid()) { + if (aCreatedFeature && anAttribute->id() == CENTER_POINT_ID()) + anAttribute = aCreatedFeature->attribute(SketchPlugin_Ellipse::CENTER_ID()); + } + 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()) + anObject = aCreatedFeature->lastResult(); + aRefAttr->setObject(anObject); + } + } + Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED)); + } + return aFilledAttributeName; +} + +void SketchPlugin_MacroEllipse::constraintsForEllipse(FeaturePtr theEllipseFeature) +{ + // Create constraints. + SketchPlugin_Tools::createConstraint( + this, CENTER_POINT_REF_ID(), + theEllipseFeature->attribute(SketchPlugin_Ellipse::CENTER_ID()), + ObjectPtr(), false); + SketchPlugin_Tools::createConstraint( + this, MAJOR_AXIS_POINT_REF_ID(), AttributePtr(), + theEllipseFeature->lastResult(), true); + SketchPlugin_Tools::createConstraint( + this, PASSED_POINT_REF_ID(), AttributePtr(), + theEllipseFeature->lastResult(), true); +} + +FeaturePtr SketchPlugin_MacroEllipse::createEllipseFeature() +{ + FeaturePtr aEllipseFeature = sketch()->addFeature(SketchPlugin_Ellipse::ID()); + + AttributePoint2DPtr aCenterAttr = std::dynamic_pointer_cast( + aEllipseFeature->attribute(SketchPlugin_Ellipse::CENTER_ID())); + aCenterAttr->setValue(myCenter->x(), myCenter->y()); + + AttributePoint2DPtr aFocusAttr = std::dynamic_pointer_cast( + aEllipseFeature->attribute(SketchPlugin_Ellipse::FOCUS_ID())); + aFocusAttr->setValue(myFocus->x(), myFocus->y()); + + aEllipseFeature->real(SketchPlugin_Ellipse::MAJOR_RADIUS_ID())->setValue(myMajorRadius); + aEllipseFeature->real(SketchPlugin_Ellipse::MINOR_RADIUS_ID())->setValue(myMinorRadius); + + aEllipseFeature->boolean(SketchPlugin_Ellipse::AUXILIARY_ID())->setValue( + boolean(AUXILIARY_ID())->value()); + + aEllipseFeature->execute(); + return aEllipseFeature; +} + +AISObjectPtr SketchPlugin_MacroEllipse::getAISObject(AISObjectPtr thePrevious) +{ + SketchPlugin_Sketch* aSketch = sketch(); + if (!aSketch || !myCenter || myMajorRadius == 0) + return AISObjectPtr(); + + std::shared_ptr aNDir = std::dynamic_pointer_cast( + aSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID())); + + // Compute a ellipse in 3D view. + std::shared_ptr aCenter(aSketch->to3D(myCenter->x(), myCenter->y())); + std::shared_ptr aFocus(aSketch->to3D(myFocus->x(), myFocus->y())); + std::shared_ptr aNormal = aNDir->dir(); + std::shared_ptr aMajorAxis(new GeomAPI_Dir(aFocus->x() - aCenter->x(), + aFocus->y() - aCenter->y(), aFocus->z() - aCenter->z())); + + std::shared_ptr anEllipseShape = + GeomAlgoAPI_EdgeBuilder::ellipse(aCenter, aNormal, aMajorAxis, myMajorRadius, myMinorRadius); + GeomShapePtr aCenterPointShape = GeomAlgoAPI_PointBuilder::vertex(aCenter); + if (!anEllipseShape.get() || !aCenterPointShape.get()) + return AISObjectPtr(); + + std::list > aShapes; + aShapes.push_back(anEllipseShape); + aShapes.push_back(aCenterPointShape); + + std::shared_ptr aCompound = GeomAlgoAPI_CompoundBuilder::compound(aShapes); + AISObjectPtr anAIS = thePrevious; + if (!anAIS) + anAIS.reset(new GeomAPI_AISObject()); + anAIS->createShape(aCompound); + return anAIS; +} diff --git a/src/SketchPlugin/SketchPlugin_MacroEllipse.h b/src/SketchPlugin/SketchPlugin_MacroEllipse.h new file mode 100644 index 000000000..29ae08978 --- /dev/null +++ b/src/SketchPlugin/SketchPlugin_MacroEllipse.h @@ -0,0 +1,142 @@ +// Copyright (C) 2017-20xx CEA/DEN, EDF R&D --> + +// File: SketchPlugin_MacroEllipse.h +// Created: 26 April 2017 +// Author: Artem ZHIDKOV + +#ifndef SketchPlugin_MacroEllipse_H_ +#define SketchPlugin_MacroEllipse_H_ + +#include +#include +#include +#include + +////class GeomAPI_Circ2d; +class GeomAPI_Pnt2d; + +/**\class SketchPlugin_MacroEllipse + * \ingroup Plugins + * \brief Feature for creation of the new ellipse in Sketch. + */ +class SketchPlugin_MacroEllipse: public SketchPlugin_SketchEntity, + public GeomAPI_IPresentable, + public ModelAPI_IReentrant +{ + public: + /// Ellipse feature kind + inline static const std::string& ID() + { + static const std::string ID("SketchMacroEllipse"); + return ID; + } + + /// 2D point - center of the ellipse. + inline static const std::string& CENTER_POINT_ID() + { + static const std::string ID("center_point"); + return ID; + } + + /// Reference for center point selection. + inline static const std::string& CENTER_POINT_REF_ID() + { + static const std::string ID("center_point_ref"); + return ID; + } + + /// 2D point - major axis point of the ellipse. + inline static const std::string& MAJOR_AXIS_POINT_ID() + { + static const std::string ID("major_axis_point"); + return ID; + } + + /// Reference for major axis point selection. + inline static const std::string& MAJOR_AXIS_POINT_REF_ID() + { + static const std::string ID("major_axis_point_ref"); + return ID; + } + + /// 2D point - passed point of the ellipse + inline static const std::string& PASSED_POINT_ID() + { + static const std::string ID("passed_point"); + return ID; + } + + /// Reference for passed point selection. + inline static const std::string& PASSED_POINT_REF_ID() + { + static const std::string ID("passed_point_ref"); + return ID; + } + + /// Major radius of the ellipse + inline static const std::string& MAJOR_RADIUS_ID() + { + static const std::string ID("ellipse_major_radius"); + return ID; + } + + /// Minor radius of the ellipse + inline static const std::string& MINOR_RADIUS_ID() + { + static const std::string ID("ellipse_minor_radius"); + return ID; + } + + /// Returns the kind of a feature + SKETCHPLUGIN_EXPORT virtual const std::string& getKind() + { + static std::string MY_KIND = SketchPlugin_MacroEllipse::ID(); + return MY_KIND; + } + + /// \brief Request for initialization of data model of the feature: adding all attributes. + SKETCHPLUGIN_EXPORT virtual void initAttributes(); + + /// Called on change of any argument-attribute of this object + SKETCHPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID); + + /// Returns the AIS preview + virtual AISObjectPtr getAISObject(AISObjectPtr thePrevious); + + /// Creates a new part document if needed + SKETCHPLUGIN_EXPORT virtual void execute(); + + /// Moves the feature + /// \param theDeltaX the delta for X coordinate is moved + /// \param theDeltaY the delta for Y coordinate is moved + SKETCHPLUGIN_EXPORT virtual void move(const double theDeltaX, const double theDeltaY) + {} + + /// Reimplemented from ModelAPI_Feature::isMacro(). + /// \returns true + SKETCHPLUGIN_EXPORT virtual bool isMacro() const + {return true;} + + SKETCHPLUGIN_EXPORT virtual bool isPreviewNeeded() const + {return false;} + + /// Apply information of the message to current object. It fills reference object, + /// tangent type and tangent point refence in case of tangent arc + virtual std::string processEvent(const std::shared_ptr& theMessage); + + /// Use plugin manager for features creation + SketchPlugin_MacroEllipse(); + +private: + void constraintsForEllipse(FeaturePtr theEllipseFeature); + + FeaturePtr createEllipseFeature(); + +private: + std::shared_ptr myCenter; + std::shared_ptr myFocus; + double myMajorRadius; + double myMinorRadius; +}; + +#endif diff --git a/src/SketchPlugin/SketchPlugin_Plugin.cpp b/src/SketchPlugin/SketchPlugin_Plugin.cpp index e6451367d..9999ea08c 100644 --- a/src/SketchPlugin/SketchPlugin_Plugin.cpp +++ b/src/SketchPlugin/SketchPlugin_Plugin.cpp @@ -32,6 +32,8 @@ #include #include #include +#include +#include #include #include @@ -208,6 +210,10 @@ FeaturePtr SketchPlugin_Plugin::createFeature(std::string theFeatureID) return FeaturePtr(new SketchPlugin_MacroArc); } else if (theFeatureID == SketchPlugin_MacroCircle::ID()) { return FeaturePtr(new SketchPlugin_MacroCircle); + } else if (theFeatureID == SketchPlugin_Ellipse::ID()) { + return FeaturePtr(new SketchPlugin_Ellipse); + } else if (theFeatureID == SketchPlugin_MacroEllipse::ID()) { + return FeaturePtr(new SketchPlugin_MacroEllipse); } // feature of such kind is not found return FeaturePtr(); diff --git a/src/SketchPlugin/icons/ellipse.png b/src/SketchPlugin/icons/ellipse.png new file mode 100644 index 000000000..6f311635d Binary files /dev/null and b/src/SketchPlugin/icons/ellipse.png differ diff --git a/src/SketchPlugin/plugin-Sketch.xml b/src/SketchPlugin/plugin-Sketch.xml index 45cb3cec8..e33f3dede 100644 --- a/src/SketchPlugin/plugin-Sketch.xml +++ b/src/SketchPlugin/plugin-Sketch.xml @@ -7,6 +7,7 @@ id="Sketch" nested="SketchPoint SketchIntersectionPoint SketchLine SketchCircle SketchMacroCircle SketchArc SketchMacroArc + SketchEllipse SketchMacroEllipse SketchRectangle SketchProjection SketchConstraintLength SketchConstraintRadius SketchConstraintDistance @@ -340,6 +341,95 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +