From 696c9e8e1d766f0d019961fa3be816df2b7ac445 Mon Sep 17 00:00:00 2001 From: dish Date: Mon, 29 Jan 2024 13:43:50 +0000 Subject: [PATCH] [bos #35154][EDF](2023-T1) Edge thickness. Add edge thickness option for individual edges. --- src/Model/Model_Document.cpp | 59 +++++++++ src/Model/Model_Document.h | 18 +++ src/Model/Model_Objects.cpp | 202 ++++++++++++++++++++++++++++- src/Model/Model_Objects.h | 38 ++++++ src/Model/Model_ResultBody.cpp | 53 ++++++++ src/Model/Model_ResultBody.h | 15 +++ src/Model/Model_ResultPart.cpp | 45 +++++++ src/Model/Model_ResultPart.h | 9 ++ src/ModelAPI/ModelAPI_Document.h | 13 ++ src/ModelAPI/ModelAPI_ResultBody.h | 18 +++ src/ModelAPI/ModelAPI_ResultPart.h | 10 ++ src/ModelAPI/ModelAPI_Tools.cpp | 123 +++++++++++++++++- src/ModelAPI/ModelAPI_Tools.h | 37 ++++-- src/PartSet/PartSet_Module.cpp | 3 + src/XGUI/XGUI_Selection.cpp | 40 ++++++ src/XGUI/XGUI_Selection.h | 3 + src/XGUI/XGUI_Workshop.cpp | 91 +++++++++---- src/XGUI/XGUI_Workshop.h | 4 +- 18 files changed, 739 insertions(+), 42 deletions(-) diff --git a/src/Model/Model_Document.cpp b/src/Model/Model_Document.cpp index 5f313a855..986213a3c 100644 --- a/src/Model/Model_Document.cpp +++ b/src/Model/Model_Document.cpp @@ -1375,6 +1375,13 @@ const int Model_Document::index(std::shared_ptr theObject, return myObjs->index(theObject, theAllowFolder); } +const int Model_Document::index(std::shared_ptr theResult, + std::shared_ptr theShape, + const bool theAllowFolder) +{ + return myObjs->index(theResult, theShape, theAllowFolder); +} + int Model_Document::size(const std::string& theGroupID, const bool theAllowFolder) { if (myObjs == 0) // may be on close @@ -2120,6 +2127,47 @@ AttributeSelectionListPtr Model_Document::selectionInPartFeature() return mySelectionFeature->selectionList("selection"); } +/// Feature that is used for use selection attribute +class Model_SelectionInResult : public ModelAPI_Feature +{ +public: + /// Nothing to do in constructor + Model_SelectionInResult() : ModelAPI_Feature() {} + + /// Returns the unique kind of a feature + virtual const std::string& getKind() + { + static std::string MY_KIND("InternalSelectionInResult"); + return MY_KIND; + } + /// Request for initialization of data model of the object: adding all attributes + virtual void initAttributes() + { + data()->addAttribute("selection", ModelAPI_AttributeSelection::typeId()); + } + /// Nothing to do in the execution function + virtual void execute() {} +}; + +AttributeSelectionPtr Model_Document::selectionInResult() +{ + FeaturePtr aFeatureNameGen = FeaturePtr(new Model_SelectionInResult); + + TDF_Label aFeatureLab = generalLabel().FindChild(TAG_SELECTION_FEATURE); + std::shared_ptr aData(new Model_Data); + aData->setLabel(aFeatureLab.FindChild(1)); + aData->setObject(aFeatureNameGen); + aFeatureNameGen->setDoc(myObjs->owner()); + aFeatureNameGen->setData(aData); + std::wstring aName = id() + L"_Part"; + aFeatureNameGen->data()->setName(aName); + aFeatureNameGen->setDoc(myObjs->owner()); + aFeatureNameGen->initAttributes(); + aFeatureNameGen->init(); + + return aFeatureNameGen->selection("selection"); +} + FeaturePtr Model_Document::lastFeature() { if (myObjs) @@ -2290,6 +2338,17 @@ void Model_Document::storeNodesState(const std::list& theStates) } } +void Model_Document::storeShape(const std::shared_ptr theData, + const std::shared_ptr theResult, + const std::shared_ptr theShape) +{ + if (index(theData->owner()) == -1) + return; + int anIndex = index(theResult, theShape); + if (anIndex == -1) + myObjs->storeShape(theData, theResult, theShape); +} + void Model_Document::restoreNodesState(std::list& theStates) const { TDF_Label aLab = generalLabel().FindChild(TAG_NODES_STATE); diff --git a/src/Model/Model_Document.h b/src/Model/Model_Document.h index 001758919..e54310864 100644 --- a/src/Model/Model_Document.h +++ b/src/Model/Model_Document.h @@ -33,6 +33,7 @@ class Handle_Model_Document; class Model_Objects; class ModelAPI_AttributeSelectionList; +class TopoDS_Shape; /**\class Model_Document * \ingroup DataModel @@ -146,6 +147,14 @@ class Model_Document : public ModelAPI_Document MODEL_EXPORT virtual const int index(std::shared_ptr theObject, const bool theAllowFolder = false); + //! Returns the shape index in the result. + //! \param theResult result + //! \param theShape result subshape + //! \returns index started from zero, or -1 if shape is not stored or is not a subshape of the result + MODEL_EXPORT virtual const int index(std::shared_ptr theResult, + std::shared_ptr theShape, + const bool theAllowFolder = false); + //! Internal sub-document by ID MODEL_EXPORT virtual std::shared_ptr subDoc(int theDocID); @@ -385,10 +394,18 @@ class Model_Document : public ModelAPI_Document //! for calculation of selection externally from the document std::shared_ptr selectionInPartFeature(); + //! Returns the selection attribute that is used + std::shared_ptr selectionInResult(); + /// Stores in the document boolean flags: states of the nodes in the object browser. /// Normally is called outside of the transaction, just before "save". virtual void storeNodesState(const std::list& theStates); + /// Store Shape from Result to document + virtual void storeShape(const std::shared_ptr theData, + const std::shared_ptr theResult, + const std::shared_ptr theShape); + /// Returns the stored nodes states. Normally it is called just after "open". /// Appends the values to theStates list. virtual void restoreNodesState(std::list& theStates) const; @@ -424,6 +441,7 @@ class Model_Document : public ModelAPI_Document friend class Model_ResultPart; friend class Model_ResultBody; friend class Model_ResultConstruction; + friend class Model_SelectionInResult; friend class Model_SelectionNaming; friend class Model_BodyBuilder; friend class DFBrowser; diff --git a/src/Model/Model_Objects.cpp b/src/Model/Model_Objects.cpp index 544b5bef8..bbce6b42d 100644 --- a/src/Model/Model_Objects.cpp +++ b/src/Model/Model_Objects.cpp @@ -46,15 +46,19 @@ #include #include #include +#include #include #include #include #include #include +#include #include -#if OCC_VERSION_LARGE < 0x07080000 +#include +#include +#if OCC_VERSION_LARGE < 0x07080000 #include // for TDF_Label map usage static Standard_Integer HashCode(const TDF_Label& theLab, const Standard_Integer theUpper); @@ -97,11 +101,13 @@ static const int TAG_OBJECTS = 2; // tag of the objects sub-tree (features, res // feature sub-labels static const int TAG_FEATURE_ARGUMENTS = 1; ///< where the arguments are located static const int TAG_FEATURE_RESULTS = 2; ///< where the results are located +static const int TAG_RESULT_SHAPES = 2; ///< where the shapes are located /// /// 0:1:2 - where features are located /// 0:1:2:N:1 - data of the feature N /// 0:1:2:N:2:K:1 - data of the K result of the feature N +/// 0:1:2:N:2:K:2:M:1 - data of the M shape of the K result of the feature N Model_Objects::Model_Objects(TDF_Label theMainLab) : myMain(theMainLab) { @@ -689,6 +695,39 @@ const int Model_Objects::index(std::shared_ptr theObject, return -1; } +const int Model_Objects::index(std::shared_ptr theResult, + std::shared_ptr theShape, + const bool theAllowFolder) +{ + ResultBodyPtr aMain = std::dynamic_pointer_cast(theResult); + aMain = ModelAPI_Tools::mainBody(aMain); + + int anIndex = -1; + if (aMain.get()) + anIndex = index(aMain, theAllowFolder); + else + anIndex = index(theResult, theAllowFolder); + + if (anIndex == -1) + return -1; // Object not store to document + TDF_Label aShapesLabel = shapesFromResult(resultLabel(theResult->data(), anIndex)); + + int aShapesIndex = 0; + for (TDF_ChildIterator anIt(aShapesLabel); anIt.More(); anIt.Next(), ++aShapesIndex) + { + Handle(TNaming_NamedShape) aCurShape; + if (anIt.Value().FindAttribute(TNaming_NamedShape::GetID(), aCurShape)) + { + if (aCurShape->Get().IsSame(theShape->impl())) + { + return aShapesIndex; + } + } + } + //not found + return -1; +} + int Model_Objects::size(const std::string& theGroupID, const bool theAllowFolder) { createHistory(theGroupID); @@ -740,6 +779,135 @@ TDF_Label Model_Objects::featuresLabel() const return myMain.FindChild(TAG_OBJECTS); } +TDF_Label Model_Objects::shapesFromResult(TDF_Label theResult) const +{ + return theResult.Father().FindChild(TAG_RESULT_SHAPES); +} + +void Model_Objects::setAttribute(const Handle(TDF_Attribute)& theAttribute, + std::shared_ptr theResult, + std::shared_ptr theShape) +{ + ResultBodyPtr aMain = std::dynamic_pointer_cast(theResult); + aMain = ModelAPI_Tools::mainBody(aMain); + TDF_Label aResultLabel; + if (aMain.get()) + aResultLabel = resultLabel(theResult->data(), index(aMain)); + else + aResultLabel = resultLabel(theResult->data(), index(theResult)); + TDF_Label anAttributeLabel = subShapeLabel(aResultLabel, index(theResult, theShape)).FindChild(TAG_FEATURE_ARGUMENTS); + + if (Standard_GUID::IsEqual(theAttribute->ID(), TDataStd_IntegerArray::GetID())) + { + Handle(TDataStd_IntegerArray) anColor; + Handle(TDataStd_IntegerArray) anAttr = + Handle(TDataStd_IntegerArray)::DownCast(theAttribute); + + if (anAttributeLabel.FindAttribute(TDataStd_IntegerArray::GetID(), anColor)) + { + anAttributeLabel.ForgetAttribute(TDataStd_IntegerArray::GetID()); + } + anAttributeLabel.AddAttribute(anAttr); + static const Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED); + ModelAPI_EventCreator::get()->sendUpdated(theResult, anEvent); + } + else if (Standard_GUID::IsEqual(theAttribute->ID(), TDataStd_Integer::GetID())) { + Handle(TDataStd_Integer) aThicknessAttr; + Handle(TDataStd_Integer) anAttr = Handle(TDataStd_Integer)::DownCast(theAttribute); + + if (anAttributeLabel.FindAttribute(TDataStd_Integer::GetID(), aThicknessAttr)) + anAttributeLabel.ForgetAttribute(TDataStd_Integer::GetID()); + + anAttributeLabel.AddAttribute(anAttr); + static const Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED); + ModelAPI_EventCreator::get()->sendUpdated(theResult, anEvent); + } +} + +Handle(TDF_Attribute) Model_Objects::getAttribute(const Standard_GUID& theID, + std::shared_ptr theResult, + std::shared_ptr theShape) +{ + ResultBodyPtr aMain = std::dynamic_pointer_cast(theResult); + aMain = ModelAPI_Tools::mainBody(aMain); + + int anIndex = index(theResult, theShape); + if (anIndex == -1) { + return opencascade::handle(nullptr); + } + + TDF_Label aResultLabel; + if (aMain.get()) + aResultLabel = resultLabel(theResult->data(), index(aMain)); + else + aResultLabel = resultLabel(theResult->data(), index(theResult)); + + TDF_Label anAttributeLabel = subShapeLabel(aResultLabel, anIndex).FindChild(TAG_FEATURE_ARGUMENTS); + + Handle(TDF_Attribute) anAttr; + anAttributeLabel.FindAttribute(theID, anAttr); + return anAttr; +} + +void Model_Objects::getSubShapesWithEdgeThickness( + const std::shared_ptr theResult, + std::map, int>& oShapes +) const { + ResultBodyPtr aMainBody = std::dynamic_pointer_cast(theResult); + aMainBody = ModelAPI_Tools::mainBody(aMainBody); + TDF_Label aShapesLabel; + if (aMainBody.get()) + aShapesLabel = shapesFromResult(resultLabel(theResult->data(), index(aMainBody))); + else + aShapesLabel = shapesFromResult(resultLabel(theResult->data(), index(theResult))); + + for (TDF_ChildIterator aChilds(aShapesLabel); aChilds.More(); aChilds.Next()) + { + TDF_Label aCurSubShape = aChilds.Value(); + Handle(TNaming_NamedShape) aNamedShape; + aCurSubShape.FindAttribute(TNaming_NamedShape::GetID(), aNamedShape); + if (aNamedShape.IsNull()) + continue; + + std::shared_ptr aSub(new GeomAPI_Shape); + aSub->setImpl(new TopoDS_Shape(aNamedShape->Get())); + + Handle(TDataStd_Integer) aEdgeThicknessAttr; + aCurSubShape.FindChild(TAG_FEATURE_ARGUMENTS).FindAttribute(TDataStd_Integer::GetID(), aEdgeThicknessAttr); + if (aEdgeThicknessAttr.IsNull()) + continue; + + oShapes[aSub] = aEdgeThicknessAttr->Get(); + } +} + +void Model_Objects::removeSubShapeEdgeThickness(const std::shared_ptr theResult) const +{ + ResultBodyPtr aMainBody = std::dynamic_pointer_cast(theResult); + aMainBody = ModelAPI_Tools::mainBody(aMainBody); + + TDF_Label aShapesLabel; + if (aMainBody.get()) + aShapesLabel = shapesFromResult(resultLabel(theResult->data(), index(aMainBody))); + else + { + ResultPartPtr aResPart = std::dynamic_pointer_cast(theResult); + if (!aResPart.get()) + return; + aShapesLabel = shapesFromResult(resultLabel(theResult->data(), index(aResPart))); + } + for (TDF_ChildIterator aChilds(aShapesLabel); aChilds.More(); aChilds.Next()) + { + TDF_Label aCurSubShape = aChilds.Value(); + Handle(TNaming_NamedShape) aNamedShape; + aCurSubShape.FindAttribute(TNaming_NamedShape::GetID(), aNamedShape); + if (aNamedShape.IsNull()) + continue; + + aCurSubShape.FindChild(TAG_FEATURE_ARGUMENTS).ForgetAttribute(TDataStd_Integer::GetID()); + } +} + static std::wstring composeName(const std::string& theFeatureKind, const int theIndex) { std::stringstream aNameStream; @@ -1194,6 +1362,12 @@ TDF_Label Model_Objects::resultLabel( return aData->label().Father().FindChild(TAG_FEATURE_RESULTS).FindChild(theResultIndex + 1); } +TDF_Label Model_Objects::subShapeLabel(TDF_Label& theResultLabel, + const int theResultIndex) +{ + return theResultLabel.Father().FindChild(TAG_RESULT_SHAPES).FindChild(theResultIndex + 1); +} + bool Model_Objects::hasCustomName(DataPtr theFeatureData, ResultPtr theResult, int /*theResultIndex*/, @@ -1263,6 +1437,28 @@ void Model_Objects::storeResult(std::shared_ptr theFeatureData, } } +void Model_Objects::storeShape(std::shared_ptr theData, + std::shared_ptr theResult, + std::shared_ptr theShape, + const int theResultIndex) +{ + std::shared_ptr aResultData = + std::dynamic_pointer_cast(theResult->data()); + TDF_Label aResultLabel = resultLabel(aResultData, index(theData->owner())); + TDF_Label aShapesLabel = shapesFromResult(aResultLabel); + + int anIndex = aShapesLabel.NbChildren(); + TDF_Label aSubShapeLabel = subShapeLabel(aResultLabel, anIndex); + + Handle(TNaming_NamedShape) aNS; + if (aSubShapeLabel.FindAttribute(TNaming_NamedShape::GetID(), aNS)) + return; + + // GeomAPI_Shape -> TNaming_NamedShape + TNaming_Builder aBuilder(aSubShapeLabel); + aBuilder.Select(theShape->impl(), theShape->impl()); +} + std::shared_ptr Model_Objects::createConstruction( const std::shared_ptr& theFeatureData, const int theIndex) { @@ -1293,7 +1489,7 @@ std::shared_ptr Model_Objects::createBody( aResult = std::dynamic_pointer_cast(anOldObject); } if (!aResult.get()) { - aResult = std::shared_ptr(new Model_ResultBody); + aResult = std::shared_ptr(new Model_ResultBody()); storeResult(theFeatureData, aResult, theIndex, theNameShape); } return aResult; @@ -2046,7 +2242,7 @@ FeaturePtr Model_Objects::lastFeature() bool Model_Objects::isLater(FeaturePtr theLater, FeaturePtr theCurrent) const { - if (theLater->getKind() == "InternalSelectionInPartFeature") + if (theLater->getKind() == "InternalSelectionInPartFeature" || theLater->getKind() == "InternalSelectionInResult") return true; std::shared_ptr aLaterD = std::static_pointer_cast(theLater->data()); std::shared_ptr aCurrentD = std::static_pointer_cast(theCurrent->data()); diff --git a/src/Model/Model_Objects.h b/src/Model/Model_Objects.h index e810e10ad..b0ce8b4fe 100644 --- a/src/Model/Model_Objects.h +++ b/src/Model/Model_Objects.h @@ -92,6 +92,14 @@ class Model_Objects const int index(std::shared_ptr theObject, const bool theAllowFolder = false); + //! Returns the shape index in the result. + //! \param theResult result + //! \param theShape result subshape + //! \returns index started from zero, or -1 if shape is not stored or is not a subshape of the result + const int index(std::shared_ptr theResult, + std::shared_ptr theShape, + const bool theAllowFolder = false); + //! Returns the feature in the group by the index (started from zero) //! \param theGroupID group that contains a feature //! \param theIndex zero-based index of feature in the group @@ -181,6 +189,23 @@ class Model_Objects bool removeFromFolder(const std::list >& theFeatures, const bool theBefore = true); + //! set attribute to subShape + void setAttribute(const Handle(TDF_Attribute)& theAttribute, + std::shared_ptr theResult, + std::shared_ptr theShape); + + //! get attribute from subshape + Handle(TDF_Attribute) getAttribute(const Standard_GUID& theID, + std::shared_ptr theResult, + std::shared_ptr theShape); + + void getSubShapesWithEdgeThickness( + const std::shared_ptr theResult, + std::map, int>& oShapes + ) const; + + void removeSubShapeEdgeThickness(const std::shared_ptr theResult) const; + //! Sets the owner of this manager void setOwner(DocumentPtr theDoc); @@ -195,6 +220,9 @@ class Model_Objects //! Returns (creates if needed) the features label TDF_Label featuresLabel() const; + //! Returns (creates if needed) the shapes label from result label + TDF_Label shapesFromResult(TDF_Label theResult) const; + //! Initializes feature with a unique name in this group (unique name is generated as //! feature type + "_" + index void setUniqueName(FeaturePtr theFeature); @@ -227,10 +255,20 @@ class Model_Objects const int theResultIndex = 0, const std::wstring& theNameShape = L""); + //! Allows to store the shape from result in the data tree of the document + void storeShape(std::shared_ptr theData, + std::shared_ptr theResult, + std::shared_ptr theShape, + const int theResultIndex = 0); + //! returns the label of result by index; creates this label if it was not created before TDF_Label resultLabel(const std::shared_ptr& theFeatureData, const int theResultIndex); + //! Returns the label of result subshapes by index; creates this label if it was not created before + TDF_Label subShapeLabel(TDF_Label& theResultLabel, + const int theResultIndex); + //! Updates the results list of the feature basing on the current data tree //! theProcessed is used to avoid update twice (since the function is recursive) void updateResults(FeaturePtr theFeature, std::set& theProcessed); diff --git a/src/Model/Model_ResultBody.cpp b/src/Model/Model_ResultBody.cpp index f6bc7d31a..c3915e428 100644 --- a/src/Model/Model_ResultBody.cpp +++ b/src/Model/Model_ResultBody.cpp @@ -38,6 +38,10 @@ #include #include #include +#include +#include +#include + // if this attribute exists, the shape is connected topology Standard_GUID kIsConnectedTopology("e51392e0-3a4d-405d-8e36-bbfe19858ef5"); @@ -249,6 +253,49 @@ void Model_ResultBody::updateConcealment() } } +void Model_ResultBody::setSubShapeEdgeThickness( + const std::shared_ptr theResult, + const std::shared_ptr theSubShape, + int theEdgeThickness +) +{ + TopoDS_Shape aShape = shape()->impl(); + TopoDS_Shape aSubShape = theSubShape->impl(); + if (!shape()->isSubShape(theSubShape)) + return; + + Model_Objects* anObjects = std::dynamic_pointer_cast(document())->objects(); + document()->storeShape(data(), theResult, theSubShape); + + Handle(TDataStd_Integer) aThickness = new TDataStd_Integer(); + aThickness->Set(theEdgeThickness); + anObjects->setAttribute(aThickness, theResult, theSubShape); +} + +int Model_ResultBody::getSubShapeEdgeThickness(const std::shared_ptr theResult, const std::shared_ptr theSubShape) const +{ + TopoDS_Shape aShape = shape()->impl(); + TopoDS_Shape aSubShape = theSubShape->impl(); + if (!shape()->isSubShape(theSubShape)) + return -1; + + Model_Objects* anObjects = std::dynamic_pointer_cast(document())->objects(); + auto anAttr = Handle(TDataStd_Integer)::DownCast(anObjects->getAttribute(TDataStd_Integer::GetID(), theResult, theSubShape)); + if (anAttr.IsNull()) + return; + + return anAttr->Get(); +} + +void Model_ResultBody::getSubShapesWithEdgeThickness( + const std::shared_ptr theResult, + std::map, int>& oShapes +) const +{ + Model_Objects* anObjects = std::dynamic_pointer_cast(document())->objects(); + anObjects->getSubShapesWithEdgeThickness(theResult, oShapes); +} + void Model_ResultBody::addShapeColor( const std::wstring& theName,std::vector& color) { if (myColorsShape.find(theName) == myColorsShape.end()) @@ -497,6 +544,12 @@ static void collectSubs( } } +void Model_ResultBody::removeSubShapeEdgeThickness(const std::shared_ptr theResult) +{ + Model_Objects* anObjects = std::dynamic_pointer_cast(document())->objects(); + anObjects->removeSubShapeEdgeThickness(theResult); +} + void Model_ResultBody::computeOldForSub(const GeomShapePtr& theSub, const std::list& theAllOlds, std::list& theOldForSub) { diff --git a/src/Model/Model_ResultBody.h b/src/Model/Model_ResultBody.h index bda42cdf5..315748913 100644 --- a/src/Model/Model_ResultBody.h +++ b/src/Model/Model_ResultBody.h @@ -139,6 +139,21 @@ protected: /// Checks the state of children and parents to send events of creation/erase when needed void updateConcealment(); + void setSubShapeEdgeThickness( + const std::shared_ptr theResult, + const std::shared_ptr theSubShape, + int theEdgeThickness + ); + + int getSubShapeEdgeThickness(const std::shared_ptr theResult, const std::shared_ptr theSubShape) const; + + void getSubShapesWithEdgeThickness( + const std::shared_ptr theResult, + std::map, int>& oSubShapes + ) const; + + void removeSubShapeEdgeThickness(const std::shared_ptr theResult); + /// Adds to theOldForSub only old shapes that where used for theSub creation void computeOldForSub(const GeomShapePtr& theSub, const std::list& theAllOlds, std::list& theOldForSub); diff --git a/src/Model/Model_ResultPart.cpp b/src/Model/Model_ResultPart.cpp index 43bc45c12..91fdda8b5 100644 --- a/src/Model/Model_ResultPart.cpp +++ b/src/Model/Model_ResultPart.cpp @@ -25,12 +25,14 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include #include #include @@ -44,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -431,6 +434,48 @@ std::shared_ptr Model_ResultPart::shapeInPart( return aResult; } +void Model_ResultPart::setSubShapeEdgeThickness(const std::shared_ptr& theSubShape, int theThickness) +{ + TopoDS_Shape aShape = shape()->impl(); + TopoDS_Shape aSubShape = theSubShape->impl(); + if (!shape()->isSubShape(theSubShape)) + return; + + Model_Objects* anObjects = std::dynamic_pointer_cast(document())->objects(); + + document()->storeShape(data(), original(), theSubShape); + Handle(TDataStd_Integer) aThickness = new TDataStd_Integer(); + aThickness->Set(theThickness); + anObjects->setAttribute(aThickness, original(), theSubShape); +} + +int Model_ResultPart::getSubShapeEdgeThickness(const std::shared_ptr& theSubShape) const +{ + TopoDS_Shape aShape = shape()->impl(); + TopoDS_Shape aSubShape = theSubShape->impl(); + if (!shape()->isSubShape(theSubShape)) + return; + + Model_Objects* anObjects = std::dynamic_pointer_cast(document())->objects(); + Handle(TDataStd_Integer) anAttr = Handle(TDataStd_Integer)::DownCast(anObjects->getAttribute(TDataStd_Integer::GetID(), original(), theSubShape)); + if (anAttr.IsNull()) + return; + + return anAttr->Get(); +} + +void Model_ResultPart::getSubShapesWithEdgeThickness(std::map, int>& oShapes) +{ + Model_Objects* anObjects = std::dynamic_pointer_cast(document())->objects(); + anObjects->getSubShapesWithEdgeThickness(original(), oShapes); +} + +void Model_ResultPart::removeSubShapeEdgeThickness() +{ + Model_Objects* anObjects = std::dynamic_pointer_cast(document())->objects(); + anObjects->removeSubShapeEdgeThickness(original()); +} + std::shared_ptr Model_ResultPart::selectionValue(const int theIndex) { std::shared_ptr aResult; diff --git a/src/Model/Model_ResultPart.h b/src/Model/Model_ResultPart.h index 172bf8bed..7c1d2551f 100644 --- a/src/Model/Model_ResultPart.h +++ b/src/Model/Model_ResultPart.h @@ -78,6 +78,15 @@ class Model_ResultPart : public ModelAPI_ResultPart /// Returns the shape by the name in the part MODEL_EXPORT virtual std::shared_ptr shapeInPart( const std::wstring& theName, const std::string& theType, int& theIndex); + + MODEL_EXPORT virtual void setSubShapeEdgeThickness(const std::shared_ptr& theSubShape, int theThickness); + + MODEL_EXPORT virtual int getSubShapeEdgeThickness(const std::shared_ptr& theSubShape) const; + + MODEL_EXPORT virtual void getSubShapesWithEdgeThickness(std::map, int>& oSubShapes); + + MODEL_EXPORT virtual void removeSubShapeEdgeThickness(); + /// Updates the selection inside of the part as a geometrical selection MODEL_EXPORT virtual bool combineGeometrical(const int theIndex, std::wstring& theNewName); /// Updates the shape-result of the part (called on Part feature execution) diff --git a/src/ModelAPI/ModelAPI_Document.h b/src/ModelAPI/ModelAPI_Document.h index acec2b808..f07b86c5d 100644 --- a/src/ModelAPI/ModelAPI_Document.h +++ b/src/ModelAPI/ModelAPI_Document.h @@ -109,6 +109,14 @@ public: virtual const int index(std::shared_ptr theObject, const bool theAllowFolder = false) = 0; + //! Returns the shape index in the result. + //! \param theResult result + //! \param theShape result subshape + //! \returns index started from zero, or -1 if shape is not stored or is not a subshape of the result + virtual const int index(std::shared_ptr theResult, + std::shared_ptr theShape, + const bool theAllowFolder = false) = 0; + //! Returns the number of objects in the group of objects //! \param theGroupID group of objects //! \param theAllowFolder take into account grouping feature by folders @@ -251,6 +259,11 @@ public: /// Appends the values to theStates list. MODELAPI_EXPORT virtual void restoreNodesState(std::list& theStates) const = 0; + /// Store Shape from Result to document + MODELAPI_EXPORT virtual void storeShape(const std::shared_ptr theData, + const std::shared_ptr theResult, + const std::shared_ptr theShape) = 0; + /// Just removes all features without touching the document data (to be able undo) MODELAPI_EXPORT virtual void eraseAllFeatures() = 0; diff --git a/src/ModelAPI/ModelAPI_ResultBody.h b/src/ModelAPI/ModelAPI_ResultBody.h index 223c91d55..a9d106820 100644 --- a/src/ModelAPI/ModelAPI_ResultBody.h +++ b/src/ModelAPI/ModelAPI_ResultBody.h @@ -216,6 +216,24 @@ public: MODELAPI_EXPORT virtual const std::vector& findShapeColor( const std::wstring& theShapeName) = 0; + MODELAPI_EXPORT virtual void setSubShapeEdgeThickness( + const std::shared_ptr theResult, + const std::shared_ptr theSubShape, + int theEdgeThickness + ) = 0; + + MODELAPI_EXPORT virtual int getSubShapeEdgeThickness( + const std::shared_ptr theResult, + const std::shared_ptr theSubShape + ) const = 0; + + MODELAPI_EXPORT virtual void getSubShapesWithEdgeThickness( + const std::shared_ptr theResult, + std::map, int>& oSubShapes + ) const = 0; + + MODELAPI_EXPORT virtual void removeSubShapeEdgeThickness(const std::shared_ptr theResult) = 0; + protected: /// Default constructor accessible only from Model_Objects diff --git a/src/ModelAPI/ModelAPI_ResultPart.h b/src/ModelAPI/ModelAPI_ResultPart.h index 148315a5f..2b23383f9 100644 --- a/src/ModelAPI/ModelAPI_ResultPart.h +++ b/src/ModelAPI/ModelAPI_ResultPart.h @@ -24,6 +24,8 @@ class GeomAPI_Trsf; #include +#include +#include /**\class ModelAPI_ResultPart * \ingroup DataModel @@ -89,6 +91,14 @@ class ModelAPI_ResultPart : public ModelAPI_Result virtual std::shared_ptr shapeInPart( const std::wstring& theName, const std::string& theType, int& theIndex) = 0; + virtual void setSubShapeEdgeThickness(const std::shared_ptr& theSubShape, int theThickness) = 0; + + virtual int getSubShapeEdgeThickness(const std::shared_ptr& theSubShape) const = 0; + + virtual void getSubShapesWithEdgeThickness(std::map, int>& oSubShapes) = 0; + + virtual void removeSubShapeEdgeThickness() = 0; + /// Updates the selection inside of the part as a geometrical selection virtual bool combineGeometrical(const int theIndex, std::wstring& theNewName) = 0; diff --git a/src/ModelAPI/ModelAPI_Tools.cpp b/src/ModelAPI/ModelAPI_Tools.cpp index 76af01b48..ee7afe9a1 100644 --- a/src/ModelAPI/ModelAPI_Tools.cpp +++ b/src/ModelAPI/ModelAPI_Tools.cpp @@ -519,6 +519,19 @@ ResultBodyPtr bodyOwner(const ResultPtr& theSub, const bool theRoot) return ResultBodyPtr(); // not found } +std::shared_ptr mainBody(const std::shared_ptr theSubBody) +{ + ResultBodyPtr aBody = theSubBody; + while (aBody.get()) + { // get the top-most main + ResultBodyPtr aNextBody = bodyOwner(aBody); + if (aNextBody.get()) + aBody = aNextBody; + else break; + } + return aBody; +} + int bodyIndex(const ResultPtr& theSub) { int anIndex = -1; @@ -1208,14 +1221,118 @@ int getEdgeThickness(const std::shared_ptr& theResult) return aThickness; } -void setEdgeThickness(ResultPtr theResult, int theEdgeThickness) +int getSubShapeEdgeThickness(const std::shared_ptr theResult, const std::shared_ptr theSubShape) +{ + if (!theResult || theSubShape->isNull()) + return -1; + + if (!theResult->shape()->isSubShape(theSubShape)) + return -1; + + auto resultBody = std::dynamic_pointer_cast(theResult); + if (resultBody) { + resultBody = mainBody(resultBody); + return resultBody->getSubShapeEdgeThickness(theResult, theSubShape); + } + else { + const auto resultPart = std::dynamic_pointer_cast(theResult); + if (!resultPart) + return -1; + + return resultPart->getSubShapeEdgeThickness(theSubShape); + } +} + +void getSubShapesWithEdgeThickness( + const std::shared_ptr theResult, + std::map, int>& oShapes, + bool theGetSubResults +) { + if (!theResult) + return; + + const auto resultBody = std::dynamic_pointer_cast(theResult); + if (resultBody) { + ResultBodyPtr mainBody = ModelAPI_Tools::mainBody(resultBody); + if (!mainBody) + return; + + if (theGetSubResults) { + std::list subResults; + allSubs(resultBody, subResults); + for (auto itSubRes = subResults.begin(); itSubRes != subResults.end(); ++itSubRes) { + mainBody->getSubShapesWithEdgeThickness(*itSubRes, oShapes); + } + } + + mainBody->getSubShapesWithEdgeThickness(theResult, oShapes); + } + else { + const auto resultPart = std::dynamic_pointer_cast(theResult); + if (!resultPart) + return; + + resultPart->getSubShapesWithEdgeThickness(oShapes); + } +} + +void removeSubShapeEdgeThickness(const std::shared_ptr theResult) +{ + if (!theResult) + return; + + auto resultBody = std::dynamic_pointer_cast(theResult); + if (resultBody) { + resultBody = mainBody(resultBody); + resultBody->removeSubShapeEdgeThickness(theResult); + } + else { + auto resultPart = std::dynamic_pointer_cast(theResult); + if (!resultPart) + return; + + resultPart->removeSubShapeEdgeThickness(); + } +} + +void setEdgeThickness(std::shared_ptr theResult, int theEdgeThickness) { if (!theResult) return; - AttributeIntegerPtr anAttribute = theResult->data()->integer(ModelAPI_Result::EDGE_THICKNESS_ID()); - if (anAttribute) + const AttributeIntegerPtr anAttribute = theResult->data()->integer(ModelAPI_Result::EDGE_THICKNESS_ID()); + if (anAttribute) { anAttribute->setValue(theEdgeThickness); + removeSubShapeEdgeThickness(theResult); + } +} + +void setSubShapeEdgeThickness( + std::shared_ptr theResult, + std::shared_ptr theSubShape, + int theEdgeThickness +) { + if (!theResult || theSubShape->isNull()) + return; + + if (!theResult->shape()->isSubShape(theSubShape)) + return; + + auto resultBody = std::dynamic_pointer_cast(theResult); + if (resultBody) { + resultBody = mainBody(resultBody); + resultBody->setSubShapeEdgeThickness(theResult, theSubShape, theEdgeThickness); + } + else { + const auto resultPart = std::dynamic_pointer_cast(theResult); + if (!resultPart) + return; + + resultPart->setSubShapeEdgeThickness(theSubShape, theEdgeThickness); + } + + static const Events_ID EVENT = Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY); + ModelAPI_EventCreator::get()->sendUpdated(theResult, EVENT); } //****************************************************** diff --git a/src/ModelAPI/ModelAPI_Tools.h b/src/ModelAPI/ModelAPI_Tools.h index f7eac8c7f..56b2a5d32 100644 --- a/src/ModelAPI/ModelAPI_Tools.h +++ b/src/ModelAPI/ModelAPI_Tools.h @@ -139,6 +139,10 @@ MODELAPI_EXPORT std::shared_ptr compositeOwner( */ MODELAPI_EXPORT std::shared_ptr bodyOwner(const std::shared_ptr& theSub, const bool theRoot = false); + +/*! \returns Root result body. */ +MODELAPI_EXPORT std::shared_ptr mainBody(const std::shared_ptr theSubBody); + /*! * Returns index of this result in parent (if parent exists, returned by bodyOwner) * \returns zero-base index, or -1 if not found @@ -312,18 +316,31 @@ MODELAPI_EXPORT void showEdgesDirection(std::shared_ptr theResu MODELAPI_EXPORT bool isShowEdgesDirection(std::shared_ptr theResult); -/*! Returns current edge thickness in the given result -* \param theResult a result object -* \return an egde thickness value or -1 if it was not defined -*/ +/*! \returns -1, if edge thickness is not defined. */ MODELAPI_EXPORT int getEdgeThickness(const std::shared_ptr& theResult); -/*! Set edge thickness for the given result -* \param theResult a result object -* \param theEdgeThickness edge thickness value -*/ -MODELAPI_EXPORT void setEdgeThickness(std::shared_ptr theResult, - int theEdgeThickness); +/*! \returns -1, if edge thickness is not defined. */ +MODELAPI_EXPORT int getSubShapeEdgeThickness(const std::shared_ptr theResult, const std::shared_ptr theSubShape); + +/*! \returns theResult subshapes with defined edge thickness. +* \param theSubResults - true, to include subshapes of subresults. */ +MODELAPI_EXPORT void getSubShapesWithEdgeThickness( + const std::shared_ptr theResult, + std::map,int>& oShapes, + bool theGetSubResults = false +); + +/*! \brief Removes edge thickness data of result subshapes. */ +MODELAPI_EXPORT void removeSubShapeEdgeThickness(const std::shared_ptr theResult); + +MODELAPI_EXPORT void setEdgeThickness(std::shared_ptr theResult, int theEdgeThickness); + +/*! \param theShape belongs to theResult. */ +MODELAPI_EXPORT void setSubShapeEdgeThickness( + std::shared_ptr theResult, + std::shared_ptr theSubShape, + int theEdgeThickness +); /*! Set flag to bring result in front of other results * \param[in] theResult a result object diff --git a/src/PartSet/PartSet_Module.cpp b/src/PartSet/PartSet_Module.cpp index efc795171..0ed547e95 100644 --- a/src/PartSet/PartSet_Module.cpp +++ b/src/PartSet/PartSet_Module.cpp @@ -273,6 +273,9 @@ PartSet_Module::PartSet_Module(ModuleBase_IWorkshop* theWshop) Config_PropManager::registerProp("Visualization", "axis_arrow_size", "Trihedron arrows constant size", Config_Prop::IntSpin, "10"); + Config_PropManager::registerProp("Visualization", "result_subshape_with_edge_thickness", + "Set edge thickness of subshape of result", Config_Prop::Boolean, "true"); + Config_PropManager::registerProp("Windows", "use_hide_faces_panel", "Use HideFaces panel in operations", Config_Prop::Boolean, "false"); } diff --git a/src/XGUI/XGUI_Selection.cpp b/src/XGUI/XGUI_Selection.cpp index 7a80eb0a9..6e2ad3f7e 100644 --- a/src/XGUI/XGUI_Selection.cpp +++ b/src/XGUI/XGUI_Selection.cpp @@ -400,6 +400,46 @@ QObjectPtrList XGUI_Selection::selectedPresentations() const return aSelectedList; } +QMap> XGUI_Selection::selectedObjectsAndSubObjects() const +{ + QMap> aSelectedObjects; + + // Add all objects, which selected in Viewer + QList aValues = getSelected(ModuleBase_ISelection::Viewer); + foreach(ModuleBase_ViewerPrsPtr aPrs, aValues) + { + ResultPtr aResult = std::dynamic_pointer_cast(aPrs->object()); + GeomShapePtr aShape = aPrs->shape(); + + aSelectedObjects[aResult].push_back(aShape); + } + + // Add object, which selected in browser, but not selected in Viewer + QObjectPtrList anObjects = selectedObjects(); + foreach(ObjectPtr anObject, anObjects) + { + ResultBodyPtr aResultBody = std::dynamic_pointer_cast(anObject); + if (!aResultBody.get()) + continue; + GeomShapePtr aBodyShape = aResultBody->shape(); + + if (aSelectedObjects.contains(aResultBody)) + continue; + bool isContains = false; + foreach(GeomShapePtr aCurShape, aSelectedObjects[aResultBody]) + { + if (aCurShape->impl().IsEqual(aBodyShape->impl())) + { + isContains = true; + break; + } + } + if (!isContains) + aSelectedObjects[aResultBody].push_back(aBodyShape); + } + return aSelectedObjects; +} + //************************************************************** QModelIndexList XGUI_Selection::selectedIndexes() const { diff --git a/src/XGUI/XGUI_Selection.h b/src/XGUI/XGUI_Selection.h index 9cf5ea963..4056cd11d 100644 --- a/src/XGUI/XGUI_Selection.h +++ b/src/XGUI/XGUI_Selection.h @@ -66,6 +66,9 @@ class XGUI_EXPORT XGUI_Selection : public ModuleBase_ISelection /// Returns list of currently selected results virtual QObjectPtrList selectedPresentations() const; + /// Returns selected results and their selected subobjects. + virtual QMap> selectedObjectsAndSubObjects() const; + /// Returns list of currently selected QModelIndexes virtual QModelIndexList selectedIndexes() const; diff --git a/src/XGUI/XGUI_Workshop.cpp b/src/XGUI/XGUI_Workshop.cpp index 3932c53a1..ff3149b52 100644 --- a/src/XGUI/XGUI_Workshop.cpp +++ b/src/XGUI/XGUI_Workshop.cpp @@ -1786,6 +1786,7 @@ ModuleBase_IViewer* XGUI_Workshop::salomeViewer() const void XGUI_Workshop::onContextMenuCommand(const QString& theId, bool isChecked) { QObjectPtrList anObjects = mySelector->selection()->selectedObjects(); + QMap> aSelectedObjects = mySelector->selection()->selectedObjectsAndSubObjects(); if (theId == "DELETE_CMD") deleteObjects(); else if (theId == "CLEAN_HISTORY_CMD") @@ -1814,7 +1815,7 @@ void XGUI_Workshop::onContextMenuCommand(const QString& theId, bool isChecked) else if (theId == "TRANSPARENCY_CMD") changeTransparency(anObjects); else if (theId == "EDGE_THICKNESS_CMD") - changeEdgeThickness(anObjects); + changeEdgeThickness(aSelectedObjects); else if (theId == "SHOW_CMD") { showObjects(anObjects, true); mySelector->updateSelectionBy(ModuleBase_ISelection::Browser); @@ -2898,52 +2899,95 @@ void setEdgeThickness(int theThickness, const QObjectPtrList& theObjects) } //************************************************************** -void XGUI_Workshop::changeEdgeThickness(const QObjectPtrList& theObjects) +void XGUI_Workshop::changeEdgeThickness(const QMap>& theSelectedObjects) { - // 1. Get current value. - int currentValue = -1; - foreach(ObjectPtr object, theObjects) { - ResultPtr result = std::dynamic_pointer_cast(object); + // 1. Find current thickness - thickness of AIS presentation. + // The objects are iterated until a first valid thickness is found. + int thickness; + const bool isSubShapeWithEdgeThickness = Config_PropManager::boolean("Visualization", "result_subshape_with_edge_thickness"); + foreach(ResultPtr result, theSelectedObjects.keys()) { if (!result) continue; - currentValue = ModelAPI_Tools::getEdgeThickness(result); - if (currentValue < 0) - currentValue = getDefaultEdgeThickness(); + foreach(GeomShapePtr shape, theSelectedObjects[result]) { + if (result->shape()->impl().IsEqual(shape->impl()) || !isSubShapeWithEdgeThickness) + thickness = ModelAPI_Tools::getEdgeThickness(result); + else if (!shape->isNull()) { + thickness = ModelAPI_Tools::getSubShapeEdgeThickness(result, shape); + if (thickness < 0) + thickness = ModelAPI_Tools::getEdgeThickness(result); + } + + if (thickness < 0) { + AISObjectPtr anAISObj = myDisplayer->getAISObject(result); + if (anAISObj) + thickness = anAISObj->width(); + } + + if (thickness < 0) + thickness = getDefaultEdgeThickness(); + + if (thickness >= 0 || !isSubShapeWithEdgeThickness) + break; + } - if (currentValue > 0) + if (thickness >= 0) break; } - if (currentValue < 0) + + if (thickness < 0) return; if (!abortAllOperations()) return; - // 2. Show the dialog. const auto dialog = new XGUI_PropertyDialog(desktop()); dialog->setWindowTitle(tr("Edge Thickness")); XGUI_EdgeThicknessWidget* edgeThicknessWidget = new XGUI_EdgeThicknessWidget(dialog); connect(edgeThicknessWidget, SIGNAL(thicknessValueChanged()), this, SLOT(onEdgeThicknessValueChanged())); dialog->setContent(edgeThicknessWidget); - aEdgeThicknessWidget->setValue(currentValue); + edgeThicknessWidget->setValue(thickness); + + if (dialog->exec() != QDialog::Accepted) + return; - // 3. Abort the previous operation and start a new one. + // 3. Abort previous operation and start a new one. SessionPtr session = ModelAPI_Session::get(); QString description = contextMenuMgr()->action("EDGE_THICKNESS_CMD")->text(); session->startOperation(description.toStdString()); - if (dialog->exec() == QDialog::Accepted) { - // 4. Set the value to all results. - currentValue = edgeThicknessWidget->getValue(); - setEdgeThickness(currentValue, theObjects); - session->finishOperation(); - } else { - session->abortOperation(); - Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY)); + // 4. Set new value to all results and subshapes of results. + int newThickness = edgeThicknessWidget->getValue(); + foreach(ResultPtr result, theSelectedObjects.keys()) { + if (!result) + continue; + + ResultBodyPtr bodyResult = std::dynamic_pointer_cast(result); + foreach(GeomShapePtr shape, theSelectedObjects[result]) { + if (result->shape()->impl().IsEqual(shape->impl()) || !isSubShapeWithEdgeThickness) { + if (result) { + // Change edge thickness for all sub-solids. + std::list allSubResults; + ModelAPI_Tools::allSubs(bodyResult, allSubResults); + for (auto itSubRes = allSubResults.begin(); itSubRes != allSubResults.end(); itSubRes++) { + ModelAPI_Tools::setEdgeThickness(*itSubRes, newThickness); + } + + ModelAPI_Tools::setEdgeThickness(result, newThickness); + } + + if (!isSubShapeWithEdgeThickness) + break; + } + else if (!shape->isNull()) + ModelAPI_Tools::setSubShapeEdgeThickness(result, shape, newThickness); + } } + Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY)); + session->finishOperation(); updateCommandStatus(); + myViewerProxy->update(); } //************************************************************** @@ -2955,8 +2999,7 @@ void XGUI_Workshop::onEdgeThicknessValueChanged() QObjectPtrList anObjects = mySelector->selection()->selectedObjects(); setEdgeThickness(aWidget->getValue(), anObjects); - static const Events_ID kRedisplayEvent = - Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY); + static const Events_ID kRedisplayEvent = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY); Events_Loop::loop()->flush(kRedisplayEvent); myViewerProxy->update(); diff --git a/src/XGUI/XGUI_Workshop.h b/src/XGUI/XGUI_Workshop.h index 213e09275..09ea4c266 100644 --- a/src/XGUI/XGUI_Workshop.h +++ b/src/XGUI/XGUI_Workshop.h @@ -224,7 +224,7 @@ Q_OBJECT /// Change edge thickness of the results if it is possible. /// The operation is available for construction, body and group results. /// \param theObjects refers to selected objects. - void changeEdgeThickness(const QObjectPtrList& theObjects); + void changeEdgeThickness(const QMap>& theObjects); /// Change number of iso-lines for the given objects /// theObjects a list of selected objects @@ -457,7 +457,7 @@ signals: /// Apply the current transparency value if preview in transparency dialog is switched on void onTransparencyValueChanged(); - + void onEdgeThicknessValueChanged(); protected: -- 2.39.2