X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2FModel%2FModel_AttributeSelection.cpp;h=21cb7ee6eea0c727911709f3198dfa62a1dbabd0;hb=745c72679f6346375d5e886b25cc3865f3c4daae;hp=496f1e2afffb3f1dd3953076fbe0c2c7c0f74dff;hpb=2cb4458b35ae6c9561a35b3b18dbdb673d0c12c9;p=modules%2Fshaper.git diff --git a/src/Model/Model_AttributeSelection.cpp b/src/Model/Model_AttributeSelection.cpp index 496f1e2af..21cb7ee6e 100644 --- a/src/Model/Model_AttributeSelection.cpp +++ b/src/Model/Model_AttributeSelection.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2019 CEA/DEN, EDF R&D +// Copyright (C) 2014-2021 CEA/DEN, EDF R&D // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -46,6 +46,8 @@ #include #include +#include + #include #include #include @@ -94,7 +96,7 @@ Standard_GUID kELLIPSE_CENTER1("f70df04c-3168-4dc9-87a4-f1f840c1275d"); Standard_GUID kELLIPSE_CENTER2("1395ae73-8e02-4cf8-b204-06ff35873a32"); // prefix for the whole feature context identification -const static std::string kWHOLE_FEATURE = "all-in-"; +const static std::wstring kWHOLE_FEATURE = L"all-in-"; // on this label is stored: // TNaming_NamedShape - selected shape @@ -146,8 +148,6 @@ bool Model_AttributeSelection::setValue(const ObjectPtr& theContext, isDegeneratedEdge = BRep_Tool::Degenerated(TopoDS::Edge(aSubShape)) == Standard_True; } if (!theContext.get() || isDegeneratedEdge) { - // to keep the reference attribute label - TDF_Label aRefLab = myRef.myRef->Label(); aSelLab.ForgetAllAttributes(true); myRef.myRef = TDF_Reference::Set(aSelLab.Father(), aSelLab.Father()); if (aToUnblock) @@ -185,10 +185,11 @@ bool Model_AttributeSelection::setValue(const ObjectPtr& theContext, } else if (theContext->groupName() == ModelAPI_ResultGroup::group()) { aSelLab.ForgetAllAttributes(true); TDataStd_UAttribute::Set(aSelLab, kSIMPLE_REF_ID); - } else { // check the feature context: parent-Part of this feature should not be used + } else { // check the feature context: only construction features of PartSet could be selected FeaturePtr aFeatureContext = std::dynamic_pointer_cast(theContext); - if (aFeatureContext.get()) { - if (owner()->document() != aFeatureContext->document()) { + if (aFeatureContext.get() && owner()->document() != aFeatureContext->document()) { + if (aFeatureContext->results().empty() || + aFeatureContext->firstResult()->groupName() != ModelAPI_ResultConstruction::group()) { aSelLab.ForgetAllAttributes(true); myRef.setValue(ObjectPtr()); if (aToUnblock) @@ -231,6 +232,8 @@ void Model_AttributeSelection::setValueCenter( anUpdated = !aSelLab.IsAttribute(kELLIPSE_CENTER2); TDataStd_UAttribute::Set(aSelLab, kELLIPSE_CENTER2); break; + default: // [to avoid compilation warning] + break; } if (anUpdated) owner()->data()->sendAttributeUpdated(this); @@ -260,7 +263,7 @@ void Model_AttributeSelection::removeTemporaryValues() } } -// returns the center of the edge: circular or elliptical +// returns the center of the edge: circular or elliptic GeomShapePtr centerByEdge(GeomShapePtr theEdge, ModelAPI_AttributeSelection::CenterType theType) { if (theType != ModelAPI_AttributeSelection::NOT_CENTER && theEdge.get() != NULL) { @@ -302,7 +305,7 @@ GeomShapePtr centerByEdge(GeomShapePtr theEdge, ModelAPI_AttributeSelection::Cen std::shared_ptr Model_AttributeSelection::value() { - if (!ModelAPI_AttributeSelection::isInitialized() && !myTmpContext.get() && !myTmpSubShape.get()) + if (!myRef.isInitialized() && !myTmpContext.get() && !myTmpSubShape.get()) return std::shared_ptr(); CenterType aType = NOT_CENTER; std::shared_ptr aResult = internalValue(aType); @@ -361,13 +364,13 @@ std::shared_ptr Model_AttributeSelection::internalValue(CenterTyp } else { // face with name is already in the data model, so try to take it by name Handle(TDataStd_Name) aName; if (aSelLab.FindAttribute(TDataStd_Name::GetID(), aName)) { - std::string aSubShapeName(TCollection_AsciiString(aName->Get()).ToCString()); - std::size_t aPartEnd = aSubShapeName.find('/'); - if (aPartEnd != std::string::npos && aPartEnd != aSubShapeName.rfind('/')) { - std::string aNameInPart = aSubShapeName.substr(aPartEnd + 1); - int anIndex; + std::wstring aSubShapeName = Locale::Convert::toWString(aName->Get().ToExtString()); + std::size_t aPartEnd = aSubShapeName.find(L'/'); + if (aPartEnd != std::wstring::npos && aPartEnd != aSubShapeName.rfind(L'/')) { + std::wstring aNameInPart = aSubShapeName.substr(aPartEnd + 1); + int anInd; std::string aType; // to reuse already existing selection the type is not needed - return aPart->shapeInPart(aNameInPart, aType, anIndex); + return aPart->shapeInPart(aNameInPart, aType, anInd); } } } @@ -421,32 +424,29 @@ bool Model_AttributeSelection::isInvalid() bool Model_AttributeSelection::isInitialized() { - if (ModelAPI_AttributeSelection::isInitialized()) { // additional checks if it is initialized - std::shared_ptr aResult; - if (myRef.isInitialized()) { - TDF_Label aSelLab = selectionLabel(); - // it is just reference to shape, not sub-shape - if (aSelLab.IsAttribute(kSIMPLE_REF_ID) || aSelLab.IsAttribute(kPART_REF_ID)) { - ResultPtr aContext = context(); - return aContext.get() != NULL; - } - 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 - if (myRef.value().get()) - return true; - // check that this is on open of document, so, results are not initialized yet - TDF_Label aRefLab = myRef.myRef->Get(); - if (aRefLab.IsNull() || !owner().get()) - return false; - std::shared_ptr aMyDoc = - std::dynamic_pointer_cast(owner()->document()); - if (!aMyDoc.get()) - return false; - // check at least the feature exists - return aMyDoc->featureByLab(aRefLab).get() != NULL; - } + if (myRef.isInitialized()) { + TDF_Label aSelLab = selectionLabel(); + // it is just reference to shape, not sub-shape + if (aSelLab.IsAttribute(kSIMPLE_REF_ID) || aSelLab.IsAttribute(kPART_REF_ID)) { + ResultPtr aContext = context(); + return aContext.get() != NULL; + } + 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 + if (myRef.value().get()) + return true; + // check that this is on open of document, so, results are not initialized yet + TDF_Label aRefLab = myRef.myRef->Get(); + if (aRefLab.IsNull() || !owner().get()) + return false; + std::shared_ptr aMyDoc = + std::dynamic_pointer_cast(owner()->document()); + if (!aMyDoc.get()) + return false; + // check at least the feature exists + return aMyDoc->featureByLab(aRefLab).get() != NULL; } } return false; @@ -476,7 +476,7 @@ void Model_AttributeSelection::setID(const std::string theID) ResultPtr Model_AttributeSelection::context() { - if (!ModelAPI_AttributeSelection::isInitialized() && !myTmpContext.get() && !myTmpSubShape.get()) + if (!myRef.isInitialized() && !myTmpContext.get() && !myTmpSubShape.get()) return ResultPtr(); if (myTmpContext.get() || myTmpSubShape.get()) { @@ -559,7 +559,7 @@ void Model_AttributeSelection::split( aSubSh->setImpl(new TopoDS_Shape(aSub.Value())); setValue(theContext, aSubSh); for(aSub.Next(); aSub.More(); aSub.Next()) { - GeomShapePtr aSubSh(new GeomAPI_Shape); + aSubSh.reset(new GeomAPI_Shape); aSubSh->setImpl(new TopoDS_Shape(aSub.Value())); myParent->append(theContext, aSubSh); } @@ -602,19 +602,56 @@ bool Model_AttributeSelection::update() TopoDS_Shape aContextShape = aContext->shape()->impl(); Selector_Selector aSelector(aSelLab, baseDocumentLab()); aResult = aSelector.restore(aContextShape); + bool aWasInvalid = aSelLab.IsAttribute(kINVALID_SELECTION); setInvalidIfFalse(aSelLab, aResult); TopoDS_Shape aNewShape; if (aSelLab.FindAttribute(TNaming_NamedShape::GetID(), aNS)) aNewShape = aNS->Get(); - if (anOldShape.IsNull() || aNewShape.IsNull() || !anOldShape.IsEqual(aNewShape)) { + // check the selected value is a part of the context + if (aResult && !aNewShape.IsNull() && !aContextShape.IsNull() && + !aContextShape.IsSame(aNewShape)) { + TopoDS_Shape aNewS = aNewShape; + // take only sub-shape of composite for checking + if (aNewS.ShapeType() == TopAbs_WIRE || aNewS.ShapeType() == TopAbs_SHELL || + aNewS.ShapeType() == TopAbs_COMPOUND || aNewS.ShapeType() == TopAbs_COMPSOLID) { + TopoDS_Iterator anIter(aNewS); + if (anIter.More()) + aNewS = anIter.Value(); + } + bool anIsInside = false; + TopExp_Explorer anExp(aContextShape, aNewS.ShapeType()); + for (; anExp.More() && !anIsInside; anExp.Next()) { + if (anExp.Current().IsSame(aNewS)) + anIsInside = true; + } + if (!anIsInside) { + aResult = false; + aNewShape.Nullify(); + setInvalidIfFalse(aSelLab, aResult); + } + } + + if (anOldShape.IsNull() || aNewShape.IsNull() || !anOldShape.IsEqual(aNewShape) || aWasInvalid) + { // shape type should not be changed: if shape becomes compound of such shapes, then split if (myParent && !anOldShape.IsNull() && !aNewShape.IsNull() && anOldShape.ShapeType() != aNewShape.ShapeType() && aNewShape.ShapeType() == TopAbs_COMPOUND) { split(aContext, aNewShape, anOldShape.ShapeType()); } + // for issue #3076 check that the new value belongs to the new context + if (!aNewShape.IsNull() && !aContextShape.IsNull() && + (aNewShape.ShapeType() == TopAbs_VERTEX || aNewShape.ShapeType() == TopAbs_EDGE || + aNewShape.ShapeType() == TopAbs_FACE)) { + TopExp_Explorer anExp(aContextShape, aNewShape.ShapeType()); + for(; anExp.More(); anExp.Next()) { + if (anExp.Current().IsSame(aNewShape)) + break; + } + aResult = setInvalidIfFalse(aSelLab, anExp.More()); + } owner()->data()->sendAttributeUpdated(this); // send updated if shape is changed } return aResult; @@ -704,13 +741,13 @@ bool Model_AttributeSelection::selectPart( } // store the shape (in case part is not loaded it should be useful TopoDS_Shape aShape; - std::string aName = theContext->data()->name(); + std::wstring aName = theContext->data()->name(); if (!theSubShape.get() || theSubShape->isNull()) {// the whole part shape is selected aShape = theContext->shape()->impl(); } else { aShape = theSubShape->impl(); int anIndex; - aName += "/" + aPart->nameInPart(theSubShape, anIndex); + aName += L"/" + aPart->nameInPart(theSubShape, anIndex); TDataStd_Integer::Set(selectionLabel(), anIndex); } TNaming_Builder aBuilder(selectionLabel()); @@ -726,22 +763,22 @@ TDF_Label Model_AttributeSelection::selectionLabel() } /// prefixes of the shape names with centers defined -static std::map kCENTERS_PREFIX; +static std::map kCENTERS_PREFIX; /// returns the map that contains all possible prefixes of the center-names -static std::map& centersMap() +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"; + kCENTERS_PREFIX[ModelAPI_AttributeSelection::CIRCLE_CENTER] = L"__cc"; + kCENTERS_PREFIX[ModelAPI_AttributeSelection::ELLIPSE_FIRST_FOCUS] = L"__eff"; + kCENTERS_PREFIX[ModelAPI_AttributeSelection::ELLIPSE_SECOND_FOCUS] = L"__esf"; } return kCENTERS_PREFIX; } -std::string Model_AttributeSelection::namingName(const std::string& theDefaultName) +std::wstring Model_AttributeSelection::namingName(const std::wstring& theDefaultName) { - std::string aName(""); + std::wstring aName(L""); if(!this->isInitialized()) return !theDefaultName.empty() ? theDefaultName : aName; @@ -750,32 +787,39 @@ std::string Model_AttributeSelection::namingName(const std::string& theDefaultNa GeomShapePtr aShape = value(); if (!aShape.get() && context().get()) aShape = context()->shape(); - std::string aName; + std::wstring aNotArgName; if (aShape.get()) { - aName = aShape->shapeTypeStr(); + aNotArgName = Locale::Convert::toWString(aShape->shapeTypeStr()); if (myParent) { - aName += std::string("_") + - TCollection_AsciiString(selectionLabel().Father().Tag()).ToCString(); + std::wostringstream aStream; + aStream << "_" << selectionLabel().Father().Tag(); + aNotArgName += aStream.str(); } } - return aName; + return aNotArgName; } CenterType aCenterType = NOT_CENTER; std::shared_ptr aSubSh = internalValue(aCenterType); - ResultPtr aCont = context(); - if (!aCont.get() || - (aCont->groupName() == ModelAPI_ResultConstruction::group() && contextFeature().get())) { + FeaturePtr aContFeature = contextFeature(); + if (aContFeature.get()) { + std::wstring aResName; + // checking part-owner + if (aContFeature->document() != owner()->document()) + aResName += Locale::Convert::toWString(aContFeature->document()->kind()) + L"/"; // selection of a full feature - FeaturePtr aFeatureCont = contextFeature(); - if (aFeatureCont.get()) { - return kWHOLE_FEATURE + aFeatureCont->name(); + if (aContFeature.get()) { + return aResName + kWHOLE_FEATURE + aContFeature->name(); } // in case of selection of removed result - return ""; + return L""; } + ResultPtr aCont = context(); + if (!aCont.get()) { + return L""; // invalid case + } TDF_Label aSelLab = selectionLabel(); if (aSelLab.IsAttribute(kSIMPLE_REF_ID)) { // whole context, no value return contextName(aCont); @@ -785,14 +829,14 @@ std::string Model_AttributeSelection::namingName(const std::string& theDefaultNa if (aCont->groupName() == ModelAPI_ResultPart::group()) { ResultPartPtr aPart = std::dynamic_pointer_cast(aCont); int anIndex; - GeomShapePtr aValue = value(); - if (aValue.get()) - return aPart->data()->name() + "/" + aPart->nameInPart(aValue, anIndex); - else - return aPart->data()->name(); + std::wstring aResult = aSubSh.get() ? + aPart->data()->name() + L"/" + aPart->nameInPart(aSubSh, anIndex) + : aPart->data()->name(); + if (aCenterType != NOT_CENTER) + aResult += centersMap()[aCenterType]; + return aResult; } - // whole infinitive construction if (aCont->groupName() == ModelAPI_ResultConstruction::group()) { ResultConstructionPtr aConstr = std::dynamic_pointer_cast(aCont); @@ -802,7 +846,7 @@ std::string Model_AttributeSelection::namingName(const std::string& theDefaultNa } Selector_Selector aSelector(aSelLab, baseDocumentLab()); - std::string aResult; + std::wstring aResult; if (aCont->shape().get() && aSelector.restore(aCont->shape()->impl())) aResult = aSelector.name(this); if (aCenterType != NOT_CENTER) { @@ -812,13 +856,13 @@ std::string Model_AttributeSelection::namingName(const std::string& theDefaultNa } // returns the center type and modifies the shape name if this name is center-name -static ModelAPI_AttributeSelection::CenterType centerTypeByName(std::string& theShapeName) +static ModelAPI_AttributeSelection::CenterType centerTypeByName(std::wstring& theShapeName) { - std::map::iterator aPrefixIter = + std::map::iterator aPrefixIter = centersMap().begin(); for(; aPrefixIter != centersMap().end(); aPrefixIter++) { std::size_t aFound = theShapeName.find(aPrefixIter->second); - if (aFound != std::string::npos && + if (aFound != std::wstring::npos && aFound == theShapeName.size() - aPrefixIter->second.size()) { theShapeName = theShapeName.substr(0, aFound); return aPrefixIter->first; @@ -829,11 +873,11 @@ static ModelAPI_AttributeSelection::CenterType centerTypeByName(std::string& the // type ::= COMP | COMS | SOLD | SHEL | FACE | WIRE | EDGE | VERT void Model_AttributeSelection::selectSubShape( - const std::string& theType, const std::string& theSubShapeName) + const std::string& theType, const std::wstring& theSubShapeName) { if(theSubShapeName.empty() || theType.empty()) return; - std::string aSubShapeName = theSubShapeName; + std::wstring 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 @@ -852,19 +896,20 @@ void Model_AttributeSelection::selectSubShape( 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) { - std::string aPartName = aSubShapeName.substr(0, aPartEnd); + std::size_t aPartEnd = aSubShapeName.find(L'/'); + if (aPartEnd != std::wstring::npos) { + std::wstring aPartName = aSubShapeName.substr(0, aPartEnd); DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument(); - if (aPartName == aRootDoc->kind()) { + if (aPartName == Locale::Convert::toWString(aRootDoc->kind())) { aDoc = std::dynamic_pointer_cast(aRootDoc); aSubShapeName = aSubShapeName.substr(aPartEnd + 1); - } else { + } + 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); - std::string aNameInPart = aSubShapeName.substr(aPartEnd + 1); + std::wstring aNameInPart = aSubShapeName.substr(aPartEnd + 1); if (aNameInPart.empty()) { // whole part setValue(aPart, anEmptyShape); return; @@ -878,11 +923,28 @@ void Model_AttributeSelection::selectSubShape( continue; std::shared_ptr aSelectedEdge(new GeomAPI_Edge(aSelected)); setValueCenter(aPart, aSelectedEdge, aCenterType); - } else + } + else setValue(aPart, aSelected); TDataStd_Integer::Set(selectionLabel(), anIndex); return; } + } else { // for the ImportResult feature Objects widget this may be a result in other part + // result may be hidden (like, tranlsatiomn of part) in PartSet, so iterate Part-features + int aNum = aRootDoc->size(ModelAPI_Feature::group()); + for (int a = 0; a < aNum; a++) { + FeaturePtr aFeat = std::dynamic_pointer_cast( + aRootDoc->object(ModelAPI_Feature::group(), a)); + if (aFeat.get() && aFeat->data() && aFeat->data()->isValid() && + aFeat->getKind() == "Part" && aFeat->results().size()) { + ResultPartPtr aPart = + std::dynamic_pointer_cast(aFeat->firstResult()); + if (aPart.get() && aPart->partDoc().get() && aPart->data()->name() == aPartName) { + aDoc = std::dynamic_pointer_cast(aPart->partDoc()); + aSubShapeName = aSubShapeName.substr(aPartEnd + 1); + } + } + } } } } @@ -890,7 +952,7 @@ void Model_AttributeSelection::selectSubShape( // 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()); + std::wstring aFeatureName = aSubShapeName.substr(kWHOLE_FEATURE.size()); ObjectPtr anObj = aDoc->objectByName(ModelAPI_Feature::group(), aFeatureName); if (anObj.get()) { setValue(anObj, anEmptyShape); @@ -899,7 +961,7 @@ void Model_AttributeSelection::selectSubShape( } // the whole result selection check - if (aSubShapeName.find('/') == std::string::npos) { + if (aSubShapeName.find(L'/') == std::wstring::npos) { ObjectPtr aRes = aDoc->objectByName(ModelAPI_ResultConstruction::group(), aSubShapeName); if (!aRes.get()) { aRes = aDoc->objectByName(ModelAPI_ResultBody::group(), aSubShapeName); @@ -993,7 +1055,22 @@ void Model_AttributeSelection::selectSubShape(const std::string& theType, // collect features from PartSet and the current part SessionPtr aSession = ModelAPI_Session::get(); std::list aFeatures = aSession->moduleDocument()->allFeatures(); - if (aSession->moduleDocument() != owner()->document()) { + if (anOwner->getKind() == "ImportResult") { + // special case: feature "ImportResult" refers to the results from another parts, + // thus, it is necessary to go through the features of these parts too. + std::list aPartSetFeatures = aFeatures; + aFeatures.clear(); + for (std::list::iterator it = aPartSetFeatures.begin(); + it != aPartSetFeatures.end(); ++it) { + aFeatures.push_back(*it); + if ((*it)->firstResult()->groupName() == ModelAPI_ResultPart::group()) { + ResultPartPtr aPart = std::dynamic_pointer_cast((*it)->firstResult()); + std::list aPartFeatures = aPart->partDoc()->allFeatures(); + aFeatures.insert(aFeatures.end(), aPartFeatures.begin(), aPartFeatures.end()); + } + } + } + else if (aSession->moduleDocument() != owner()->document()) { std::list aPartFeatures = owner()->document()->allFeatures(); aFeatures.insert(aFeatures.end(), aPartFeatures.begin(), aPartFeatures.end()); } @@ -1041,7 +1118,7 @@ void Model_AttributeSelection::selectSubShape(const std::string& theType, } void Model_AttributeSelection::selectSubShape(const std::string& theType, - const std::string& theContextName, const int theIndex) + const std::wstring& theContextName, const int theIndex) { // selection of context by name selectSubShape(theType, theContextName); @@ -1094,17 +1171,17 @@ void Model_AttributeSelection::setId(int theID) setValue(aContextRes, aSelection); } -std::string Model_AttributeSelection::contextName(const ResultPtr& theContext) const +std::wstring Model_AttributeSelection::contextName(const ResultPtr& theContext) const { - std::string aResult; + std::wstring aResult; if (owner()->document() != theContext->document()) { if (theContext->document() == ModelAPI_Session::get()->moduleDocument()) { - aResult = theContext->document()->kind() + "/"; + aResult = Locale::Convert::toWString(theContext->document()->kind()) + L"/"; } else { ResultPtr aDocRes = ModelAPI_Tools::findPartResult( ModelAPI_Session::get()->moduleDocument(), theContext->document()); if (aDocRes.get()) { - aResult = aDocRes->data()->name() + "/"; + aResult = aDocRes->data()->name() + L"/"; } } } @@ -1218,8 +1295,7 @@ void Model_AttributeSelection::computeValues( NCollection_DataMap aSubs; TopTools_DataMapOfShapeShape::Iterator aContIter(aNewToOld); for(; aContIter.More(); aContIter.Next()) { - TopExp_Explorer aSubExp(aContIter.Key(), aValType); - for(; aSubExp.More(); aSubExp.Next()) { + for(aSubExp.Init(aContIter.Key(), aValType); aSubExp.More(); aSubExp.Next()) { if (!aSubs.IsBound(aSubExp.Current())) { aSubs.Bind(aSubExp.Current(), TopTools_MapOfShape()); } @@ -1283,24 +1359,39 @@ void Model_AttributeSelection::computeValues( void Model_AttributeSelection::concealedFeature( - const FeaturePtr theFeature, const FeaturePtr theStop, std::list& theConcealers) + const FeaturePtr theFeature, const FeaturePtr theStop, const bool theCheckCopy, + std::list& theConcealers, const ResultPtr theResultOfFeature, + const bool theCheckWholeFeature) { std::set alreadyProcessed; alreadyProcessed.insert(theFeature); if (theStop.get()) alreadyProcessed.insert(theStop); /// iterate all results to find the concealment-attribute - const std::list& aRootRes = theFeature->results(); + std::list aRootRes; + if (theResultOfFeature.get()) { + ResultPtr aRoot = ModelAPI_Tools::bodyOwner(theResultOfFeature, true); + aRootRes.push_back(aRoot ? aRoot : theResultOfFeature); + } else { // all results of a feature + aRootRes = theFeature->results(); + } std::list::const_iterator aRootIter = aRootRes.cbegin(); for(; aRootIter != aRootRes.cend(); aRootIter++) { - std::list allRes; - allRes.push_back(*aRootIter); + std::list allRes; + allRes.push_back((*aRootIter)->data()); ResultBodyPtr aRootBody = ModelAPI_Tools::bodyOwner(*aRootIter, true); + if (!aRootBody.get()) + aRootBody = std::dynamic_pointer_cast(*aRootIter); if (aRootBody.get()) { - ModelAPI_Tools::allSubs(aRootBody, allRes); - } - for(std::list::iterator aRIter = allRes.begin(); aRIter != allRes.end(); aRIter++) { - const std::set& aRefs = (*aRIter)->data()->refsToMe(); + std::list allSub; + ModelAPI_Tools::allSubs(aRootBody, allSub); + for(std::list::iterator anIt = allSub.begin(); anIt != allSub.end(); anIt++) + allRes.push_back((*anIt)->data()); + } + if (theCheckWholeFeature) + allRes.push_back(theFeature->data()); + for(std::list::iterator aRIter = allRes.begin(); aRIter != allRes.end(); aRIter++) { + const std::set& aRefs = (*aRIter)->refsToMe(); std::set::const_iterator aRef = aRefs.cbegin(); for (; aRef != aRefs.cend(); aRef++) { if (!aRef->get() || !(*aRef)->owner().get()) @@ -1310,7 +1401,9 @@ void Model_AttributeSelection::concealedFeature( if (alreadyProcessed.find(aRefFeat) != alreadyProcessed.end()) // optimization continue; alreadyProcessed.insert(aRefFeat); - if (ModelAPI_Session::get()->validators()->isConcealed(aRefFeat->getKind(), (*aRef)->id())) + if (ModelAPI_Session::get()->validators()->isConcealed(aRefFeat->getKind(), (*aRef)->id()) + || (theCheckCopy && + std::dynamic_pointer_cast(aRefFeat).get())) { // for extrusion cut in python script the nested sketch reference may be concealed before // it is nested, so, check this composite feature is valid @@ -1336,7 +1429,8 @@ bool Model_AttributeSelection::searchNewContext(std::shared_ptr TDF_Label theAccessLabel, std::list& theResults, TopTools_ListOfShape& theValShapes) { - std::set aResults; // to avoid duplicates, new context, null if deleted + std::list aResults; // keep order, new context, null if deleted + std::set aResultsSet; // to avoid duplicates // iterate context and shape, but also if it is sub-shape of main shape, check also it TopTools_ListOfShape aContextList; aContextList.Append(theContShape); @@ -1372,32 +1466,42 @@ bool Model_AttributeSelection::searchNewContext(std::shared_ptr Handle(TNaming_NamedShape) aNewNS; aModifIter.Label().FindAttribute(TNaming_NamedShape::GetID(), aNewNS); if (aNewNS->Evolution() == TNaming_MODIFY || aNewNS->Evolution() == TNaming_GENERATED) { - aResults.insert(aModifierObj); + if (aResultsSet.find(aModifierObj) == aResultsSet.end()) { + aResultsSet.insert(aModifierObj); + aResults.push_back(aModifierObj); + } } else if (aNewNS->Evolution() == TNaming_DELETE) { // a shape was deleted => result is empty - aResults.insert(ResultPtr()); + aResults.push_back(ResultPtr()); } else { // not-processed modification => don't support it continue; } } } // if there exist context composite and sub-result(s), leave only sub(s) - for(std::set::iterator aResIter = aResults.begin(); aResIter != aResults.end();) { + for(std::list::iterator aResIter = aResults.begin(); aResIter != aResults.end();) { ResultPtr aParent = ModelAPI_Tools::bodyOwner(*aResIter); for(; aParent.get(); aParent = ModelAPI_Tools::bodyOwner(aParent)) - if (aResults.count(aParent)) + if (aResultsSet.count(aParent)) break; - if (aParent.get()) { // erase from set, so, restart iteration - aResults.erase(aParent); - aResIter = aResults.begin(); + if (aParent.get()) { + aResultsSet.erase(aParent); + for(std::list::iterator anIt = aResults.begin(); anIt != aResults.end(); anIt++) { + if (*anIt == aParent) { + aResults.erase(anIt); + aResIter = aResults.begin(); // erase from set, so, restart iteration + break; + } + } } else aResIter++; } + bool aStaySame = false; if (aResults.empty()) { // check the context become concealed by operation which is earlier than this selection FeaturePtr aThisFeature = std::dynamic_pointer_cast(owner()); FeaturePtr aContextOwner = theDoc->feature(theContext); std::list aConcealers; - concealedFeature(aContextOwner, aThisFeature, aConcealers); + concealedFeature(aContextOwner, aThisFeature, false, aConcealers, theContext); std::list::iterator aConcealer = aConcealers.begin(); for(; aConcealer != aConcealers.end(); aConcealer++) { std::list aRefResults; @@ -1412,32 +1516,92 @@ bool Model_AttributeSelection::searchNewContext(std::shared_ptr continue; if (aRefShape->impl().IsSame(theContShape)) { // add the new context result with the same shape - aResults.insert(aRefBody); + aResults.push_back(aRefBody); } } if (aResults.empty()) return true; // feature conceals result, return true, so the context will be removed } - if (aResults.empty()) - return false; // no modifications found, must stay the same + aStaySame = aResults.empty(); + } + if (myParent && myParent->isMakeCopy()) { + // check there are copies before the new results, so, make a copy + std::list aCopyContext; + std::list aCopyVals; + // features between the new and the old: check the "Move" interface to get a copy + FeaturePtr aRootOwner = theDoc->feature(theContext); + FeaturePtr anOwner = ModelAPI_Tools::compositeOwner(aRootOwner); + for(; anOwner.get(); anOwner = ModelAPI_Tools::compositeOwner(anOwner)) + aRootOwner = anOwner; + FeaturePtr aThisFeature = std::dynamic_pointer_cast(owner()); + // iterate all results to find a "Copy" features between the new and one and to add the + // copy-results also to results if this attribute refers to the copied shape + int anIndex = kUNDEFINED_FEATURE_INDEX; + for(FeaturePtr aFeat = theDoc->objects()->nextFeature(aRootOwner, anIndex); aFeat.get() && + aFeat != aThisFeature; aFeat = theDoc->objects()->nextFeature(aFeat, anIndex)) { + std::shared_ptr aCopier = + std::dynamic_pointer_cast(aFeat); + if (aCopier.get()) { + GeomShapePtr aValShape(new GeomAPI_Shape); + aValShape->setImpl(new TopoDS_Shape( + theValShape.IsNull() ? theContShape : theValShape)); + aCopier->getCopies(theContext, aValShape, aCopyContext, aCopyVals); + } + } + // check for the further modifications of the copy contexts and values + std::list::iterator aCopyContIter = aCopyContext.begin(); + std::list::iterator aCopyValIter = aCopyVals.begin(); + for(; aCopyContIter != aCopyContext.end(); aCopyContIter++, aCopyValIter++) { + ResultPtr aNewCont = std::dynamic_pointer_cast(*aCopyContIter); + TopoDS_Shape aNewContShape = aNewCont->shape()->impl(); + GeomShapePtr aNewVal = *aCopyValIter; + TopoDS_Shape aNewValShape; + if (aNewVal.get() && !aNewVal->isNull()) + aNewValShape = aNewVal->impl(); + std::list aNewRes; + TopTools_ListOfShape aNewUpdatedVal; + if (searchNewContext(theDoc, aNewContShape, aNewCont, aNewValShape, + theAccessLabel, aNewRes, aNewUpdatedVal)) { + // append 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(aNewCont); + theValShapes.Append(aNewValShape); + } + } + if (aStaySame && !theResults.empty()) { // no changes except copy, so, keep the origin as first + theResults.push_front(theContext); + theValShapes.Prepend(theValShape); + return true; + } } + if (aStaySame) + return false; + // iterate all results to find further modifications - std::set::iterator aResIter = aResults.begin(); - for(; aResIter != aResults.end(); aResIter++) { + std::list::iterator aResIter = aResults.begin(); + for(aResIter = aResults.begin(); aResIter != aResults.end(); aResIter++) { if (aResIter->get() != NULL) { + ResultPtr aNewResObj = *aResIter; // compute new values by two contexts: the old and the new TopTools_ListOfShape aValShapes; - computeValues(theContext, *aResIter, theValShape, aValShapes); + computeValues(theContext, aNewResObj, theValShape, aValShapes); TopTools_ListIteratorOfListOfShape aNewVal(aValShapes); for(; aNewVal.More(); aNewVal.Next()) { std::list aNewRes; TopTools_ListOfShape aNewUpdatedVal; TopoDS_Shape aNewValSh = aNewVal.Value(); - TopoDS_Shape aNewContShape = (*aResIter)->shape()->impl(); + TopoDS_Shape aNewContShape = aNewResObj->shape()->impl(); + if (theValShape.IsNull() && aNewContShape.IsSame(aNewValSh)) aNewValSh.Nullify(); - if (searchNewContext(theDoc, aNewContShape, *aResIter, aNewValSh, + if (searchNewContext(theDoc, aNewContShape, aNewResObj, aNewValSh, theAccessLabel, aNewRes, aNewUpdatedVal)) { // append new results instead of the current ones @@ -1448,7 +1612,7 @@ bool Model_AttributeSelection::searchNewContext(std::shared_ptr theValShapes.Append(aNewUpdVal.Value()); } } else { // the current result is good - theResults.push_back(*aResIter); + theResults.push_back(aNewResObj); theValShapes.Append(aNewValSh); } } @@ -1470,25 +1634,40 @@ void Model_AttributeSelection::updateInHistory(bool& theRemove) if (aFeature.get()) { FeaturePtr aThisFeature = std::dynamic_pointer_cast(owner()); std::list aConcealers; - concealedFeature(aFeature, aThisFeature, aConcealers); + bool aCopyPossible = myParent && myParent->isMakeCopy(); + concealedFeature(aFeature, aThisFeature, aCopyPossible, aConcealers, ResultPtr()); if (aConcealers.empty()) return; + // if there are copies, but no direct modification, keep the original + bool aKeepOrigin = false; + if (aCopyPossible) { + std::list::iterator aConcealer = aConcealers.begin(); + for(aKeepOrigin = true; aConcealer != aConcealers.end(); aConcealer++) + if (!std::dynamic_pointer_cast(*aConcealer).get()) { + aKeepOrigin = false; + break; + } + if (aKeepOrigin) { + aConcealers.push_front(aFeature); + } + } bool aChanged = false; std::list::iterator aConcealer = aConcealers.begin(); for(; aConcealer != aConcealers.end(); aConcealer++) - if (!myParent->isInList(*aConcealer, anEmptyShape)) {// avoid addition of duplicates - setValue(*aConcealer, anEmptyShape); - aChanged = true; - } - if (aConcealer == aConcealers.end()) { - if (!aChanged) // remove this - theRemove = true; - } else { // append new - for(aConcealer++; aConcealer != aConcealers.end(); aConcealer++) - if (!myParent->isInList(*aConcealer, anEmptyShape)) // avoid addition of duplicates + if (aChanged) { + if (aKeepOrigin || !myParent->isInList(*aConcealer, anEmptyShape)) myParent->append(*aConcealer, anEmptyShape); - } - if (aChanged) // searching for the further modifications + } else { + if (!myParent->isInList(*aConcealer, anEmptyShape)) {// avoid addition of duplicates + setValue(*aConcealer, anEmptyShape); + aChanged = true; + } else if (aCopyPossible && *aConcealer == aFeature) {// keep origin in case of copy + aChanged = true; + } + } + if (!aChanged) // remove this + theRemove = true; + else if (!aKeepOrigin) // searching further modifications only if current changed updateInHistory(theRemove); } } @@ -1559,7 +1738,6 @@ void Model_AttributeSelection::updateInHistory(bool& theRemove) if (!aPairIter.More()) return; 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())) @@ -1573,10 +1751,8 @@ void Model_AttributeSelection::updateInHistory(bool& theRemove) TopTools_ListOfShape aValShapes; if (searchNewContext(aDoc, aNewCShape, aContext, aValShape, aContLab, aNewContexts, aValShapes)) { - std::set allContexts, aSkippedContext; - std::list::iterator aNewContext = aNewContexts.begin(); - for(; aNewContext != aNewContexts.end(); aNewContext++) - allContexts.insert(*aNewContext); + std::set allContexts(aNewContexts.begin(), aNewContexts.end()); + std::set aSkippedContext; // if there exist context composite and sub-result(s), leave only sub(s) std::set::iterator aResIter = allContexts.begin(); @@ -1597,6 +1773,42 @@ void Model_AttributeSelection::updateInHistory(bool& theRemove) aListShapeType = GeomAPI_Shape::FACE; } + // issue #3031: skip topology if there is more convenient shape type presents in the + // same context as a result of this + bool isWholeResult = myParent && myParent->isWholeResultAllowed() && !aSubShape.get(); + GeomAPI_Shape::ShapeType allowedType = GeomAPI_Shape::SHAPE; + if (isWholeResult) { + std::list::iterator aNewCont = aNewContexts.begin(); + TopTools_ListIteratorOfListOfShape aNewValues(aValShapes); + for(; aNewCont != aNewContexts.end(); aNewCont++, aNewValues.Next()) { + if (aNewValues.Value().IsNull()) { // only for the whole context + GeomAPI_Shape::ShapeType aShapeType = (*aNewCont)->shape()->shapeType(); + if (allowedType == GeomAPI_Shape::SHAPE) { // just set this one + allowedType = aShapeType; + } else { + GeomAPI_Shape::ShapeType anAllowed = allowedType; + if (anAllowed != aShapeType) { // select the best, nearest to the origin + GeomAPI_Shape::ShapeType anOldShapeType = aContext->shape()->shapeType(); + GeomAPI_Shape::ShapeType aDeltaAllowed = + (GeomAPI_Shape::ShapeType)(anOldShapeType - anAllowed); + if (aDeltaAllowed < 0) + aDeltaAllowed = (GeomAPI_Shape::ShapeType)(-aDeltaAllowed); + GeomAPI_Shape::ShapeType aDeltaThis = + (GeomAPI_Shape::ShapeType)(anOldShapeType - aShapeType); + if (aDeltaThis < 0) + aDeltaThis = (GeomAPI_Shape::ShapeType)(-aDeltaThis); + if (aDeltaThis == aDeltaAllowed) { // equal distance to context, select complicated + if (anOldShapeType < anAllowed) + allowedType = aShapeType; + } else if (aDeltaAllowed > aDeltaThis) { // this wins + allowedType = aShapeType; + } + } + } + } + } + } + std::list::iterator aNewCont = aNewContexts.begin(); TopTools_ListIteratorOfListOfShape aNewValues(aValShapes); bool aFirst = true; // first is set to this, next are appended to parent @@ -1604,6 +1816,11 @@ void Model_AttributeSelection::updateInHistory(bool& theRemove) if (aSkippedContext.count(*aNewCont)) continue; + if (isWholeResult && aNewValues.Value().IsNull()) + if (allowedType != GeomAPI_Shape::SHAPE && + (*aNewCont)->shape()->shapeType() != allowedType) + continue; // there is better result exists with the better shape type (issue #3031) + GeomShapePtr aValueShape; if (!aNewValues.Value().IsNull()) { aValueShape = std::make_shared(); @@ -1618,7 +1835,7 @@ void Model_AttributeSelection::updateInHistory(bool& theRemove) } if (aListShapeType != GeomAPI_Shape::SHAPE && aListShapeType != aShapeShapeType) { // exception is for whole results selected - if (!myParent || !myParent->isWholeResultAllowed() || aSubShape.get()) { + if (!isWholeResult) { continue; } } @@ -1645,6 +1862,9 @@ void Model_AttributeSelection::updateInHistory(bool& theRemove) if (!myParent || !myParent->isInList(aNewContext, aValueShape)) { // avoid duplicates setValue(aNewContext, aValueShape); aFirst = false; + } else if (aNewContext == aContext && myParent && myParent->isMakeCopy()) { + // this may be exactly the old one, not modified in case of copy + aFirst = false; } } else if (myParent) { if (!myParent->isInList(aNewContext, aValueShape)) // avoid addition of duplicates @@ -1668,7 +1888,7 @@ void Model_AttributeSelection::setParent(Model_AttributeSelectionList* theParent myParent = theParent; } -std::string Model_AttributeSelection::contextName(const TDF_Label theSelectionLab) +std::wstring Model_AttributeSelection::contextName(const TDF_Label theSelectionLab) { std::shared_ptr aDoc = myRestoreDocument.get() ? myRestoreDocument : std::dynamic_pointer_cast(owner()->document()); @@ -1693,7 +1913,7 @@ std::string Model_AttributeSelection::contextName(const TDF_Label theSelectionLa } if (aResult.get()) { // this is to avoid duplicated names of results problem - std::string aContextName = aResult->data()->name(); + std::wstring aContextName = aResult->data()->name(); // myLab corresponds to the current time TDF_Label aCurrentLab = selectionLabel(); while(aCurrentLab.Depth() > 3) @@ -1702,31 +1922,31 @@ std::string Model_AttributeSelection::contextName(const TDF_Label theSelectionLa int aNumInHistoryNames = aDoc->numberOfNameInHistory(aResult, aCurrentLab); while(aNumInHistoryNames > 1) { // add "_" before name the needed number of times - aContextName = "_" + aContextName; + aContextName = L"_" + aContextName; aNumInHistoryNames--; } if (aBaseDocumnetUsed) - aContextName = aDoc->kind() + "/" + aContextName; + aContextName = Locale::Convert::toWString(aDoc->kind()) + L"/" + aContextName; return aContextName; } } - return ""; // invalid case + return L""; // 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, +bool Model_AttributeSelection::restoreContext(std::wstring theName, TDF_Label& theContext, TDF_Label& theValue) { static const GeomShapePtr anEmptyShape; // to store context only - std::string aName = theName; + std::wstring 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) { + std::wstring aSubShapeName = aName; + std::wstring::size_type n = aName.find(L'/'); + if (n != std::wstring::npos) { aName = aName.substr(0, n); } @@ -1737,11 +1957,12 @@ bool Model_AttributeSelection::restoreContext(std::string theName, // name in PartSet? aDoc = std::dynamic_pointer_cast( ModelAPI_Session::get()->moduleDocument()); - if (theName.find(aDoc->kind()) == 0) { // remove the document identifier from name if exists + if (theName.find(Locale::Convert::toWString(aDoc->kind())) == 0) { + // remove the document identifier from name if exists aSubShapeName = theName.substr(aDoc->kind().size() + 1); aName = aSubShapeName; - std::string::size_type n = aName.find('/'); - if (n != std::string::npos) { + n = aName.find(L'/'); + if (n != std::wstring::npos) { aName = aName.substr(0, n); } } @@ -1756,9 +1977,9 @@ bool Model_AttributeSelection::restoreContext(std::string theName, // 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); + std::wstring::size_type aSlash = aSubShapeName.rfind(L'/'); + if (aSlash != std::wstring::npos) { + std::wstring aCompName = aSubShapeName.substr(aSlash + 1); CompositeFeaturePtr aComposite = std::dynamic_pointer_cast(aDoc->feature(aCont)); if (aComposite.get() && aComposite->numberOfSubs()) { @@ -1846,23 +2067,28 @@ ResultPtr Model_AttributeSelection::newestContext( //if (aResult->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; + std::list allRes; ResultPtr aCompContext; ResultBodyPtr aCompBody = ModelAPI_Tools::bodyOwner(aResult, true); if (aCompBody.get()) { - ModelAPI_Tools::allSubs(aCompBody, allRes); - allRes.push_back(aCompBody); + std::list allSub; + ModelAPI_Tools::allSubs(aCompBody, allSub); + for(std::list::iterator anIt = allSub.begin(); anIt != allSub.end(); anIt++) + allRes.push_back((*anIt)->data()); + allRes.push_back(aCompBody->data()); aCompContext = aCompBody; } if (allRes.empty()) - allRes.push_back(aResult); + allRes.push_back(aResult->data()); + allRes.push_back(aResult->document()->feature(aResult)->data()); - for (std::list::iterator aSub = allRes.begin(); aSub != allRes.end(); aSub++) { - ResultPtr aResCont = *aSub; - ResultBodyPtr aResBody = std::dynamic_pointer_cast(aResCont); + bool aFoundReferernce = false; + for (std::list::iterator aSub = allRes.begin(); aSub != allRes.end(); aSub++) { + DataPtr aResCont = *aSub; + ResultBodyPtr aResBody = std::dynamic_pointer_cast(aResCont->owner()); if (aResBody.get() && aResBody->numberOfSubs() > 0 && aResBody != aCompContext) continue; // only lower and higher level subs are counted - const std::set& aRefs = aResCont->data()->refsToMe(); + const std::set& aRefs = aResCont->refsToMe(); std::set::const_iterator aRef = aRefs.begin(); for (; !aFindNewContext && aRef != aRefs.end(); aRef++) { if (!aRef->get() || !(*aRef)->owner().get()) @@ -1890,6 +2116,7 @@ ResultPtr Model_AttributeSelection::newestContext( for (; aResIter != aResults.end(); aResIter++) { if (!aResIter->get() || !(*aResIter)->data()->isValid() || (*aResIter)->isDisabled()) continue; + aFoundReferernce = true; GeomShapePtr aShape = (*aResIter)->shape(); if (aShape.get() && aShape->isSubShape(aSelectedShape, false)) { aResult = *aResIter; // found new context (produced from this) with same subshape @@ -1899,6 +2126,11 @@ ResultPtr Model_AttributeSelection::newestContext( } } } + if (aFoundReferernce && !aFindNewContext && + aResult->groupName() != ModelAPI_ResultConstruction::group()) { + // #19019 : result is concealed by object that contains no such sub-shape + return theCurrent; + } } // if compsolid is context, try to take sub-solid as context: like in GUI and scripts ResultBodyPtr aComp = std::dynamic_pointer_cast(aResult); @@ -1915,10 +2147,16 @@ ResultPtr Model_AttributeSelection::newestContext( } } } - // in case sketch line was selected for wire, but wire was concealed and not such line anymore, - // so, actually, the sketch element was selected (which is never concealed) - if (aResult != theCurrent && aResult->isConcealed()) - aResult = theCurrent; + // in case sketch line was selected for wire, but wire was concealed and there is no such line + // anymore, so, actually, the sketch element was selected (which is never concealed) + if (aResult != theCurrent && theCurrent->groupName() == ModelAPI_ResultConstruction::group()) { + std::list aConcealers; + FeaturePtr aResFeature = aDoc->feature(aResult); + FeaturePtr aThisFeature = std::dynamic_pointer_cast(owner()); + concealedFeature(aResFeature, aThisFeature, false, aConcealers, aResult, true); + if (aConcealers.size()) + aResult = theCurrent; + } return aResult; } @@ -1941,7 +2179,7 @@ void Model_AttributeSelection::combineGeometrical() Handle(TDataStd_Integer) anIndex; if (aSelLab.FindAttribute(TDataStd_Integer::GetID(), anIndex)) { if (anIndex->Get()) { // special selection attribute was created, use it - std::string aNewName; + std::wstring aNewName; aPart->combineGeometrical(anIndex->Get(), aNewName); TDataStd_Name::Set(aSelLab, aNewName.c_str()); } @@ -1972,3 +2210,9 @@ TDF_Label Model_AttributeSelection::baseDocumentLab() static TDF_Label anEmpty; return anEmpty; } + +void Model_AttributeSelection::reset() +{ + ModelAPI_AttributeSelection::reset(); + myRef.reset(); +}