X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FModel%2FModel_AttributeSelection.cpp;h=1e8aca1927a429aca3eb9b1037ccccc75d11becf;hb=f3af7540eb79629e249c042f590478eb3623f12c;hp=7348703eeb17c95499f749f23305f4cee53a7d7b;hpb=5c59bf6725e7e4855b5ca956475d705e2d5b014c;p=modules%2Fshaper.git diff --git a/src/Model/Model_AttributeSelection.cpp b/src/Model/Model_AttributeSelection.cpp index 7348703ee..1e8aca192 100644 --- a/src/Model/Model_AttributeSelection.cpp +++ b/src/Model/Model_AttributeSelection.cpp @@ -47,6 +47,8 @@ #include #include #include +#include +#include #include #include #include @@ -54,6 +56,7 @@ #include #include #include +#include //#define DEB_NAMING 1 #ifdef DEB_NAMING @@ -772,6 +775,178 @@ std::string Model_AttributeSelection::contextName(const ResultPtr& theContext) c return aResult; } +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; + } + // 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()) { + if (aSubExp.Current().IsSame(theValShape)) { + theShapes.Append(theValShape); + return; + } + } + // if new context becomes compsolid, the resulting sub may be in sub-solids + std::list aNewToIterate; + aNewToIterate.push_back(theNewContext); + ResultCompSolidPtr aComp = std::dynamic_pointer_cast(theNewContext); + if (aComp.get()) { + for(int a = 0; a < aComp->numberOfSubs(); a++) + aNewToIterate.push_back(aComp->subResult(a, false)); + } + + // first iteration: searching for the whole shape appearance (like face of the box) + // second iteration: searching for sub-shapes that contain the sub (like vertex on faces) + int aToFindPart = 0; + TopTools_DataMapOfShapeShape aNewToOld; // map from new containers to old containers (with val) + TopTools_MapOfShape anOlds; // to know how many olds produced new containers + for(; aToFindPart != 2 && theShapes.IsEmpty(); aToFindPart++) { + std::list::iterator aNewContIter = aNewToIterate.begin(); + for(; aNewContIter != aNewToIterate.end(); aNewContIter++) { + std::shared_ptr aNewData = + std::dynamic_pointer_cast((*aNewContIter)->data()); + TDF_Label aNewLab = aNewData->label(); + // searching for produced sub-shape fully on some label + TDF_ChildIDIterator aNSIter(aNewLab, TNaming_NamedShape::GetID(), Standard_True); + for(; aNSIter.More(); aNSIter.Next()) { + Handle(TNaming_NamedShape) aNS = Handle(TNaming_NamedShape)::DownCast(aNSIter.Value()); + for(TNaming_Iterator aPairIter(aNS); aPairIter.More(); aPairIter.Next()) { + if (aToFindPart == 0) { // search shape is fully inside + if (aPairIter.OldShape().IsSame(theValShape)) { + if (aPairIter.NewShape().IsNull()) {// value was removed + theShapes.Clear(); + return; + } + theShapes.Append(aPairIter.NewShape()); + } + } else if (!aPairIter.OldShape().IsNull()) { // search shape that contains this sub + TopExp_Explorer anExp(aPairIter.OldShape(), theValShape.ShapeType()); + for(; anExp.More(); anExp.Next()) { + if (anExp.Current().IsSame(theValShape)) { // found a new container + if (aPairIter.NewShape().IsNull()) {// value was removed + theShapes.Clear(); + return; + } + aNewToOld.Bind(aPairIter.NewShape(), aPairIter.OldShape()); + anOlds.Add(aPairIter.OldShape()); + break; + } + } + } + } + } + } + } + if (aToFindPart == 2 && !aNewToOld.IsEmpty()) { + // map of sub-shapes -> number of occurences of these shapes in containers + NCollection_DataMap aSubs; + TopTools_DataMapOfShapeShape::Iterator aContIter(aNewToOld); + for(; aContIter.More(); aContIter.Next()) { + TopExp_Explorer aSubExp(aContIter.Key(), theValShape.ShapeType()); + for(; aSubExp.More(); aSubExp.Next()) { + if (!aSubs.IsBound(aSubExp.Current())) { + aSubs.Bind(aSubExp.Current(), TopTools_MapOfShape()); + } + // store old to know how many olds produced this shape + aSubs.ChangeFind(aSubExp.Current()).Add(aContIter.Value()); + } + } + // if sub is appeared same times in containers as the number of old shapes that contain it + int aCountInOld = anOlds.Size(); + NCollection_DataMap::Iterator + aSubsIter(aSubs); + for(; aSubsIter.More(); aSubsIter.Next()) { + if (aSubsIter.Value().Size() == aCountInOld) { + theShapes.Append(aSubsIter.Key()); + } + } + } + if (theShapes.IsEmpty()) // nothing was changed + theShapes.Append(theValShape); +} + +bool Model_AttributeSelection::searchNewContext(std::shared_ptr theDoc, + const TopoDS_Shape theContShape, ResultPtr theContext, TopoDS_Shape theValShape, + TDF_Label theAccessLabel, + std::list& theResults, TopTools_ListOfShape& theValShapes) +{ + std::set aResults; // to avoid duplicates + TopTools_ListOfShape aResContShapes; + TNaming_SameShapeIterator aModifIter(theContShape, theAccessLabel); + for(; aModifIter.More(); aModifIter.Next()) { + ResultPtr aModifierObj = std::dynamic_pointer_cast + (theDoc->objects()->object(aModifIter.Label().Father())); + if (!aModifierObj.get()) + break; + FeaturePtr aModifierFeat = theDoc->feature(aModifierObj); + if (!aModifierFeat.get()) + break; + 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 + FeaturePtr aCurrentModifierFeat = theDoc->feature(theContext); + if (aCurrentModifierFeat == aModifierFeat || + theDoc->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); + if (aNewNS->Evolution() == TNaming_MODIFY || aNewNS->Evolution() == TNaming_GENERATED) { + aResults.insert(aModifierObj); + TNaming_Iterator aPairIter(aNewNS); + aResContShapes.Append(aPairIter.NewShape()); + } 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; + } + } + if (aResults.empty()) + 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()) { + if (aResIter->get() != NULL) { + // compute new values by two contextes: the old and the new + TopTools_ListOfShape aValShapes; + computeValues(theContext, *aResIter, theValShape, aValShapes); + + TopTools_ListIteratorOfListOfShape aNewVal(aValShapes); + for(; aNewVal.More(); aNewVal.Next()) { + std::list aNewRes; + TopTools_ListOfShape aNewUpdatedVal; + if (searchNewContext(theDoc, aResShapes.Value(), *aResIter, aNewVal.Value(), + theAccessLabel, aNewRes, aNewUpdatedVal)) + { + // appeand new results instead of the current ones + std::list::iterator aNewIter = aNewRes.begin(); + TopTools_ListIteratorOfListOfShape aNewUpdVal(aNewUpdatedVal); + for(; aNewIter != aNewRes.end(); aNewIter++, aNewUpdVal.Next()) { + theResults.push_back(*aNewIter); + theValShapes.Append(aNewUpdVal.Value()); + } + } else { // the current result is good + theResults.push_back(*aResIter); + theValShapes.Append(aNewVal.Value()); + } + } + } + } + return true; // theResults must be empty: everything is deleted +} + void Model_AttributeSelection::updateInHistory() { ResultPtr aContext = std::dynamic_pointer_cast(myRef.value()); @@ -795,66 +970,50 @@ void Model_AttributeSelection::updateInHistory() TNaming_Iterator aPairIter(aContNS); if (!aPairIter.More()) return; - TopoDS_Shape aNewShape = aPairIter.NewShape(); + TopoDS_Shape aNewCShape = aPairIter.NewShape(); bool anIterate = true; // trying to update also the sub-shape selected GeomShapePtr aSubShape = value(); if (aSubShape.get() && aSubShape->isEqual(aContext->shape())) aSubShape.reset(); - - while(anIterate) { - anIterate = false; - TNaming_SameShapeIterator aModifIter(aNewShape, aContLab); - 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)) - continue; // the modifier feature is later than this, so, should not be used - 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); - if (aNewNS->Evolution() == TNaming_MODIFY || aNewNS->Evolution() == TNaming_GENERATED) { - aModifierResFound = aModifierObj; - aCurrentModifierFeat = aModifierFeat; - TNaming_Iterator aPairIter(aNewNS); - aNewShape = aPairIter.NewShape(); - anIterate = true; - break; - } 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 - continue; - } - } + TopoDS_Shape aValShape; + if (aSubShape.get()) { + aValShape = aSubShape->impl(); } - if (aModifierResFound.get()) { + + std::list aNewContexts; + TopTools_ListOfShape aValShapes; + if (searchNewContext(aDoc, aNewCShape, aContext, aValShape, aContLab, aNewContexts, aValShapes)) + { // update scope to reset to a new one myScope.Clear(); - myRef.setValue(aModifierResFound); - // 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()); + + std::list::iterator aNewCont = aNewContexts.begin(); + TopTools_ListIteratorOfListOfShape aNewValues(aValShapes); + if (aNewCont == aNewContexts.end()) { // all results were deleted + ResultPtr anEmptyContext; + std::shared_ptr anEmptyShape; + setValue(anEmptyContext, anEmptyShape); // nullify the selection + return; + } + + GeomShapePtr aValueShape; + if (!aNewValues.Value().IsNull()) { + aValueShape = std::make_shared(); + aValueShape->setImpl(new TopoDS_Shape(aNewValues.Value())); + } + setValue(*aNewCont, aValueShape); + // if there are more than one result, put them by "append" into "parent" list + if (myParent) { + for(aNewCont++, aNewValues.Next(); aNewCont != aNewContexts.end(); aNewCont++, aNewValues.Next()) { + GeomShapePtr aValueShape; + if (!aNewValues.Value().IsNull()) { + aValueShape = std::make_shared(); + aValueShape->setImpl(new TopoDS_Shape(aNewValues.Value())); + } + myParent->append(*aNewCont, aValueShape); } } - update(); // it must recompute a new sub-shape automatically } }