-// Copyright (C) 2014-2017 CEA/DEN, EDF R&D
+// Copyright (C) 2014-2019 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
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
-// See http://www.salome-platform.org/ or
-// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//
#include "Model_AttributeSelection.h"
#include <ModelAPI_ResultBody.h>
#include <ModelAPI_ResultBody.h>
#include <ModelAPI_ResultConstruction.h>
+#include <ModelAPI_ResultGroup.h>
#include <ModelAPI_ResultPart.h>
#include <ModelAPI_CompositeFeature.h>
#include <ModelAPI_Tools.h>
#include <Events_InfoMessage.h>
#include <GeomAPI_Edge.h>
#include <GeomAPI_Pnt.h>
+#include <GeomAPI_ShapeIterator.h>
#include <GeomAPI_Vertex.h>
#include <GeomAPI_ShapeExplorer.h>
#include <GeomAlgoAPI_CompoundBuilder.h>
Standard_GUID kELLIPSE_CENTER1("f70df04c-3168-4dc9-87a4-f1f840c1275d");
// identifier of the selection of the second focus point of ellipse on edge
Standard_GUID kELLIPSE_CENTER2("1395ae73-8e02-4cf8-b204-06ff35873a32");
-// reference to the external sketch face
-Standard_GUID kEXT_SKETCH_FACE("ba32aa31-bde7-422f-80b4-79c757c77b49");
-// reference to the external sketch wire
-Standard_GUID kEXT_SKETCH_WIRE("ba32aa31-bde7-422f-80b4-79c757c77b46");
-// reference to the external sketch edge
-Standard_GUID kEXT_SKETCH_EDGE("ba32aa31-bde7-422f-80b4-79c757c77b48");
-// reference to the external sketch vertex
-Standard_GUID kEXT_SKETCH_VERT("ba32aa31-bde7-422f-80b4-79c757c77b47");
// prefix for the whole feature context identification
const static std::string kWHOLE_FEATURE = "all-in-";
bool Model_AttributeSelection::setValue(const ObjectPtr& theContext,
const std::shared_ptr<GeomAPI_Shape>& theSubShape, const bool theTemporarily)
{
- if (theTemporarily &&
- (!theContext.get() || theContext->groupName() != ModelAPI_Feature::group())) {
+ if (theTemporarily) {
// just keep the stored without DF update
- myTmpContext = std::dynamic_pointer_cast<ModelAPI_Result>(theContext);
+ myTmpContext = theContext;
myTmpSubShape = theSubShape;
owner()->data()->sendAttributeUpdated(this);
return true;
aSelLab.ForgetAttribute(kCIRCLE_CENTER);
aSelLab.ForgetAttribute(kELLIPSE_CENTER1);
aSelLab.ForgetAttribute(kELLIPSE_CENTER2);
- aSelLab.ForgetAttribute(kEXT_SKETCH_FACE);
- aSelLab.ForgetAttribute(kEXT_SKETCH_WIRE);
- aSelLab.ForgetAttribute(kEXT_SKETCH_EDGE);
- aSelLab.ForgetAttribute(kEXT_SKETCH_VERT);
bool isDegeneratedEdge = false;
// do not use the degenerated edge as a shape, a null context and shape is used in the case
std::shared_ptr<GeomAPI_Shape> aSubShape;
if (theSubShape.get() && !aConstruction->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(aConstruction->shape()->impl<TopoDS_Shape>());
- std::string anInfinitiveName = contextName(aConstruction);
- TDataStd_Name::Set(aSelLab, anInfinitiveName.c_str());
- std::dynamic_pointer_cast<Model_Document>(owner()->document())
- ->addNamingName(aSelLab, anInfinitiveName.c_str());
- */
- }
} else if (theContext->groupName() == ModelAPI_ResultPart::group()) {
aSelLab.ForgetAllAttributes(true);
TDataStd_UAttribute::Set(aSelLab, kPART_REF_ID);
selectPart(std::dynamic_pointer_cast<ModelAPI_Result>(theContext), theSubShape);
+ } 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
FeaturePtr aFeatureContext = std::dynamic_pointer_cast<ModelAPI_Feature>(theContext);
if (aFeatureContext.get()) {
// it is just reference to construction.
return myTmpSubShape;
}
- return myTmpSubShape.get() ? myTmpSubShape : myTmpContext->shape();
+ FeaturePtr aFeature =
+ std::dynamic_pointer_cast<ModelAPI_Feature>(myTmpContext);
+ if (aFeature.get()) {
+ // it is just reference to construction.
+ return myTmpSubShape;
+ }
+ return myTmpSubShape.get() ? myTmpSubShape :
+ std::dynamic_pointer_cast<ModelAPI_Result>(myTmpContext)->shape();
}
TDF_Label aSelLab = selectionLabel();
if (aConstr) {
if (aConstr->isInfinite())
return aResult; // empty result
- // external sketch face
- Handle(TDataStd_Integer) anIndex;
- if (aSelLab.FindAttribute(kEXT_SKETCH_FACE, anIndex)) {
- return aConstr->face(anIndex->Get());
- }
- if (aSelLab.FindAttribute(kEXT_SKETCH_WIRE, anIndex)) {
- GeomShapePtr aFace = aConstr->face(anIndex->Get());
- if (aFace.get()) {
- GeomAPI_ShapeExplorer aFaceExp(aFace, GeomAPI_Shape::WIRE);
- if (aFaceExp.more()) {
- return aFaceExp.current();
- }
- }
- }
- if (aSelLab.FindAttribute(kEXT_SKETCH_EDGE, anIndex) ||
- aSelLab.FindAttribute(kEXT_SKETCH_VERT, anIndex)) {
- bool isVert = anIndex->ID() == kEXT_SKETCH_VERT; // vertex is selected
- CompositeFeaturePtr aComposite = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(
- aConstr->document()->feature(aConstr));
- if (aComposite.get()) {
- int aSubNum = anIndex->Get() % 1000000;
- int aVertShape = (anIndex->Get() - aSubNum) / 1000000;
- FeaturePtr aSubFeat = aComposite->subFeature(aSubNum);
- if (aSubFeat.get()) {
- const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aSubFeat->results();
- std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRes = aResults.cbegin();
- for (; aRes != aResults.cend(); aRes++) {
- ResultConstructionPtr aConstr =
- std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aRes);
- if (aConstr->shape()) {
- if (!isVert && aConstr->shape()->isEdge())
- return aConstr->shape();
- else if (isVert && aVertShape == 0 && aConstr->shape()->isVertex())
- return aConstr->shape();
- else if (isVert && aVertShape > 1 && aConstr->shape()->isEdge()) {
- GeomAPI_ShapeExplorer anExp(aConstr->shape(), GeomAPI_Shape::VERTEX);
- for(; anExp.more(); anExp.next()) {
- if (aVertShape == 1)
- return anExp.current();
- aVertShape--;
- }
- }
- }
- }
- }
- }
- }
}
if (!aConstr.get()) { // for construction context, return empty result as usual even
// the whole feature is selected
std::shared_ptr<GeomAPI_Shape> aResult;
if (myRef.isInitialized()) {
TDF_Label aSelLab = selectionLabel();
- if (aSelLab.IsAttribute(kSIMPLE_REF_ID)) { // it is just reference to shape, not sub-shape
+ // 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;
}
if (selectionLabel().FindAttribute(TNaming_NamedShape::GetID(), aSelection)) {
return !aSelection->Get().IsNull();
} else { // for simple construction element: just shape of this construction element
- std::shared_ptr<Model_ResultConstruction> aConstr =
- std::dynamic_pointer_cast<Model_ResultConstruction>(context());
- if (aConstr.get()) {
- return true;
- }
- // for the whole feature, a feature object
- FeaturePtr aFeat = contextFeature();
- if (aFeat.get())
+ 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<Model_Document> aMyDoc =
+ std::dynamic_pointer_cast<Model_Document>(owner()->document());
+ if (!aMyDoc.get())
+ return false;
+ // check at least the feature exists
+ return aMyDoc->featureByLab(aRefLab).get() != NULL;
}
}
}
}
Model_AttributeSelection::Model_AttributeSelection(TDF_Label& theLabel)
- : myRef(theLabel)
+: myRef(theLabel),
+ myIsGeometricalSelection(false)
{
myIsInitialized = myRef.isInitialized();
myParent = NULL;
{
myRef.setID(theID);
ModelAPI_AttributeSelection::setID(theID);
+ FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(owner());
+ if (myParent) {
+ // to be able to select as geometrical selection and then - split
+ myIsGeometricalSelection = true; // myParent->isGeometricalSelection();
+ } else {
+ myIsGeometricalSelection =
+ ModelAPI_Session::get()->validators()->isGeometricalSelection(aFeature->getKind(), id());
+ }
}
ResultPtr Model_AttributeSelection::context()
return ResultPtr();
if (myTmpContext.get() || myTmpSubShape.get()) {
- return myTmpContext;
+ return std::dynamic_pointer_cast<ModelAPI_Result>(myTmpContext);
}
ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(myRef.value());
}
FeaturePtr Model_AttributeSelection::contextFeature() {
- if (myTmpContext.get() || myTmpSubShape.get()) {
- return FeaturePtr(); // feature can not be selected temporarily
+ if (myTmpContext.get()) {
+ return std::dynamic_pointer_cast<ModelAPI_Feature>(myTmpContext);
}
return std::dynamic_pointer_cast<ModelAPI_Feature>(myRef.value());
}
if (aSelLab.FindAttribute(TNaming_NamedShape::GetID(), aNS))
anOldShape = aNS->Get();
- Selector_Selector aSelector(aSelLab);
- if (aSelector.restore()) { // it is stored in old OCCT format, use TNaming_Selector
- TopoDS_Shape aContextShape = aContext->shape()->impl<TopoDS_Shape>();
- aResult = aSelector.solve(aContextShape);
- }
- aResult = setInvalidIfFalse(aSelLab, aResult);
+ TopoDS_Shape aContextShape = aContext->shape()->impl<TopoDS_Shape>();
+ Selector_Selector aSelector(aSelLab, baseDocumentLab());
+ aResult = aSelector.restore(aContextShape);
+ setInvalidIfFalse(aSelLab, aResult);
TopoDS_Shape aNewShape;
if (aSelLab.FindAttribute(TNaming_NamedShape::GetID(), aNS))
// 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 || aNewShape.ShapeType() == TopAbs_COMPSOLID))
- {
+ aNewShape.ShapeType() == TopAbs_COMPOUND) {
split(aContext, aNewShape, anOldShape.ShapeType());
}
owner()->data()->sendAttributeUpdated(this); // send updated if shape is changed
std::shared_ptr<Model_ResultConstruction> aConstructionContext =
std::dynamic_pointer_cast<Model_ResultConstruction>(aContext);
if (!aConstructionContext->isInfinite()) {
- // external sketch face
- Handle(TDataStd_Integer) anIndex;
- if (aSelLab.FindAttribute(kEXT_SKETCH_FACE, anIndex) ||
- aSelLab.FindAttribute(kEXT_SKETCH_WIRE, anIndex)) {
- return setInvalidIfFalse(aSelLab, anIndex->Get() < aConstructionContext->facesNum());
- }
- if (aSelLab.FindAttribute(kEXT_SKETCH_EDGE, anIndex) ||
- aSelLab.FindAttribute(kEXT_SKETCH_VERT, anIndex)) {
- CompositeFeaturePtr aComposite = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(
- aConstructionContext->document()->feature(aConstructionContext));
- if (aComposite.get()) {
- FeaturePtr aSubFeat = aComposite->subFeature(anIndex->Get() % 1000000);
- return setInvalidIfFalse(aSelLab, aSubFeat.get() != NULL);
- }
- return setInvalidIfFalse(aSelLab, false); // composite sub-feature is not found
- }
- Selector_Selector aSelector(aSelLab);
- aResult = aSelector.restore();
+ TopoDS_Shape aContextShape = aContext->shape()->impl<TopoDS_Shape>();
+ Selector_Selector aSelector(aSelLab, baseDocumentLab());
TopoDS_Shape anOldShape = aSelector.value();
- if (aResult) {
- TopoDS_Shape aContextShape = aContext->shape()->impl<TopoDS_Shape>();
- aResult = aSelector.solve(aContextShape);
- }
- aResult = setInvalidIfFalse(aSelLab, aResult);
+ aResult = aSelector.restore(aContextShape);
+ setInvalidIfFalse(aSelLab, aResult);
if (aResult && !anOldShape.IsEqual(aSelector.value()))
owner()->data()->sendAttributeUpdated(this); // send updated if shape is changed
} else {
if (!aContext.IsNull()) {
TDF_Label aSelLab = selectionLabel();
TopoDS_Shape aNewSub = theSubShape->impl<TopoDS_Shape>();
- FeaturePtr aFeatureOwner = std::dynamic_pointer_cast<ModelAPI_Feature>(owner());
- if (aFeatureOwner->document() != theContext->document() &&
- theContext->groupName() == ModelAPI_ResultConstruction::group()) {// condition for parts
- // reference to the sketch face
- if (theSubShape->shapeType() == GeomAPI_Shape::FACE ||
- theSubShape->shapeType() == GeomAPI_Shape::WIRE) { // sketch face or sketch face wire
- ResultConstructionPtr aConstr =
- std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(theContext);
- int aFaceIndex = -1, aFacesNum = aConstr->facesNum();
- for(int a = 0; a < aFacesNum; a++) {
- bool isEqual = false;
- GeomShapePtr aFace = aConstr->face(a);
- if (!aFace.get() || aFace->isNull())
- continue;
- if (theSubShape->shapeType() == GeomAPI_Shape::FACE) {
- isEqual = aFace->isEqual(theSubShape);
- } else {
- GeomAPI_ShapeExplorer anExp(aFace, GeomAPI_Shape::WIRE);
- if (anExp.more())
- isEqual = anExp.current()->isEqual(theSubShape);
- }
- if (isEqual) {
- aFaceIndex = a;
- break;
- }
- }
- if (aFaceIndex >= 0) {
- TDataStd_Integer::Set(aSelLab, theSubShape->shapeType() == GeomAPI_Shape::FACE ?
- kEXT_SKETCH_FACE : kEXT_SKETCH_WIRE, aFaceIndex); // store index of the face
- return;
- }
- } else if (theSubShape->shapeType() == GeomAPI_Shape::EDGE ||// sketch result edge (full one)
- theSubShape->shapeType() == GeomAPI_Shape::VERTEX) { // or start/end vertex
- bool isVertex = theSubShape->shapeType() == GeomAPI_Shape::VERTEX;
- CompositeFeaturePtr aComposite = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(
- theContext->document()->feature(theContext));
- if (aComposite.get()) { // iterate edges of composite to find index of matched with value
- int aSub, anEdgeIndex = -1, aSubNum = aComposite->numberOfSubs();
- int aVertIndex = -1, aVertShape = -1; // shape: 0 full, 1 start, 2 end
- for(aSub = 0; aSub < aSubNum && anEdgeIndex == -1; aSub++) {
- FeaturePtr aSubFeat = aComposite->subFeature(aSub);
- const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aSubFeat->results();
- std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRes = aResults.cbegin();
- for (; aRes != aResults.cend(); aRes++) {
- ResultConstructionPtr aConstr =
- std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aRes);
- if (aConstr->shape() && aConstr->shape()->isEdge()) {
- if (isVertex) {
- GeomAPI_ShapeExplorer aVertExp(aConstr->shape(), GeomAPI_Shape::VERTEX);
- for(int aNum = 1; aVertExp.more(); aVertExp.next(), aNum++) {
- if (aVertExp.current()->isSame(theSubShape) && aVertShape != 0) {
- aVertIndex = aSub;
- aVertShape = aNum;
- }
- }
- } else {
- if (aConstr->shape()->isSame(theSubShape)) {
- anEdgeIndex = aSub;
- break;
- }
- }
- } else if (isVertex && aConstr->shape() && aConstr->shape()->isVertex()) {
- if (aConstr->shape()->isSame(theSubShape)) {
- aVertIndex = aSub;
- aVertShape = 0;
- }
- }
- }
- }
- if (anEdgeIndex >= 0) {
- TDataStd_Integer::Set(aSelLab, kEXT_SKETCH_EDGE, anEdgeIndex); // store index of edge
- return;
- } else if (aVertIndex >= 0) {
- aVertIndex += aVertShape * 1000000; // to store both integers: index and shape
- TDataStd_Integer::Set(aSelLab, kEXT_SKETCH_VERT, aVertIndex); // store index of edge
- return;
- }
- }
- }
- }
+
bool aSelectorOk = true;
- Selector_Selector aSel(aSelLab);
+ Selector_Selector aSelector(aSelLab, baseDocumentLab());
try {
- aSelectorOk = aSel.select(aContext, aNewSub);
+ aSelectorOk = aSelector.select(aContext, aNewSub, myIsGeometricalSelection);
if (aSelectorOk) {
- aSel.store();
- aSelectorOk = aSel.solve(aContext);
+ aSelectorOk = aSelector.store(aContext);
}
} catch(...) {
aSelectorOk = false;
}
- Handle(TNaming_NamedShape) aSelectorShape;
- if (aSelectorOk && aSelLab.FindAttribute(TNaming_NamedShape::GetID(), aSelectorShape))
- {
- TopoDS_Shape aShape = aSelectorShape->Get();
- if (aShape.IsNull() || aShape.ShapeType() != aNewSub.ShapeType())
- aSelectorOk = false;
- }
- if (!aSelectorOk) {
- setInvalidIfFalse(aSelLab, false);
+ if (aSelectorOk) {
+ TopoDS_Shape aShape = aSelector.value();
+ aSelectorOk = !aShape.IsNull() && aShape.ShapeType() == aNewSub.ShapeType();
}
+ setInvalidIfFalse(aSelLab, aSelectorOk);
}
}
if(!this->isInitialized())
return !theDefaultName.empty() ? theDefaultName : aName;
+ // not argument has not parametric name (filters)
+ if (!this->isArgument() || (myParent && !myParent->isArgument())) {
+ GeomShapePtr aShape = value();
+ if (!aShape.get() && context().get())
+ aShape = context()->shape();
+ std::string aName;
+ if (aShape.get()) {
+ aName = aShape->shapeTypeStr();
+ if (myParent) {
+ aName += std::string("_") +
+ TCollection_AsciiString(selectionLabel().Father().Tag()).ToCString();
+ }
+ }
+ return aName;
+ }
+
CenterType aCenterType = NOT_CENTER;
std::shared_ptr<GeomAPI_Shape> aSubSh = internalValue(aCenterType);
ResultPtr aCont = context();
ResultConstructionPtr aConstr = std::dynamic_pointer_cast<Model_ResultConstruction>(aCont);
if (aConstr->isInfinite()) {
return contextName(aCont);
- } else {
- // external sketch face
- Handle(TDataStd_Integer) anIndex;
- if (aSelLab.FindAttribute(kEXT_SKETCH_FACE, anIndex) ||
- aSelLab.FindAttribute(kEXT_SKETCH_WIRE, anIndex) ||
- aSelLab.FindAttribute(kEXT_SKETCH_EDGE, anIndex) ||
- aSelLab.FindAttribute(kEXT_SKETCH_VERT, anIndex)) {
- std::shared_ptr<Model_Document> anExtDoc =
- std::dynamic_pointer_cast<Model_Document>(aCont->document());
- Selector_Selector aSelector(anExtDoc->extConstructionsLabel());
- TopoDS_Shape aContShape = aConstr->shape()->impl<TopoDS_Shape>();
- TopoDS_Shape aValShape = value()->impl<TopoDS_Shape>();
- aSelector.select(aContShape, aValShape);
- myRestoreDocument = anExtDoc;
- std::string aName = anExtDoc->kind() + "/" + aSelector.name(this);
- myRestoreDocument.reset();
- return aName;
- }
}
}
- Selector_Selector aSelector(aSelLab);
+ Selector_Selector aSelector(aSelLab, baseDocumentLab());
std::string aResult;
- if (aSelector.restore())
+ if (aCont->shape().get() && aSelector.restore(aCont->shape()->impl<TopoDS_Shape>()))
aResult = aSelector.name(this);
- /*
- Model_SelectionNaming aSelNaming(aSelLab);
- std::string aResult = aSelNaming.namingName(
- aCont, aSubSh, theDefaultName, owner()->document() != aCont->document());
- */
if (aCenterType != NOT_CENTER) {
aResult += centersMap()[aCenterType];
}
}
}
- Selector_Selector aSelector(aDoc->generalLabel());
+ Selector_Selector aSelector(selectionLabel(), baseDocumentLab());
myRestoreDocument = aDoc;
- TDF_Label aContextLabel = aSelector.restoreByName(aSubShapeName, aShapeType, this);
+ TDF_Label aContextLabel = aSelector.restoreByName(
+ aSubShapeName, aShapeType, this, myIsGeometricalSelection);
myRestoreDocument.reset();
if (!aContextLabel.IsNull()) {
ResultPtr aContext = aDoc->resultByLab(aContextLabel); // any label for document access
aShapeToBeSelected->setImpl<TopoDS_Shape>(new TopoDS_Shape(aSelectorShape));
// make the context result the latest existing
aContext = newestContext(aContext, aShapeToBeSelected);
- if (aCenterType != NOT_CENTER) {
+ if (myIsGeometricalSelection || aCenterType == NOT_CENTER) {
+ // store the currently generated name
+ selectionLabel().ForgetAllAttributes(true);
+ bool aToUnblock = false;
+ aToUnblock = !owner()->data()->blockSendAttributeUpdated(true);
+ myRef.setValue(aContext);
+ aSelector.store(aContextShape);
+ owner()->data()->sendAttributeUpdated(this);
+ if (aToUnblock)
+ owner()->data()->blockSendAttributeUpdated(false);
+ return;
+ } else { // re-select center of circle/arc by context and value
if (!aShapeToBeSelected->isEdge())
continue;
std::shared_ptr<GeomAPI_Edge> aSelectedEdge(new GeomAPI_Edge(aShapeToBeSelected));
setValueCenter(aContext, aSelectedEdge, aCenterType);
}
- else
- setValue(aContext, aShapeToBeSelected);
return;
}
}
}
}
-int Model_AttributeSelection::Id()
-{
- int anID = 0;
- std::shared_ptr<GeomAPI_Shape> aSelection = value();
- ResultPtr aContextRes = context();
- // support for compsolids:
- while(ModelAPI_Tools::bodyOwner(aContextRes).get()) {
- aContextRes = ModelAPI_Tools::bodyOwner(aContextRes);
- }
- std::shared_ptr<GeomAPI_Shape> aContext = aContextRes->shape();
-
-
- TopoDS_Shape aMainShape = aContext->impl<TopoDS_Shape>();
- const TopoDS_Shape& aSubShape = aSelection->impl<TopoDS_Shape>();
- // 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)
{
std::shared_ptr<GeomAPI_Shape> aSelection;
if (aWasWholeContext) {
theValShape = theOldContext->shape()->impl<TopoDS_Shape>();
}
+ TopAbs_ShapeEnum aValType = theValShape.ShapeType();
TopoDS_Shape aNewContShape = theNewContext->shape()->impl<TopoDS_Shape>();
// if a new value is unchanged in the new context, do nothing: value is correct
- TopExp_Explorer aSubExp(aNewContShape, theValShape.ShapeType());
+ TopExp_Explorer aSubExp(aNewContShape, aValType);
for(; aSubExp.More(); aSubExp.Next()) {
if (aSubExp.Current().IsSame(theValShape)) {
theShapes.Append(theValShape);
std::dynamic_pointer_cast<Model_Data>((*aNewContIter)->data());
TDF_Label aNewLab = aNewData->shapeLab();
// searching for produced sub-shape fully on some label
- TDF_ChildIDIterator aNSIter(aNewLab, TNaming_NamedShape::GetID(), Standard_True);
+ TDF_ChildIDIterator aNSIter(aNewLab, TNaming_NamedShape::GetID());
for(; aNSIter.More(); aNSIter.Next()) {
Handle(TNaming_NamedShape) aNS = Handle(TNaming_NamedShape)::DownCast(aNSIter.Value());
for(TNaming_Iterator aPairIter(aNS); aPairIter.More(); aPairIter.Next()) {
theShapes.Clear();
return;
}
- theShapes.Append(aPairIter.NewShape());
+ // don't add edges generated from faces
+ if (aPairIter.NewShape().ShapeType() <= aValType)
+ theShapes.Append(aPairIter.NewShape());
}
} else if (!aPairIter.OldShape().IsNull()) { // search shape that contains this sub
- TopExp_Explorer anExp(aPairIter.OldShape(), theValShape.ShapeType());
+ TopExp_Explorer anExp(aPairIter.OldShape(), aValType);
for(; anExp.More(); anExp.Next()) {
if (anExp.Current().IsSame(theValShape)) { // found a new container
- if (aPairIter.NewShape().IsNull()) {// value was removed
- theShapes.Clear();
- return;
- }
+ if (aPairIter.NewShape().IsNull()) // skip removed high-level shape
+ continue;
aNewToOld.Bind(aPairIter.NewShape(), aPairIter.OldShape());
anOlds.Add(aPairIter.OldShape());
break;
}
}
if (aToFindPart == 2 && !aNewToOld.IsEmpty()) {
+ // also iterate the whole old shape to find not-modified shapes that contain this old
+ TopoDS_Shape anOldContShape = theOldContext->shape()->impl<TopoDS_Shape>();
+ NCollection_Map<TopAbs_ShapeEnum> aNewTypes; // types of shapes to iterate
+ TopTools_DataMapOfShapeShape::Iterator aNewTypeIter(aNewToOld);
+ for(; aNewTypeIter.More(); aNewTypeIter.Next()) {
+ if (aNewTypeIter.Key().ShapeType() != aValType)
+ aNewTypes.Add(aNewTypeIter.Key().ShapeType());
+ }
+ NCollection_Map<TopAbs_ShapeEnum>::Iterator aTypeIter(aNewTypes);
+ for(; aTypeIter.More(); aTypeIter.Next()) {
+ for(TopExp_Explorer anExp(anOldContShape, aTypeIter.Value()); anExp.More(); anExp.Next()) {
+ TopoDS_Shape anOld = anExp.Current();
+ if (aNewToOld.IsBound(anOld) || anOlds.Contains(anOld)) // this was modified
+ continue;
+ TopExp_Explorer aValExp(anOld, aValType);
+ for(; aValExp.More(); aValExp.Next()) {
+ const TopoDS_Shape& anUnchanged = aValExp.Current();
+ if (anUnchanged.IsSame(theValShape)) {
+ aNewToOld.Bind(anOld, anOld);
+ anOlds.Add(anOld);
+ break;
+ }
+ }
+ }
+ }
+
// map of sub-shapes -> number of occurrences of these shapes in containers
NCollection_DataMap<TopoDS_Shape, TopTools_MapOfShape, TopTools_ShapeMapHasher> aSubs;
TopTools_DataMapOfShapeShape::Iterator aContIter(aNewToOld);
for(; aContIter.More(); aContIter.Next()) {
- TopExp_Explorer aSubExp(aContIter.Key(), theValShape.ShapeType());
+ TopExp_Explorer aSubExp(aContIter.Key(), aValType);
for(; aSubExp.More(); aSubExp.Next()) {
if (!aSubs.IsBound(aSubExp.Current())) {
aSubs.Bind(aSubExp.Current(), TopTools_MapOfShape());
aSubsIter(aSubs);
for(; aSubsIter.More(); aSubsIter.Next()) {
if (aSubsIter.Value().Size() == aCountInOld) {
- theShapes.Append(aSubsIter.Key());
+ TopoDS_Shape anOld = aSubsIter.Key();
+ // check this exists in the new shape
+ TopExp_Explorer aNew(aNewContShape, anOld.ShapeType());
+ for (; aNew.More(); aNew.Next()) {
+ if (aNew.Current().IsSame(anOld))
+ break;
+ }
+ if (aNew.More())
+ theShapes.Append(anOld);
}
}
}
if (theShapes.IsEmpty()) { // nothing was changed
- theShapes.Append(aWasWholeContext ? TopoDS_Shape() : theValShape);
+ if (aWasWholeContext)
+ theShapes.Append(TopoDS_Shape());
+ else { // if theValShape exists in new context, add it without changes, otherwise - nothing
+ for (TopExp_Explorer aNew(aNewContShape, aValType); aNew.More(); aNew.Next()){
+ if (aNew.Current().IsSame(theValShape)) {
+ theShapes.Append(theValShape);
+ break;
+ }
+ }
+ }
+ } else if (theShapes.Size() > 1) {
+ // check it is possible to remove extra sub-shapes:
+ // keep only shapes with the same number of containers if possible
+ TopAbs_ShapeEnum anAncType = TopAbs_FACE;
+ if (aValType == TopAbs_VERTEX)
+ anAncType = TopAbs_EDGE;
+ TopoDS_Shape anOldContext = theOldContext->shape()->impl<TopoDS_Shape>();
+ TopTools_IndexedDataMapOfShapeListOfShape anOldMap;
+ TopExp::MapShapesAndUniqueAncestors(anOldContext, aValType, anAncType, anOldMap);
+ if (anOldMap.Contains(theValShape)) {
+ int aNumInOld = anOldMap.FindFromKey(theValShape).Extent();
+ TopTools_IndexedDataMapOfShapeListOfShape aNewMap;
+ TopExp::MapShapesAndUniqueAncestors(aNewContShape, aValType, anAncType, aNewMap);
+ TopTools_ListOfShape aNewResults;
+ for(TopTools_ListOfShape::Iterator aNewSubs(theShapes); aNewSubs.More(); aNewSubs.Next()) {
+ TopoDS_Shape aCand = aNewSubs.Value();
+ if (aNewMap.Contains(aCand) && aNewMap.FindFromKey(aCand).Extent() == aNumInOld)
+ aNewResults.Append(aCand);
+ }
+ if (!aNewResults.IsEmpty() && aNewResults.Size() < theShapes.Size())
+ theShapes = aNewResults;
+ }
}
}
std::list<ResultPtr>& theResults, TopTools_ListOfShape& theValShapes)
{
std::set<ResultPtr> aResults; // to avoid duplicates, new context, null if deleted
- TopTools_ListOfShape aResContShapes;
// iterate context and shape, but also if it is sub-shape of main shape, check also it
TopTools_ListOfShape aContextList;
aContextList.Append(theContShape);
aModifIter.Label().FindAttribute(TNaming_NamedShape::GetID(), aNewNS);
if (aNewNS->Evolution() == TNaming_MODIFY || aNewNS->Evolution() == TNaming_GENERATED) {
aResults.insert(aModifierObj);
- aResContShapes.Append(aModifierObj->shape()->impl<TopoDS_Shape>());
} else if (aNewNS->Evolution() == TNaming_DELETE) { // a shape was deleted => result is empty
aResults.insert(ResultPtr());
} else { // not-processed modification => don't support it
}
}
}
- if (aResults.empty())
- return false; // no modifications found, must stay the same
+ // if there exist context composite and sub-result(s), leave only sub(s)
+ for(std::set<ResultPtr>::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))
+ break;
+ if (aParent.get()) { // erase from set, so, restart iteration
+ aResults.erase(aParent);
+ aResIter = aResults.begin();
+ } else aResIter++;
+ }
+
+ if (aResults.empty()) {
+ // check the context become concealed by operation which is earlier than this selection
+ std::list<ResultPtr> allRes;
+ ResultPtr aRoot = ModelAPI_Tools::bodyOwner(theContext, true);
+ if (!aRoot.get())
+ aRoot = theContext;
+ ResultBodyPtr aRootBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aRoot);
+ if (aRootBody.get()) {
+ ModelAPI_Tools::allSubs(aRootBody, allRes);
+ allRes.push_back(aRootBody);
+ } else
+ allRes.push_back(aRoot);
+
+ FeaturePtr aThisFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(owner());
+ for (std::list<ResultPtr>::iterator aSub = allRes.begin(); aSub != allRes.end(); aSub++) {
+ ResultPtr aResCont = *aSub;
+ const std::set<AttributePtr>& aRefs = aResCont->data()->refsToMe();
+ std::set<AttributePtr>::const_iterator aRef = aRefs.begin();
+ for (; aRef != aRefs.end(); aRef++) {
+ if (!aRef->get() || !(*aRef)->owner().get())
+ continue;
+ // concealed attribute only
+ FeaturePtr aRefFeat = std::dynamic_pointer_cast<ModelAPI_Feature>((*aRef)->owner());
+ if (aRefFeat == aThisFeature)
+ continue;
+ if (!ModelAPI_Session::get()->validators()->isConcealed(
+ aRefFeat->getKind(), (*aRef)->id()))
+ continue;
+ if (theDoc->isLaterByDep(aThisFeature, aRefFeat)) {
+ // for extrusion cut in python script the nested sketch reference may be concealed before
+ // it is nested, so, check this composite feature is valid
+ static ModelAPI_ValidatorsFactory* aFactory = ModelAPI_Session::get()->validators();
+ // need to be validated to update the "Apply" state if not previewed
+ if (aFactory->validate(aRefFeat)) {
+ // there could be a reference to unmodified object, check result contain same shape
+ std::list<ResultPtr> aRefResults;
+ ModelAPI_Tools::allResults(aRefFeat, aRefResults);
+ std::list<ResultPtr>::iterator aRefIter = aRefResults.begin();
+ for(; aRefIter != aRefResults.end(); aRefIter++) {
+ ResultBodyPtr aRefBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(*aRefIter);
+ if (!aRefBody.get() || aRefBody->numberOfSubs() != 0) // iterate only leafs
+ continue;
+ GeomShapePtr aRefShape = aRefBody->shape();
+ if (!aRefShape.get() || aRefShape->isNull())
+ continue;
+ if (aRefShape->impl<TopoDS_Shape>().IsSame(theContShape)) {
+ // add the new context result with the same shape
+ aResults.insert(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
+ }
// iterate all results to find further modifications
std::set<ResultPtr>::iterator aResIter = aResults.begin();
for(; aResIter != aResults.end(); aResIter++) {
return true; // theResults must be empty: everything is deleted
}
-void Model_AttributeSelection::updateInHistory()
+void Model_AttributeSelection::updateInHistory(bool& theRemove)
{
ResultPtr aContext = std::dynamic_pointer_cast<ModelAPI_Result>(myRef.value());
// only bodies and parts may be modified later in the history, don't do anything otherwise
if (!aContData.get() || !aContData->isValid())
return;
TDF_Label aContLab = aContData->shapeLab(); // named shape where the selected context is located
+
+ // checking this may be just a reference to another context (same shape), so use that label
Handle(TNaming_NamedShape) aContNS;
+ Handle(TDF_Reference) aRefAttr;
+ while(!aContLab.FindAttribute(TNaming_NamedShape::GetID(), aContNS) &&
+ aContLab.FindAttribute(TDF_Reference::GetID(), aRefAttr))
+ aContLab = aRefAttr->Get();
+
if (!aContLab.FindAttribute(TNaming_NamedShape::GetID(), aContNS)) {
bool aFoundNewContext = true;
ResultPtr aNewContext = aContext;
continue;
FeaturePtr aRefFeat = std::dynamic_pointer_cast<ModelAPI_Feature>((*aRef)->owner());
- if (aRefFeat.get() && aRefFeat != owner()) {
+
+ if (aRefFeat.get() && aRefFeat != owner() && aRefFeat->firstResult().get()) {
+ // check the reference is concealed: #2900
+ ModelAPI_ValidatorsFactory* aValidators = ModelAPI_Session::get()->validators();
+ if (!aValidators->isConcealed(aRefFeat->getKind(), (*aRef)->id()))
+ continue;
FeaturePtr aThisFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(owner());
if (!aDoc->isLaterByDep(aRefFeat, aThisFeature)) { // found better feature
aFoundNewContext = true;
TopTools_ListOfShape aValShapes;
if (searchNewContext(aDoc, aNewCShape, aContext, aValShape, aContLab, aNewContexts, aValShapes))
{
- std::list<ResultPtr>::iterator aNewCont = aNewContexts.begin();
- TopTools_ListIteratorOfListOfShape aNewValues(aValShapes);
- if (aNewCont == aNewContexts.end()) { // all results were deleted
- ResultPtr anEmptyContext;
- std::shared_ptr<GeomAPI_Shape> anEmptyShape;
- setValue(anEmptyContext, anEmptyShape); // nullify the selection
- return;
+ std::set<ResultPtr> allContexts, aSkippedContext;
+ std::list<ResultPtr>::iterator aNewContext = aNewContexts.begin();
+ for(; aNewContext != aNewContexts.end(); aNewContext++)
+ allContexts.insert(*aNewContext);
+
+ // if there exist context composite and sub-result(s), leave only sub(s)
+ std::set<ResultPtr>::iterator aResIter = allContexts.begin();
+ for(; aResIter != allContexts.end(); aResIter++) {
+ ResultPtr aParent = ModelAPI_Tools::bodyOwner(*aResIter);
+ for(; aParent.get(); aParent = ModelAPI_Tools::bodyOwner(aParent))
+ if (allContexts.count(aParent))
+ aSkippedContext.insert(aParent);
}
- GeomShapePtr aValueShape;
- if (!aNewValues.Value().IsNull()) {
- aValueShape = std::make_shared<GeomAPI_Shape>();
- aValueShape->setImpl<TopoDS_Shape>(new TopoDS_Shape(aNewValues.Value()));
- }
- setValue(*aNewCont, aValueShape);
- // if there are more than one result, put them by "append" into "parent" list
+ GeomAPI_Shape::ShapeType aListShapeType = GeomAPI_Shape::SHAPE;
if (myParent) {
- for(aNewCont++, aNewValues.Next(); aNewCont != aNewContexts.end();
- aNewCont++, aNewValues.Next()) {
- GeomShapePtr aValueShape;
- if (!aNewValues.Value().IsNull()) {
- aValueShape = std::make_shared<GeomAPI_Shape>();
- aValueShape->setImpl<TopoDS_Shape>(new TopoDS_Shape(aNewValues.Value()));
- }
+ if (myParent->selectionType() == "VERTEX" || myParent->selectionType() == "Vertices")
+ aListShapeType = GeomAPI_Shape::VERTEX;
+ else if (myParent->selectionType() == "EDGE" || myParent->selectionType() == "Edges")
+ aListShapeType = GeomAPI_Shape::EDGE;
+ else if (myParent->selectionType() == "FACE" || myParent->selectionType() == "Faces")
+ aListShapeType = GeomAPI_Shape::FACE;
+ }
- // Check that list has the same type of shape selection before adding.
- GeomAPI_Shape::ShapeType aListShapeType = GeomAPI_Shape::SHAPE;
- if (myParent->selectionType() == "VERTEX") aListShapeType = GeomAPI_Shape::VERTEX;
- else if (myParent->selectionType() == "EDGE") aListShapeType = GeomAPI_Shape::EDGE;
- else if (myParent->selectionType() == "FACE") aListShapeType = GeomAPI_Shape::FACE;
-
- GeomAPI_Shape::ShapeType aShapeShapeType = GeomAPI_Shape::SHAPE;
- if (aValueShape.get()) {
- aShapeShapeType = aValueShape->shapeType();
- } else {
- (*aNewCont)->shape()->shapeType();
- }
+ std::list<ResultPtr>::iterator aNewCont = aNewContexts.begin();
+ TopTools_ListIteratorOfListOfShape aNewValues(aValShapes);
+ bool aFirst = true; // first is set to this, next are appended to parent
+ for(; aNewCont != aNewContexts.end(); aNewCont++, aNewValues.Next()) {
+ if (aSkippedContext.count(*aNewCont))
+ continue;
- if (aListShapeType != GeomAPI_Shape::SHAPE && aListShapeType != aShapeShapeType) {
- continue;
+ GeomShapePtr aValueShape;
+ if (!aNewValues.Value().IsNull()) {
+ aValueShape = std::make_shared<GeomAPI_Shape>();
+ aValueShape->setImpl<TopoDS_Shape>(new TopoDS_Shape(aNewValues.Value()));
+ }
+ // Check that list has the same type of shape selection before adding.
+ GeomAPI_Shape::ShapeType aShapeShapeType = GeomAPI_Shape::SHAPE;
+ if (aValueShape.get()) {
+ aShapeShapeType = aValueShape->shapeType();
+ } else {
+ aShapeShapeType = (*aNewCont)->shape()->shapeType();
+ }
+ if (aListShapeType != GeomAPI_Shape::SHAPE && aListShapeType != aShapeShapeType) {
+ continue;
+ }
+
+ ResultPtr aNewContext = *aNewCont;
+ if (aValueShape.get()) { // #2892 if context is higher level result, search this sub in lower
+ ResultBodyPtr aBodyContext = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aNewContext);
+ if (aBodyContext.get() && aBodyContext->numberOfSubs() != 0) {
+ std::list<ResultPtr> aLower;
+ ModelAPI_Tools::allSubs(aBodyContext, aLower, true);
+ for(std::list<ResultPtr>::iterator aL = aLower.begin(); aL != aLower.end(); aL++) {
+ GeomShapePtr aLShape = (*aL)->shape();
+ if (aLShape.get() && !aLShape->isNull()) {
+ if (aLShape->isSubShape(aValueShape, false)) {
+ aNewContext = *aL;
+ break;
+ }
+ }
+ }
}
+ }
- myParent->append(*aNewCont, aValueShape);
+ if (aFirst) {
+ if (!myParent || !myParent->isInList(aNewContext, aValueShape)) { // avoid duplicates
+ setValue(aNewContext, aValueShape);
+ aFirst = false;
+ }
+ } else if (myParent) {
+ if (!myParent->isInList(aNewContext, aValueShape)) // avoid addition of duplicates
+ myParent->append(aNewContext, aValueShape);
+ }
+ }
+ if (aFirst) { // nothing was added, all results were deleted
+ if (myParent) {
+ theRemove = true;
+ } else {
+ ResultPtr anEmptyContext;
+ std::shared_ptr<GeomAPI_Shape> anEmptyShape;
+ setValue(anEmptyContext, anEmptyShape); // nullify the selection
+ return;
}
}
}
std::shared_ptr<Model_Document> aDoc = myRestoreDocument.get() ? myRestoreDocument :
std::dynamic_pointer_cast<Model_Document>(owner()->document());
FeaturePtr aFeatureOwner = aDoc->featureByLab(theSelectionLab);
+ bool aBaseDocumnetUsed = false;
+ if (!aFeatureOwner.get()) { // use module document
+ aDoc = std::dynamic_pointer_cast<Model_Document>(ModelAPI_Session::get()->moduleDocument());
+ aFeatureOwner = aDoc->featureByLab(theSelectionLab);
+ aBaseDocumnetUsed = true;
+ }
if (aFeatureOwner.get()) {
// if it is sub-element of the sketch, the context name is the name of the sketch
// searching also for result - real context
aContextName = "_" + aContextName;
aNumInHistoryNames--;
}
+ if (aBaseDocumnetUsed)
+ aContextName = aDoc->kind() + "/" + aContextName;
return aContextName;
}
}
if (aName.empty()) return false;
bool anUniqueContext = false;
ResultPtr aCont = aDoc->findByName(aName, aSubShapeName, anUniqueContext);
- if (!aCont.get() || !aCont->shape().get() || aCont->shape()->isNull())
- return false;
+ if (!aCont.get() || !aCont->shape().get() || aCont->shape()->isNull()) {
+ // name in PartSet?
+ aDoc = std::dynamic_pointer_cast<Model_Document>(
+ ModelAPI_Session::get()->moduleDocument());
+ if (theName.find(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) {
+ aName = aName.substr(0, n);
+ }
+ }
+ aCont = aDoc->findByName(aName, aSubShapeName, anUniqueContext);
+ if (!aCont.get() || !aCont->shape().get() || aCont->shape()->isNull())
+ return false;
+ }
// searching the sub-shape
static const ResultPtr anEmpty;
return true;
}
-TDF_Label Model_AttributeSelection::newestContext(const TDF_Label theCurrentContext) {
- std::shared_ptr<Model_Document> aDoc = myRestoreDocument.get() ? myRestoreDocument :
- std::dynamic_pointer_cast<Model_Document>(owner()->document());
- ResultPtr aContext = aDoc->resultByLab(theCurrentContext);
- if (aContext.get()) {
- aContext = newestContext(aContext, GeomShapePtr(), true);
- if (aContext.get())
- return std::dynamic_pointer_cast<Model_Data>(aContext->data())->label();
- }
- return theCurrentContext; // nothing is changed
-}
-
bool Model_AttributeSelection::isLater(
const TDF_Label theResult1, const TDF_Label theResult2) const
{
}
ResultPtr Model_AttributeSelection::newestContext(
- const ResultPtr theCurrent, const GeomShapePtr theValue, const bool theAnyValue)
+ const ResultPtr theCurrent, const GeomShapePtr theValue)
{
ResultPtr aResult = theCurrent;
GeomShapePtr aSelectedShape = theValue.get() ? theValue : theCurrent->shape();
TDF_Label aLab = aNS->Label();
ResultPtr aRes = aDoc->resultByLab(aLab);
if (aRes.get()) {
- if (theAnyValue || aRes->shape()->isSubShape(aSelectedShape)) {
+ if (aRes->shape()->isSubShape(aSelectedShape)) {
aResult = aRes;
aFindNewContext = true;
continue;
}
}
}
- if (theAnyValue) { // only for neighbors for now
- // try to find modification of sub-shapes: the best number of matches
- std::map<ResultPtr, int> aMatches; // result -> number of matches of shapes to find the best
- TDF_Label aResLab = std::dynamic_pointer_cast<Model_Data>(aResult->data())->shapeLab();
- TDF_ChildIDIterator aModifIter(aResLab, TNaming_NamedShape::GetID());
- for(; aModifIter.More(); aModifIter.Next()) {
- Handle(TNaming_NamedShape) aNS = Handle(TNaming_NamedShape)::DownCast(aModifIter.Value());
- if (aNS->Evolution() == TNaming_MODIFY || aNS->Evolution() == TNaming_GENERATED) {
- for(TNaming_Iterator aNSIter(aNS); aNSIter.More(); aNSIter.Next()) {
- TNaming_NewShapeIterator aNewIter(aNSIter.NewShape(), aNS->Label());
- for(; aNewIter.More(); aNewIter.Next()) {
- TDF_Label aLab = aNewIter.Label();
- if (isLater(aLab, aNS->Label()) && isLater(selectionLabel(), aLab)) {
- ResultPtr aRes = aDoc->resultByLab(aLab);
- if (aRes.get()) {
- if (aMatches.find(aRes) == aMatches.end())
- aMatches[aRes] = 0;
- aMatches[aRes]++; // found result, add matches
- }
- }
- }
- }
- }
- }
- // searching for the best result-candidate
- int aBest = 0;
- ResultPtr aBestResult;
- std::map<ResultPtr, int>::iterator aMatchIter = aMatches.begin();
- for(; aMatchIter != aMatches.end(); aMatchIter++) {
- if (aMatchIter->second > aBest) {
- aBest = aMatchIter->second;
- aBestResult = aMatchIter->first;
- }
- }
- if (aBestResult.get()) {
- aResult = aBestResult;
- aFindNewContext = true;
- continue;
- }
- }
-
// TestFillWireVertex.py - sketch constructions for wire may participate too
//if (aResult->groupName() == ModelAPI_ResultBody::group()) {
aResults.push_back(aBody);
}
std::list<std::shared_ptr<ModelAPI_Result> >::iterator aResIter = aResults.begin();
+
+ // searching by sub-shape
for (; aResIter != aResults.end(); aResIter++) {
if (!aResIter->get() || !(*aResIter)->data()->isValid() || (*aResIter)->isDisabled())
continue;
GeomShapePtr aShape = (*aResIter)->shape();
- if (aShape.get() && (theAnyValue || aShape->isSubShape(aSelectedShape, false))) {
+ if (aShape.get() && aShape->isSubShape(aSelectedShape, false)) {
aResult = *aResIter; // found new context (produced from this) with same subshape
aFindNewContext = true; // continue searching further
break;
for (; aS != allSubs.end(); aS++) {
ResultBodyPtr aSub = std::dynamic_pointer_cast<ModelAPI_ResultBody>(*aS);
if (aSub && aSub->numberOfSubs() == 0 && aSub->shape().get() &&
- (theAnyValue || aSub->shape()->isSubShape(aSelectedShape))) {
+ aSub->shape()->isSubShape(aSelectedShape)) {
aResult = aSub;
break;
}
aResult = theCurrent;
return aResult;
}
+
+void Model_AttributeSelection::combineGeometrical()
+{
+ if (myTmpContext.get() || myTmpSubShape.get())
+ return;
+ TDF_Label aSelLab = selectionLabel();
+ if (aSelLab.IsAttribute(kINVALID_SELECTION) || !myRef.isInitialized())
+ return;
+
+ if (aSelLab.IsAttribute(kCIRCLE_CENTER) || aSelLab.IsAttribute(kELLIPSE_CENTER1) ||
+ aSelLab.IsAttribute(kELLIPSE_CENTER2) || aSelLab.IsAttribute(kSIMPLE_REF_ID))
+ return;
+
+ if (aSelLab.IsAttribute(kPART_REF_ID)) {
+ ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(context());
+ if (!aPart.get() || !aPart->isActivated())
+ return; // postponed naming needed
+ Handle(TDataStd_Integer) anIndex;
+ if (aSelLab.FindAttribute(TDataStd_Integer::GetID(), anIndex)) {
+ if (anIndex->Get()) { // special selection attribute was created, use it
+ std::string aNewName;
+ aPart->combineGeometrical(anIndex->Get(), aNewName);
+ TDataStd_Name::Set(aSelLab, aNewName.c_str());
+ }
+ }
+ return;
+ }
+
+ std::shared_ptr<Model_ResultConstruction> aConstr =
+ std::dynamic_pointer_cast<Model_ResultConstruction>(context());
+ if (aConstr.get())
+ return;
+ FeaturePtr aFeature = contextFeature();
+ if (aFeature.get())
+ return;
+
+ Selector_Selector aSelector(aSelLab, baseDocumentLab());
+ TopoDS_Shape aContextShape = context()->shape()->impl<TopoDS_Shape>();
+ if (aSelector.restore(aContextShape)) {
+ aSelector.combineGeometrical(aContextShape);
+ }
+}
+
+TDF_Label Model_AttributeSelection::baseDocumentLab()
+{
+ if (ModelAPI_Session::get()->moduleDocument() != owner()->document())
+ return std::dynamic_pointer_cast<Model_Document>
+ (ModelAPI_Session::get()->moduleDocument())->extConstructionsLabel();
+ static TDF_Label anEmpty;
+ return anEmpty;
+}