X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FModel%2FModel_AttributeSelection.cpp;h=d2456c85e199fa4bb5f7838cf14d78549250d2a8;hb=f6bd0f4e080b833c0de7ef25822ebee641073445;hp=344ee30ee36009e59b2dea139d2c2b92d3b907ac;hpb=fca793bae8f8cf8499d03d05406f610971c9ea37;p=modules%2Fshaper.git diff --git a/src/Model/Model_AttributeSelection.cpp b/src/Model/Model_AttributeSelection.cpp index 344ee30ee..d2456c85e 100644 --- a/src/Model/Model_AttributeSelection.cpp +++ b/src/Model/Model_AttributeSelection.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -90,28 +91,31 @@ Standard_GUID kELLIPSE_CENTER2("1395ae73-8e02-4cf8-b204-06ff35873a32"); // 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 + bool aToUnblock = false; // update the referenced object if needed if (!isOldContext) { - myRef.setValue(theContext); + aToUnblock = !owner()->data()->blockSendAttributeUpdated(true); + myRef.setValue(theContext); } // do noth use naming if selected shape is result shape itself, but not sub-shape @@ -134,7 +138,9 @@ 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; + if (aToUnblock) + owner()->data()->blockSendAttributeUpdated(false); + 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 @@ -153,6 +159,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()) { @@ -162,32 +174,58 @@ void Model_AttributeSelection::setValue(const ResultPtr& theContext, } owner()->data()->sendAttributeUpdated(this); + + if (aToUnblock) + owner()->data()->blockSendAttributeUpdated(false); + + return true; } void Model_AttributeSelection::setValueCenter( const ResultPtr& theContext, const std::shared_ptr& theEdge, const CenterType theCenterType, const bool theTemporarily) { - setValue(theContext, theEdge, 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; } - owner()->data()->sendAttributeUpdated(this); + 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() { @@ -235,6 +273,8 @@ GeomShapePtr centerByEdge(GeomShapePtr theEdge, ModelAPI_AttributeSelection::Cen std::shared_ptr Model_AttributeSelection::value() { + if (!ModelAPI_AttributeSelection::isInitialized() && !myTmpContext.get() && !myTmpSubShape.get()) + return std::shared_ptr(); CenterType aType = NOT_CENTER; std::shared_ptr aResult = internalValue(aType); return centerByEdge(aResult, aType); @@ -298,21 +338,23 @@ std::shared_ptr Model_AttributeSelection::internalValue(CenterTyp } } + 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()); } } } @@ -367,6 +409,11 @@ void Model_AttributeSelection::setID(const std::string theID) } ResultPtr Model_AttributeSelection::context() { + /* + if (!ModelAPI_AttributeSelection::isInitialized() && !myTmpContext.get() && !myTmpSubShape.get()) + return ResultPtr(); + */ + if (myTmpContext.get() || myTmpSubShape.get()) { return myTmpContext; } @@ -416,13 +463,14 @@ TDF_LabelMap& Model_AttributeSelection::scope() } } // for group Scope is not limitet: this is always up to date objects - bool isGroup = aFeature.get() && aFeature->getKind() == "Group"; + // 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; + //if (isGroup) aMePassed = false; bool isInScope = !aMePassed; if (!isInScope && aComposite.get()) { // try to add sub-elements of composite if this is composite @@ -552,6 +600,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; @@ -622,7 +675,7 @@ void Model_AttributeSelection::selectBody( bool isFound = false; TopExp_Explorer anExp(aNewContext, aNewSub.ShapeType()); for(; anExp.More(); anExp.Next()) { - if (anExp.Current().IsEqual(aNewSub)) { + if (anExp.Current().IsSame(aNewSub)) { isFound = true; break; } @@ -828,6 +881,81 @@ void Model_AttributeSelection::selectSubShape( } } } + // if compsolid is context, try to take sub-solid as context: like in GUI and scripts + if (aCont.get() && aShapeToBeSelected.get()) { + ResultCompSolidPtr aComp = std::dynamic_pointer_cast(aCont); + if (aComp && aComp->numberOfSubs()) { + for(int aSubNum = 0; aSubNum < aComp->numberOfSubs(); aSubNum++) { + ResultPtr aSub = aComp->subResult(aSubNum); + if (aSub && aSub->shape().get() && aSub->shape()->isSubShape(aShapeToBeSelected)) { + aCont = aSub; + break; + } + } + } + } + // 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 + ResultCompSolidPtr aCompContext = ModelAPI_Tools::compSolidOwner(aCont); + int aSubsSize = (aCompContext.get() ? aCompContext->numberOfSubs() : 0) + 1; + for(int aResultNum = 0; aResultNum < aSubsSize; aResultNum++) { + ResultPtr aResCont = aCont; + if (aCompContext.get()) + if (aResultNum == aSubsSize - 1) + aResCont = aCompContext; + else aResCont = aCompContext->subResult(aResultNum); + 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 + const std::list >& aFResults = aRefFeat->results(); + std::list >::const_iterator aRIter = aFResults.begin(); + for (; aRIter != aFResults.cend(); aRIter++) { + // iterate sub-bodies of compsolid + ResultCompSolidPtr aComp = + std::dynamic_pointer_cast(*aRIter); + if (aComp.get() && aComp->numberOfSubs() > 0) { + int aNumSub = aComp->numberOfSubs(); + for(int a = 0; a < aNumSub; a++) { + aResults.push_back(aComp->subResult(a)); + } + } else { + aResults.push_back(*aRIter); + } + } + 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 + //if (!aShape->isSubShape(aShapeToBeSelected, true)) // take context orientation + // aShapeToBeSelected->setOrientation(); + aFindNewContext = true; // continue searching futher + break; + } + } + } + } + } + if (aCenterType != NOT_CENTER) { if (!aShapeToBeSelected->isEdge()) continue; @@ -1042,40 +1170,50 @@ bool Model_AttributeSelection::searchNewContext(std::shared_ptr { 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(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()) + // iterate context and shape, but also if it is sub-shape of main shape, check also it + TopTools_ListOfShape aContextList; + aContextList.Append(theContShape); + if (theContext.get()) { + ResultPtr aComposite = ModelAPI_Tools::compSolidOwner(theContext); + if (aComposite.get() && aComposite->shape().get() && !aComposite->shape()->isNull()) + aContextList.Append(aComposite->shape()->impl()); + } + for(TopTools_ListOfShape::Iterator aContIter(aContextList); aContIter.More(); aContIter.Next()) { + TNaming_SameShapeIterator aModifIter(aContIter.ChangeValue(), theAccessLabel); + for(; aModifIter.More(); aModifIter.Next()) { + TDF_Label anObjLab = aModifIter.Label().Father(); + ResultPtr aModifierObj = std::dynamic_pointer_cast + (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()) continue; - } - FeaturePtr aModifierFeat = theDoc->feature(aModifierObj); - if (!aModifierFeat.get()) - 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 - 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()); - 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 - 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 + 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()); + 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 + continue; + } } } if (aResults.empty())