X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FModel%2FModel_AttributeSelection.cpp;h=b2a4989dbac571ec9fd730f31e95d13bb0a46b5d;hb=bdbfb368d71ed11cc0391354a7d86c880cd94949;hp=cf482e2df5b9ba2ea221c7234e61bedd9e7b803e;hpb=8193b76f73047e852eaecfb4c0ff86cf44e1f8c9;p=modules%2Fshaper.git diff --git a/src/Model/Model_AttributeSelection.cpp b/src/Model/Model_AttributeSelection.cpp index cf482e2df..b2a4989db 100644 --- a/src/Model/Model_AttributeSelection.cpp +++ b/src/Model/Model_AttributeSelection.cpp @@ -11,57 +11,36 @@ #include "Model_Document.h" #include "Model_SelectionNaming.h" #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 #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 -using namespace std; //#define DEB_NAMING 1 #ifdef DEB_NAMING #include @@ -71,8 +50,6 @@ using namespace std; static const int kSTART_VERTEX_DELTA = 1000000; // identifier that there is simple reference: selection equals to context Standard_GUID kSIMPLE_REF_ID("635eacb2-a1d6-4dec-8348-471fae17cb29"); -// simple reference in the construction -Standard_GUID kCONSTUCTION_SIMPLE_REF_ID("635eacb2-a1d6-4dec-8348-471fae17cb28"); // reference to Part sub-object Standard_GUID kPART_REF_ID("635eacb2-a1d6-4dec-8348-471fae17cb27"); // selection is invalid after recomputation @@ -110,7 +87,6 @@ void Model_AttributeSelection::setValue(const ResultPtr& theContext, // do noth use naming if selected shape is result shape itself, but not sub-shape TDF_Label aSelLab = selectionLabel(); aSelLab.ForgetAttribute(kSIMPLE_REF_ID); - aSelLab.ForgetAttribute(kCONSTUCTION_SIMPLE_REF_ID); aSelLab.ForgetAttribute(kINVALID_SELECTION); bool isDegeneratedEdge = false; @@ -130,7 +106,7 @@ void Model_AttributeSelection::setValue(const ResultPtr& theContext, if (theContext->groupName() == ModelAPI_ResultBody::group()) { // do not select the whole shape for body:it is already must be in the data framework // equal and null selected objects mean the same: object is equal to context, - if (theContext->shape().get() && + if (theContext->shape().get() && (theContext->shape()->isEqual(theSubShape) || !theSubShape.get())) { aSelLab.ForgetAllAttributes(true); TDataStd_UAttribute::Set(aSelLab, kSIMPLE_REF_ID); @@ -138,54 +114,37 @@ void Model_AttributeSelection::setValue(const ResultPtr& theContext, selectBody(theContext, theSubShape); } } else if (theContext->groupName() == ModelAPI_ResultConstruction::group()) { - if (!theSubShape.get()) { - // to sub, so the whole result is selected - aSelLab.ForgetAllAttributes(true); - TDataStd_UAttribute::Set(aSelLab, kCONSTUCTION_SIMPLE_REF_ID); - ResultConstructionPtr aConstruction = - std::dynamic_pointer_cast(theContext); - if (aConstruction->isInfinite()) { - // For correct naming selection, put the shape into the naming structure. - // It seems sub-shapes are not needed: only this shape is (and can be ) selected. - TNaming_Builder aBuilder(aSelLab); - aBuilder.Generated(theContext->shape()->impl()); - std::shared_ptr aMyDoc = - std::dynamic_pointer_cast(owner()->document()); - //std::string aName = contextName(theContext); - // for selection in different document, add the document name - //aMyDoc->addNamingName(aSelLab, aName); - //TDataStd_Name::Set(aSelLab, aName.c_str()); - } else { // for sketch the naming is needed in DS - BRep_Builder aCompoundBuilder; - TopoDS_Compound aComp; - aCompoundBuilder.MakeCompound(aComp); - for(int a = 0; a < aConstruction->facesNum(); a++) { - TopoDS_Shape aFace = aConstruction->face(a)->impl(); - aCompoundBuilder.Add(aComp, aFace); - } - std::shared_ptr aShape(new GeomAPI_Shape); - aShape->setImpl(new TopoDS_Shape(aComp)); - selectConstruction(theContext, aShape); - } - } else { - selectConstruction(theContext, theSubShape); - } + aSelLab.ForgetAllAttributes(true); // to remove old selection data + std::shared_ptr aConstruction = + std::dynamic_pointer_cast(theContext); + std::shared_ptr aSubShape; + if (theSubShape.get() && !theContext->shape()->isEqual(theSubShape)) + aSubShape = theSubShape; // the whole context + int anIndex = aConstruction->select(theSubShape, owner()->document()); + TDataStd_Integer::Set(aSelLab, anIndex); } else if (theContext->groupName() == ModelAPI_ResultPart::group()) { aSelLab.ForgetAllAttributes(true); TDataStd_UAttribute::Set(aSelLab, kPART_REF_ID); selectPart(theContext, theSubShape); } - //the attribute initialized state should be changed by sendAttributeUpdated only - //myIsInitialized = true; owner()->data()->sendAttributeUpdated(this); } +void Model_AttributeSelection::removeTemporaryValues() +{ + if (myTmpContext.get() || myTmpSubShape.get()) { + myTmpContext.reset(); + myTmpSubShape.reset(); + } +} + std::shared_ptr Model_AttributeSelection::value() { GeomShapePtr aResult; if (myTmpContext.get() || myTmpSubShape.get()) { - ResultConstructionPtr aResulConstruction = std::dynamic_pointer_cast(myTmpContext); + ResultConstructionPtr aResulConstruction = + std::dynamic_pointer_cast(myTmpContext); if(aResulConstruction.get()) { // it is just reference to construction. return myTmpSubShape; @@ -200,28 +159,25 @@ std::shared_ptr Model_AttributeSelection::value() if (myRef.isInitialized()) { if (aSelLab.IsAttribute(kSIMPLE_REF_ID)) { // it is just reference to shape, not sub-shape ResultPtr aContext = context(); - if (!aContext.get()) + if (!aContext.get()) return aResult; // empty result return aContext->shape(); } - if (aSelLab.IsAttribute(kCONSTUCTION_SIMPLE_REF_ID)) { // it is just reference to construction, nothing is in value - return aResult; // empty result - } 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 Handle(TDataStd_Integer) anIndex; - if (selectionLabel().FindAttribute(TDataStd_Integer::GetID(), anIndex)) { + if (aSelLab.FindAttribute(TDataStd_Integer::GetID(), anIndex)) { if (anIndex->Get()) { // special selection attribute was created, use it return aPart->selectionValue(anIndex->Get()); } else { // face with name is already in the data model, so try to take it by name Handle(TDataStd_Name) aName; - if (selectionLabel().FindAttribute(TDataStd_Name::GetID(), aName)) { + if (aSelLab.FindAttribute(TDataStd_Name::GetID(), aName)) { std::string aSubShapeName(TCollection_AsciiString(aName->Get()).ToCString()); std::size_t aPartEnd = aSubShapeName.find('/'); - if (aPartEnd != string::npos && aPartEnd != aSubShapeName.rfind('/')) { - string aNameInPart = aSubShapeName.substr(aPartEnd + 1); + 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); @@ -232,15 +188,20 @@ std::shared_ptr Model_AttributeSelection::value() } Handle(TNaming_NamedShape) aSelection; - if (selectionLabel().FindAttribute(TNaming_NamedShape::GetID(), aSelection)) { + if (aSelLab.FindAttribute(TNaming_NamedShape::GetID(), aSelection)) { TopoDS_Shape aSelShape = aSelection->Get(); aResult = std::shared_ptr(new GeomAPI_Shape); aResult->setImpl(new TopoDS_Shape(aSelShape)); } else { // for simple construction element: just shape of this construction element - ResultConstructionPtr aConstr = - std::dynamic_pointer_cast(context()); + std::shared_ptr aConstr = + std::dynamic_pointer_cast(context()); if (aConstr) { - return aConstr->shape(); + 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()); + } } } } @@ -262,18 +223,18 @@ bool Model_AttributeSelection::isInitialized() ResultPtr aContext = context(); return aContext.get() != NULL; } - if (aSelLab.IsAttribute(kCONSTUCTION_SIMPLE_REF_ID)) { // it is just reference to construction, nothing is in value - return true; - } - Handle(TNaming_NamedShape) aSelection; if (selectionLabel().FindAttribute(TNaming_NamedShape::GetID(), aSelection)) { return !aSelection->Get().IsNull(); } else { // for simple construction element: just shape of this construction element - ResultConstructionPtr aConstr = - std::dynamic_pointer_cast(context()); + std::shared_ptr aConstr = + std::dynamic_pointer_cast(context()); if (aConstr.get()) { - return aConstr->shape().get() != NULL; + Handle(TDataStd_Integer) anIndex; + if (aSelLab.FindAttribute(TDataStd_Integer::GetID(), anIndex)) { + // for the whole shape it may return null, so, if index exists, returns true + return true; + } } } } @@ -285,6 +246,7 @@ Model_AttributeSelection::Model_AttributeSelection(TDF_Label& theLabel) : myRef(theLabel) { myIsInitialized = myRef.isInitialized(); + myParent = NULL; } void Model_AttributeSelection::setID(const std::string theID) @@ -332,7 +294,7 @@ TDF_LabelMap& Model_AttributeSelection::scope() std::list > allFeatures = aMyDoc->allFeatures(); std::list >::iterator aFIter = allFeatures.begin(); bool aMePassed = false; - CompositeFeaturePtr aComposite = + CompositeFeaturePtr aComposite = std::dynamic_pointer_cast(owner()); FeaturePtr aFeature = std::dynamic_pointer_cast(owner()); CompositeFeaturePtr aCompositeOwner, aCompositeOwnerOwner; @@ -351,7 +313,8 @@ TDF_LabelMap& Model_AttributeSelection::scope() } if (isGroup) aMePassed = false; bool isInScope = !aMePassed; - if (!isInScope && aComposite.get()) { // try to add sub-elements of composite if this is composite + if (!isInScope && aComposite.get()) { + // try to add sub-elements of composite if this is composite if (aComposite->isSub(*aFIter)) isInScope = true; } @@ -362,7 +325,7 @@ TDF_LabelMap& Model_AttributeSelection::scope() if (isInScope && aFIter->get() && (*aFIter)->data()->isValid()) { TDF_Label aFeatureLab = std::dynamic_pointer_cast( (*aFIter)->data())->label().Father(); - TDF_ChildIDIterator aNSIter(aFeatureLab, TNaming_NamedShape::GetID(), 1); + TDF_ChildIDIterator aNSIter(aFeatureLab, TNaming_NamedShape::GetID(), true); for(; aNSIter.More(); aNSIter.Next()) { Handle(TNaming_NamedShape) aNS = Handle(TNaming_NamedShape)::DownCast(aNSIter.Value()); if (!aNS.IsNull() && aNS->Evolution() != TNaming_SELECTED) { @@ -371,6 +334,16 @@ TDF_LabelMap& Model_AttributeSelection::scope() } } } + // also add all naming labels created for external constructions + std::shared_ptr aDoc = std::dynamic_pointer_cast(aMyDoc); + TDF_Label anExtDocLab = aDoc->extConstructionsLabel(); + TDF_ChildIDIterator aNSIter(anExtDocLab, TNaming_NamedShape::GetID(), true); + for(; aNSIter.More(); aNSIter.Next()) { + Handle(TNaming_NamedShape) aNS = Handle(TNaming_NamedShape)::DownCast(aNSIter.Value()); + if (!aNS.IsNull() && aNS->Evolution() != TNaming_SELECTED) { + myScope.Add(aNS->Label()); + } + } } return myScope; } @@ -386,43 +359,41 @@ static bool setInvalidIfFalse(TDF_Label& theLab, const bool theFlag) { return theFlag; } +void Model_AttributeSelection::split( + ResultPtr theContext, TopoDS_Shape theNewShape, TopAbs_ShapeEnum theType) +{ + TopTools_ListOfShape aSubs; + for(TopoDS_Iterator anExplorer(theNewShape); anExplorer.More(); anExplorer.Next()) { + if (!anExplorer.Value().IsNull() && + anExplorer.Value().ShapeType() == theType) { + aSubs.Append(anExplorer.Value()); + } else { // invalid case; bad result shape, so, impossible to split easily + aSubs.Clear(); + break; + } + } + if (aSubs.Extent() > 1) { // ok to split + TopTools_ListIteratorOfListOfShape aSub(aSubs); + GeomShapePtr aSubSh(new GeomAPI_Shape); + aSubSh->setImpl(new TopoDS_Shape(aSub.Value())); + setValue(theContext, aSubSh); + for(aSub.Next(); aSub.More(); aSub.Next()) { + GeomShapePtr aSubSh(new GeomAPI_Shape); + aSubSh->setImpl(new TopoDS_Shape(aSub.Value())); + myParent->append(theContext, aSubSh); + } + } +} + bool Model_AttributeSelection::update() { TDF_Label aSelLab = selectionLabel(); ResultPtr aContext = context(); - if (!aContext.get()) + if (!aContext.get()) return setInvalidIfFalse(aSelLab, false); if (aSelLab.IsAttribute(kSIMPLE_REF_ID)) { // it is just reference to shape, not sub-shape return setInvalidIfFalse(aSelLab, aContext->shape() && !aContext->shape()->isNull()); } - if (aSelLab.IsAttribute(kCONSTUCTION_SIMPLE_REF_ID)) { // it is just reference to construction, not sub-shape - // if there is a sketch, the sketch-naming must be updated - ResultConstructionPtr aConstruction = - std::dynamic_pointer_cast(aContext); - if (!aConstruction->isInfinite()) { - BRep_Builder aCompoundBuilder; - TopoDS_Compound aComp; - aCompoundBuilder.MakeCompound(aComp); - for(int a = 0; a < aConstruction->facesNum(); a++) { - TopoDS_Shape aFace = aConstruction->face(a)->impl(); - aCompoundBuilder.Add(aComp, aFace); - } - std::shared_ptr aShape(new GeomAPI_Shape); - aShape->setImpl(new TopoDS_Shape(aComp)); - selectConstruction(aContext, aShape); - } else { - // For correct naming selection, put the shape into the naming structure. - // It seems sub-shapes are not needed: only this shape is (and can be ) selected. - TNaming_Builder aBuilder(aSelLab); - aBuilder.Generated(aContext->shape()->impl()); - std::shared_ptr aMyDoc = - std::dynamic_pointer_cast(owner()->document()); - //std::string aName = contextName(aContext); - //aMyDoc->addNamingName(aSelLab, aName); - //TDataStd_Name::Set(aSelLab, aName.c_str()); - } - return setInvalidIfFalse(aSelLab, aContext->shape() && !aContext->shape()->isNull()); - } if (aSelLab.IsAttribute(kPART_REF_ID)) { // it is reference to the part object std::shared_ptr aNoSelection; @@ -442,168 +413,37 @@ bool Model_AttributeSelection::update() anOldShape = aSelector.NamedShape()->Get(); } bool aResult = aSelector.Solve(scope()) == Standard_True; - aResult = setInvalidIfFalse(aSelLab, aResult); // must be before sending of updated attribute (1556) + // must be before sending of updated attribute (1556) + aResult = setInvalidIfFalse(aSelLab, aResult); TopoDS_Shape aNewShape; if (!aSelector.NamedShape().IsNull()) { aNewShape = aSelector.NamedShape()->Get(); } if (anOldShape.IsNull() || aNewShape.IsNull() || - !anOldShape.IsEqual(aSelector.NamedShape()->Get())) // send updated if shape is changed - owner()->data()->sendAttributeUpdated(this); - return aResult; - } else if (aContext->groupName() == ModelAPI_ResultConstruction::group()) { - // construction: identification by the results indexes, recompute faces and - // take the face that more close by the indexes - ResultConstructionPtr aConstructionContext = - std::dynamic_pointer_cast(aContext); - FeaturePtr aContextFeature = aContext->document()->feature(aContext); - // sketch sub-element - if (aConstructionContext && - std::dynamic_pointer_cast(aContextFeature).get()) - { - TDF_Label aLab = myRef.myRef->Label(); - // getting a type of selected shape - Handle(TDataStd_Integer) aTypeAttr; - if (!aLab.FindAttribute(TDataStd_Integer::GetID(), aTypeAttr)) { - return setInvalidIfFalse(aSelLab, false); - } - TopAbs_ShapeEnum aShapeType = (TopAbs_ShapeEnum)(aTypeAttr->Get()); - // selected indexes will be needed in each "if" - Handle(TDataStd_IntPackedMap) aSubIds; - std::shared_ptr aNewSelected; - bool aNoIndexes = - !aLab.FindAttribute(TDataStd_IntPackedMap::GetID(), aSubIds) || aSubIds->Extent() == 0; - // for now working only with composite features - CompositeFeaturePtr aComposite = - std::dynamic_pointer_cast(aContextFeature); - if (!aComposite.get() || aComposite->numberOfSubs() == 0) { - return setInvalidIfFalse(aSelLab, false); + !anOldShape.IsEqual(aSelector.NamedShape()->Get())) { + // shape type shoud not not changed: if shape becomes compound of such shapes, then split + if (myParent && !anOldShape.IsNull() && !aNewShape.IsNull() && + anOldShape.ShapeType() != aNewShape.ShapeType() && + (aNewShape.ShapeType() == TopAbs_COMPOUND || aNewShape.ShapeType() == TopAbs_COMPSOLID)) + { + split(aContext, aNewShape, anOldShape.ShapeType()); } + owner()->data()->sendAttributeUpdated(this); // send updated if shape is changed + } + return aResult; + } - if (aShapeType == TopAbs_FACE || aShapeType == TopAbs_WIRE) { // compound is for the whole sketch selection - // If this is a wire with plane defined then it is a sketch-like object - if (!aConstructionContext->facesNum()) // no faces, update can not work correctly - return setInvalidIfFalse(aSelLab, false); - // if there is no edges indexes, any face can be used: take the first - std::shared_ptr aNewSelected; - if (aNoIndexes) { - aNewSelected = aConstructionContext->face(0); - } else { // searching for most looks-like initial face by the indexes - // prepare edges of the current result for the fast searching - NCollection_DataMap allCurves; // curves and orientations of edges - const int aSubNum = aComposite->numberOfSubs(); - for(int a = 0; a < aSubNum; a++) { - int aSubID = aComposite->subFeatureId(a); - if (aSubIds->Contains(aSubID)) { - FeaturePtr aSub = aComposite->subFeature(a); - const std::list >& aResults = aSub->results(); - std::list >::const_iterator aRes; - for(aRes = aResults.cbegin(); aRes != aResults.cend(); aRes++) { - ResultConstructionPtr aConstr = - std::dynamic_pointer_cast(*aRes); - if (aConstr->shape() && aConstr->shape()->isEdge()) { - const TopoDS_Shape& aResShape = aConstr->shape()->impl(); - TopoDS_Edge anEdge = TopoDS::Edge(aResShape); - if (!anEdge.IsNull()) { - Standard_Real aFirst, aLast; - Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast); - // searching for orientation information - int anOrient = 0; - Handle(TDataStd_Integer) anInt; - if (aSelLab.FindChild(aSubID).FindAttribute(TDataStd_Integer::GetID(), anInt)){ - anOrient = anInt->Get(); - } - allCurves.Bind(aCurve, anOrient); - } - } - } - } - } - aNewSelected = Model_SelectionNaming::findAppropriateFace( - aContext, allCurves, aShapeType == TopAbs_WIRE); - } - if (aNewSelected) { // store this new selection - selectConstruction(aContext, aNewSelected); - setInvalidIfFalse(aSelLab, true); - owner()->data()->sendAttributeUpdated(this); - return true; - } else { // if the selection is not found, put the empty shape: it's better to have disappeared shape, than the old, the lost one - TNaming_Builder anEmptyBuilder(selectionLabel()); - return setInvalidIfFalse(aSelLab, false); - } - } else if (aShapeType == TopAbs_EDGE) { - // just reselect the edge by the id - const int aSubNum = aComposite->numberOfSubs(); - for(int a = 0; a < aSubNum; a++) { - // if aSubIds take any, the first appropriate - if (aSubIds->IsEmpty() || aSubIds->Contains(aComposite->subFeatureId(a))) { - // found the appropriate feature - FeaturePtr aFeature = aComposite->subFeature(a); - std::list >::const_iterator aResIter = - aFeature->results().cbegin(); - for(;aResIter != aFeature->results().cend(); aResIter++) { - ResultConstructionPtr aRes = - std::dynamic_pointer_cast(*aResIter); - if (aRes && aRes->shape() && aRes->shape()->isEdge()) { // found! - selectConstruction(aContext, aRes->shape()); - setInvalidIfFalse(aSelLab, true); - owner()->data()->sendAttributeUpdated(this); - return true; - } - } - } - } - } else if (aShapeType == TopAbs_VERTEX) { - // just reselect the vertex by the id of edge - const int aSubNum = aComposite->numberOfSubs(); - for(int a = 0; a < aSubNum; a++) { - // if aSubIds take any, the first appropriate - int aFeatureID = aComposite->subFeatureId(a); - if (aSubIds->IsEmpty() || aSubIds->Contains(aFeatureID) || - aSubIds->Contains(aFeatureID + kSTART_VERTEX_DELTA) || - aSubIds->Contains(aFeatureID + kSTART_VERTEX_DELTA * 2)) { - // searching for deltas - int aVertexNum = 0; - if (aSubIds->Contains(aFeatureID + kSTART_VERTEX_DELTA)) aVertexNum = 1; - else if (aSubIds->Contains(aFeatureID + kSTART_VERTEX_DELTA * 2)) aVertexNum = 2; - // found the feature with appropriate edge - FeaturePtr aFeature = aComposite->subFeature(a); - std::list >::const_iterator aResIter = - aFeature->results().cbegin(); - for(;aResIter != aFeature->results().cend(); aResIter++) { - ResultConstructionPtr aRes = - std::dynamic_pointer_cast(*aResIter); - if (aRes && aRes->shape()) { - if (aRes->shape()->isVertex() && aVertexNum == 0) { // found! - selectConstruction(aContext, aRes->shape()); - setInvalidIfFalse(aSelLab, true); - owner()->data()->sendAttributeUpdated(this); - return true; - } else if (aRes->shape()->isEdge() && aVertexNum > 0) { - const TopoDS_Shape& anEdge = aRes->shape()->impl(); - int aVIndex = 1; - for(TopExp_Explorer aVExp(anEdge, TopAbs_VERTEX); aVExp.More(); aVExp.Next()) { - if (aVIndex == aVertexNum) { // found! - std::shared_ptr aVertex(new GeomAPI_Shape); - aVertex->setImpl(new TopoDS_Shape(aVExp.Current())); - selectConstruction(aContext, aVertex); - setInvalidIfFalse(aSelLab, true); - owner()->data()->sendAttributeUpdated(this); - return true; - } - aVIndex++; - } - } - } - } - } - } - } - } else { // simple construction element: the selected is that needed - selectConstruction(aContext, aContext->shape()); - setInvalidIfFalse(aSelLab, true); - owner()->data()->sendAttributeUpdated(this); - return true; + if (aContext->groupName() == ModelAPI_ResultConstruction::group()) { + Handle(TDataStd_Integer) anIndex; + if (aSelLab.FindAttribute(TDataStd_Integer::GetID(), anIndex)) { + std::shared_ptr aConstructionContext = + std::dynamic_pointer_cast(aContext); + bool aModified = true; + bool aValid = aConstructionContext->update(anIndex->Get(), owner()->document(), aModified); + setInvalidIfFalse(aSelLab, aValid); + if (aModified) + owner()->data()->sendAttributeUpdated(this); + return aValid; } } return setInvalidIfFalse(aSelLab, false); // unknown case @@ -616,11 +456,11 @@ void Model_AttributeSelection::selectBody( TNaming_Selector aSel(selectionLabel()); TopoDS_Shape aContext; - ResultBodyPtr aBody = std::dynamic_pointer_cast(myRef.value()); + ResultBodyPtr aBody = std::dynamic_pointer_cast(theContext);//myRef.value() if (aBody) { aContext = aBody->shape()->impl(); } else { - ResultPtr aResult = + ResultPtr aResult = std::dynamic_pointer_cast(myRef.value()); if (aResult) { aContext = aResult->shape()->impl(); @@ -635,9 +475,11 @@ void Model_AttributeSelection::selectBody( TDF_Label aSelLab = selectionLabel(); TopoDS_Shape aNewContext = aContext; bool isUpdated = true; - while(!aNewContext.IsNull() && isUpdated) { // searching for the very last shape that was produced from this one + while(!aNewContext.IsNull() && isUpdated) { + // searching for the very last shape that was produced from this one isUpdated = false; - if (!TNaming_Tool::HasLabel(aSelLab, aNewContext)) // to avoid crash of TNaming_SameShapeIterator if pure shape does not exists + if (!TNaming_Tool::HasLabel(aSelLab, aNewContext)) + // to avoid crash of TNaming_SameShapeIterator if pure shape does not exists break; for(TNaming_SameShapeIterator anIter(aNewContext, aSelLab); anIter.More(); anIter.Next()) { TDF_Label aNSLab = anIter.Label(); @@ -675,199 +517,37 @@ void Model_AttributeSelection::selectBody( } } if (!isFound) { // sub-shape is not found in the up-to-date instance of the context shape + // if context is sub-result of compound/compsolid, selection of sub-shape better propagate to + // the main result (which is may be modified), case is in 1799 + ResultCompSolidPtr aMain = ModelAPI_Tools::compSolidOwner(theContext); + if (aMain.get()) { + selectBody(aMain, theSubShape); + return; + } setInvalidIfFalse(aSelLab, false); - Events_InfoMessage("Model_AttributeSelection", "Failed to select sub-shape already modified").send(); + Events_InfoMessage("Model_AttributeSelection", + "Failed to select sub-shape already modified").send(); return; } } - /// fix for issue 411: result modified shapes must not participate in this selection mechanism - FeaturePtr aFeatureOwner = std::dynamic_pointer_cast(owner()); - if (aFeatureOwner.get()) - aFeatureOwner->eraseResults(); if (!aContext.IsNull()) { - aSel.Select(aNewSub, aNewContext); - } -} - -/// registers the name of the shape in the label (theID == 0) of sub label (theID is a tag) -/// if theID is zero, -/// theOrientation is additional information about the positioning of edge relatively to face -/// it is stored in the integer attribute of the edge sub-label: -/// -1 is out, 1 is in, 0 is not needed -static void registerSubShape(TDF_Label theMainLabel, TopoDS_Shape theShape, - const int theID, const FeaturePtr& theContextFeature, std::shared_ptr theDoc, - std::map& theOrientations, - std::map& theSubNames, // name of sub-elements by ID to be exported instead of indexes - Handle(TDataStd_IntPackedMap) theRefs = Handle(TDataStd_IntPackedMap)(), - const int theOrientation = 0) -{ - TDF_Label aLab = theID == 0 ? theMainLabel : theMainLabel.FindChild(theID); - if (theOrientation != 0) { // store the orientation of edge relatively to face if needed - TDataStd_Integer::Set(aLab, theOrientation); - } - TNaming_Builder aBuilder(aLab); - aBuilder.Generated(theShape); - std::stringstream aName; - // #1839 : do not store name of the feature in the tree, since this name could be changed - //aName<name(); - if (theShape.ShapeType() != TopAbs_COMPOUND) { // compound means the whole result for construction - //aName<<"/"; - if (theShape.ShapeType() == TopAbs_FACE) aName<<"Face"; - else if (theShape.ShapeType() == TopAbs_WIRE) aName<<"Wire"; - else if (theShape.ShapeType() == TopAbs_EDGE) aName<<"Edge"; - else if (theShape.ShapeType() == TopAbs_VERTEX) aName<<"Vertex"; - - if (theRefs.IsNull()) { - aName<GetMap()); - for(; aRef.More(); aRef.Next()) { - aName<<"-"<addNamingName(aLab, aName.str()); - TDataStd_Name::Set(aLab, aName.str().c_str()); -} - -void Model_AttributeSelection::selectConstruction( - const ResultPtr& theContext, const std::shared_ptr& theSubShape) -{ - std::shared_ptr aMyDoc = - std::dynamic_pointer_cast(owner()->document()); - FeaturePtr aContextFeature = theContext->document()->feature(theContext); - CompositeFeaturePtr aComposite = - std::dynamic_pointer_cast(aContextFeature); - const TopoDS_Shape& aSubShape = theSubShape->impl(); - if (!aComposite || aComposite->numberOfSubs() == 0) { - // saving of context is enough: result construction contains exactly the needed shape - TNaming_Builder aBuilder(selectionLabel()); - aBuilder.Generated(aSubShape); - //std::string aName = contextName(theContext); - //aMyDoc->addNamingName(selectionLabel(), aName); - //TDataStd_Name::Set(selectionLabel(), aName.c_str()); - return; - } - std::shared_ptr aData = std::dynamic_pointer_cast(owner()->data()); - TDF_Label aLab = myRef.myRef->Label(); - // identify the results of sub-object of the composite by edges - // save type of the selected shape in integer attribute - TopAbs_ShapeEnum aShapeType = aSubShape.ShapeType(); - TDataStd_Integer::Set(aLab, (int)aShapeType); - gp_Pnt aVertexPos; - TColStd_MapOfTransient allCurves; - if (aShapeType == TopAbs_VERTEX) { // compare positions - aVertexPos = BRep_Tool::Pnt(TopoDS::Vertex(aSubShape)); - } else { - for(TopExp_Explorer anEdgeExp(aSubShape, TopAbs_EDGE); anEdgeExp.More(); anEdgeExp.Next()) { - TopoDS_Edge anEdge = TopoDS::Edge(anEdgeExp.Current()); - Standard_Real aFirst, aLast; - Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast); - allCurves.Add(aCurve); + FeaturePtr aFeatureOwner = std::dynamic_pointer_cast(owner()); + bool aEraseResults = false; + if (aFeatureOwner.get()) { + aEraseResults = !aFeatureOwner->results().empty(); + if (aEraseResults) // erase results without flash deleted and redisplay: do it after Select + aFeatureOwner->removeResults(0, false, false); } - } - // iterate and store the result ids of sub-elements and sub-elements to sub-labels - Handle(TDataStd_IntPackedMap) aRefs = TDataStd_IntPackedMap::Set(aLab); - std::map anOrientations; //map from edges IDs to orientations of these edges in face - std::map aSubNames; //map from edges IDs to names of edges - aRefs->Clear(); - const int aSubNum = aComposite->numberOfSubs(); - for(int a = 0; a < aSubNum; a++) { - FeaturePtr aSub = aComposite->subFeature(a); - const std::list >& aResults = aSub->results(); - std::list >::const_iterator aRes = aResults.cbegin(); - // there may be many shapes (circle and center): register if at least one is in selection - for(; aRes != aResults.cend(); aRes++) { - ResultConstructionPtr aConstr = - std::dynamic_pointer_cast(*aRes); - if (!aConstr->shape()) { - continue; - } - if (aShapeType == TopAbs_VERTEX) { - if (aConstr->shape()->isVertex()) { // compare vertices positions - const TopoDS_Shape& aVertex = aConstr->shape()->impl(); - gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aVertex)); - if (aPnt.IsEqual(aVertexPos, Precision::Confusion())) { - aRefs->Add(aComposite->subFeatureId(a)); - aSubNames[aComposite->subFeatureId(a)] = Model_SelectionNaming::shortName(aConstr); - } - } else { // get first or last vertex of the edge: last is stored with additional delta - const TopoDS_Shape& anEdge = aConstr->shape()->impl(); - int aDelta = kSTART_VERTEX_DELTA; - for(TopExp_Explorer aVExp(anEdge, TopAbs_VERTEX); aVExp.More(); aVExp.Next()) { - gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aVExp.Current())); - if (aPnt.IsEqual(aVertexPos, Precision::Confusion())) { - aRefs->Add(aDelta + aComposite->subFeatureId(a)); - aSubNames[aDelta + aComposite->subFeatureId(a)] = - Model_SelectionNaming::shortName(aConstr, aDelta / kSTART_VERTEX_DELTA); - break; - } - aDelta += kSTART_VERTEX_DELTA; - } - } - } else { - if (aConstr->shape()->isEdge()) { - const TopoDS_Shape& aResShape = aConstr->shape()->impl(); - TopoDS_Edge anEdge = TopoDS::Edge(aResShape); - if (!anEdge.IsNull()) { - Standard_Real aFirst, aLast; - Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast); - if (allCurves.Contains(aCurve)) { - int anID = aComposite->subFeatureId(a); - aRefs->Add(anID); - aSubNames[anID] = Model_SelectionNaming::shortName(aConstr); - if (aShapeType != TopAbs_EDGE) { // face needs the sub-edges on sub-labels - // add edges to sub-label to support naming for edges selection - TopExp_Explorer anEdgeExp(aSubShape, TopAbs_EDGE); - for(; anEdgeExp.More(); anEdgeExp.Next()) { - TopoDS_Edge anEdge = TopoDS::Edge(anEdgeExp.Current()); - Standard_Real aFirst, aLast; - Handle(Geom_Curve) aFaceCurve = BRep_Tool::Curve(anEdge, aFirst, aLast); - if (aFaceCurve == aCurve) { - int anOrient = Model_SelectionNaming::edgeOrientation(aSubShape, anEdge); - anOrientations[anID] = anOrient; - registerSubShape( - selectionLabel(), anEdge, anID, aContextFeature, aMyDoc, anOrientations, - aSubNames, Handle(TDataStd_IntPackedMap)(), anOrient); - } - } - } else { // put vertices of the selected edge to sub-labels - // add edges to sub-label to support naming for edges selection - TopExp_Explorer anEdgeExp(aSubShape, TopAbs_VERTEX); - int aTagIndex = anID + kSTART_VERTEX_DELTA; - for(; anEdgeExp.More(); anEdgeExp.Next(), aTagIndex += kSTART_VERTEX_DELTA) { - TopoDS_Vertex aV = TopoDS::Vertex(anEdgeExp.Current()); + aSel.Select(aNewSub, aNewContext); - std::stringstream anAdditionalName; - registerSubShape( - selectionLabel(), aV, aTagIndex, aContextFeature, aMyDoc, anOrientations, - aSubNames); - } - } - } - } - } - } + if (aEraseResults) { // flash after Select : in Groups it makes selection with shift working + static Events_Loop* aLoop = Events_Loop::loop(); + static const Events_ID kDeletedEvent = aLoop->eventByName(EVENT_OBJECT_DELETED); + aLoop->flush(kDeletedEvent); } } - // store the selected as primitive - TNaming_Builder aBuilder(selectionLabel()); - aBuilder.Generated(aSubShape); - registerSubShape( - selectionLabel(), aSubShape, 0, aContextFeature, aMyDoc, anOrientations, aSubNames, aRefs); } bool Model_AttributeSelection::selectPart( @@ -879,7 +559,8 @@ bool Model_AttributeSelection::selectPart( return true; // postponed naming if (theUpdate) { Handle(TDataStd_Integer) anIndex; - if (selectionLabel().FindAttribute(TDataStd_Integer::GetID(), anIndex)) { // by internal selection + if (selectionLabel().FindAttribute(TDataStd_Integer::GetID(), anIndex)) { + // by internal selection if (anIndex->Get() > 0) { // update the selection by index return aPart->updateInPart(anIndex->Get()); @@ -921,6 +602,9 @@ std::string Model_AttributeSelection::namingName(const std::string& theDefaultNa std::shared_ptr aSubSh = value(); ResultPtr aCont = context(); + if (!aCont.get()) // in case of selection of removed result + return ""; + Model_SelectionNaming aSelNaming(selectionLabel()); return aSelNaming.namingName( aCont, aSubSh, theDefaultName, owner()->document() != aCont->document()); @@ -934,12 +618,12 @@ void Model_AttributeSelection::selectSubShape( // check this is Part-name: 2 delimiters in the name std::size_t aPartEnd = theSubShapeName.find('/'); - if (aPartEnd != string::npos && aPartEnd != theSubShapeName.rfind('/')) { + if (aPartEnd != std::string::npos && aPartEnd != theSubShapeName.rfind('/')) { std::string aPartName = theSubShapeName.substr(0, aPartEnd); ObjectPtr aFound = owner()->document()->objectByName(ModelAPI_ResultPart::group(), aPartName); if (aFound.get()) { // found such part, so asking it for the name ResultPartPtr aPart = std::dynamic_pointer_cast(aFound); - string aNameInPart = theSubShapeName.substr(aPartEnd + 1); + std::string aNameInPart = theSubShapeName.substr(aPartEnd + 1); int anIndex; std::shared_ptr aSelected = aPart->shapeInPart(aNameInPart, theType, anIndex); if (aSelected.get()) { @@ -951,12 +635,12 @@ void Model_AttributeSelection::selectSubShape( } Model_SelectionNaming aSelNaming(selectionLabel()); - std::shared_ptr aDoc = + std::shared_ptr aDoc = std::dynamic_pointer_cast(owner()->document()); std::shared_ptr aShapeToBeSelected; ResultPtr aCont; if (aSelNaming.selectSubShape(theType, theSubShapeName, aDoc, aShapeToBeSelected, aCont)) { - // try to find the last context to find the up to dat shape + // try to find the last context to find the up to date shape if (aCont->shape().get() && !aCont->shape()->isNull() && aCont->groupName() == ModelAPI_ResultBody::group() && aDoc == owner()->document()) { const TopoDS_Shape aConShape = aCont->shape()->impl(); @@ -979,7 +663,12 @@ void Model_AttributeSelection::selectSubShape( } } setValue(aCont, aShapeToBeSelected); + return; } + + TDF_Label aSelLab = selectionLabel(); + setInvalidIfFalse(aSelLab, false); + reset(); } int Model_AttributeSelection::Id() @@ -1082,7 +771,7 @@ void Model_AttributeSelection::updateInHistory() Handle(TNaming_NamedShape) aContNS; if (!aContLab.FindAttribute(TNaming_NamedShape::GetID(), aContNS)) return; - std::shared_ptr aDoc = + std::shared_ptr aDoc = std::dynamic_pointer_cast(aContext->document()); FeaturePtr aThisFeature = std::dynamic_pointer_cast(owner()); FeaturePtr aCurrentModifierFeat = aDoc->feature(aContext); @@ -1090,6 +779,8 @@ void Model_AttributeSelection::updateInHistory() // that this one and is really modifies the referenced result to refer to it ResultPtr aModifierResFound; TNaming_Iterator aPairIter(aContNS); + if (!aPairIter.More()) + return; TopoDS_Shape aNewShape = aPairIter.NewShape(); bool anIterate = true; // trying to update also the sub-shape selected @@ -1110,7 +801,8 @@ void Model_AttributeSelection::updateInHistory() break; if (aModifierFeat == aThisFeature || aDoc->objects()->isLater(aModifierFeat, aThisFeature)) continue; // the modifier feature is later than this, so, should not be used - if (aCurrentModifierFeat == aModifierFeat || aDoc->objects()->isLater(aCurrentModifierFeat, aModifierFeat)) + if (aCurrentModifierFeat == aModifierFeat || + aDoc->objects()->isLater(aCurrentModifierFeat, aModifierFeat)) continue; // the current modifier is later than the found, so, useless Handle(TNaming_NamedShape) aNewNS; aModifIter.Label().FindAttribute(TNaming_NamedShape::GetID(), aNewNS); @@ -1119,15 +811,6 @@ void Model_AttributeSelection::updateInHistory() aCurrentModifierFeat = aModifierFeat; TNaming_Iterator aPairIter(aNewNS); aNewShape = aPairIter.NewShape(); - /* - // searching for sub-shape equivalent on the sub-label of the new context result - TDF_ChildIDIterator aNSIter(aNewNS->Label(), TNaming_NamedShape::GetID()); - for(; aNSIter.More(); aNSIter.Next()) { - TNaming_Iterator aPairsIter(aNSIter.Value()->Label()); - for(; aPairsIter.More(); aPairsIter.Next()) { - if (aSubShape->impl().IsEqual() - } - }*/ anIterate = true; break; } else if (aNewNS->Evolution() == TNaming_DELETE) { // a shape was deleted => result is null @@ -1139,75 +822,29 @@ void Model_AttributeSelection::updateInHistory() continue; } } - - /* - TNaming_NewShapeIterator aModifIter(aPairIter.NewShape(), aContLab); - if (aModifIter.More()) aModifIter.Next(); // skip this shape result - for(; aModifIter.More(); aModifIter.Next()) { - ResultPtr aModifierObj = std::dynamic_pointer_cast - (aDoc->objects()->object(aModifIter.Label().Father())); - if (!aModifierObj.get()) - break; - FeaturePtr aModifierFeat = aDoc->feature(aModifierObj); - if (!aModifierFeat.get()) - break; - if (aModifierFeat == aThisFeature || aDoc->objects()->isLater(aModifierFeat, aThisFeature)) - break; // the modifier feature is later than this, so, should not be used - Handle(TNaming_NamedShape) aNewNS = aModifIter.NamedShape(); - if (aNewNS->Evolution() == TNaming_MODIFY || aNewNS->Evolution() == TNaming_GENERATED) { - aModifierResFound = aModifierObj; - } else if (aNewNS->Evolution() == TNaming_DELETE) { // a shape was deleted => result is null - ResultPtr anEmptyContext; - std::shared_ptr anEmptyShape; - setValue(anEmptyContext, anEmptyShape); // nullify the selection - return; - } else { // not-precessed modification => don't support it - break; - } - } - // already found what is needed, don't iterate the next pair since normally - if (aModifierResFound.get()) // there must be only one pair in the result-shape - break; - */ } if (aModifierResFound.get()) { // update scope to reset to a new one myScope.Clear(); myRef.setValue(aModifierResFound); - update(); // it must recompute a new sub-shape automatically - } - /* - if (aModifierResFound.get()) { - // update scope to reset to a new one - myScope.Clear(); - if (!aSubShape.get() || aSubShape->isNull()) { // no sub-shape, so, just update a context - setValue(aModifierResFound, aSubShape); - return; - } - // seaching for the same sub-shape: the old topology stays the same - TopoDS_Shape anOldShape = aSubShape->impl(); - TopAbs_ShapeEnum aSubType = anOldShape.ShapeType(); - TopoDS_Shape aNewContext = aModifierResFound->shape()->impl(); - TopExp_Explorer anExp(aNewContext, aSubType); - for(; anExp.More(); anExp.Next()) { - if (anExp.Current().IsEqual(anOldShape)) - break; - } - if (anExp.More()) { // found - setValue(aModifierResFound, aSubShape); - return; - } - // seaching for the same sub-shape: equal geometry - for(anExp.Init(aNewContext, aSubType); anExp.More(); anExp.Next()) { - if (aSubType == TopAbs_VERTEX) { - + // if context shape type is changed to more complicated and this context is selected, split + if (myParent &&!aSubShape.get() && aModifierResFound->shape().get() && aContext->shape().get()) + { + TopoDS_Shape anOldShape = aContext->shape()->impl(); + TopoDS_Shape aNewShape = aModifierResFound->shape()->impl(); + if (!anOldShape.IsNull() && !aNewShape.IsNull() && + anOldShape.ShapeType() != aNewShape.ShapeType() && + (aNewShape.ShapeType() == TopAbs_COMPOUND || aNewShape.ShapeType() == TopAbs_COMPSOLID)) { + // prepare for split in "update" + TDF_Label aSelLab = selectionLabel(); + split(aContext, aNewShape, anOldShape.ShapeType()); } } - }*/ - // if sub-shape selection exists, search also sub-shape new instance - /* - GeomShapePtr aSubShape = value(); - if (aSubShape.get() && aSubShape != aContext->shape()) { + update(); // it must recompute a new sub-shape automatically + } +} - }*/ +void Model_AttributeSelection::setParent(Model_AttributeSelectionList* theParent) +{ + myParent = theParent; }