X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FModel%2FModel_AttributeSelection.cpp;h=c29cca22998cc6c335de633a089f0a77f9eb0baa;hb=72b9423caaa48805589d6ab87d366f79ecde5bfe;hp=315e60a885196f817fb09b94d3ebd533e411bbb1;hpb=c27bc66f8641cb233c14819de31d7e2eba2109d3;p=modules%2Fshaper.git diff --git a/src/Model/Model_AttributeSelection.cpp b/src/Model/Model_AttributeSelection.cpp index 315e60a88..c29cca229 100644 --- a/src/Model/Model_AttributeSelection.cpp +++ b/src/Model/Model_AttributeSelection.cpp @@ -36,6 +36,8 @@ #include #include #include +#include +#include #include #include @@ -57,6 +59,9 @@ #include #include #include +#include +#include +#include //#define DEB_NAMING 1 #ifdef DEB_NAMING @@ -72,30 +77,39 @@ Standard_GUID kPART_REF_ID("635eacb2-a1d6-4dec-8348-471fae17cb27"); // selection is invalid after recomputation Standard_GUID kINVALID_SELECTION("bce47fd7-80fa-4462-9d63-2f58acddd49d"); +// identifier of the selection of the center of circle on edge +Standard_GUID kCIRCLE_CENTER("d0d0e0f1-217a-4b95-8fbb-0c4132f23718"); +// identifier of the selection of the first focus point of ellipse on edge +Standard_GUID kELLIPSE_CENTER1("f70df04c-3168-4dc9-87a4-f1f840c1275d"); +// identifier of the selection of the second focus point of ellipse on edge +Standard_GUID kELLIPSE_CENTER2("1395ae73-8e02-4cf8-b204-06ff35873a32"); + // on this label is stored: // TNaming_NamedShape - selected shape // TNaming_Naming - topological selection information (for the body) // TDataStd_IntPackedMap - indexes of edges in composite element (for construction) // TDataStd_Integer - type of the selected shape (for construction) // TDF_Reference - from ReferenceAttribute, the context -void Model_AttributeSelection::setValue(const ResultPtr& theContext, +bool Model_AttributeSelection::setValue(const ResultPtr& theContext, const std::shared_ptr& theSubShape, const bool theTemporarily) { if (theTemporarily) { // just keep the stored without DF update myTmpContext = theContext; myTmpSubShape = theSubShape; owner()->data()->sendAttributeUpdated(this); - return; + return true; } else { myTmpContext.reset(); myTmpSubShape.reset(); + myTmpCenterType = NOT_CENTER; } - const std::shared_ptr& anOldShape = value(); + CenterType aType; + const std::shared_ptr& anOldShape = internalValue(aType); bool isOldContext = theContext == myRef.value(); bool isOldShape = isOldContext && (theSubShape == anOldShape || (theSubShape && anOldShape && theSubShape->isEqual(anOldShape))); - if (isOldShape) return; // shape is the same, so context is also unchanged + if (isOldShape) return false; // shape is the same, so context is also unchanged // update the referenced object if needed if (!isOldContext) { myRef.setValue(theContext); @@ -105,6 +119,9 @@ void Model_AttributeSelection::setValue(const ResultPtr& theContext, TDF_Label aSelLab = selectionLabel(); aSelLab.ForgetAttribute(kSIMPLE_REF_ID); aSelLab.ForgetAttribute(kINVALID_SELECTION); + aSelLab.ForgetAttribute(kCIRCLE_CENTER); + aSelLab.ForgetAttribute(kELLIPSE_CENTER1); + aSelLab.ForgetAttribute(kELLIPSE_CENTER2); bool isDegeneratedEdge = false; // do not use the degenerated edge as a shape, a null context and shape is used in the case @@ -118,7 +135,7 @@ void Model_AttributeSelection::setValue(const ResultPtr& theContext, TDF_Label aRefLab = myRef.myRef->Label(); aSelLab.ForgetAllAttributes(true); myRef.myRef = TDF_Reference::Set(aSelLab.Father(), aSelLab.Father()); - return; + return false; } if (theContext->groupName() == ModelAPI_ResultBody::group()) { // do not select the whole shape for body:it is already must be in the data framework @@ -137,6 +154,12 @@ void Model_AttributeSelection::setValue(const ResultPtr& theContext, std::shared_ptr aSubShape; if (theSubShape.get() && !theContext->shape()->isEqual(theSubShape)) aSubShape = theSubShape; // the whole context + 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()); + } int anIndex = aConstruction->select(theSubShape, owner()->document()); TDataStd_Integer::Set(aSelLab, anIndex); } else if (theContext->groupName() == ModelAPI_ResultPart::group()) { @@ -146,6 +169,53 @@ void Model_AttributeSelection::setValue(const ResultPtr& theContext, } owner()->data()->sendAttributeUpdated(this); + return true; +} + +void Model_AttributeSelection::setValueCenter( + const ResultPtr& theContext, const std::shared_ptr& theEdge, + const CenterType theCenterType, const bool theTemporarily) +{ + bool anUpdated = setValue(theContext, theEdge, theTemporarily); + if (theTemporarily) { + myTmpCenterType = theCenterType; + } else { // store in the data structure + TDF_Label aSelLab = selectionLabel(); + switch(theCenterType) { + case CIRCLE_CENTER: + if (!anUpdated) + anUpdated = !aSelLab.IsAttribute(kCIRCLE_CENTER); + TDataStd_UAttribute::Set(aSelLab, kCIRCLE_CENTER); + break; + case ELLIPSE_FIRST_FOCUS: + if (!anUpdated) + anUpdated = !aSelLab.IsAttribute(kELLIPSE_CENTER1); + TDataStd_UAttribute::Set(aSelLab, kELLIPSE_CENTER1); + break; + case ELLIPSE_SECOND_FOCUS: + if (!anUpdated) + anUpdated = !aSelLab.IsAttribute(kELLIPSE_CENTER2); + TDataStd_UAttribute::Set(aSelLab, kELLIPSE_CENTER2); + break; + } + if (anUpdated) + owner()->data()->sendAttributeUpdated(this); + } +} + +void Model_AttributeSelection::selectValue( + const std::shared_ptr& theSource) +{ + CenterType aType; + std::shared_ptr aValue = + std::dynamic_pointer_cast(theSource)->internalValue(aType); + if (!aValue.get() || aType == NOT_CENTER) { + setValue(theSource->context(), aValue); + } else { + std::shared_ptr anEdge(new GeomAPI_Edge); + anEdge->setImpl(new TopoDS_Shape(aValue->impl())); + setValueCenter(theSource->context(), anEdge, aType); + } } void Model_AttributeSelection::removeTemporaryValues() @@ -156,10 +226,55 @@ void Model_AttributeSelection::removeTemporaryValues() } } +// returns the center of the edge: circular or elliptical +GeomShapePtr centerByEdge(GeomShapePtr theEdge, ModelAPI_AttributeSelection::CenterType theType) +{ + if (theType != ModelAPI_AttributeSelection::NOT_CENTER && theEdge.get() != NULL) { + TopoDS_Shape aShape = theEdge->impl(); + if (!aShape.IsNull() && aShape.ShapeType() == TopAbs_EDGE) { + TopoDS_Edge anEdge = TopoDS::Edge(aShape); + double aFirst, aLast; + Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast); + if (!aCurve.IsNull()) { + TopoDS_Vertex aVertex; + BRep_Builder aBuilder; + if (theType == ModelAPI_AttributeSelection::CIRCLE_CENTER) { + Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast(aCurve); + if (!aCirc.IsNull()) { + aBuilder.MakeVertex(aVertex, aCirc->Location(), Precision::Confusion()); + } + } else { // ellipse + Handle(Geom_Ellipse) anEll = Handle(Geom_Ellipse)::DownCast(aCurve); + if (!anEll.IsNull()) { + aBuilder.MakeVertex(aVertex, + theType == ModelAPI_AttributeSelection::ELLIPSE_FIRST_FOCUS ? + anEll->Focus1() : anEll->Focus2(), Precision::Confusion()); + } + } + if (!aVertex.IsNull()) { + std::shared_ptr aResult(new GeomAPI_Vertex); + aResult->setImpl(new TopoDS_Vertex(aVertex)); + return aResult; + } + } + } + } + return theEdge; // no vertex, so, return the initial edge +} + std::shared_ptr Model_AttributeSelection::value() { + CenterType aType = NOT_CENTER; + std::shared_ptr aResult = internalValue(aType); + return centerByEdge(aResult, aType); +} + +std::shared_ptr Model_AttributeSelection::internalValue(CenterType& theType) +{ + theType = NOT_CENTER; GeomShapePtr aResult; if (myTmpContext.get() || myTmpSubShape.get()) { + theType = myTmpCenterType; ResultConstructionPtr aResulConstruction = std::dynamic_pointer_cast(myTmpContext); if(aResulConstruction.get()) { @@ -173,6 +288,14 @@ std::shared_ptr Model_AttributeSelection::value() if (aSelLab.IsAttribute(kINVALID_SELECTION)) return aResult; + if (aSelLab.IsAttribute(kCIRCLE_CENTER)) + theType = CIRCLE_CENTER; + else if (aSelLab.IsAttribute(kELLIPSE_CENTER1)) + theType = ELLIPSE_FIRST_FOCUS; + else if (aSelLab.IsAttribute(kELLIPSE_CENTER2)) + theType = ELLIPSE_SECOND_FOCUS; + + if (myRef.isInitialized()) { if (aSelLab.IsAttribute(kSIMPLE_REF_ID)) { // it is just reference to shape, not sub-shape ResultPtr aContext = context(); @@ -204,21 +327,23 @@ std::shared_ptr Model_AttributeSelection::value() } } + std::shared_ptr aConstr = + std::dynamic_pointer_cast(context()); + if (aConstr) { + if (aConstr->isInfinite()) + return aResult; // empty result + } Handle(TNaming_NamedShape) 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 - std::shared_ptr aConstr = - std::dynamic_pointer_cast(context()); - if (aConstr) { - 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()); - } + } else if (aConstr) { // simple construction element: just shape of this construction element + 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()); } } } @@ -458,6 +583,11 @@ bool Model_AttributeSelection::update() bool aModified = true; bool aValid = aConstructionContext->update(anIndex->Get(), owner()->document(), aModified); setInvalidIfFalse(aSelLab, aValid); + if (aConstructionContext->isInfinite()) { + // Update the selected shape. + TNaming_Builder aBuilder(aSelLab); + aBuilder.Generated(aConstructionContext->shape()->impl()); + } if (aModified) owner()->data()->sendAttributeUpdated(this); return aValid; @@ -610,21 +740,56 @@ TDF_Label Model_AttributeSelection::selectionLabel() return myRef.myRef->Label().FindChild(1); } +/// prefixes of the shape names with centers defined +static std::map kCENTERS_PREFIX; + +/// returns the map that contains all possible prefixes of the center-names +static std::map& centersMap() +{ + if (kCENTERS_PREFIX.empty()) { // fill map by initial values + kCENTERS_PREFIX[ModelAPI_AttributeSelection::CIRCLE_CENTER] = "__cc"; + kCENTERS_PREFIX[ModelAPI_AttributeSelection::ELLIPSE_FIRST_FOCUS] = "__eff"; + kCENTERS_PREFIX[ModelAPI_AttributeSelection::ELLIPSE_SECOND_FOCUS] = "__esf"; + } + return kCENTERS_PREFIX; +} + std::string Model_AttributeSelection::namingName(const std::string& theDefaultName) { std::string aName(""); if(!this->isInitialized()) return !theDefaultName.empty() ? theDefaultName : aName; - std::shared_ptr aSubSh = value(); + CenterType aCenterType = NOT_CENTER; + std::shared_ptr aSubSh = internalValue(aCenterType); ResultPtr aCont = context(); if (!aCont.get()) // in case of selection of removed result return ""; Model_SelectionNaming aSelNaming(selectionLabel()); - return aSelNaming.namingName( + std::string aResult = aSelNaming.namingName( aCont, aSubSh, theDefaultName, owner()->document() != aCont->document()); + if (aCenterType != NOT_CENTER) { + aResult += centersMap()[aCenterType]; + } + return aResult; +} + +// returns the center type and modifies the shape name if this name is center-name +static ModelAPI_AttributeSelection::CenterType centerTypeByName(std::string& theShapeName) +{ + std::map::iterator aPrefixIter = + centersMap().begin(); + for(; aPrefixIter != centersMap().end(); aPrefixIter++) { + std::size_t aFound = theShapeName.find(aPrefixIter->second); + if (aFound != std::string::npos && + aFound == theShapeName.size() - aPrefixIter->second.size()) { + theShapeName = theShapeName.substr(0, aFound); + return aPrefixIter->first; + } + } + return ModelAPI_AttributeSelection::NOT_CENTER; } // type ::= COMP | COMS | SOLD | SHEL | FACE | WIRE | EDGE | VERT @@ -633,54 +798,81 @@ void Model_AttributeSelection::selectSubShape( { if(theSubShapeName.empty() || theType.empty()) return; - // check this is Part-name: 2 delimiters in the name - std::size_t aPartEnd = theSubShapeName.find('/'); - 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); - std::string aNameInPart = theSubShapeName.substr(aPartEnd + 1); - int anIndex; - std::shared_ptr aSelected = aPart->shapeInPart(aNameInPart, theType, anIndex); - if (aSelected.get()) { - setValue(aPart, aSelected); - TDataStd_Integer::Set(selectionLabel(), anIndex); - return; + std::string aSubShapeName = theSubShapeName; + 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 + + // 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--) { + if (aUseCenter == 0 && aCenterType != NOT_CENTER) { + aSubShapeName = theSubShapeName; + aCenterType = NOT_CENTER; + aType = theType; + } else if (aUseCenter != 1) continue; + + // check this is Part-name: 2 delimiters in the name + std::size_t aPartEnd = aSubShapeName.find('/'); + if (aPartEnd != std::string::npos && aPartEnd != aSubShapeName.rfind('/')) { + 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; + } } } - } - Model_SelectionNaming aSelNaming(selectionLabel()); - 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 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(); - while(aLab.Depth() != 7 && aLab.Depth() > 5) - aLab = aLab.Father(); - ObjectPtr anObj = aDoc->objects()->object(aLab); - if (anObj.get()) { - ResultPtr aRes = std::dynamic_pointer_cast(anObj); - if (aRes) - aCont = aRes; + Model_SelectionNaming aSelNaming(selectionLabel()); + std::shared_ptr aDoc = + std::dynamic_pointer_cast(owner()->document()); + 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(); + while(aLab.Depth() != 7 && aLab.Depth() > 5) + aLab = aLab.Father(); + ObjectPtr anObj = aDoc->objects()->object(aLab); + if (anObj.get()) { + ResultPtr aRes = std::dynamic_pointer_cast(anObj); + if (aRes) + aCont = aRes; + } } } } } + 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; } - setValue(aCont, aShapeToBeSelected); - return; } TDF_Label aSelLab = selectionLabel(); @@ -779,16 +971,18 @@ void Model_AttributeSelection::computeValues( ResultPtr theOldContext, ResultPtr theNewContext, TopoDS_Shape theValShape, TopTools_ListOfShape& theShapes) { - TopoDS_Shape anOldContShape = theOldContext->shape()->impl(); - TopoDS_Shape aNewContShape = theNewContext->shape()->impl(); - if (anOldContShape.IsSame(theValShape)) { // full context shape substituted by new full context - theShapes.Append(aNewContShape); - return; - } - if (theValShape.IsNull()) { - theShapes.Append(theValShape); - return; + bool aWasWholeContext = theValShape.IsNull(); + if (aWasWholeContext) { + //theShapes.Append(theValShape); + //return; + theValShape = theOldContext->shape()->impl(); } + //TopoDS_Shape anOldContShape = theOldContext->shape()->impl(); + TopoDS_Shape aNewContShape = theNewContext->shape()->impl(); + //if (anOldContShape.IsSame(theValShape)) { // full context shape substituted by new full context + //theShapes.Append(aNewContShape); + //return; + //} // if a new value is unchanged in the new context, do nothing: value is correct TopExp_Explorer aSubExp(aNewContShape, theValShape.ShapeType()); for(; aSubExp.More(); aSubExp.Next()) { @@ -872,8 +1066,9 @@ void Model_AttributeSelection::computeValues( } } } - if (theShapes.IsEmpty()) // nothing was changed - theShapes.Append(theValShape); + if (theShapes.IsEmpty()) { // nothing was changed + theShapes.Append(aWasWholeContext ? TopoDS_Shape() : theValShape); + } } bool Model_AttributeSelection::searchNewContext(std::shared_ptr theDoc, @@ -881,17 +1076,24 @@ bool Model_AttributeSelection::searchNewContext(std::shared_ptr TDF_Label theAccessLabel, std::list& theResults, TopTools_ListOfShape& theValShapes) { - std::set aResults; // to avoid duplicates + std::set aResults; // to avoid duplicates, new context, null if deleted TopTools_ListOfShape aResContShapes; TNaming_SameShapeIterator aModifIter(theContShape, theAccessLabel); for(; aModifIter.More(); aModifIter.Next()) { + TDF_Label anObjLab = aModifIter.Label().Father(); ResultPtr aModifierObj = std::dynamic_pointer_cast - (theDoc->objects()->object(aModifIter.Label().Father())); - if (!aModifierObj.get()) - break; + (theDoc->objects()->object(anObjLab)); + if (!aModifierObj.get()) { + // #2241: shape may be sub-element of new object, not main (shell created from faces) + if (!anObjLab.IsRoot()) + aModifierObj = std::dynamic_pointer_cast + (theDoc->objects()->object(anObjLab.Father())); + if (!aModifierObj.get()) + continue; + } FeaturePtr aModifierFeat = theDoc->feature(aModifierObj); if (!aModifierFeat.get()) - break; + continue; FeaturePtr aThisFeature = std::dynamic_pointer_cast(owner()); if (aModifierFeat == aThisFeature || theDoc->objects()->isLater(aModifierFeat, aThisFeature)) continue; // the modifier feature is later than this, so, should not be used @@ -903,11 +1105,11 @@ bool Model_AttributeSelection::searchNewContext(std::shared_ptr aModifIter.Label().FindAttribute(TNaming_NamedShape::GetID(), aNewNS); if (aNewNS->Evolution() == TNaming_MODIFY || aNewNS->Evolution() == TNaming_GENERATED) { aResults.insert(aModifierObj); - TNaming_Iterator aPairIter(aNewNS); - aResContShapes.Append(aPairIter.NewShape()); + //TNaming_Iterator aPairIter(aNewNS); + //aResContShapes.Append(aPairIter.NewShape()); + aResContShapes.Append(aModifierObj->shape()->impl()); } else if (aNewNS->Evolution() == TNaming_DELETE) { // a shape was deleted => result is empty aResults.insert(ResultPtr()); - aResContShapes.Append(TopoDS_Shape()); } else { // not-precessed modification => don't support it continue; } @@ -916,8 +1118,7 @@ bool Model_AttributeSelection::searchNewContext(std::shared_ptr return false; // no modifications found, must stay the same // iterate all results to find futher modifications std::set::iterator aResIter = aResults.begin(); - TopTools_ListOfShape::Iterator aResShapes(aResContShapes); - for(; aResIter != aResults.end(); aResIter++, aResShapes.Next()) { + for(; aResIter != aResults.end(); aResIter++) { if (aResIter->get() != NULL) { // compute new values by two contextes: the old and the new TopTools_ListOfShape aValShapes; @@ -927,7 +1128,11 @@ bool Model_AttributeSelection::searchNewContext(std::shared_ptr for(; aNewVal.More(); aNewVal.Next()) { std::list aNewRes; TopTools_ListOfShape aNewUpdatedVal; - if (searchNewContext(theDoc, aResShapes.Value(), *aResIter, aNewVal.Value(), + TopoDS_Shape aNewValSh = aNewVal.Value(); + TopoDS_Shape aNewContShape = (*aResIter)->shape()->impl(); + if (theValShape.IsNull() && aNewContShape.IsSame(aNewValSh)) + aNewValSh.Nullify(); + if (searchNewContext(theDoc, aNewContShape, *aResIter, aNewValSh, theAccessLabel, aNewRes, aNewUpdatedVal)) { // appeand new results instead of the current ones @@ -939,7 +1144,7 @@ bool Model_AttributeSelection::searchNewContext(std::shared_ptr } } else { // the current result is good theResults.push_back(*aResIter); - theValShapes.Append(aNewVal.Value()); + theValShapes.Append(aNewValSh); } } } @@ -950,18 +1155,52 @@ bool Model_AttributeSelection::searchNewContext(std::shared_ptr void Model_AttributeSelection::updateInHistory() { ResultPtr aContext = std::dynamic_pointer_cast(myRef.value()); - // only bodies may be modified later in the history, don't do anything otherwise - if (!aContext.get() || aContext->groupName() != ModelAPI_ResultBody::group()) + // only bodies and parts may be modified later in the history, don't do anything otherwise + if (!aContext.get() || (aContext->groupName() != ModelAPI_ResultBody::group() && + aContext->groupName() != ModelAPI_ResultPart::group())) return; + std::shared_ptr aDoc = + std::dynamic_pointer_cast(aContext->document()); 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 Handle(TNaming_NamedShape) aContNS; - if (!aContLab.FindAttribute(TNaming_NamedShape::GetID(), aContNS)) + if (!aContLab.FindAttribute(TNaming_NamedShape::GetID(), aContNS)) { + bool aFoundNewContext = true; + ResultPtr aNewContext = aContext; + while(aFoundNewContext) { + aFoundNewContext = false; + // parts have no shape in result, so, trace references using the Part info + if (aNewContext->groupName() == ModelAPI_ResultPart::group()) { + ResultPartPtr aPartContext = std::dynamic_pointer_cast(aNewContext); + if (aPartContext.get()) { // searching for the up to date references to the referenced cont + const std::set& aRefs = aPartContext->data()->refsToMe(); + std::set::const_iterator aRef = aRefs.begin(); + for(; aRef != aRefs.end(); aRef++) { + // to avoid detection of part changes by local selection only + AttributeSelectionPtr aSel = + std::dynamic_pointer_cast(*aRef); + if (aSel.get() && !aSel->value()->isSame(aSel->context()->shape())) + continue; + + 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 + aFoundNewContext = true; + aNewContext = aRefFeat->firstResult(); + } + } + } + } + } + } + if (aNewContext != aContext) { + setValue(aNewContext, value()); + } return; - std::shared_ptr aDoc = - std::dynamic_pointer_cast(aContext->document()); + } FeaturePtr aThisFeature = std::dynamic_pointer_cast(owner()); FeaturePtr aCurrentModifierFeat = aDoc->feature(aContext); // iterate the context shape modifications in order to find a feature that is upper in history