#include "Model_Data.h"
#include "Model_Document.h"
#include "Model_SelectionNaming.h"
+#include <Model_Objects.h>
+#include <Model_AttributeSelectionList.h>
#include <ModelAPI_Feature.h>
#include <ModelAPI_ResultBody.h>
#include <ModelAPI_ResultConstruction.h>
#include <ModelAPI_ResultPart.h>
#include <ModelAPI_CompositeFeature.h>
+#include <ModelAPI_Tools.h>
#include <GeomAPI_Shape.h>
+#include <ModelAPI_Session.h>
#include <GeomAPI_PlanarEdges.h>
-#include <Events_Error.h>
+#include <Events_InfoMessage.h>
#include <TNaming_Selector.hxx>
#include <TNaming_NamedShape.hxx>
#include <TNaming_Tool.hxx>
#include <TNaming_Builder.hxx>
#include <TNaming_Localizer.hxx>
+#include <TNaming_SameShapeIterator.hxx>
+#include <TNaming_Iterator.hxx>
+#include <TNaming_NewShapeIterator.hxx>
#include <TopoDS_Shape.hxx>
#include <TopoDS_Compound.hxx>
#include <TDataStd_IntPackedMap.hxx>
#include <TDataStd_Name.hxx>
#include <TopAbs_ShapeEnum.hxx>
#include <TopoDS_Iterator.hxx>
-#include <TNaming_Iterator.hxx>
-using namespace std;
+#include <BRep_Builder.hxx>
+
//#define DEB_NAMING 1
#ifdef DEB_NAMING
#include <BRepTools.hxx>
#endif
-/// adeed to the index in the packed map to signalize that the vertex of edge is seleted
+/// added to the index in the packed map to signalize that the vertex of edge is selected
/// (multiplied by the index of the edge)
static const int kSTART_VERTEX_DELTA = 1000000;
// identifier that there is simple reference: selection equals to context
(theSubShape == anOldShape || (theSubShape && anOldShape && theSubShape->isEqual(anOldShape)));
if (isOldShape) return; // shape is the same, so context is also unchanged
// update the referenced object if needed
- if (!isOldContext)
- myRef.setValue(theContext);
+ if (!isOldContext) {
+ myRef.setValue(theContext);
+ }
// do noth use naming if selected shape is result shape itself, but not sub-shape
TDF_Label aSelLab = selectionLabel();
if (theContext->groupName() == ModelAPI_ResultBody::group()) {
// do not select the whole shape for body:it is already must be in the data framework
// equal and null selected objects mean the same: object is equal to context,
- // TODO: synchronize with GUI later that it must be null always
- if (theContext->shape().get() &&
+ if (theContext->shape().get() &&
(theContext->shape()->isEqual(theSubShape) || !theSubShape.get())) {
aSelLab.ForgetAllAttributes(true);
TDataStd_UAttribute::Set(aSelLab, kSIMPLE_REF_ID);
// to sub, so the whole result is selected
aSelLab.ForgetAllAttributes(true);
TDataStd_UAttribute::Set(aSelLab, kCONSTUCTION_SIMPLE_REF_ID);
+ ResultConstructionPtr aConstruction =
+ std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(theContext);
+ 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<TopoDS_Shape>());
+ std::shared_ptr<Model_Document> aMyDoc =
+ std::dynamic_pointer_cast<Model_Document>(owner()->document());
+ //std::string aName = contextName(theContext);
+ // for selection in different document, add the document name
+ //aMyDoc->addNamingName(aSelLab, aName);
+ //TDataStd_Name::Set(aSelLab, aName.c_str());
+ } else { // for sketch the naming is needed in DS
+ BRep_Builder aCompoundBuilder;
+ TopoDS_Compound aComp;
+ aCompoundBuilder.MakeCompound(aComp);
+ for(int a = 0; a < aConstruction->facesNum(); a++) {
+ TopoDS_Shape aFace = aConstruction->face(a)->impl<TopoDS_Shape>();
+ aCompoundBuilder.Add(aComp, aFace);
+ }
+ std::shared_ptr<GeomAPI_Shape> aShape(new GeomAPI_Shape);
+ aShape->setImpl<TopoDS_Shape>(new TopoDS_Shape(aComp));
+ selectConstruction(theContext, aShape);
+ }
} else {
selectConstruction(theContext, theSubShape);
}
//myIsInitialized = true;
owner()->data()->sendAttributeUpdated(this);
+}
- std::string aSelName = namingName();
- if(!aSelName.empty())
- TDataStd_Name::Set(selectionLabel(), aSelName.c_str()); //set name
+void Model_AttributeSelection::removeTemporaryValues()
+{
+ if (myTmpContext.get() || myTmpSubShape.get()) {
+ myTmpContext.reset();
+ myTmpSubShape.reset();
+ }
}
std::shared_ptr<GeomAPI_Shape> Model_AttributeSelection::value()
{
+ GeomShapePtr aResult;
if (myTmpContext.get() || myTmpSubShape.get()) {
- return myTmpSubShape;
+ ResultConstructionPtr aResulConstruction =
+ std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(myTmpContext);
+ if(aResulConstruction.get()) {
+ // it is just reference to construction.
+ return myTmpSubShape;
+ }
+ return myTmpSubShape.get() ? myTmpSubShape : myTmpContext->shape();
}
- std::shared_ptr<GeomAPI_Shape> aResult;
TDF_Label aSelLab = selectionLabel();
if (aSelLab.IsAttribute(kINVALID_SELECTION))
return aResult;
if (myRef.isInitialized()) {
if (aSelLab.IsAttribute(kSIMPLE_REF_ID)) { // it is just reference to shape, not sub-shape
ResultPtr aContext = context();
- if (!aContext.get())
+ if (!aContext.get())
return aResult; // empty result
return aContext->shape();
}
- if (aSelLab.IsAttribute(kCONSTUCTION_SIMPLE_REF_ID)) { // it is just reference to construction, nothing is in value
+ if (aSelLab.IsAttribute(kCONSTUCTION_SIMPLE_REF_ID)) {
+ // it is just reference to construction, nothing is in value
return aResult; // empty result
}
if (aSelLab.IsAttribute(kPART_REF_ID)) {
- /* TODO: implement used text here
ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(context());
if (!aPart.get() || !aPart->isActivated())
return std::shared_ptr<GeomAPI_Shape>(); // postponed naming needed
Handle(TDataStd_Integer) anIndex;
if (selectionLabel().FindAttribute(TDataStd_Integer::GetID(), anIndex)) {
- return aPart->selectionValue(anIndex->Get());
- }
- Handle(TDataStd_Name) aName;
- if (!selectionLabel().FindAttribute(TDataStd_Name::GetID(), aName)) {
- return std::shared_ptr<GeomAPI_Shape>(); // something is wrong
+ if (anIndex->Get()) { // special selection attribute was created, use it
+ return aPart->selectionValue(anIndex->Get());
+ } else { // face with name is already in the data model, so try to take it by name
+ Handle(TDataStd_Name) aName;
+ if (selectionLabel().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::string aType; // to reuse already existing selection the type is not needed
+ return aPart->shapeInPart(aNameInPart, aType, anIndex);
+ }
+ }
+ }
}
- return aPart->shapeInPart(TCollection_AsciiString(aName).ToCString());
- */
}
Handle(TNaming_NamedShape) aSelection;
aResult = std::shared_ptr<GeomAPI_Shape>(new GeomAPI_Shape);
aResult->setImpl(new TopoDS_Shape(aSelShape));
} else { // for simple construction element: just shape of this construction element
- ResultConstructionPtr aConstr =
+ ResultConstructionPtr aConstr =
std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(context());
if (aConstr) {
return aConstr->shape();
bool Model_AttributeSelection::isInitialized()
{
- if (ModelAPI_AttributeSelection::isInitialized()) { // additional checkings if it is initialized
+ if (ModelAPI_AttributeSelection::isInitialized()) { // additional checks if it is initialized
std::shared_ptr<GeomAPI_Shape> aResult;
if (myRef.isInitialized()) {
TDF_Label aSelLab = selectionLabel();
ResultPtr aContext = context();
return aContext.get() != NULL;
}
- if (aSelLab.IsAttribute(kCONSTUCTION_SIMPLE_REF_ID)) { // it is just reference to construction, nothing is in value
+ if (aSelLab.IsAttribute(kCONSTUCTION_SIMPLE_REF_ID)) {
+ // it is just reference to construction, nothing is in value
return true;
}
if (selectionLabel().FindAttribute(TNaming_NamedShape::GetID(), aSelection)) {
return !aSelection->Get().IsNull();
} else { // for simple construction element: just shape of this construction element
- ResultConstructionPtr aConstr =
+ ResultConstructionPtr aConstr =
std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(context());
if (aConstr.get()) {
return aConstr->shape().get() != NULL;
: myRef(theLabel)
{
myIsInitialized = myRef.isInitialized();
+ myParent = NULL;
}
void Model_AttributeSelection::setID(const std::string theID)
TDF_LabelMap& Model_AttributeSelection::scope()
{
if (myScope.IsEmpty()) { // create a new scope if not yet done
- // gets all featueres with named shapes that are bofore this feature label (before in history)
+ // gets all features with named shapes that are before this feature label (before in history)
DocumentPtr aMyDoc = owner()->document();
std::list<std::shared_ptr<ModelAPI_Feature> > allFeatures = aMyDoc->allFeatures();
std::list<std::shared_ptr<ModelAPI_Feature> >::iterator aFIter = allFeatures.begin();
+ bool aMePassed = false;
+ CompositeFeaturePtr aComposite =
+ std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(owner());
+ FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(owner());
+ CompositeFeaturePtr aCompositeOwner, aCompositeOwnerOwner;
+ if (aFeature.get()) {
+ aCompositeOwner = ModelAPI_Tools::compositeOwner(aFeature);
+ if (aCompositeOwner.get()) {
+ aCompositeOwnerOwner = ModelAPI_Tools::compositeOwner(aCompositeOwner);
+ }
+ }
+ // for group Scope is not limitet: this is always up to date objects
+ bool isGroup = aFeature.get() && aFeature->getKind() == "Group";
for(; aFIter != allFeatures.end(); aFIter++) {
- if (*aFIter == owner()) break; // the left features are created later
- if (aFIter->get() && (*aFIter)->data()->isValid()) {
+ if (*aFIter == owner()) { // the left features are created later (except subs of composite)
+ aMePassed = true;
+ continue;
+ }
+ if (isGroup) aMePassed = false;
+ bool isInScope = !aMePassed;
+ if (!isInScope && aComposite.get()) {
+ // try to add sub-elements of composite if this is composite
+ if (aComposite->isSub(*aFIter))
+ isInScope = true;
+ }
+ // remove the composite-owner of this feature (sketch in extrusion-cut)
+ if (isInScope && (aCompositeOwner == *aFIter || aCompositeOwnerOwner == *aFIter))
+ isInScope = false;
+
+ if (isInScope && aFIter->get() && (*aFIter)->data()->isValid()) {
TDF_Label aFeatureLab = std::dynamic_pointer_cast<Model_Data>(
(*aFIter)->data())->label().Father();
TDF_ChildIDIterator aNSIter(aFeatureLab, TNaming_NamedShape::GetID(), 1);
return myScope;
}
-/// produces theEdge orientation relatively to theContext face
-int edgeOrientation(const TopoDS_Shape& theContext, TopoDS_Edge& theEdge)
-{
- if (theContext.ShapeType() != TopAbs_FACE)
- return 0;
- TopoDS_Face aContext = TopoDS::Face(theContext);
- if (theEdge.Orientation() == TopAbs_FORWARD)
- return 1;
- if (theEdge.Orientation() == TopAbs_REVERSED)
- return -1;
- return 0; // unknown
-}
-
/// Sets the invalid flag if flag is false, or removes it if "true"
/// Returns theFlag
static bool setInvalidIfFalse(TDF_Label& theLab, const bool theFlag) {
{
TDF_Label aSelLab = selectionLabel();
ResultPtr aContext = context();
- if (!aContext.get())
+ if (!aContext.get())
return setInvalidIfFalse(aSelLab, false);
if (aSelLab.IsAttribute(kSIMPLE_REF_ID)) { // it is just reference to shape, not sub-shape
return setInvalidIfFalse(aSelLab, aContext->shape() && !aContext->shape()->isNull());
}
- if (aSelLab.IsAttribute(kCONSTUCTION_SIMPLE_REF_ID)) { // it is just reference to construction, not sub-shape
+ if (aSelLab.IsAttribute(kCONSTUCTION_SIMPLE_REF_ID)) {
+ // it is just reference to construction, not sub-shape
+ // if there is a sketch, the sketch-naming must be updated
+ ResultConstructionPtr aConstruction =
+ std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
+ if (!aConstruction->isInfinite()) {
+ BRep_Builder aCompoundBuilder;
+ TopoDS_Compound aComp;
+ aCompoundBuilder.MakeCompound(aComp);
+ for(int a = 0; a < aConstruction->facesNum(); a++) {
+ TopoDS_Shape aFace = aConstruction->face(a)->impl<TopoDS_Shape>();
+ aCompoundBuilder.Add(aComp, aFace);
+ }
+ std::shared_ptr<GeomAPI_Shape> aShape(new GeomAPI_Shape);
+ aShape->setImpl<TopoDS_Shape>(new TopoDS_Shape(aComp));
+ selectConstruction(aContext, aShape);
+ } else {
+ // 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(aContext->shape()->impl<TopoDS_Shape>());
+ std::shared_ptr<Model_Document> aMyDoc =
+ std::dynamic_pointer_cast<Model_Document>(owner()->document());
+ }
return setInvalidIfFalse(aSelLab, aContext->shape() && !aContext->shape()->isNull());
}
if (aSelLab.IsAttribute(kPART_REF_ID)) { // it is reference to the part object
std::shared_ptr<GeomAPI_Shape> aNoSelection;
- return setInvalidIfFalse(aSelLab, selectPart(aContext, aNoSelection, true));
+ bool aResult = selectPart(aContext, aNoSelection, true);
+ aResult = setInvalidIfFalse(aSelLab, aResult);
+ if (aResult) {
+ owner()->data()->sendAttributeUpdated(this);
+ }
+ return aResult;
}
if (aContext->groupName() == ModelAPI_ResultBody::group()) {
// body: just a named shape, use selection mechanism from OCCT
TNaming_Selector aSelector(aSelLab);
+ TopoDS_Shape anOldShape;
+ if (!aSelector.NamedShape().IsNull()) {
+ anOldShape = aSelector.NamedShape()->Get();
+ }
bool aResult = aSelector.Solve(scope()) == Standard_True;
- owner()->data()->sendAttributeUpdated(this);
- return setInvalidIfFalse(aSelLab, aResult);
- } else if (aContext->groupName() == ModelAPI_ResultConstruction::group()) {
+ // must be before sending of updated attribute (1556)
+ aResult = setInvalidIfFalse(aSelLab, aResult);
+ TopoDS_Shape aNewShape;
+ if (!aSelector.NamedShape().IsNull()) {
+ aNewShape = aSelector.NamedShape()->Get();
+ }
+ if (anOldShape.IsNull() || aNewShape.IsNull() ||
+ !anOldShape.IsEqual(aSelector.NamedShape()->Get())) {
+ // shape type shoud not not changed: if shape becomes compound of such shapes, then split
+ if (myParent && !anOldShape.IsNull() && !aNewShape.IsNull() &&
+ anOldShape.ShapeType() != aNewShape.ShapeType() &&
+ aNewShape.ShapeType() == TopAbs_COMPOUND) {
+ TopTools_ListOfShape aSubs;
+ for(TopoDS_Iterator anExplorer(aNewShape); anExplorer.More(); anExplorer.Next()) {
+ if (!anExplorer.Value().IsNull() &&
+ anExplorer.Value().ShapeType() == anOldShape.ShapeType()) {
+ aSubs.Append(anExplorer.Value());
+ } else { // invalid case; bad result shape, so, impossible to split easily
+ aSubs.Clear();
+ break;
+ }
+ }
+ if (aSubs.Extent() > 1) { // ok to split
+ TopTools_ListIteratorOfListOfShape aSub(aSubs);
+ GeomShapePtr aSubSh(new GeomAPI_Shape);
+ aSubSh->setImpl(new TopoDS_Shape(aSub.Value()));
+ setValue(aContext, aSubSh);
+ for(aSub.Next(); aSub.More(); aSub.Next()) {
+ GeomShapePtr aSubSh(new GeomAPI_Shape);
+ aSubSh->setImpl(new TopoDS_Shape(aSub.Value()));
+ myParent->append(aContext, aSubSh);
+ }
+ }
+ }
+ owner()->data()->sendAttributeUpdated(this); // send updated if shape is changed
+ }
+ return aResult;
+ }
+
+ if (aContext->groupName() == ModelAPI_ResultConstruction::group()) {
// construction: identification by the results indexes, recompute faces and
// take the face that more close by the indexes
- ResultConstructionPtr aConstructionContext =
+ ResultConstructionPtr aConstructionContext =
std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
FeaturePtr aContextFeature = aContext->document()->feature(aContext);
// sketch sub-element
- if (aConstructionContext &&
+ if (aConstructionContext &&
std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aContextFeature).get())
{
TDF_Label aLab = myRef.myRef->Label();
// selected indexes will be needed in each "if"
Handle(TDataStd_IntPackedMap) aSubIds;
std::shared_ptr<GeomAPI_Shape> aNewSelected;
- bool aNoIndexes =
+ bool aNoIndexes =
!aLab.FindAttribute(TDataStd_IntPackedMap::GetID(), aSubIds) || aSubIds->Extent() == 0;
// for now working only with composite features
- CompositeFeaturePtr aComposite =
+ CompositeFeaturePtr aComposite =
std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aContextFeature);
if (!aComposite.get() || aComposite->numberOfSubs() == 0) {
return setInvalidIfFalse(aSelLab, false);
}
- if (aShapeType == TopAbs_FACE) { // compound is for the whole sketch selection
- // If this is a wire with plane defined thin it is a sketch-like object
+ if (aShapeType == TopAbs_FACE || aShapeType == TopAbs_WIRE) {
+ // compound is for the whole sketch selection
+ // If this is a wire with plane defined then it is a sketch-like object
if (!aConstructionContext->facesNum()) // no faces, update can not work correctly
return setInvalidIfFalse(aSelLab, false);
// if there is no edges indexes, any face can be used: take the first
if (aNoIndexes) {
aNewSelected = aConstructionContext->face(0);
} else { // searching for most looks-like initial face by the indexes
- // prepare edges of the current resut for the fast searching
- NCollection_DataMap<Handle(Geom_Curve), int> allCurves; // curves and orientations of edges
+ // prepare edges of the current result for the fast searching
+ // curves and orientations of edges
+ NCollection_DataMap<Handle(Geom_Curve), int> allCurves;
const int aSubNum = aComposite->numberOfSubs();
for(int a = 0; a < aSubNum; a++) {
int aSubID = aComposite->subFeatureId(a);
const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aSub->results();
std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRes;
for(aRes = aResults.cbegin(); aRes != aResults.cend(); aRes++) {
- ResultConstructionPtr aConstr =
+ ResultConstructionPtr aConstr =
std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aRes);
if (aConstr->shape() && aConstr->shape()->isEdge()) {
const TopoDS_Shape& aResShape = aConstr->shape()->impl<TopoDS_Shape>();
}
}
}
- double aBestFound = 0; // best percentage of found edges
- int aBestOrient = 0; // for the equal "BestFound" additional parameter is orientation
- for(int aFaceIndex = 0; aFaceIndex < aConstructionContext->facesNum(); aFaceIndex++) {
- int aFound = 0, aNotFound = 0, aSameOrientation = 0;
- TopoDS_Face aFace =
- TopoDS::Face(aConstructionContext->face(aFaceIndex)->impl<TopoDS_Shape>());
- TopExp_Explorer anEdgesExp(aFace, TopAbs_EDGE);
- TColStd_MapOfTransient alreadyProcessed; // to avoid counting edges with same curved (841)
- for(; anEdgesExp.More(); anEdgesExp.Next()) {
- TopoDS_Edge anEdge = TopoDS::Edge(anEdgesExp.Current());
- if (!anEdge.IsNull()) {
- Standard_Real aFirst, aLast;
- Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
- if (alreadyProcessed.Contains(aCurve))
- continue;
- alreadyProcessed.Add(aCurve);
- if (allCurves.IsBound(aCurve)) {
- aFound++;
- int anOrient = allCurves.Find(aCurve);
- if (anOrient != 0) { // extra comparision score is orientation
- if (edgeOrientation(aFace, anEdge) == anOrient)
- aSameOrientation++;
- }
- } else {
- aNotFound++;
- }
- }
- }
- if (aFound + aNotFound != 0) {
- double aSum = aFound + aNotFound;
- // aSameOrientation: if edges are same, take where orientation is better
- double aPercentage = double(aFound) / double(aFound + aNotFound);
- if (aPercentage > aBestFound ||
- (aPercentage == aBestFound && aSameOrientation > aBestOrient)) {
- aBestFound = aPercentage;
- aBestOrient = aSameOrientation;
- aNewSelected = aConstructionContext->face(aFaceIndex);
- }
- }
- }
+ aNewSelected = Model_SelectionNaming::findAppropriateFace(
+ aContext, allCurves, aShapeType == TopAbs_WIRE);
}
if (aNewSelected) { // store this new selection
selectConstruction(aContext, aNewSelected);
+ setInvalidIfFalse(aSelLab, true);
owner()->data()->sendAttributeUpdated(this);
- return setInvalidIfFalse(aSelLab, true);
- } else { // if the selection is not found, put the empty shape: it's better to have disappeared shape, than the old, the lost one
+ return true;
+ } else {
+ // if the selection is not found, put the empty shape:
+ // it's better to have disappeared shape, than the old, the lost one
TNaming_Builder anEmptyBuilder(selectionLabel());
return setInvalidIfFalse(aSelLab, false);
}
std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aResIter =
aFeature->results().cbegin();
for(;aResIter != aFeature->results().cend(); aResIter++) {
- ResultConstructionPtr aRes =
+ ResultConstructionPtr aRes =
std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aResIter);
if (aRes && aRes->shape() && aRes->shape()->isEdge()) { // found!
selectConstruction(aContext, aRes->shape());
+ setInvalidIfFalse(aSelLab, true);
owner()->data()->sendAttributeUpdated(this);
- return setInvalidIfFalse(aSelLab, true);
+ return true;
}
}
}
std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aResIter =
aFeature->results().cbegin();
for(;aResIter != aFeature->results().cend(); aResIter++) {
- ResultConstructionPtr aRes =
+ ResultConstructionPtr aRes =
std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aResIter);
if (aRes && aRes->shape()) {
if (aRes->shape()->isVertex() && aVertexNum == 0) { // found!
selectConstruction(aContext, aRes->shape());
+ setInvalidIfFalse(aSelLab, true);
owner()->data()->sendAttributeUpdated(this);
- return setInvalidIfFalse(aSelLab, true);
+ return true;
} else if (aRes->shape()->isEdge() && aVertexNum > 0) {
const TopoDS_Shape& anEdge = aRes->shape()->impl<TopoDS_Shape>();
int aVIndex = 1;
std::shared_ptr<GeomAPI_Shape> aVertex(new GeomAPI_Shape);
aVertex->setImpl(new TopoDS_Shape(aVExp.Current()));
selectConstruction(aContext, aVertex);
+ setInvalidIfFalse(aSelLab, true);
owner()->data()->sendAttributeUpdated(this);
- return setInvalidIfFalse(aSelLab, true);
+ return true;
}
aVIndex++;
}
}
} else { // simple construction element: the selected is that needed
selectConstruction(aContext, aContext->shape());
+ setInvalidIfFalse(aSelLab, true);
owner()->data()->sendAttributeUpdated(this);
- return setInvalidIfFalse(aSelLab, true);
+ return true;
}
}
return setInvalidIfFalse(aSelLab, false); // unknown case
}
-
void Model_AttributeSelection::selectBody(
const ResultPtr& theContext, const std::shared_ptr<GeomAPI_Shape>& theSubShape)
{
TNaming_Selector aSel(selectionLabel());
TopoDS_Shape aContext;
- ResultBodyPtr aBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(myRef.value());
+ ResultBodyPtr aBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(theContext);//myRef.value()
if (aBody) {
aContext = aBody->shape()->impl<TopoDS_Shape>();
} else {
- ResultPtr aResult =
+ ResultPtr aResult =
std::dynamic_pointer_cast<ModelAPI_Result>(myRef.value());
if (aResult) {
aContext = aResult->shape()->impl<TopoDS_Shape>();
} else {
- Events_Error::send("A result with shape is expected");
+ Events_InfoMessage("Model_AttributeSelection", "A result with shape is expected").send();
return;
}
}
- TopoDS_Shape aNewShape = theSubShape ? theSubShape->impl<TopoDS_Shape>() : aContext;
+
+ // with "recover" feature the selected context may be not up to date (issue 1710)
+ Handle(TNaming_NamedShape) aResult;
+ TDF_Label aSelLab = selectionLabel();
+ TopoDS_Shape aNewContext = aContext;
+ bool isUpdated = true;
+ while(!aNewContext.IsNull() && isUpdated) {
+ // searching for the very last shape that was produced from this one
+ isUpdated = false;
+ if (!TNaming_Tool::HasLabel(aSelLab, aNewContext))
+ // to avoid crash of TNaming_SameShapeIterator if pure shape does not exists
+ break;
+ for(TNaming_SameShapeIterator anIter(aNewContext, aSelLab); anIter.More(); anIter.Next()) {
+ TDF_Label aNSLab = anIter.Label();
+ if (!scope().Contains(aNSLab))
+ continue;
+ Handle(TNaming_NamedShape) aNS;
+ if (aNSLab.FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
+ for(TNaming_Iterator aShapesIter(aNS); aShapesIter.More(); aShapesIter.Next()) {
+ if (aShapesIter.Evolution() == TNaming_SELECTED)
+ continue; // don't use the selection evolution
+ if (!aShapesIter.OldShape().IsNull() && aShapesIter.OldShape().IsSame(aNewContext)) {
+ // found the original shape
+ aNewContext = aShapesIter.NewShape(); // go to the newer shape
+ isUpdated = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ if (aNewContext.IsNull()) { // a context is already deleted
+ setInvalidIfFalse(aSelLab, false);
+ Events_InfoMessage("Model_AttributeSelection", "Failed to select shape already deleted").send();
+ return;
+ }
+
+ TopoDS_Shape aNewSub = theSubShape ? theSubShape->impl<TopoDS_Shape>() : aContext;
+ if (!aNewSub.IsEqual(aContext)) { // searching for subshape in the new context
+ bool isFound = false;
+ TopExp_Explorer anExp(aNewContext, aNewSub.ShapeType());
+ for(; anExp.More(); anExp.Next()) {
+ if (anExp.Current().IsEqual(aNewSub)) {
+ isFound = true;
+ break;
+ }
+ }
+ if (!isFound) { // sub-shape is not found in the up-to-date instance of the context shape
+ // if context is sub-result of compound/compsolid, selection of sub-shape better propagate to
+ // the main result (which is may be modified), case is in 1799
+ ResultCompSolidPtr aMain = ModelAPI_Tools::compSolidOwner(theContext);
+ if (aMain.get()) {
+ selectBody(aMain, theSubShape);
+ return;
+ }
+ setInvalidIfFalse(aSelLab, false);
+ Events_InfoMessage("Model_AttributeSelection",
+ "Failed to select sub-shape already modified").send();
+ return;
+ }
+ }
+
/// fix for issue 411: result modified shapes must not participate in this selection mechanism
- /*
- FeaturePtr aFeatureOwner = std::dynamic_pointer_cast<ModelAPI_Feature>(owner());
- if (aFeatureOwner.get())
- aFeatureOwner->eraseResults();
- */
if (!aContext.IsNull()) {
- aSel.Select(aNewShape, aContext);
+ FeaturePtr aFeatureOwner = std::dynamic_pointer_cast<ModelAPI_Feature>(owner());
+ bool aEraseResults = false;
+ if (aFeatureOwner.get()) {
+ aEraseResults = !aFeatureOwner->results().empty();
+ if (aEraseResults) // erase results without flash deleted and redisplay: do it after Select
+ aFeatureOwner->removeResults(0, false);
+ }
+ aSel.Select(aNewSub, aNewContext);
+
+ if (aEraseResults) { // flash after Select : in Groups it makes selection with shift working
+ static Events_Loop* aLoop = Events_Loop::loop();
+ static const Events_ID kDeletedEvent = aLoop->eventByName(EVENT_OBJECT_DELETED);
+ aLoop->flush(kDeletedEvent);
+ }
}
}
/// registers the name of the shape in the label (theID == 0) of sub label (theID is a tag)
-/// if theID is zero,
+/// if theID is zero,
/// theOrientation is additional information about the positioning of edge relatively to face
-/// it is stored in the integer attribute of the edge sub-label:
+/// it is stored in the integer attribute of the edge sub-label:
/// -1 is out, 1 is in, 0 is not needed
static void registerSubShape(TDF_Label theMainLabel, TopoDS_Shape theShape,
const int theID, const FeaturePtr& theContextFeature, std::shared_ptr<Model_Document> theDoc,
- std::string theAdditionalName, std::map<int, int>& theOrientations,
+ std::map<int, int>& theOrientations,
+ // name of sub-elements by ID to be exported instead of indexes
+ std::map<int, std::string>& theSubNames,
Handle(TDataStd_IntPackedMap) theRefs = Handle(TDataStd_IntPackedMap)(),
const int theOrientation = 0)
{
TNaming_Builder aBuilder(aLab);
aBuilder.Generated(theShape);
std::stringstream aName;
- aName<<theContextFeature->name()<<"/";
- if (!theAdditionalName.empty())
- aName<<theAdditionalName<<"/";
- if (theShape.ShapeType() == TopAbs_FACE) aName<<"Face";
- else if (theShape.ShapeType() == TopAbs_EDGE) aName<<"Edge";
- else if (theShape.ShapeType() == TopAbs_VERTEX) aName<<"Vertex";
-
- if (theRefs.IsNull()) {
- aName<<theID;
- if (theOrientation == 1)
- aName<<"f";
- else if (theOrientation == -1)
- aName<<"r";
- } else { // make a compisite name from all sub-elements indexes: "1_2_3_4"
- TColStd_MapIteratorOfPackedMapOfInteger aRef(theRefs->GetMap());
- for(; aRef.More(); aRef.Next()) {
- aName<<"-"<<aRef.Key();
- if (theOrientations.find(aRef.Key()) != theOrientations.end()) {
- if (theOrientations[aRef.Key()] == 1)
- aName<<"f";
- else if (theOrientations[aRef.Key()] == -1)
- aName<<"r";
+ // #1839 : do not store name of the feature in the tree, since this name could be changed
+ //aName<<theContextFeature->name();
+ if (theShape.ShapeType() != TopAbs_COMPOUND) { // compound means the whole result for construction
+ //aName<<"/";
+ if (theShape.ShapeType() == TopAbs_FACE) aName<<"Face";
+ else if (theShape.ShapeType() == TopAbs_WIRE) aName<<"Wire";
+ else if (theShape.ShapeType() == TopAbs_EDGE) aName<<"Edge";
+ else if (theShape.ShapeType() == TopAbs_VERTEX) aName<<"Vertex";
+
+ if (theRefs.IsNull()) {
+ aName<<theID;
+ if (theOrientation == 1)
+ aName<<"f";
+ else if (theOrientation == -1)
+ aName<<"r";
+ } else { // make a composite name from all sub-elements indexes: "1_2_3_4"
+ TColStd_MapIteratorOfPackedMapOfInteger aRef(theRefs->GetMap());
+ for(; aRef.More(); aRef.Next()) {
+ aName<<"-"<<theSubNames[aRef.Key()];
+ if (theOrientations.find(aRef.Key()) != theOrientations.end()) {
+ if (theOrientations[aRef.Key()] == 1)
+ aName<<"f";
+ else if (theOrientations[aRef.Key()] == -1)
+ aName<<"r";
+ }
}
}
}
void Model_AttributeSelection::selectConstruction(
const ResultPtr& theContext, const std::shared_ptr<GeomAPI_Shape>& theSubShape)
{
- std::shared_ptr<Model_Document> aMyDoc =
+ std::shared_ptr<Model_Document> aMyDoc =
std::dynamic_pointer_cast<Model_Document>(owner()->document());
FeaturePtr aContextFeature = theContext->document()->feature(theContext);
- CompositeFeaturePtr aComposite =
+ CompositeFeaturePtr aComposite =
std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aContextFeature);
const TopoDS_Shape& aSubShape = theSubShape->impl<TopoDS_Shape>();
if (!aComposite || aComposite->numberOfSubs() == 0) {
// saving of context is enough: result construction contains exactly the needed shape
TNaming_Builder aBuilder(selectionLabel());
aBuilder.Generated(aSubShape);
- aMyDoc->addNamingName(selectionLabel(), theContext->data()->name());
- TDataStd_Name::Set(selectionLabel(), theContext->data()->name().c_str());
+ //std::string aName = contextName(theContext);
+ //aMyDoc->addNamingName(selectionLabel(), aName);
+ //TDataStd_Name::Set(selectionLabel(), aName.c_str());
return;
}
std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(owner()->data());
TDF_Label aLab = myRef.myRef->Label();
- // identify the reuslts of sub-object of the composite by edges
+ // identify the results of sub-object of the composite by edges
// save type of the selected shape in integer attribute
TopAbs_ShapeEnum aShapeType = aSubShape.ShapeType();
TDataStd_Integer::Set(aLab, (int)aShapeType);
TColStd_MapOfTransient allCurves;
if (aShapeType == TopAbs_VERTEX) { // compare positions
aVertexPos = BRep_Tool::Pnt(TopoDS::Vertex(aSubShape));
- } else {
+ } else {
for(TopExp_Explorer anEdgeExp(aSubShape, TopAbs_EDGE); anEdgeExp.More(); anEdgeExp.Next()) {
TopoDS_Edge anEdge = TopoDS::Edge(anEdgeExp.Current());
Standard_Real aFirst, aLast;
// iterate and store the result ids of sub-elements and sub-elements to sub-labels
Handle(TDataStd_IntPackedMap) aRefs = TDataStd_IntPackedMap::Set(aLab);
std::map<int, int> anOrientations; //map from edges IDs to orientations of these edges in face
+ std::map<int, std::string> aSubNames; //map from edges IDs to names of edges
aRefs->Clear();
const int aSubNum = aComposite->numberOfSubs();
for(int a = 0; a < aSubNum; a++) {
std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRes = aResults.cbegin();
// there may be many shapes (circle and center): register if at least one is in selection
for(; aRes != aResults.cend(); aRes++) {
- ResultConstructionPtr aConstr =
+ ResultConstructionPtr aConstr =
std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aRes);
if (!aConstr->shape()) {
continue;
gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aVertex));
if (aPnt.IsEqual(aVertexPos, Precision::Confusion())) {
aRefs->Add(aComposite->subFeatureId(a));
+ aSubNames[aComposite->subFeatureId(a)] = Model_SelectionNaming::shortName(aConstr);
}
- } else { // get first or last vertex of the edge: last is stored with negative sign
+ } else { // get first or last vertex of the edge: last is stored with additional delta
const TopoDS_Shape& anEdge = aConstr->shape()->impl<TopoDS_Shape>();
int aDelta = kSTART_VERTEX_DELTA;
for(TopExp_Explorer aVExp(anEdge, TopAbs_VERTEX); aVExp.More(); aVExp.Next()) {
gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aVExp.Current()));
if (aPnt.IsEqual(aVertexPos, Precision::Confusion())) {
aRefs->Add(aDelta + aComposite->subFeatureId(a));
+ aSubNames[aDelta + aComposite->subFeatureId(a)] =
+ Model_SelectionNaming::shortName(aConstr, aDelta / kSTART_VERTEX_DELTA);
break;
}
aDelta += kSTART_VERTEX_DELTA;
if (allCurves.Contains(aCurve)) {
int anID = aComposite->subFeatureId(a);
aRefs->Add(anID);
- if (aShapeType != TopAbs_EDGE) { // face nneds the sub-edges on sub-labels
+ aSubNames[anID] = Model_SelectionNaming::shortName(aConstr);
+ if (aShapeType != TopAbs_EDGE) { // face needs the sub-edges on sub-labels
// add edges to sub-label to support naming for edges selection
TopExp_Explorer anEdgeExp(aSubShape, TopAbs_EDGE);
for(; anEdgeExp.More(); anEdgeExp.Next()) {
Standard_Real aFirst, aLast;
Handle(Geom_Curve) aFaceCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
if (aFaceCurve == aCurve) {
- int anOrient = edgeOrientation(aSubShape, anEdge);
+ int anOrient = Model_SelectionNaming::edgeOrientation(aSubShape, anEdge);
anOrientations[anID] = anOrient;
registerSubShape(
- selectionLabel(), anEdge, anID, aContextFeature, aMyDoc, "", anOrientations,
- Handle(TDataStd_IntPackedMap)(), anOrient);
+ selectionLabel(), anEdge, anID, aContextFeature, aMyDoc, anOrientations,
+ aSubNames, Handle(TDataStd_IntPackedMap)(), anOrient);
}
}
} else { // put vertices of the selected edge to sub-labels
for(; anEdgeExp.More(); anEdgeExp.Next(), aTagIndex += kSTART_VERTEX_DELTA) {
TopoDS_Vertex aV = TopoDS::Vertex(anEdgeExp.Current());
- std::stringstream anAdditionalName;
+ std::stringstream anAdditionalName;
registerSubShape(
- selectionLabel(), aV, aTagIndex, aContextFeature, aMyDoc, "", anOrientations);
+ selectionLabel(), aV, aTagIndex, aContextFeature, aMyDoc, anOrientations,
+ aSubNames);
}
}
}
TNaming_Builder aBuilder(selectionLabel());
aBuilder.Generated(aSubShape);
registerSubShape(
- selectionLabel(), aSubShape, 0, aContextFeature, aMyDoc, "", anOrientations, aRefs);
+ selectionLabel(), aSubShape, 0, aContextFeature, aMyDoc, anOrientations, aSubNames, aRefs);
}
bool Model_AttributeSelection::selectPart(
return true; // postponed naming
if (theUpdate) {
Handle(TDataStd_Integer) anIndex;
- if (selectionLabel().FindAttribute(TDataStd_Integer::GetID(), anIndex)) { // by internal selection
+ if (selectionLabel().FindAttribute(TDataStd_Integer::GetID(), anIndex)) {
+ // by internal selection
if (anIndex->Get() > 0) {
// update the selection by index
return aPart->updateInPart(anIndex->Get());
}
return true; // nothing to do, referencing just by name
}
- // store the shape (in case part is not loaded it should be usefull
+ // store the shape (in case part is not loaded it should be useful
TopoDS_Shape aShape;
std::string aName = theContext->data()->name();
if (!theSubShape.get() || theSubShape->isNull()) {// the whole part shape is selected
std::string aName("");
if(!this->isInitialized())
return !theDefaultName.empty() ? theDefaultName : aName;
- Handle(TDataStd_Name) anAtt;
- if(selectionLabel().FindAttribute(TDataStd_Name::GetID(), anAtt)) {
- aName = TCollection_AsciiString(anAtt->Get()).ToCString();
- return aName;
- }
std::shared_ptr<GeomAPI_Shape> aSubSh = value();
ResultPtr aCont = context();
Model_SelectionNaming aSelNaming(selectionLabel());
- return aSelNaming.namingName(aCont, aSubSh, theDefaultName);
+ return aSelNaming.namingName(
+ aCont, aSubSh, theDefaultName, owner()->document() != aCont->document());
}
// type ::= COMP | COMS | SOLD | SHEL | FACE | WIRE | EDGE | VERT
{
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<ModelAPI_ResultPart>(aFound);
+ std::string aNameInPart = theSubShapeName.substr(aPartEnd + 1);
+ int anIndex;
+ std::shared_ptr<GeomAPI_Shape> aSelected = aPart->shapeInPart(aNameInPart, theType, anIndex);
+ if (aSelected.get()) {
+ setValue(aPart, aSelected);
+ TDataStd_Integer::Set(selectionLabel(), anIndex);
+ return;
+ }
+ }
+ }
+
Model_SelectionNaming aSelNaming(selectionLabel());
- std::shared_ptr<Model_Document> aDoc =
+ std::shared_ptr<Model_Document> aDoc =
std::dynamic_pointer_cast<Model_Document>(owner()->document());
std::shared_ptr<GeomAPI_Shape> 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<TopoDS_Shape>();
+ if (!aConShape.IsNull()) {
+ Handle(TNaming_NamedShape) aNS = TNaming_Tool::NamedShape(aConShape, selectionLabel());
+ if (!aNS.IsNull()) {
+ aNS = TNaming_Tool::CurrentNamedShape(aNS);
+ if (!aNS.IsNull()) {
+ 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<ModelAPI_Result>(anObj);
+ if (aRes)
+ aCont = aRes;
+ }
+ }
+ }
+ }
+ }
setValue(aCont, aShapeToBeSelected);
}
}
int Model_AttributeSelection::Id()
{
+ int anID = 0;
std::shared_ptr<GeomAPI_Shape> aSelection = value();
std::shared_ptr<GeomAPI_Shape> aContext = context()->shape();
- const TopoDS_Shape& aMainShape = aContext->impl<TopoDS_Shape>();
+ // support for compsolids:
+ if (context().get() && ModelAPI_Tools::compSolidOwner(context()).get())
+ aContext = ModelAPI_Tools::compSolidOwner(context())->shape();
+
+
+ TopoDS_Shape aMainShape = aContext->impl<TopoDS_Shape>();
const TopoDS_Shape& aSubShape = aSelection->impl<TopoDS_Shape>();
- int anID = 0;
+ // searching for the latest main shape
if (aSelection && !aSelection->isNull() &&
aContext && !aContext->isNull())
{
+ std::shared_ptr<Model_Document> aDoc =
+ std::dynamic_pointer_cast<Model_Document>(context()->document());
+ if (aDoc.get()) {
+ Handle(TNaming_NamedShape) aNS = TNaming_Tool::NamedShape(aMainShape, aDoc->generalLabel());
+ if (!aNS.IsNull()) {
+ aMainShape = TNaming_Tool::CurrentShape(aNS);
+ }
+ }
+
TopTools_IndexedMapOfShape aSubShapesMap;
TopExp::MapShapes(aMainShape, aSubShapesMap);
anID = aSubShapesMap.FindIndex(aSubShape);
}
return anID;
}
+
+void Model_AttributeSelection::setId(int theID)
+{
+ const ResultPtr& aContext = context();
+ std::shared_ptr<GeomAPI_Shape> aSelection;
+
+ std::shared_ptr<GeomAPI_Shape> aContextShape = aContext->shape();
+ // support for compsolids:
+ if (aContext.get() && ModelAPI_Tools::compSolidOwner(aContext).get())
+ aContextShape = ModelAPI_Tools::compSolidOwner(aContext)->shape();
+
+ TopoDS_Shape aMainShape = aContextShape->impl<TopoDS_Shape>();
+ // searching for the latest main shape
+ if (theID > 0 &&
+ aContextShape && !aContextShape->isNull())
+ {
+ std::shared_ptr<Model_Document> aDoc =
+ std::dynamic_pointer_cast<Model_Document>(aContext->document());
+ if (aDoc.get()) {
+ Handle(TNaming_NamedShape) aNS = TNaming_Tool::NamedShape(aMainShape, aDoc->generalLabel());
+ if (!aNS.IsNull()) {
+ aMainShape = TNaming_Tool::CurrentShape(aNS);
+ }
+ }
+
+ TopTools_IndexedMapOfShape aSubShapesMap;
+ TopExp::MapShapes(aMainShape, aSubShapesMap);
+ const TopoDS_Shape& aSelShape = aSubShapesMap.FindKey(theID);
+
+ std::shared_ptr<GeomAPI_Shape> aResult(new GeomAPI_Shape);
+ aResult->setImpl(new TopoDS_Shape(aSelShape));
+
+ aSelection = aResult;
+ }
+
+ setValue(aContext, aSelection);
+}
+
+std::string Model_AttributeSelection::contextName(const ResultPtr& theContext) const
+{
+ std::string aResult;
+ if (owner()->document() != theContext->document()) {
+ if (theContext->document() == ModelAPI_Session::get()->moduleDocument()) {
+ aResult = theContext->document()->kind() + "/";
+ } else {
+ ResultPtr aDocRes = ModelAPI_Tools::findPartResult(
+ ModelAPI_Session::get()->moduleDocument(), theContext->document());
+ if (aDocRes.get()) {
+ aResult = aDocRes->data()->name() + "/";
+ }
+ }
+ }
+ aResult += theContext->data()->name();
+ return aResult;
+}
+
+void Model_AttributeSelection::updateInHistory()
+{
+ ResultPtr aContext = std::dynamic_pointer_cast<ModelAPI_Result>(myRef.value());
+ // only bodies may be modified later in the history, don't do anything otherwise
+ if (!aContext.get() || aContext->groupName() != ModelAPI_ResultBody::group())
+ return;
+ std::shared_ptr<Model_Data> aContData = std::dynamic_pointer_cast<Model_Data>(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))
+ return;
+ std::shared_ptr<Model_Document> aDoc =
+ std::dynamic_pointer_cast<Model_Document>(aContext->document());
+ FeaturePtr aThisFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(owner());
+ FeaturePtr aCurrentModifierFeat = aDoc->feature(aContext);
+ // iterate the context shape modifications in order to find a feature that is upper in history
+ // that this one and is really modifies the referenced result to refer to it
+ ResultPtr aModifierResFound;
+ TNaming_Iterator aPairIter(aContNS);
+ TopoDS_Shape aNewShape = 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<ModelAPI_Result>
+ (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<GeomAPI_Shape> anEmptyShape;
+ setValue(anEmptyContext, anEmptyShape); // nullify the selection
+ return;
+ } else { // not-precessed modification => don't support it
+ continue;
+ }
+ }
+ }
+ if (aModifierResFound.get()) {
+ // update scope to reset to a new one
+ myScope.Clear();
+ myRef.setValue(aModifierResFound);
+ update(); // it must recompute a new sub-shape automatically
+ }
+}
+
+void Model_AttributeSelection::setParent(Model_AttributeSelectionList* theParent)
+{
+ myParent = theParent;
+}