X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2FModel%2FModel_AttributeSelection.cpp;h=ffa3015b4c700e765ac91bb146cc835a6a249176;hb=2da91de2a9adef6b5bc5c94f840831f33334e0cb;hp=b4739045fbe616388e4a1cfdbb6c2c70bd17d102;hpb=c4b3da21ddaf1e1f1763da7faefe54372aa38325;p=modules%2Fshaper.git diff --git a/src/Model/Model_AttributeSelection.cpp b/src/Model/Model_AttributeSelection.cpp index b4739045f..ffa3015b4 100644 --- a/src/Model/Model_AttributeSelection.cpp +++ b/src/Model/Model_AttributeSelection.cpp @@ -23,7 +23,6 @@ #include "Model_Events.h" #include "Model_Data.h" #include "Model_Document.h" -#include "Model_SelectionNaming.h" #include #include #include @@ -41,11 +40,11 @@ #include #include #include +#include #include #include #include -#include #include #include #include @@ -60,6 +59,7 @@ #include #include #include +#include #include #include #include @@ -89,10 +89,12 @@ Standard_GUID kCIRCLE_CENTER("d0d0e0f1-217a-4b95-8fbb-0c4132f23718"); 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"); -// identifier of the weak naming index -Standard_GUID kWEAK_NAMING("9dcdd9be-a3a9-46eb-9b16-1c957ab20142"); -// identifier of the weak naming sub-shape type -Standard_GUID kWEAK_NAMING_SHAPETYPE("6b9cc709-e320-4a1f-9c42-df5622369ea7"); +// reference to the external sketch face +Standard_GUID kEXT_SKETCH_FACE("ba32aa31-bde7-422f-80b4-79c757c77b49"); +// reference to the external sketch edge +Standard_GUID kEXT_SKETCH_EDGE("ba32aa31-bde7-422f-80b4-79c757c77b48"); +// reference to the external sketch vertex +Standard_GUID kEXT_SKETCH_VERT("ba32aa31-bde7-422f-80b4-79c757c77b47"); // prefix for the whole feature context identification const static std::string kWHOLE_FEATURE = "all-in-"; @@ -139,8 +141,9 @@ bool Model_AttributeSelection::setValue(const ObjectPtr& theContext, aSelLab.ForgetAttribute(kCIRCLE_CENTER); aSelLab.ForgetAttribute(kELLIPSE_CENTER1); aSelLab.ForgetAttribute(kELLIPSE_CENTER2); - aSelLab.ForgetAttribute(kWEAK_NAMING); - aSelLab.ForgetAttribute(kWEAK_NAMING_SHAPETYPE); + aSelLab.ForgetAttribute(kEXT_SKETCH_FACE); + aSelLab.ForgetAttribute(kEXT_SKETCH_EDGE); + aSelLab.ForgetAttribute(kEXT_SKETCH_VERT); bool isDegeneratedEdge = false; // do not use the degenerated edge as a shape, a null context and shape is used in the case @@ -342,8 +345,8 @@ std::shared_ptr Model_AttributeSelection::internalValue(CenterTyp 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 + if (!aContext.get() || aContext->groupName() == ModelAPI_ResultConstruction::group()) + return aResult; // empty result, for whole construction selection also return aContext->shape(); } if (aSelLab.IsAttribute(kPART_REF_ID)) { @@ -375,6 +378,44 @@ std::shared_ptr Model_AttributeSelection::internalValue(CenterTyp if (aConstr) { if (aConstr->isInfinite()) return aResult; // empty result + // external sketch face + Handle(TDataStd_Integer) anIndex; + if (aSelLab.FindAttribute(kEXT_SKETCH_FACE, anIndex)) { + return aConstr->face(anIndex->Get()); + } + if (aSelLab.FindAttribute(kEXT_SKETCH_EDGE, anIndex) || + aSelLab.FindAttribute(kEXT_SKETCH_VERT, anIndex)) { + bool isVert = anIndex->ID() == kEXT_SKETCH_VERT; // vertex is selected + CompositeFeaturePtr aComposite = std::dynamic_pointer_cast( + aConstr->document()->feature(aConstr)); + if (aComposite.get()) { + int aSubNum = anIndex->Get() % 1000000; + int aVertShape = (anIndex->Get() - aSubNum) / 1000000; + FeaturePtr aSubFeat = aComposite->subFeature(aSubNum); + if (aSubFeat.get()) { + const std::list >& aResults = aSubFeat->results(); + std::list >::const_iterator aRes = aResults.cbegin(); + for (; aRes != aResults.cend(); aRes++) { + ResultConstructionPtr aConstr = + std::dynamic_pointer_cast(*aRes); + if (aConstr->shape()) { + if (!isVert && aConstr->shape()->isEdge()) + return aConstr->shape(); + else if (isVert && aVertShape == 0 && aConstr->shape()->isVertex()) + return aConstr->shape(); + else if (isVert && aVertShape > 1 && aConstr->shape()->isEdge()) { + GeomAPI_ShapeExplorer anExp(aConstr->shape(), GeomAPI_Shape::VERTEX); + for(; anExp.more(); anExp.next()) { + if (aVertShape == 1) + return anExp.current(); + aVertShape--; + } + } + } + } + } + } + } } if (!aConstr.get()) { // for construction context, return empty result as usual even // the whole feature is selected @@ -394,30 +435,6 @@ std::shared_ptr Model_AttributeSelection::internalValue(CenterTyp } } - if (aSelLab.IsAttribute(kWEAK_NAMING)) { // a weak naming is used - Handle(TDataStd_Integer) aWeakId; - aSelLab.FindAttribute(kWEAK_NAMING, aWeakId); - // get the context shape - GeomShapePtr aContextShape; - ResultBodyPtr aBody = std::dynamic_pointer_cast(context()); - if (aBody.get()) { - aContextShape = aBody->shape(); - } else { - ResultPtr aResult = std::dynamic_pointer_cast(myRef.value()); - if (aResult) { - aContextShape = aResult->shape(); - } - } - if (!aContextShape.get()) - return GeomShapePtr(); - Handle(TDataStd_Integer) aWeakShapeType; - aSelLab.FindAttribute(kWEAK_NAMING_SHAPETYPE, aWeakShapeType); - GeomAlgoAPI_NExplode aNExplode( - aContextShape, GeomAPI_Shape::ShapeType(aWeakShapeType->Get())); - GeomShapePtr aValue = aNExplode.shape(aWeakId->Get()); - return aValue; - } - Handle(TNaming_NamedShape) aSelection; if (aSelLab.FindAttribute(TNaming_NamedShape::GetID(), aSelection)) { TopoDS_Shape aSelShape = aSelection->Get(); @@ -532,69 +549,6 @@ void Model_AttributeSelection::setObject(const std::shared_ptr& myRef.setObject(theObject); } -TDF_LabelMap& Model_AttributeSelection::scope() -{ - if (myScope.IsEmpty()) { // create a new scope if not yet done - // gets all features with named shapes that are before this feature label (before in history) - DocumentPtr aMyDoc = owner()->document(); - std::list > allFeatures = aMyDoc->allFeatures(); - std::list >::iterator aFIter = allFeatures.begin(); - bool aMePassed = false; - CompositeFeaturePtr aComposite = - std::dynamic_pointer_cast(owner()); - FeaturePtr aFeature = std::dynamic_pointer_cast(owner()); - CompositeFeaturePtr aCompositeOwner, aCompositeOwnerOwner; - if (aFeature.get()) { - aCompositeOwner = ModelAPI_Tools::compositeOwner(aFeature); - if (aCompositeOwner.get()) { - aCompositeOwnerOwner = ModelAPI_Tools::compositeOwner(aCompositeOwner); - } - } - // for group Scope is not limitet: this is always up to date objects - // this causes problem in galeries.py - //bool isGroup = aFeature.get() && aFeature->getKind() == "Group"; - for(; aFIter != allFeatures.end(); aFIter++) { - if (*aFIter == owner()) { // the left features are created later (except subs of composite) - aMePassed = true; - continue; - } - //if (isGroup) aMePassed = false; - bool isInScope = !aMePassed; - if (!isInScope && aComposite.get()) { - // try to add sub-elements of composite if this is composite - if (aComposite->isSub(*aFIter)) - isInScope = true; - } - // remove the composite-owner of this feature (sketch in extrusion-cut) - if (isInScope && (aCompositeOwner == *aFIter || aCompositeOwnerOwner == *aFIter)) - isInScope = false; - - 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(), 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()); - } - } - } - } - // 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; -} - /// Sets the invalid flag if flag is false, or removes it if "true" /// Returns theFlag static bool setInvalidIfFalse(TDF_Label& theLab, const bool theFlag) { @@ -636,6 +590,7 @@ bool Model_AttributeSelection::update() { FeaturePtr aContextFeature = contextFeature(); if (aContextFeature.get()) { + owner()->data()->sendAttributeUpdated(this); // send updated if "update" called in any way return true; } TDF_Label aSelLab = selectionLabel(); @@ -657,29 +612,6 @@ bool Model_AttributeSelection::update() } if (aContext->groupName() == ModelAPI_ResultBody::group()) { - if (aSelLab.IsAttribute(kWEAK_NAMING)) { // a weak naming is used - Handle(TDataStd_Integer) aWeakId; - aSelLab.FindAttribute(kWEAK_NAMING, aWeakId); - // get the context shape - GeomShapePtr aContextShape; - ResultBodyPtr aBody = std::dynamic_pointer_cast(aContext); - if (aBody.get()) { - aContextShape = aBody->shape(); - } else { - ResultPtr aResult = std::dynamic_pointer_cast(myRef.value()); - if (aResult) { - aContextShape = aResult->shape(); - } - } - if (!setInvalidIfFalse(aSelLab, aContextShape.get() != NULL)) // context shape not found - return false; - Handle(TDataStd_Integer) aWeakShapeType; - aSelLab.FindAttribute(kWEAK_NAMING_SHAPETYPE, aWeakShapeType); - GeomAlgoAPI_NExplode aNExplode( - aContextShape, GeomAPI_Shape::ShapeType(aWeakShapeType->Get())); - GeomShapePtr aValue = aNExplode.shape(aWeakId->Get()); - return setInvalidIfFalse(aSelLab, aValue.get() != NULL); - } // body: just a named shape, use topological selection mechanism bool aResult = false; TopoDS_Shape anOldShape; @@ -688,13 +620,7 @@ bool Model_AttributeSelection::update() anOldShape = aNS->Get(); Selector_Selector aSelector(aSelLab); - if (!aSelector.restore()) { // it is stored in old OCCT format, use TNaming_Selector - TNaming_Selector aSelector(aSelLab); - if (!aSelector.NamedShape().IsNull()) { - anOldShape = aSelector.NamedShape()->Get(); - } - aResult = aSelector.Solve(scope()) == Standard_True; - } else { + if (aSelector.restore()) { // it is stored in old OCCT format, use TNaming_Selector TopoDS_Shape aContextShape = aContext->shape()->impl(); aResult = aSelector.solve(aContextShape); } @@ -722,13 +648,33 @@ bool Model_AttributeSelection::update() std::shared_ptr aConstructionContext = std::dynamic_pointer_cast(aContext); if (!aConstructionContext->isInfinite()) { + // external sketch face + Handle(TDataStd_Integer) anIndex; + if (aSelLab.FindAttribute(kEXT_SKETCH_FACE, anIndex)) { + return setInvalidIfFalse(aSelLab, anIndex->Get() < aConstructionContext->facesNum()); + } + if (aSelLab.FindAttribute(kEXT_SKETCH_EDGE, anIndex) || + aSelLab.FindAttribute(kEXT_SKETCH_VERT, anIndex)) { + CompositeFeaturePtr aComposite = std::dynamic_pointer_cast( + aConstructionContext->document()->feature(aConstructionContext)); + if (aComposite.get()) { + FeaturePtr aSubFeat = aComposite->subFeature(anIndex->Get() % 1000000); + return setInvalidIfFalse(aSelLab, aSubFeat.get() != NULL); + } + return setInvalidIfFalse(aSelLab, false); // composite sub-feature is not found + } Selector_Selector aSelector(aSelLab); aResult = aSelector.restore(); + TopoDS_Shape anOldShape = aSelector.value(); if (aResult) { TopoDS_Shape aContextShape = aContext->shape()->impl(); aResult = aSelector.solve(aContextShape); } aResult = setInvalidIfFalse(aSelLab, aResult); + if (aResult && !anOldShape.IsEqual(aSelector.value())) + owner()->data()->sendAttributeUpdated(this); // send updated if shape is changed + } else { + owner()->data()->sendAttributeUpdated(this); // send updated if "update" called in any way } return aResult; } @@ -755,24 +701,77 @@ void Model_AttributeSelection::selectBody( } } - // with "recover" feature the selected context may be not up to date (issue 1710) - TDF_Label aSelLab = selectionLabel(); - TopoDS_Shape aNewSub = theSubShape ? theSubShape->impl() : aContext; - - /// fix for issue 411: result modified shapes must not participate in this selection mechanism if (!aContext.IsNull()) { + TDF_Label aSelLab = selectionLabel(); + TopoDS_Shape aNewSub = theSubShape->impl(); 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); + if (aFeatureOwner->document() != theContext->document()) { // reference to the sketch face + if (theSubShape->shapeType() == TopAbs_FACE) { // sketch face + ResultConstructionPtr aConstr = + std::dynamic_pointer_cast(theContext); + int aFaceIndex = -1, aFacesNum = aConstr->facesNum(); + for(int a = 0; a < aFacesNum; a++) { + if (aConstr->face(a)->isEqual(theSubShape)) { + aFaceIndex = a; + break; + } + } + if (aFaceIndex >= 0) { + TDataStd_Integer::Set(aSelLab, kEXT_SKETCH_FACE, aFaceIndex); // store index of the face + return; + } + } else if (theSubShape->shapeType() == TopAbs_EDGE || // sketch result edge (full one) + theSubShape->shapeType() == TopAbs_VERTEX) { // or start/end vertex + bool isVertex = theSubShape->shapeType() == TopAbs_VERTEX; + CompositeFeaturePtr aComposite = std::dynamic_pointer_cast( + theContext->document()->feature(theContext)); + if (aComposite.get()) { // iterate edges of composite to find index of matched with value + int aSub, anEdgeIndex = -1, aSubNum = aComposite->numberOfSubs(); + int aVertIndex = -1, aVertShape = -1; // shape: 0 full, 1 start, 2 end + for(aSub = 0; aSub < aSubNum && anEdgeIndex == -1; aSub++) { + FeaturePtr aSubFeat = aComposite->subFeature(aSub); + const std::list >& aResults = aSubFeat->results(); + std::list >::const_iterator aRes = aResults.cbegin(); + for (; aRes != aResults.cend(); aRes++) { + ResultConstructionPtr aConstr = + std::dynamic_pointer_cast(*aRes); + if (aConstr->shape() && aConstr->shape()->isEdge()) { + if (isVertex) { + GeomAPI_ShapeExplorer aVertExp(aConstr->shape(), GeomAPI_Shape::VERTEX); + for(int aNum = 1; aVertExp.more(); aVertExp.next(), aNum++) { + if (aVertExp.current()->isSame(theSubShape) && aVertShape != 0) { + aVertIndex = aSub; + aVertShape = aNum; + } + } + } else { + if (aConstr->shape()->isSame(theSubShape)) { + anEdgeIndex = aSub; + break; + } + } + } else if (isVertex && aConstr->shape() && aConstr->shape()->isVertex()) { + if (aConstr->shape()->isSame(theSubShape)) { + aVertIndex = aSub; + aVertShape = 0; + } + } + } + } + if (anEdgeIndex >= 0) { + TDataStd_Integer::Set(aSelLab, kEXT_SKETCH_EDGE, anEdgeIndex); // store index of edge + return; + } else if (aVertIndex >= 0) { + aVertIndex += aVertShape * 1000000; // to store both integers: index and shape + TDataStd_Integer::Set(aSelLab, kEXT_SKETCH_VERT, aVertIndex); // store index of edge + return; + } + } + } } bool aSelectorOk = true; - //TNaming_Selector aSel(aSelLab); Selector_Selector aSel(aSelLab); try { - //aSel.Select(aNewSub, aNewContext); aSelectorOk = aSel.select(aContext, aNewSub); if (aSelectorOk) { aSel.store(); @@ -781,12 +780,6 @@ void Model_AttributeSelection::selectBody( } catch(...) { aSelectorOk = false; } - // face may become divided after the model update, so, new labels may be added to the scope - myScope.Clear(); - - // check that selection is correct, otherwise use weak naming solution - TDF_Label aSelLab = selectionLabel(); - aSelLab.ForgetAttribute(kWEAK_NAMING); Handle(TNaming_NamedShape) aSelectorShape; if (aSelectorOk && aSelLab.FindAttribute(TNaming_NamedShape::GetID(), aSelectorShape)) { @@ -794,24 +787,8 @@ void Model_AttributeSelection::selectBody( if (aShape.IsNull() || aShape.ShapeType() != aNewSub.ShapeType()) aSelectorOk = false; } - if (!aSelectorOk) { // weak naming identifier instead - GeomShapePtr aContextShape(new GeomAPI_Shape); - aContextShape->setImpl(new TopoDS_Shape(aContext)); - GeomShapePtr aValueShape(new GeomAPI_Shape); - aValueShape->setImpl(new TopoDS_Shape(aNewSub)); - - GeomAlgoAPI_NExplode aNExplode(aContextShape, aValueShape->shapeType()); - int anId = aNExplode.index(aValueShape); - if (anId) { - TDataStd_Integer::Set(aSelLab, kWEAK_NAMING, anId); - TDataStd_Integer::Set(aSelLab, kWEAK_NAMING_SHAPETYPE, int(aValueShape->shapeType())); - } - } - - 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); + if (!aSelectorOk) { + setInvalidIfFalse(aSelLab, false); } } } @@ -899,18 +876,28 @@ std::string Model_AttributeSelection::namingName(const std::string& theDefaultNa return contextName(aCont); } - Handle(TDataStd_Integer) aWeakId; - if (aSelLab.FindAttribute(kWEAK_NAMING, aWeakId)) { // a weak naming is used - std::ostringstream aNameStream; - aNameStream<Get(); - return aNameStream.str(); - } - // whole infinitive construction if (aCont->groupName() == ModelAPI_ResultConstruction::group()) { ResultConstructionPtr aConstr = std::dynamic_pointer_cast(aCont); if (aConstr->isInfinite()) { return contextName(aCont); + } else { + // external sketch face + Handle(TDataStd_Integer) anIndex; + if (aSelLab.FindAttribute(kEXT_SKETCH_FACE, anIndex) || + aSelLab.FindAttribute(kEXT_SKETCH_EDGE, anIndex) || + aSelLab.FindAttribute(kEXT_SKETCH_VERT, anIndex)) { + std::shared_ptr anExtDoc = + std::dynamic_pointer_cast(aCont->document()); + Selector_Selector aSelector(anExtDoc->extConstructionsLabel()); + TopoDS_Shape aContShape = aConstr->shape()->impl(); + TopoDS_Shape aValShape = value()->impl(); + aSelector.select(aContShape, aValShape); + myRestoreDocument = anExtDoc; + std::string aName = anExtDoc->kind() + "/" + aSelector.name(this); + myRestoreDocument.reset(); + return aName; + } } } @@ -955,172 +942,86 @@ void Model_AttributeSelection::selectSubShape( CenterType aCenterType = theType[0] == 'v' || theType[0] == 'V' ? // only for vertex-type centerTypeByName(aSubShapeName) : NOT_CENTER; std::string aType = aCenterType == NOT_CENTER ? theType : "EDGE"; // search for edge now + TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(GeomAPI_Shape::shapeTypeByStr(theType)); + static const GeomShapePtr anEmptyShape; // first iteration is selection by name without center prefix, second - in case of problem, // try with initial name - for(int aUseCenter = 1; aUseCenter >= 0; aUseCenter--) { + for(int aUseCenter = 1; aUseCenter >= 0; aUseCenter--) { + std::string aSubShapeName = theSubShapeName; if (aUseCenter == 0 && aCenterType != NOT_CENTER) { - aSubShapeName = theSubShapeName; aCenterType = NOT_CENTER; aType = theType; } else if (aUseCenter != 1) continue; + std::shared_ptr aDoc = + std::dynamic_pointer_cast(owner()->document()); // check this is Part-name: 2 delimiters in the name std::size_t aPartEnd = aSubShapeName.find('/'); - if (aPartEnd != std::string::npos && aPartEnd != aSubShapeName.rfind('/')) { + if (aPartEnd != std::string::npos) { std::string aPartName = aSubShapeName.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); - std::string aNameInPart = aSubShapeName.substr(aPartEnd + 1); - int anIndex; - std::shared_ptr aSelected = aPart->shapeInPart(aNameInPart, aType, anIndex); - if (aSelected.get()) { - if (aCenterType != NOT_CENTER) { - if (!aSelected->isEdge()) - continue; - std::shared_ptr aSelectedEdge(new GeomAPI_Edge(aSelected)); - setValueCenter(aPart, aSelectedEdge, aCenterType); - } else - setValue(aPart, aSelected); - TDataStd_Integer::Set(selectionLabel(), anIndex); - return; + DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument(); + if (aPartName == aRootDoc->kind()) { + aDoc = std::dynamic_pointer_cast(aRootDoc); + aSubShapeName = aSubShapeName.substr(aPartEnd + 1); + } else { + 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); + aDoc = std::dynamic_pointer_cast(aPart->partDoc()); + aSubShapeName = aSubShapeName.substr(aPartEnd +1); } } } - std::shared_ptr aDoc = - std::dynamic_pointer_cast(owner()->document()); // check this is a whole feature context if (aSubShapeName.size() > kWHOLE_FEATURE.size() && aSubShapeName.substr(0, kWHOLE_FEATURE.size()) == kWHOLE_FEATURE) { std::string aFeatureName = aSubShapeName.substr(kWHOLE_FEATURE.size()); ObjectPtr anObj = aDoc->objectByName(ModelAPI_Feature::group(), aFeatureName); if (anObj.get()) { - static const GeomShapePtr anEmptyShape; setValue(anObj, anEmptyShape); return; } } - Model_SelectionNaming aSelNaming(selectionLabel()); - std::shared_ptr aShapeToBeSelected; - ResultPtr aCont; - if (aSelNaming.selectSubShape(aType, aSubShapeName, aDoc, aShapeToBeSelected, aCont)) { - // 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(); - if (!aConShape.IsNull()) { - Handle(TNaming_NamedShape) aNS = TNaming_Tool::NamedShape(aConShape, selectionLabel()); - if (!aNS.IsNull()) { - aNS = TNaming_Tool::CurrentNamedShape(aNS); - if (!aNS.IsNull() && scope().Contains(aNS->Label())) { // scope check is for 2228 - TDF_Label aLab = aNS->Label(); - if (aLab.Depth() % 2 == 0) - aLab = aLab.Father(); - ObjectPtr anObj = aDoc->objects()->object(aLab); - while(!anObj.get() && aLab.Depth() > 5) { - aLab = aLab.Father().Father(); - anObj = aDoc->objects()->object(aLab); - } - - if (anObj.get()) { - ResultPtr aRes = std::dynamic_pointer_cast(anObj); - if (aRes) - aCont = aRes; - } - } - } - } - } - // if compsolid is context, try to take sub-solid as context: like in GUI and scripts - if (aCont.get() && aShapeToBeSelected.get()) { - ResultBodyPtr aComp = std::dynamic_pointer_cast(aCont); - if (aComp && aComp->numberOfSubs()) { - std::list allSubs; - ModelAPI_Tools::allSubs(aComp, allSubs); - std::list::iterator aS = allSubs.begin(); - for(; aS != allSubs.end(); aS++) { - ResultBodyPtr aSub = std::dynamic_pointer_cast(*aS); - if (aSub && aSub->numberOfSubs() == 0 && aSub->shape().get() && - aSub->shape()->isSubShape(aShapeToBeSelected)) { - aCont = aSub; - break; - } - } - } + // the whole result selection check + if (aSubShapeName.find('/') == std::string::npos) { + ObjectPtr aRes = aDoc->objectByName(ModelAPI_ResultConstruction::group(), aSubShapeName); + if (!aRes.get()) + aRes = aDoc->objectByName(ModelAPI_ResultBody::group(), aSubShapeName); + if (aRes.get()) { + setValue(aRes, anEmptyShape); + return; } - // try to find the latest active result that must be used instead of the selected - // to set the active context (like in GUI selection), not concealed one - bool aFindNewContext = true; - while(aFindNewContext && aCont.get()) { - aFindNewContext = false; - // take references to all results: root one, any sub - ResultBodyPtr aCompContext = ModelAPI_Tools::bodyOwner(aCont, true); - std::list allRes; - if (aCompContext.get()) { - ModelAPI_Tools::allSubs(aCompContext, allRes); - allRes.push_back(aCompContext); - } else { - allRes.push_back(aCont); - } - for(std::list::iterator aSub = allRes.begin(); aSub != allRes.end(); aSub++) { - ResultPtr aResCont = *aSub; - ResultBodyPtr aResBody = std::dynamic_pointer_cast(aResCont); - // only lower and higher level subs are counted - if (aResBody.get() && aResBody->numberOfSubs() > 0 && aResBody != aCompContext) - continue; - const std::set& aRefs = aResCont->data()->refsToMe(); - std::set::const_iterator aRef = aRefs.begin(); - for(; !aFindNewContext && aRef != aRefs.end(); aRef++) { - if (!aRef->get() || !(*aRef)->owner().get()) - continue; - // concealed attribute only - FeaturePtr aRefFeat = std::dynamic_pointer_cast((*aRef)->owner()); - if (!ModelAPI_Session::get()->validators()->isConcealed( - aRefFeat->getKind(), (*aRef)->id())) + } + + Selector_Selector aSelector(aDoc->generalLabel()); + myRestoreDocument = aDoc; + TDF_Label aContextLabel = aSelector.restoreByName(aSubShapeName, aShapeType, this); + myRestoreDocument.reset(); + if (!aContextLabel.IsNull()) { + ResultPtr aContext = aDoc->resultByLab(aContextLabel); // any label for document access + if (aContext.get() && aContext->shape().get()) { + TopoDS_Shape aContextShape = aContext->shape()->impl(); + if (aSelector.solve(aContextShape)) { + GeomShapePtr aShapeToBeSelected(new GeomAPI_Shape); + aShapeToBeSelected->setImpl(new TopoDS_Shape(aSelector.value())); + if (aCenterType != NOT_CENTER) { + if (!aShapeToBeSelected->isEdge()) continue; - // search the feature result that contains sub-shape selected - std::list > aResults; - - // take all sub-results or one result - std::list aRefFeatResults; - ModelAPI_Tools::allResults(aRefFeat, aRefFeatResults); - std::list::iterator aRefResIter = aRefFeatResults.begin(); - for(; aRefResIter != aRefFeatResults.end(); aRefResIter++) { - ResultBodyPtr aBody = std::dynamic_pointer_cast(*aRefResIter); - if (aBody.get() && aBody->numberOfSubs() == 0) // add only lower level subs - aResults.push_back(aBody); - } - std::list >::iterator aResIter = aResults.begin(); - for(; aResIter != aResults.end(); aResIter++) { - if (!aResIter->get() || !(*aResIter)->data()->isValid() || (*aResIter)->isDisabled()) - continue; - GeomShapePtr aShape = (*aResIter)->shape(); - GeomShapePtr aSelectedShape = - aShapeToBeSelected.get() ? aShapeToBeSelected : aCont->shape(); - if (aShape.get() && aShape->isSubShape(aSelectedShape, false)) { - aCont = *aResIter; // found new context (produced from this) with same subshape - aFindNewContext = true; // continue searching futher - break; - } - } + std::shared_ptr aSelectedEdge(new GeomAPI_Edge(aShapeToBeSelected)); + setValueCenter(aContext, aSelectedEdge, aCenterType); } + else + setValue(aContext, aShapeToBeSelected); + return; } } - - if (aCenterType != NOT_CENTER) { - if (!aShapeToBeSelected->isEdge()) - continue; - std::shared_ptr aSelectedEdge(new GeomAPI_Edge(aShapeToBeSelected)); - setValueCenter(aCont, aSelectedEdge, aCenterType); - } else - setValue(aCont, aShapeToBeSelected); - return; } + aSubShapeName = theSubShapeName; } - + // invalid TDF_Label aSelLab = selectionLabel(); setInvalidIfFalse(aSelLab, false); reset(); @@ -1374,7 +1275,7 @@ void Model_AttributeSelection::computeValues( for(; aNewContIter != aNewToIterate.end(); aNewContIter++) { std::shared_ptr aNewData = std::dynamic_pointer_cast((*aNewContIter)->data()); - TDF_Label aNewLab = aNewData->label(); + TDF_Label aNewLab = aNewData->shapeLab(); // searching for produced sub-shape fully on some label TDF_ChildIDIterator aNSIter(aNewLab, TNaming_NamedShape::GetID(), Standard_True); for(; aNSIter.More(); aNSIter.Next()) { @@ -1468,11 +1369,11 @@ bool Model_AttributeSelection::searchNewContext(std::shared_ptr if (!aModifierFeat.get()) continue; FeaturePtr aThisFeature = std::dynamic_pointer_cast(owner()); - if (aModifierFeat == aThisFeature || theDoc->objects()->isLater(aModifierFeat, aThisFeature)) + if (aModifierFeat == aThisFeature || !theDoc->isLaterByDep(aThisFeature, aModifierFeat)) continue; // the modifier feature is later than this, so, should not be used FeaturePtr aCurrentModifierFeat = theDoc->feature(theContext); if (aCurrentModifierFeat == aModifierFeat || - theDoc->objects()->isLater(aCurrentModifierFeat, aModifierFeat)) + !theDoc->isLaterByDep(aModifierFeat, aCurrentModifierFeat)) continue; // the current modifier is later than the found, so, useless Handle(TNaming_NamedShape) aNewNS; aModifIter.Label().FindAttribute(TNaming_NamedShape::GetID(), aNewNS); @@ -1483,7 +1384,7 @@ bool Model_AttributeSelection::searchNewContext(std::shared_ptr aResContShapes.Append(aModifierObj->shape()->impl()); } else if (aNewNS->Evolution() == TNaming_DELETE) { // a shape was deleted => result is empty aResults.insert(ResultPtr()); - } else { // not-precessed modification => don't support it + } else { // not-processed modification => don't support it continue; } } @@ -1538,7 +1439,7 @@ void Model_AttributeSelection::updateInHistory() std::shared_ptr aContData = std::dynamic_pointer_cast(aContext->data()); if (!aContData.get() || !aContData->isValid()) return; - TDF_Label aContLab = aContData->label(); // named shape where the selected context is located + TDF_Label aContLab = aContData->shapeLab(); // named shape where the selected context is located Handle(TNaming_NamedShape) aContNS; if (!aContLab.FindAttribute(TNaming_NamedShape::GetID(), aContNS)) { bool aFoundNewContext = true; @@ -1561,7 +1462,7 @@ void Model_AttributeSelection::updateInHistory() FeaturePtr aRefFeat = std::dynamic_pointer_cast((*aRef)->owner()); if (aRefFeat.get() && aRefFeat != owner()) { FeaturePtr aThisFeature = std::dynamic_pointer_cast(owner()); - if (aDoc->objects()->isLater(aThisFeature, aRefFeat)) { // found better feature + if (!aDoc->isLaterByDep(aRefFeat, aThisFeature)) { // found better feature aFoundNewContext = true; aNewContext = aRefFeat->firstResult(); } @@ -1598,9 +1499,6 @@ void Model_AttributeSelection::updateInHistory() TopTools_ListOfShape aValShapes; if (searchNewContext(aDoc, aNewCShape, aContext, aValShape, aContLab, aNewContexts, aValShapes)) { - // update scope to reset to a new one - myScope.Clear(); - std::list::iterator aNewCont = aNewContexts.begin(); TopTools_ListIteratorOfListOfShape aNewValues(aValShapes); if (aNewCont == aNewContexts.end()) { // all results were deleted @@ -1654,15 +1552,10 @@ void Model_AttributeSelection::setParent(Model_AttributeSelectionList* theParent myParent = theParent; } -bool Model_AttributeSelection::isWeakNaming() -{ - return selectionLabel().IsAttribute(kWEAK_NAMING); -} - std::string Model_AttributeSelection::contextName(const TDF_Label theSelectionLab) { - DocumentPtr aMyDoc = owner()->document(); - std::shared_ptr aDoc = std::dynamic_pointer_cast(aMyDoc); + std::shared_ptr aDoc = myRestoreDocument.get() ? myRestoreDocument : + std::dynamic_pointer_cast(owner()->document()); FeaturePtr aFeatureOwner = aDoc->featureByLab(theSelectionLab); if (aFeatureOwner.get()) { // if it is sub-element of the sketch, the context name is the name of the sketch @@ -1695,3 +1588,187 @@ std::string Model_AttributeSelection::contextName(const TDF_Label theSelectionLa } return ""; // invalid case } + +/// This method restores by the context and value name the context label and +/// sub-label where the value is. Returns true if it is valid. +bool Model_AttributeSelection::restoreContext(std::string theName, + TDF_Label& theContext, TDF_Label& theValue) +{ + static const GeomShapePtr anEmptyShape; // to store context only + std::string aName = theName; + std::shared_ptr aDoc = myRestoreDocument.get() ? myRestoreDocument : + std::dynamic_pointer_cast(owner()->document()); + + // remove the sub-value part if exists + std::string aSubShapeName = aName; + std::string::size_type n = aName.find('/'); + if (n != std::string::npos) { + aName = aName.substr(0, n); + } + + if (aName.empty()) return false; + bool anUniqueContext = false; + ResultPtr aCont = aDoc->findByName(aName, aSubShapeName, anUniqueContext); + if (!aCont.get() || !aCont->shape().get() || aCont->shape()->isNull()) + return false; + + // searching the sub-shape + static const ResultPtr anEmpty; + theValue = aDoc->findNamingName(aSubShapeName, anUniqueContext ? aCont : anEmpty); + + // sketch sub-component shape and name is located in separated feature label, try the sub-name + if (theValue.IsNull() && aCont->groupName() == ModelAPI_ResultConstruction::group()) { + std::string::size_type aSlash = aSubShapeName.rfind('/'); + if (aSlash != std::string::npos) { + std::string aCompName = aSubShapeName.substr(aSlash + 1); + CompositeFeaturePtr aComposite = + std::dynamic_pointer_cast(aDoc->feature(aCont)); + if (aComposite.get() && aComposite->numberOfSubs()) { + const int aSubNum = aComposite->numberOfSubs(); + for (int a = 0; a < aSubNum && theValue.IsNull(); a++) { + FeaturePtr aSub = aComposite->subFeature(a); + const std::list >& aResults = aSub->results(); + std::list >::const_iterator aRes = aResults.cbegin(); + for (; aRes != aResults.cend() && theValue.IsNull(); aRes++) { + if ((*aRes)->data()->name() == aCompName) { + theValue = std::dynamic_pointer_cast((*aRes)->data())->shapeLab(); + break; + } else if (aCompName.find((*aRes)->data()->name()) != std::string::npos) {// sub-vertex + TDF_Label aLab = std::dynamic_pointer_cast((*aRes)->data())->shapeLab(); + TDF_ChildIDIterator aSubNames(aLab, TDataStd_Name::GetID()); + for(; aSubNames.More(); aSubNames.Next()) { + if (Handle(TDataStd_Name)::DownCast(aSubNames.Value())->Get(). + IsEqual(aCompName.c_str())) { + theValue = aSubNames.Value()->Label(); + break; + } + } + } + } + } + } + } + } + + /* to find the latest lower result that keeps given shape + bool aFindNewContext = true; + while(aFindNewContext && aCont.get()) { + aFindNewContext = false; + // try to find the last context to find the up to date shape + TopoDS_Shape aConShape = aCont->shape()->impl(); + Handle(TNaming_NamedShape) aNS = TNaming_Tool::NamedShape(aConShape, selectionLabel()); + if (!aNS.IsNull()) { + aNS = TNaming_Tool::CurrentNamedShape(aNS); + if (!aNS.IsNull() && isOlderThanMe(aNS->Label())) { // scope check is for 2228 + TDF_Label aLab = aNS->Label(); + if (aLab.Depth() % 2 == 0) + aLab = aLab.Father(); + ObjectPtr anObj = aDoc->objects()->object(aLab); + while (!anObj.get() && aLab.Depth() > 5) { + aLab = aLab.Father().Father(); + anObj = aDoc->objects()->object(aLab); + } + + if (anObj.get()) { + ResultPtr aRes = std::dynamic_pointer_cast(anObj); + if (aRes) { + aCont = aRes; + aFindNewContext = true; + } + } + } + } else if (aCont->groupName() == ModelAPI_ResultBody::group()) { + // try to search newer context by the concealment references + // take references to all results: root one, any sub + std::list allRes; + ResultPtr aCompContext; + if (aCont->groupName() == ModelAPI_ResultBody::group()) { + ResultBodyPtr aCompBody = ModelAPI_Tools::bodyOwner(aCont, true); + if (aCompBody.get()) { + ModelAPI_Tools::allSubs(aCompBody, allRes); + allRes.push_back(aCompBody); + aCompContext = aCompBody; + } + } + if (allRes.empty()) + allRes.push_back(aCont); + + for(std::list::iterator aSub = allRes.begin(); aSub != allRes.end(); aSub++) { + ResultPtr aResCont = *aSub; + ResultBodyPtr aResBody = std::dynamic_pointer_cast(aResCont); + if (aResBody.get() && aResBody->numberOfSubs() > 0 && aResBody != aCompContext) + continue; // only lower and higher level subs are counted + const std::set& aRefs = aResCont->data()->refsToMe(); + std::set::const_iterator aRef = aRefs.begin(); + for(; !aFindNewContext && aRef != aRefs.end(); aRef++) { + if (!aRef->get() || !(*aRef)->owner().get()) + continue; + // concealed attribute only + FeaturePtr aRefFeat = std::dynamic_pointer_cast((*aRef)->owner()); + if (!ModelAPI_Session::get()->validators()->isConcealed( + aRefFeat->getKind(), (*aRef)->id())) + continue; + // search the feature result that contains sub-shape selected + std::list > aResults; + + // take all sub-results or one result + std::list aRefFeatResults; + ModelAPI_Tools::allResults(aRefFeat, aRefFeatResults); + std::list::iterator aRefResIter = aRefFeatResults.begin(); + for(; aRefResIter != aRefFeatResults.end(); aRefResIter++) { + ResultBodyPtr aBody = std::dynamic_pointer_cast(*aRefResIter); + if (aBody.get() && aBody->numberOfSubs() == 0) // add only lower level subs + aResults.push_back(aBody); + } + std::list >::iterator aResIter = aResults.begin(); + for(; aResIter != aResults.end(); aResIter++) { + if (!aResIter->get() || !(*aResIter)->data()->isValid() || (*aResIter)->isDisabled()) + continue; + GeomShapePtr aShape = (*aResIter)->shape(); + GeomShapePtr aSelectedShape = + aShapeToBeSelected.get() ? aShapeToBeSelected : aCont->shape(); + if (aShape.get() && aShape->isSubShape(aSelectedShape, false)) { + aCont = *aResIter; // found new context (produced from this) with same subshape + aFindNewContext = true; // continue searching futher + break; + } + } + } + } + } + } + // if compsolid is context, try to take sub-solid as context: like in GUI and scripts + ResultBodyPtr aComp = std::dynamic_pointer_cast(aCont); + if (aComp && aComp->numberOfSubs()) { + std::list allSubs; + ModelAPI_Tools::allSubs(aComp, allSubs); + std::list::iterator aS = allSubs.begin(); + for (; aS != allSubs.end(); aS++) { + ResultBodyPtr aSub = std::dynamic_pointer_cast(*aS); + if (aSub && aSub->numberOfSubs() == 0 && aSub->shape().get() && + aSub->shape()->isSubShape(aShapeToBeSelected)) { + aCont = aSub; + break; + } + } + } + */ + if (aCont.get()) { + theContext = std::dynamic_pointer_cast(aCont->data())->label(); + } + return true; +} + +bool Model_AttributeSelection::isLater( + const TDF_Label theResult1, const TDF_Label theResult2) const +{ + std::shared_ptr aDoc = myRestoreDocument.get() ? myRestoreDocument : + std::dynamic_pointer_cast(owner()->document()); + FeaturePtr aFeat1 = aDoc->featureByLab(theResult1); + if (!aFeat1.get()) + return false; + FeaturePtr aFeat2 = aDoc->featureByLab(theResult2); + if (!aFeat2.get()) + return false; + return aDoc->isLaterByDep(aFeat1, aFeat2); +}