From 26ed1d962bfb3629e8b2f677d05a416738a3da4f Mon Sep 17 00:00:00 2001 From: mpv Date: Tue, 25 Apr 2017 11:57:30 +0300 Subject: [PATCH] Ability to select centers of circles and ellipses, not existing in the context shape. --- src/Model/Model_AttributeSelection.cpp | 103 +++++++++++++++++++-- src/Model/Model_AttributeSelection.h | 9 ++ src/ModelAPI/ModelAPI_AttributeSelection.h | 17 ++++ 3 files changed, 120 insertions(+), 9 deletions(-) diff --git a/src/Model/Model_AttributeSelection.cpp b/src/Model/Model_AttributeSelection.cpp index b2a4989db..b7f1d19d6 100644 --- a/src/Model/Model_AttributeSelection.cpp +++ b/src/Model/Model_AttributeSelection.cpp @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include #include @@ -40,6 +42,9 @@ #include #include #include +#include +#include +#include //#define DEB_NAMING 1 #ifdef DEB_NAMING @@ -55,6 +60,13 @@ Standard_GUID kPART_REF_ID("635eacb2-a1d6-4dec-8348-471fae17cb27"); // selection is invalid after recomputation Standard_GUID kINVALID_SELECTION("bce47fd7-80fa-4462-9d63-2f58acddd49d"); +// identifier of the selection of the center of circle on edge +Standard_GUID kCIRCLE_CENTER("d0d0e0f1-217a-4b95-8fbb-0c4132f23718"); +// identifier of the selection of the first focus point of ellipse on edge +Standard_GUID kELLIPSE_CENTER1("f70df04c-3168-4dc9-87a4-f1f840c1275d"); +// identifier of the selection of the second focus point of ellipse on edge +Standard_GUID kELLIPSE_CENTER2("1395ae73-8e02-4cf8-b204-06ff35873a32"); + // on this label is stored: // TNaming_NamedShape - selected shape // TNaming_Naming - topological selection information (for the body) @@ -72,6 +84,7 @@ void Model_AttributeSelection::setValue(const ResultPtr& theContext, } else { myTmpContext.reset(); myTmpSubShape.reset(); + myTmpCenterType = NOT_CENTER; } const std::shared_ptr& anOldShape = value(); @@ -88,6 +101,9 @@ void Model_AttributeSelection::setValue(const ResultPtr& theContext, TDF_Label aSelLab = selectionLabel(); aSelLab.ForgetAttribute(kSIMPLE_REF_ID); aSelLab.ForgetAttribute(kINVALID_SELECTION); + aSelLab.ForgetAttribute(kCIRCLE_CENTER); + aSelLab.ForgetAttribute(kELLIPSE_CENTER1); + aSelLab.ForgetAttribute(kELLIPSE_CENTER2); bool isDegeneratedEdge = false; // do not use the degenerated edge as a shape, a null context and shape is used in the case @@ -131,6 +147,30 @@ void Model_AttributeSelection::setValue(const ResultPtr& theContext, owner()->data()->sendAttributeUpdated(this); } +void Model_AttributeSelection::setValueCenter( + const ResultPtr& theContext, const std::shared_ptr& theEdge, + const CenterType theCenterType, const bool theTemporarily) +{ + setValue(theContext, theEdge, theTemporarily); + if (theTemporarily) { + myTmpCenterType = theCenterType; + } else { // store in the data structure + TDF_Label aSelLab = selectionLabel(); + switch(theCenterType) { + case CIRCLE_CENTER: + TDataStd_UAttribute::Set(aSelLab, kCIRCLE_CENTER); + break; + case ELLIPSE_FIRST_FOCUS: + TDataStd_UAttribute::Set(aSelLab, kELLIPSE_CENTER1); + break; + case ELLIPSE_SECOND_FOCUS: + TDataStd_UAttribute::Set(aSelLab, kELLIPSE_CENTER2); + break; + } + } +} + + void Model_AttributeSelection::removeTemporaryValues() { if (myTmpContext.get() || myTmpSubShape.get()) { @@ -139,6 +179,42 @@ void Model_AttributeSelection::removeTemporaryValues() } } +// returns the center of the edge: circular or elliptical +GeomShapePtr centerByEdge(GeomShapePtr theEdge, ModelAPI_AttributeSelection::CenterType theType) +{ + if (theType != ModelAPI_AttributeSelection::NOT_CENTER && theEdge.get() != NULL) { + TopoDS_Shape aShape = theEdge->impl(); + if (!aShape.IsNull()) { + TopoDS_Edge anEdge = TopoDS::Edge(aShape); + double aFirst, aLast; + Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast); + if (!aCurve.IsNull()) { + TopoDS_Vertex aVertex; + BRep_Builder aBuilder; + if (theType == ModelAPI_AttributeSelection::CIRCLE_CENTER) { + Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast(aCurve); + if (!aCirc.IsNull()) { + aBuilder.MakeVertex(aVertex, aCirc->Location(), Precision::Confusion()); + } + } else { // ellipse + Handle(Geom_Ellipse) anEll = Handle(Geom_Ellipse)::DownCast(aCurve); + if (!anEll.IsNull()) { + aBuilder.MakeVertex(aVertex, + theType == ModelAPI_AttributeSelection::ELLIPSE_FIRST_FOCUS ? + anEll->Focus1() : anEll->Focus2(), Precision::Confusion()); + } + } + if (!aVertex.IsNull()) { + std::shared_ptr aResult(new GeomAPI_Vertex); + aResult->setImpl(new TopoDS_Vertex(aVertex)); + return aResult; + } + } + } + } + return theEdge; // no vertex, so, return the initial edge +} + std::shared_ptr Model_AttributeSelection::value() { GeomShapePtr aResult; @@ -147,30 +223,39 @@ std::shared_ptr Model_AttributeSelection::value() std::dynamic_pointer_cast(myTmpContext); if(aResulConstruction.get()) { // it is just reference to construction. - return myTmpSubShape; + return centerByEdge(myTmpSubShape, myTmpCenterType); } - return myTmpSubShape.get() ? myTmpSubShape : myTmpContext->shape(); + return centerByEdge(myTmpSubShape.get() ? myTmpSubShape : myTmpContext->shape(), myTmpCenterType); } TDF_Label aSelLab = selectionLabel(); if (aSelLab.IsAttribute(kINVALID_SELECTION)) return aResult; + CenterType aType = NOT_CENTER; + if (aSelLab.IsAttribute(kCIRCLE_CENTER)) + aType = CIRCLE_CENTER; + else if (aSelLab.IsAttribute(kELLIPSE_CENTER1)) + aType = CIRCLE_CENTER; + else if (aSelLab.IsAttribute(kELLIPSE_CENTER2)) + aType = CIRCLE_CENTER; + + if (myRef.isInitialized()) { if (aSelLab.IsAttribute(kSIMPLE_REF_ID)) { // it is just reference to shape, not sub-shape ResultPtr aContext = context(); if (!aContext.get()) return aResult; // empty result - return aContext->shape(); + return centerByEdge(aContext->shape(), aType); } if (aSelLab.IsAttribute(kPART_REF_ID)) { ResultPartPtr aPart = std::dynamic_pointer_cast(context()); if (!aPart.get() || !aPart->isActivated()) - return std::shared_ptr(); // postponed naming needed + return aResult; // postponed naming needed Handle(TDataStd_Integer) anIndex; if (aSelLab.FindAttribute(TDataStd_Integer::GetID(), anIndex)) { if (anIndex->Get()) { // special selection attribute was created, use it - return aPart->selectionValue(anIndex->Get()); + return centerByEdge(aPart->selectionValue(anIndex->Get()), aType); } else { // face with name is already in the data model, so try to take it by name Handle(TDataStd_Name) aName; if (aSelLab.FindAttribute(TDataStd_Name::GetID(), aName)) { @@ -179,8 +264,8 @@ std::shared_ptr Model_AttributeSelection::value() if (aPartEnd != std::string::npos && aPartEnd != aSubShapeName.rfind('/')) { std::string aNameInPart = aSubShapeName.substr(aPartEnd + 1); int anIndex; - std::string aType; // to reuse already existing selection the type is not needed - return aPart->shapeInPart(aNameInPart, aType, anIndex); + std::string aTypeStr; // to reuse already existing selection the type is not needed + return centerByEdge(aPart->shapeInPart(aNameInPart, aTypeStr, anIndex), aType); } } } @@ -199,8 +284,8 @@ std::shared_ptr Model_AttributeSelection::value() Handle(TDataStd_Integer) anIndex; if (aSelLab.FindAttribute(TDataStd_Integer::GetID(), anIndex)) { if (anIndex->Get() == 0) // it is just reference to construction, nothing is in value - return aResult; - return aConstr->shape(anIndex->Get(), owner()->document()); + return centerByEdge(aResult, aType); + return centerByEdge(aConstr->shape(anIndex->Get(), owner()->document()), aType); } } } diff --git a/src/Model/Model_AttributeSelection.h b/src/Model/Model_AttributeSelection.h index b387297ef..16388be0c 100644 --- a/src/Model/Model_AttributeSelection.h +++ b/src/Model/Model_AttributeSelection.h @@ -27,6 +27,8 @@ class Model_AttributeSelection : public ModelAPI_AttributeSelection ResultPtr myTmpContext; /// temporarily storages to avoid keeping in the data structure if not needed std::shared_ptr myTmpSubShape; + /// temporarily storages to avoid keeping in the data structure if not needed + CenterType myTmpCenterType; /// Reference to the partent attribute, if any (to split selection compounds in issue 1799) Model_AttributeSelectionList* myParent; public: @@ -39,6 +41,13 @@ public: const ResultPtr& theContext, const std::shared_ptr& theSubShape, const bool theTemporarily = false); + /// Same as SetValue, but it takes an edge (on circular or elliptical curve) + /// and stores the vertex of the central point (for ellipse the first or the second focus point) + MODEL_EXPORT virtual void setValueCenter( + const ResultPtr& theContext, const std::shared_ptr& theEdge, + const CenterType theCenterType, + const bool theTemporarily = false); + /// Reset temporary stored values virtual void removeTemporaryValues(); diff --git a/src/ModelAPI/ModelAPI_AttributeSelection.h b/src/ModelAPI/ModelAPI_AttributeSelection.h index cc9862d88..5af29b52c 100644 --- a/src/ModelAPI/ModelAPI_AttributeSelection.h +++ b/src/ModelAPI/ModelAPI_AttributeSelection.h @@ -10,6 +10,8 @@ #include "ModelAPI_Attribute.h" #include +class GeomAPI_Edge; + /**\class ModelAPI_AttributeSelection * \ingroup DataModel * \brief Attribute that contains reference to the sub-shape of some result, the selected shape. @@ -18,6 +20,14 @@ class ModelAPI_AttributeSelection : public ModelAPI_Attribute { public: + /// Type of the center of the circular of elliptical edge + enum CenterType { + NOT_CENTER, ///< this is not a center + CIRCLE_CENTER, ///< center of the circle + ELLIPSE_FIRST_FOCUS, ///< first focus point of the ellipse + ELLIPSE_SECOND_FOCUS, ///< second focus point of the ellipse + }; + /// Defines the result and its selected sub-shape /// \param theContext object where the sub-shape was selected /// \param theSubShape selected sub-shape (if null, the whole context is selected) @@ -27,6 +37,13 @@ class ModelAPI_AttributeSelection : public ModelAPI_Attribute const ResultPtr& theContext, const std::shared_ptr& theSubShape, const bool theTemporarily = false) = 0; + /// Same as SetValue, but it takes an edge (on circular or elliptical curve) + /// and stores the vertex of the central point (for ellipse the first or the second focus point) + virtual void setValueCenter( + const ResultPtr& theContext, const std::shared_ptr& theEdge, + const CenterType theCenterType, + const bool theTemporarily = false) = 0; + /// Reset temporary stored values virtual void removeTemporaryValues() = 0; -- 2.39.2