X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FModel%2FModel_AttributeSelection.cpp;h=d8fbc9878a5b3bb5c5164558499c75ee41a50296;hb=1b93f1881c5fec599aa79707f93c84dd9c287bc0;hp=29c1b950f1d05e0fab739bbb33b88ceba99029f1;hpb=e34439bfd0fd53f5c10a1539835b77f535067a91;p=modules%2Fshaper.git diff --git a/src/Model/Model_AttributeSelection.cpp b/src/Model/Model_AttributeSelection.cpp index 29c1b950f..d8fbc9878 100644 --- a/src/Model/Model_AttributeSelection.cpp +++ b/src/Model/Model_AttributeSelection.cpp @@ -1,6 +1,6 @@ // Copyright (C) 2014-20xx CEA/DEN, EDF R&D -// File: Model_AttributeSelection.h +// File: Model_AttributeSelection.cpp // Created: 2 Oct 2014 // Author: Mikhail PONIKAROV @@ -9,13 +9,15 @@ #include "Model_Events.h" #include "Model_Data.h" #include "Model_Document.h" +#include "Model_SelectionNaming.h" #include #include #include +#include #include +#include #include #include -#include #include #include @@ -33,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -51,16 +54,24 @@ #include #include #include +#include +#include using namespace std; //#define DEB_NAMING 1 #ifdef DEB_NAMING #include #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 Standard_GUID kSIMPLE_REF_ID("635eacb2-a1d6-4dec-8348-471fae17cb29"); +// simple reference in the construction +Standard_GUID kCONSTUCTION_SIMPLE_REF_ID("635eacb2-a1d6-4dec-8348-471fae17cb28"); +// reference to Part sub-object +Standard_GUID kPART_REF_ID("635eacb2-a1d6-4dec-8348-471fae17cb27"); +// selection is invalid after recomputation +Standard_GUID kINVALID_SELECTION("bce47fd7-80fa-4462-9d63-2f58acddd49d"); // on this label is stored: // TNaming_NamedShape - selected shape @@ -68,61 +79,142 @@ Standard_GUID kSIMPLE_REF_ID("635eacb2-a1d6-4dec-8348-471fae17cb29"); // TDataStd_IntPackedMap - indexes of edges in composite element (for construction) // TDataStd_Integer - type of the selected shape (for construction) // TDF_Reference - from ReferenceAttribute, the context -#define DDDD 1 void Model_AttributeSelection::setValue(const ResultPtr& theContext, - const std::shared_ptr& theSubShape) + const std::shared_ptr& theSubShape, const bool theTemporarily) { + if (theTemporarily) { // just keep the stored without DF update + myTmpContext = theContext; + myTmpSubShape = theSubShape; + owner()->data()->sendAttributeUpdated(this); + return; + } else { + myTmpContext.reset(); + myTmpSubShape.reset(); + } + const std::shared_ptr& anOldShape = value(); - bool isOldShape = + bool isOldContext = theContext == myRef.value(); + bool isOldShape = isOldContext && (theSubShape == anOldShape || (theSubShape && anOldShape && theSubShape->isEqual(anOldShape))); if (isOldShape) return; // shape is the same, so context is also unchanged // update the referenced object if needed - bool isOldContext = theContext == myRef.value(); - - if (!isOldContext) myRef.setValue(theContext); // do noth use naming if selected shape is result shape itself, but not sub-shape TDF_Label aSelLab = selectionLabel(); aSelLab.ForgetAttribute(kSIMPLE_REF_ID); + aSelLab.ForgetAttribute(kCONSTUCTION_SIMPLE_REF_ID); + aSelLab.ForgetAttribute(kINVALID_SELECTION); + + bool isDegeneratedEdge = false; + // do not use the degenerated edge as a shape, a null context and shape is used in the case + if (theSubShape.get() && !theSubShape->isNull() && theSubShape->isEdge()) { + const TopoDS_Shape& aSubShape = theSubShape->impl(); + if (aSubShape.ShapeType() == TopAbs_EDGE) + 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()); + return; + } if (theContext->groupName() == ModelAPI_ResultBody::group()) { // do not select the whole shape for body:it is already must be in the data framework - if (theContext->shape().get() && theContext->shape()->isEqual(theSubShape)) { + // equal and null selected objects mean the same: object is equal to context, + if (theContext->shape().get() && + (theContext->shape()->isEqual(theSubShape) || !theSubShape.get())) { aSelLab.ForgetAllAttributes(true); TDataStd_UAttribute::Set(aSelLab, kSIMPLE_REF_ID); } else { selectBody(theContext, theSubShape); } } else if (theContext->groupName() == ModelAPI_ResultConstruction::group()) { - selectConstruction(theContext, theSubShape); + if (!theSubShape.get()) { + // 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(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()); + std::shared_ptr aMyDoc = + std::dynamic_pointer_cast(owner()->document()); + std::string aName = theContext->data()->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(); + aCompoundBuilder.Add(aComp, aFace); + } + std::shared_ptr aShape(new GeomAPI_Shape); + aShape->setImpl(new TopoDS_Shape(aComp)); + selectConstruction(theContext, aShape); + } + } else { + selectConstruction(theContext, theSubShape); + } + } else if (theContext->groupName() == ModelAPI_ResultPart::group()) { + aSelLab.ForgetAllAttributes(true); + TDataStd_UAttribute::Set(aSelLab, kPART_REF_ID); + selectPart(theContext, theSubShape); } - myIsInitialized = true; + //the attribute initialized state should be changed by sendAttributeUpdated only + //myIsInitialized = true; + + owner()->data()->sendAttributeUpdated(this); std::string aSelName = namingName(); if(!aSelName.empty()) - TDataStd_Name::Set(selectionLabel(), aSelName.c_str()); //set name -#ifdef DDDD - //#### - //selectSubShape("FACE", "Extrusion_1/LateralFace_3"); - //selectSubShape("FACE", "Extrusion_1/TopFace"); - //selectSubShape("EDGE", "Extrusion_1/TopFace|Extrusion_1/LateralFace_1"); - //selectSubShape("EDGE", "Sketch_1/Edge_6"); -#endif - owner()->data()->sendAttributeUpdated(this); + TDataStd_Name::Set(selectionLabel(), aSelName.c_str()); //set name } std::shared_ptr Model_AttributeSelection::value() { + if (myTmpContext.get() || myTmpSubShape.get()) { + return myTmpSubShape; + } + std::shared_ptr aResult; - if (myIsInitialized) { - TDF_Label aSelLab = selectionLabel(); + 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()) return aResult; // empty result return aContext->shape(); } + 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)) { + ResultPartPtr aPart = std::dynamic_pointer_cast(context()); + if (!aPart.get() || !aPart->isActivated()) + return std::shared_ptr(); // 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(); // something is wrong + } + return aPart->shapeInPart(TCollection_AsciiString(aName->Get()).ToCString()); + */ + } Handle(TNaming_NamedShape) aSelection; if (selectionLabel().FindAttribute(TNaming_NamedShape::GetID(), aSelection)) { @@ -140,14 +232,74 @@ std::shared_ptr Model_AttributeSelection::value() return aResult; } +bool Model_AttributeSelection::isInvalid() +{ + return selectionLabel().IsAttribute(kINVALID_SELECTION) == Standard_True; +} + +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(); + if (aSelLab.IsAttribute(kSIMPLE_REF_ID)) { // it is just reference to shape, not sub-shape + ResultPtr aContext = context(); + return aContext.get() != NULL; + } + if (aSelLab.IsAttribute(kCONSTUCTION_SIMPLE_REF_ID)) { // it is just reference to construction, nothing is in value + return true; + } + + 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 + ResultConstructionPtr aConstr = + std::dynamic_pointer_cast(context()); + if (aConstr.get()) { + return aConstr->shape().get() != NULL; + } + } + } + } + return false; +} + Model_AttributeSelection::Model_AttributeSelection(TDF_Label& theLabel) : myRef(theLabel) { myIsInitialized = myRef.isInitialized(); } +void Model_AttributeSelection::setID(const std::string theID) +{ + myRef.setID(theID); + ModelAPI_AttributeSelection::setID(theID); +} + ResultPtr Model_AttributeSelection::context() { - return std::dynamic_pointer_cast(myRef.value()); + if (myTmpContext.get() || myTmpSubShape.get()) { + return myTmpContext; + } + + ResultPtr aResult = std::dynamic_pointer_cast(myRef.value()); + // for parts there could be same-data result, so take the last enabled + if (aResult.get() && aResult->groupName() == ModelAPI_ResultPart::group()) { + int aSize = aResult->document()->size(ModelAPI_ResultPart::group()); + for(int a = aSize - 1; a >= 0; a--) { + ObjectPtr aPart = aResult->document()->object(ModelAPI_ResultPart::group(), a); + if (aPart.get() && aPart->data() == aResult->data()) { + ResultPtr aPartResult = std::dynamic_pointer_cast(aPart); + FeaturePtr anOwnerFeature = std::dynamic_pointer_cast(owner()); + // check that this result is not this-feature result (it is forbidden t oselect itself) + if (anOwnerFeature.get() && anOwnerFeature->firstResult() != aPartResult) { + return aPartResult; + } + } + } + } + return aResult; } @@ -160,19 +312,44 @@ void Model_AttributeSelection::setObject(const std::shared_ptr& TDF_LabelMap& Model_AttributeSelection::scope() { if (myScope.IsEmpty()) { // create a new scope if not yet done - // gets all labels with named shapes that are bofore this feature label (before in history) - TDF_Label aFeatureLab = std::dynamic_pointer_cast( - owner()->data())->label().Father(); - int aFeatureID = aFeatureLab.Tag(); - TDF_ChildIterator aFeaturesIter(aFeatureLab.Father()); - for(; aFeaturesIter.More(); aFeaturesIter.Next()) { - if (aFeaturesIter.Value().Tag() >= aFeatureID) // the left labels are created later - break; - TDF_ChildIDIterator aNSIter(aFeaturesIter.Value(), TNaming_NamedShape::GetID(), 1); - for(; aNSIter.More(); aNSIter.Next()) { - Handle(TNaming_NamedShape) aNS = Handle(TNaming_NamedShape)::DownCast(aNSIter.Value()); - if (!aNS.IsNull() && aNS->Evolution() != TNaming_SELECTED) { - myScope.Add(aNS->Label()); + // gets all features with named shapes that are before this feature label (before in history) + DocumentPtr aMyDoc = owner()->document(); + std::list > allFeatures = aMyDoc->allFeatures(); + std::list >::iterator aFIter = allFeatures.begin(); + bool aMePassed = false; + CompositeFeaturePtr aComposite = + std::dynamic_pointer_cast(owner()); + FeaturePtr aFeature = std::dynamic_pointer_cast(owner()); + CompositeFeaturePtr aCompositeOwner, aCompositeOwnerOwner; + if (aFeature.get()) { + aCompositeOwner = ModelAPI_Tools::compositeOwner(aFeature); + if (aCompositeOwner.get()) { + aCompositeOwnerOwner = ModelAPI_Tools::compositeOwner(aCompositeOwner); + } + } + for(; aFIter != allFeatures.end(); aFIter++) { + if (*aFIter == owner()) { // the left features are created later (except subs of composite) + aMePassed = true; + continue; + } + 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( + (*aFIter)->data())->label().Father(); + TDF_ChildIDIterator aNSIter(aFeatureLab, TNaming_NamedShape::GetID(), 1); + for(; aNSIter.More(); aNSIter.Next()) { + Handle(TNaming_NamedShape) aNS = Handle(TNaming_NamedShape)::DownCast(aNSIter.Value()); + if (!aNS.IsNull() && aNS->Evolution() != TNaming_SELECTED) { + myScope.Add(aNS->Label()); + } } } } @@ -180,13 +357,61 @@ TDF_LabelMap& Model_AttributeSelection::scope() 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) { + if (theFlag) { + theLab.ForgetAttribute(kINVALID_SELECTION); + } else { + TDataStd_UAttribute::Set(theLab, kINVALID_SELECTION); + } + return theFlag; +} + bool Model_AttributeSelection::update() { - ResultPtr aContext = context(); - if (!aContext.get()) return false; TDF_Label aSelLab = selectionLabel(); + ResultPtr aContext = context(); + if (!aContext.get()) + return setInvalidIfFalse(aSelLab, false); if (aSelLab.IsAttribute(kSIMPLE_REF_ID)) { // it is just reference to shape, not sub-shape - return aContext->shape() && !aContext->shape()->isNull(); + 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 there is a sketch, the sketch-naming must be updated + ResultConstructionPtr aConstruction = + std::dynamic_pointer_cast(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(); + aCompoundBuilder.Add(aComp, aFace); + } + std::shared_ptr aShape(new GeomAPI_Shape); + aShape->setImpl(new TopoDS_Shape(aComp)); + selectConstruction(aContext, aShape); + } + return setInvalidIfFalse(aSelLab, aContext->shape() && !aContext->shape()->isNull()); + } + + if (aSelLab.IsAttribute(kPART_REF_ID)) { // it is reference to the part object + std::shared_ptr aNoSelection; + return setInvalidIfFalse(aSelLab, selectPart(aContext, aNoSelection, true)); } if (aContext->groupName() == ModelAPI_ResultBody::group()) { @@ -194,19 +419,22 @@ bool Model_AttributeSelection::update() TNaming_Selector aSelector(aSelLab); bool aResult = aSelector.Solve(scope()) == Standard_True; owner()->data()->sendAttributeUpdated(this); - return aResult; + return setInvalidIfFalse(aSelLab, aResult); } else if (aContext->groupName() == ModelAPI_ResultConstruction::group()) { // construction: identification by the results indexes, recompute faces and // take the face that more close by the indexes - std::shared_ptr aWirePtr = - std::dynamic_pointer_cast( - std::dynamic_pointer_cast(aContext)->shape()); - if (aWirePtr && aWirePtr->hasPlane()) { // sketch sub-element + ResultConstructionPtr aConstructionContext = + std::dynamic_pointer_cast(aContext); + FeaturePtr aContextFeature = aContext->document()->feature(aContext); + // sketch sub-element + if (aConstructionContext && + std::dynamic_pointer_cast(aContextFeature).get()) + { TDF_Label aLab = myRef.myRef->Label(); // getting a type of selected shape Handle(TDataStd_Integer) aTypeAttr; if (!aLab.FindAttribute(TDataStd_Integer::GetID(), aTypeAttr)) { - return false; + return setInvalidIfFalse(aSelLab, false); } TopAbs_ShapeEnum aShapeType = (TopAbs_ShapeEnum)(aTypeAttr->Get()); // selected indexes will be needed in each "if" @@ -215,30 +443,27 @@ bool Model_AttributeSelection::update() bool aNoIndexes = !aLab.FindAttribute(TDataStd_IntPackedMap::GetID(), aSubIds) || aSubIds->Extent() == 0; // for now working only with composite features - FeaturePtr aContextFeature = aContext->document()->feature(aContext); CompositeFeaturePtr aComposite = std::dynamic_pointer_cast(aContextFeature); - if (!aComposite || aComposite->numberOfSubs() == 0) { - return false; + if (!aComposite.get() || aComposite->numberOfSubs() == 0) { + return setInvalidIfFalse(aSelLab, false); } - if (aShapeType == TopAbs_FACE) { + 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 - std::list > aFaces; - GeomAlgoAPI_SketchBuilder::createFaces(aWirePtr->origin(), aWirePtr->dirX(), - aWirePtr->dirY(), aWirePtr->norm(), aWirePtr, aFaces); - if (aFaces.empty()) // no faces, update can not work correctly - return false; + 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 std::shared_ptr aNewSelected; if (aNoIndexes) { - aNewSelected = *(aFaces.begin()); + 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 - TColStd_MapOfTransient allCurves; + // prepare edges of the current result for the fast searching + NCollection_DataMap allCurves; // curves and orientations of edges const int aSubNum = aComposite->numberOfSubs(); for(int a = 0; a < aSubNum; a++) { - if (aSubIds->Contains(aComposite->subFeatureId(a))) { + int aSubID = aComposite->subFeatureId(a); + if (aSubIds->Contains(aSubID)) { FeaturePtr aSub = aComposite->subFeature(a); const std::list >& aResults = aSub->results(); std::list >::const_iterator aRes; @@ -251,35 +476,52 @@ bool Model_AttributeSelection::update() if (!anEdge.IsNull()) { Standard_Real aFirst, aLast; Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast); - allCurves.Add(aCurve); + // searching for orientation information + int anOrient = 0; + Handle(TDataStd_Integer) anInt; + if (aSelLab.FindChild(aSubID).FindAttribute(TDataStd_Integer::GetID(), anInt)){ + anOrient = anInt->Get(); + } + allCurves.Bind(aCurve, anOrient); } } } } } - // iterate new result faces and searching for these edges - std::list >::iterator aFacesIter = aFaces.begin(); - double aBestFound = 0; // best percentage of found edges - for(; aFacesIter != aFaces.end(); aFacesIter++) { - int aFound = 0, aNotFound = 0; - TopExp_Explorer anEdgesExp((*aFacesIter)->impl(), TopAbs_EDGE); + int aBestFound = 0; // best number of found edges (not percentage: issue 1019) + 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()); + 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 (allCurves.Contains(aCurve)) { + 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 aPercentage = double(aFound) / double(aFound + aNotFound); - if (aPercentage > aBestFound) { - aBestFound = aPercentage; - aNewSelected = *aFacesIter; + if (aFound > aBestFound || + (aFound == aBestFound && aSameOrientation > aBestOrient)) { + aBestFound = aFound; + aBestOrient = aSameOrientation; + aNewSelected = aConstructionContext->face(aFaceIndex); } } } @@ -287,7 +529,10 @@ bool Model_AttributeSelection::update() if (aNewSelected) { // store this new selection selectConstruction(aContext, aNewSelected); owner()->data()->sendAttributeUpdated(this); - return true; + 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 + TNaming_Builder anEmptyBuilder(selectionLabel()); + return setInvalidIfFalse(aSelLab, false); } } else if (aShapeType == TopAbs_EDGE) { // just reselect the edge by the id @@ -305,7 +550,7 @@ bool Model_AttributeSelection::update() if (aRes && aRes->shape() && aRes->shape()->isEdge()) { // found! selectConstruction(aContext, aRes->shape()); owner()->data()->sendAttributeUpdated(this); - return true; + return setInvalidIfFalse(aSelLab, true); } } } @@ -317,89 +562,98 @@ bool Model_AttributeSelection::update() // if aSubIds take any, the first appropriate int aFeatureID = aComposite->subFeatureId(a); if (aSubIds->IsEmpty() || aSubIds->Contains(aFeatureID) || - aSubIds->Contains(aFeatureID + kSTART_VERTEX_DELTA) || - aSubIds->Contains(aFeatureID + kSTART_VERTEX_DELTA * 2)) { - // searching for deltas - int aVertexNum = 0; - if (aSubIds->Contains(aFeatureID + kSTART_VERTEX_DELTA)) aVertexNum = 1; - else if (aSubIds->Contains(aFeatureID + kSTART_VERTEX_DELTA * 2)) aVertexNum = 2; - // found the feature with appropriate edge - FeaturePtr aFeature = aComposite->subFeature(a); - std::list >::const_iterator aResIter = - aFeature->results().cbegin(); - for(;aResIter != aFeature->results().cend(); aResIter++) { - ResultConstructionPtr aRes = - std::dynamic_pointer_cast(*aResIter); - if (aRes && aRes->shape()) { - if (aRes->shape()->isVertex() && aVertexNum == 0) { // found! - selectConstruction(aContext, aRes->shape()); - owner()->data()->sendAttributeUpdated(this); - return true; - } else if (aRes->shape()->isEdge() && aVertexNum > 0) { - const TopoDS_Shape& anEdge = aRes->shape()->impl(); - int aVIndex = 1; - for(TopExp_Explorer aVExp(anEdge, TopAbs_VERTEX); aVExp.More(); aVExp.Next()) { - if (aVIndex == aVertexNum) { // found! - std::shared_ptr aVertex(new GeomAPI_Shape); - aVertex->setImpl(new TopoDS_Shape(aVExp.Current())); - selectConstruction(aContext, aVertex); - owner()->data()->sendAttributeUpdated(this); - return true; + aSubIds->Contains(aFeatureID + kSTART_VERTEX_DELTA) || + aSubIds->Contains(aFeatureID + kSTART_VERTEX_DELTA * 2)) { + // searching for deltas + int aVertexNum = 0; + if (aSubIds->Contains(aFeatureID + kSTART_VERTEX_DELTA)) aVertexNum = 1; + else if (aSubIds->Contains(aFeatureID + kSTART_VERTEX_DELTA * 2)) aVertexNum = 2; + // found the feature with appropriate edge + FeaturePtr aFeature = aComposite->subFeature(a); + std::list >::const_iterator aResIter = + aFeature->results().cbegin(); + for(;aResIter != aFeature->results().cend(); aResIter++) { + ResultConstructionPtr aRes = + std::dynamic_pointer_cast(*aResIter); + if (aRes && aRes->shape()) { + if (aRes->shape()->isVertex() && aVertexNum == 0) { // found! + selectConstruction(aContext, aRes->shape()); + owner()->data()->sendAttributeUpdated(this); + return setInvalidIfFalse(aSelLab, true); + } else if (aRes->shape()->isEdge() && aVertexNum > 0) { + const TopoDS_Shape& anEdge = aRes->shape()->impl(); + int aVIndex = 1; + for(TopExp_Explorer aVExp(anEdge, TopAbs_VERTEX); aVExp.More(); aVExp.Next()) { + if (aVIndex == aVertexNum) { // found! + std::shared_ptr aVertex(new GeomAPI_Shape); + aVertex->setImpl(new TopoDS_Shape(aVExp.Current())); + selectConstruction(aContext, aVertex); + owner()->data()->sendAttributeUpdated(this); + return setInvalidIfFalse(aSelLab, true); + } + aVIndex++; } - aVIndex++; } } } - } } } } } else { // simple construction element: the selected is that needed selectConstruction(aContext, aContext->shape()); owner()->data()->sendAttributeUpdated(this); - return true; + return setInvalidIfFalse(aSelLab, true); } } - return false; // unknown case + return setInvalidIfFalse(aSelLab, false); // unknown case } void Model_AttributeSelection::selectBody( - const ResultPtr& theContext, const std::shared_ptr& theSubShape) + const ResultPtr& theContext, const std::shared_ptr& theSubShape) { // perform the selection TNaming_Selector aSel(selectionLabel()); - TopoDS_Shape aNewShape = theSubShape ? theSubShape->impl() : TopoDS_Shape(); TopoDS_Shape aContext; ResultBodyPtr aBody = std::dynamic_pointer_cast(myRef.value()); if (aBody) { aContext = aBody->shape()->impl(); } else { - ResultConstructionPtr aConstr = std::dynamic_pointer_cast(myRef.value()); - if (aConstr) { - aContext = aConstr->shape()->impl(); + ResultPtr aResult = + std::dynamic_pointer_cast(myRef.value()); + if (aResult) { + aContext = aResult->shape()->impl(); } else { Events_Error::send("A result with shape is expected"); return; } } + TopoDS_Shape aNewShape = theSubShape ? theSubShape->impl() : aContext; /// fix for issue 411: result modified shapes must not participate in this selection mechanism FeaturePtr aFeatureOwner = std::dynamic_pointer_cast(owner()); if (aFeatureOwner.get()) aFeatureOwner->eraseResults(); - - aSel.Select(aNewShape, aContext); + if (!aContext.IsNull()) { + aSel.Select(aNewShape, aContext); + } } /// registers the name of the shape in the label (theID == 0) of sub label (theID is a tag) /// 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: +/// -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 theDoc, - std::string theAdditionalName, - Handle(TDataStd_IntPackedMap) theRefs = Handle(TDataStd_IntPackedMap)()) + std::string theAdditionalName, std::map& theOrientations, + Handle(TDataStd_IntPackedMap) theRefs = Handle(TDataStd_IntPackedMap)(), + const int theOrientation = 0) { TDF_Label aLab = theID == 0 ? theMainLabel : theMainLabel.FindChild(theID); + if (theOrientation != 0) { // store the orientation of edge relatively to face if needed + TDataStd_Integer::Set(aLab, theOrientation); + } TNaming_Builder aBuilder(aLab); aBuilder.Generated(theShape); std::stringstream aName; @@ -412,10 +666,20 @@ static void registerSubShape(TDF_Label theMainLabel, TopoDS_Shape theShape, if (theRefs.IsNull()) { aName<GetMap()); for(; aRef.More(); aRef.Next()) { aName<<"-"<& theSubShape) + const ResultPtr& theContext, const std::shared_ptr& theSubShape) { std::shared_ptr aMyDoc = std::dynamic_pointer_cast(owner()->document()); @@ -442,7 +706,7 @@ void Model_AttributeSelection::selectConstruction( } std::shared_ptr aData = std::dynamic_pointer_cast(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); @@ -460,6 +724,7 @@ void Model_AttributeSelection::selectConstruction( } // 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 anOrientations; //map from edges IDs to orientations of these edges in face aRefs->Clear(); const int aSubNum = aComposite->numberOfSubs(); for(int a = 0; a < aSubNum; a++) { @@ -502,7 +767,7 @@ void Model_AttributeSelection::selectConstruction( if (allCurves.Contains(aCurve)) { int anID = aComposite->subFeatureId(a); aRefs->Add(anID); - if (aShapeType != TopAbs_EDGE) { // edge do not need the sub-edges on sub-labels + 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()) { @@ -510,7 +775,11 @@ void Model_AttributeSelection::selectConstruction( Standard_Real aFirst, aLast; Handle(Geom_Curve) aFaceCurve = BRep_Tool::Curve(anEdge, aFirst, aLast); if (aFaceCurve == aCurve) { - registerSubShape(selectionLabel(), anEdge, anID, aContextFeature, aMyDoc, ""); + int anOrient = edgeOrientation(aSubShape, anEdge); + anOrientations[anID] = anOrient; + registerSubShape( + selectionLabel(), anEdge, anID, aContextFeature, aMyDoc, "", anOrientations, + Handle(TDataStd_IntPackedMap)(), anOrient); } } } else { // put vertices of the selected edge to sub-labels @@ -521,8 +790,8 @@ void Model_AttributeSelection::selectConstruction( TopoDS_Vertex aV = TopoDS::Vertex(anEdgeExp.Current()); std::stringstream anAdditionalName; - registerSubShape(selectionLabel(), aV, aTagIndex, aContextFeature, aMyDoc, - ""); + registerSubShape( + selectionLabel(), aV, aTagIndex, aContextFeature, aMyDoc, "", anOrientations); } } } @@ -534,523 +803,102 @@ void Model_AttributeSelection::selectConstruction( // store the selected as primitive TNaming_Builder aBuilder(selectionLabel()); aBuilder.Generated(aSubShape); - registerSubShape(selectionLabel(), aSubShape, 0, aContextFeature, aMyDoc, "", aRefs); -} - -TDF_Label Model_AttributeSelection::selectionLabel() -{ - return myRef.myRef->Label().FindChild(1); + registerSubShape( + selectionLabel(), aSubShape, 0, aContextFeature, aMyDoc, "", anOrientations, aRefs); } -#define FIX_BUG1 1 -std::string GetShapeName(std::shared_ptr theDoc, const TopoDS_Shape& theShape, - const TDF_Label& theLabel) +bool Model_AttributeSelection::selectPart( + const ResultPtr& theContext, const std::shared_ptr& theSubShape, + const bool theUpdate) { - std::string aName; - // check if the subShape is already in DF - Handle(TNaming_NamedShape) aNS = TNaming_Tool::NamedShape(theShape, theLabel); - Handle(TDataStd_Name) anAttr; - if(!aNS.IsNull() && !aNS->IsEmpty()) { // in the document - if(aNS->Label().FindAttribute(TDataStd_Name::GetID(), anAttr)) { - aName = TCollection_AsciiString(anAttr->Get()).ToCString(); - if(!aName.empty()) { - const TDF_Label& aLabel = theDoc->findNamingName(aName); - /* MPV: the same shape with the same name may be duplicated on different labels (selection of the same construction object) - if(!aLabel.IsEqual(aNS->Label())) { - //aName.erase(); //something is wrong, to be checked!!! - aName += "_SomethingWrong"; - return aName; - }*/ - const TopoDS_Shape& aShape = aNS->Get(); - if(aShape.ShapeType() == TopAbs_COMPOUND) { - std::string aPostFix("_"); - TopoDS_Iterator it(aShape); - for (int i = 1;it.More();it.Next(), i++) { - if(it.Value() == theShape) { - aPostFix += TCollection_AsciiString (i).ToCString(); - aName += aPostFix; - break; - } - else continue; - } - } - } - } + ResultPartPtr aPart = std::dynamic_pointer_cast(theContext); + if (!aPart.get() || !aPart->isActivated()) + return true; // postponed naming + if (theUpdate) { + Handle(TDataStd_Integer) anIndex; + if (selectionLabel().FindAttribute(TDataStd_Integer::GetID(), anIndex)) { // by internal selection + if (anIndex->Get() > 0) { + // update the selection by index + return aPart->updateInPart(anIndex->Get()); + } else { + return true; // nothing to do, referencing just by name + } + } + return true; // nothing to do, referencing just by name + } + // 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 + aShape = theContext->shape()->impl(); + } else { + aShape = theSubShape->impl(); + int anIndex; + aName += "/" + aPart->nameInPart(theSubShape, anIndex); + TDataStd_Integer::Set(selectionLabel(), anIndex); } - return aName; + TNaming_Builder aBuilder(selectionLabel()); + aBuilder.Select(aShape, aShape); + // identify by name in the part + TDataStd_Name::Set(selectionLabel(), aName.c_str()); + return !aName.empty(); } -bool isTrivial (const TopTools_ListOfShape& theAncestors, TopTools_IndexedMapOfShape& theSMap) +TDF_Label Model_AttributeSelection::selectionLabel() { -// a trivial case: F1 & F2, aNumber = 1, i.e. intersection gives 1 edge. - TopoDS_Compound aCmp; - BRep_Builder BB; - BB.MakeCompound(aCmp); - TopTools_ListIteratorOfListOfShape it(theAncestors); - for(;it.More();it.Next()) { - BB.Add(aCmp, it.Value()); - theSMap.Add(it.Value()); - } - int aNumber(0); - TopTools_IndexedDataMapOfShapeListOfShape aMap2; - TopExp::MapShapesAndAncestors(aCmp, TopAbs_EDGE, TopAbs_FACE, aMap2); - for (int i = 1; i <= aMap2.Extent(); i++) { - const TopoDS_Shape& aKey = aMap2.FindKey(i); - const TopTools_ListOfShape& anAncestors = aMap2.FindFromIndex(i); - if(anAncestors.Extent() > 1) aNumber++; - } - if(aNumber > 1) return false; - return true; + return myRef.myRef->Label().FindChild(1); } -std::string Model_AttributeSelection::namingName() + +std::string Model_AttributeSelection::namingName(const std::string& theDefaultName) { std::string aName(""); - if(!this->isInitialized()) return 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; + aName = TCollection_AsciiString(anAtt->Get()).ToCString(); + return aName; } std::shared_ptr aSubSh = value(); ResultPtr aCont = context(); - aName = "Undefined name"; - if(!aSubSh.get() || aSubSh->isNull() || !aCont.get() || aCont->shape()->isNull()) - return aName; - TopoDS_Shape aSubShape = aSubSh->impl(); - TopoDS_Shape aContext = aCont->shape()->impl(); -#ifdef DEB_NAMING - BRepTools::Write(aSubShape, "Selection.brep"); - BRepTools::Write(aContext, "Context.brep"); -#endif - std::shared_ptr aDoc = - std::dynamic_pointer_cast(aCont->document()); - // check if the subShape is already in DF - aName = GetShapeName(aDoc, aSubShape, selectionLabel()); - if(aName.empty() ) { // not in the document! - TopAbs_ShapeEnum aType = aSubShape.ShapeType(); - switch (aType) { - case TopAbs_FACE: - // the Face should be in DF. If it is not the case, it is an error ==> to be debugged - break; - case TopAbs_EDGE: - { - // name structure: F1 | F2 [| F3 | F4], where F1 & F2 the faces which gives the Edge in trivial case - // if it is not atrivial case we use localization by neighbours. F3 & F4 - neighbour faces - TopTools_IndexedDataMapOfShapeListOfShape aMap; - TopExp::MapShapesAndAncestors(aContext, TopAbs_EDGE, TopAbs_FACE, aMap); - TopTools_IndexedMapOfShape aSMap; // map for ancestors of the sub-shape - bool isTrivialCase(true); -/* for (int i = 1; i <= aMap.Extent(); i++) { - const TopoDS_Shape& aKey = aMap.FindKey(i); - //if (aKey.IsNotEqual(aSubShape)) continue; // find exactly the selected key - if (aKey.IsSame(aSubShape)) continue; - const TopTools_ListOfShape& anAncestors = aMap.FindFromIndex(i); - // check that it is not a trivial case (F1 & F2: aNumber = 1) - isTrivialCase = isTrivial(anAncestors, aSMap); - break; - }*/ - if(aMap.Contains(aSubShape)) { - const TopTools_ListOfShape& anAncestors = aMap.FindFromKey(aSubShape); - // check that it is not a trivial case (F1 & F2: aNumber = 1) - isTrivialCase = isTrivial(anAncestors, aSMap); - } else - break; - TopTools_ListOfShape aListOfNbs; - if(!isTrivialCase) { // find Neighbors - TNaming_Localizer aLocalizer; - TopTools_MapOfShape aMap3; - aLocalizer.FindNeighbourg(aContext, aSubShape, aMap3); - //int n = aMap3.Extent(); - TopTools_MapIteratorOfMapOfShape it(aMap3); - for(;it.More();it.Next()) { - const TopoDS_Shape& aNbShape = it.Key(); // neighbor edge - //TopAbs_ShapeEnum aType = aNbShape.ShapeType(); - const TopTools_ListOfShape& aList = aMap.FindFromKey(aNbShape); - TopTools_ListIteratorOfListOfShape it2(aList); - for(;it2.More();it2.Next()) { - if(aSMap.Contains(it2.Value())) continue; // skip this Face - aListOfNbs.Append(it2.Value()); - } - } - } // else a trivial case - - // build name of the sub-shape Edge - for(int i=1; i <= aSMap.Extent(); i++) { - const TopoDS_Shape& aFace = aSMap.FindKey(i); - std::string aFaceName = GetShapeName(aDoc, aFace, selectionLabel()); - if(i == 1) - aName = aFaceName; - else - aName += "|" + aFaceName; - } - TopTools_ListIteratorOfListOfShape itl(aListOfNbs); - for (;itl.More();itl.Next()) { - std::string aFaceName = GetShapeName(aDoc, itl.Value(), selectionLabel()); - aName += "|" + aFaceName; - } - } - break; - - case TopAbs_VERTEX: - // name structure (Monifold Topology): - // 1) F1 | F2 | F3 - intersection of 3 faces defines a vertex - trivial case. - // 2) F1 | F2 | F3 [|F4 [|Fn]] - redundant definition, but it should be kept as is to obtain safe recomputation - // 2) F1 | F2 - intersection of 2 faces definses a vertex - applicable for case - // when 1 faces is cylindrical, conical, spherical or revolution and etc. - // 3) E1 | E2 | E3 - intersection of 3 edges defines a vertex - when we have case of a shell - // or compound of 2 open faces. - // 4) E1 | E2 - intesection of 2 edges defines a vertex - when we have a case of - // two independent edges (wire or compound) - // implemented 2 first cases - { - TopTools_IndexedDataMapOfShapeListOfShape aMap; - TopExp::MapShapesAndAncestors(aContext, TopAbs_VERTEX, TopAbs_FACE, aMap); - const TopTools_ListOfShape& aList2 = aMap.FindFromKey(aSubShape); - TopTools_ListOfShape aList; - TopTools_MapOfShape aFMap; -#ifdef FIX_BUG1 - //int n = aList2.Extent(); //bug! duplication - // fix is below - TopTools_ListIteratorOfListOfShape itl2(aList2); - for (int i = 1;itl2.More();itl2.Next(),i++) { - if(aFMap.Add(itl2.Value())) - aList.Append(itl2.Value()); - } - //n = aList.Extent(); -#endif - int n = aList.Extent(); - if(n < 3) { // open topology case => via edges - TopTools_IndexedDataMapOfShapeListOfShape aMap; - TopExp::MapShapesAndAncestors(aContext, TopAbs_VERTEX, TopAbs_EDGE, aMap); - const TopTools_ListOfShape& aList2 = aMap.FindFromKey(aSubShape); - if(aList2.Extent() >= 2) { // regular solution - TopTools_ListIteratorOfListOfShape itl(aList2); - for (int i = 1;itl.More();itl.Next(),i++) { - const TopoDS_Shape& anEdge = itl.Value(); - std::string anEdgeName = GetShapeName(aDoc, anEdge, selectionLabel()); - if(i == 1) - aName = anEdgeName; - else - aName += "|" + anEdgeName; - } - } - } - else { - TopTools_ListIteratorOfListOfShape itl(aList); - for (int i = 1;itl.More();itl.Next(),i++) { - const TopoDS_Shape& aFace = itl.Value(); - std::string aFaceName = GetShapeName(aDoc, aFace, selectionLabel()); - if(i == 1) - aName = aFaceName; - else - aName += "|" + aFaceName; - } - } - } - break; - } - // register name - // aDoc->addNamingName(selectionLabel(), aName); - // the selected sub-shape will not be shared and as result it will not require registration - } - return aName; -} - -TopAbs_ShapeEnum translateType (const std::string& theType) -{ - TCollection_AsciiString aStr(theType.c_str()); - aStr.UpperCase(); - if(aStr.IsEqual("COMP")) - return TopAbs_COMPOUND; - else if(aStr.IsEqual("COMS")) - return TopAbs_COMPSOLID; - else if(aStr.IsEqual("SOLD")) - return TopAbs_SOLID; - else if(aStr.IsEqual("SHEL")) - return TopAbs_SHELL; - else if(aStr.IsEqual("FACE")) - return TopAbs_FACE; - else if(aStr.IsEqual("WIRE")) - return TopAbs_WIRE; - else if(aStr.IsEqual("EDGE")) - return TopAbs_EDGE; - else if(aStr.IsEqual("VERT")) - return TopAbs_VERTEX; - - return TopAbs_SHAPE; -} - -const TopoDS_Shape getShapeFromCompound(const std::string& theSubShapeName, const TopoDS_Shape& theCompound) -{ - TopoDS_Shape aSelection; - std::string::size_type n = theSubShapeName.rfind('/'); - if (n == std::string::npos) n = 0; - std::string aSubString = theSubShapeName.substr(n + 1); - n = aSubString.rfind('_'); - if (n == std::string::npos) return aSelection; - aSubString = aSubString.substr(n+1); - int indx = atoi(aSubString.c_str()); - TopoDS_Iterator it(theCompound); - for (int i = 1;it.More();it.Next(), i++) { - if(i == indx) { - aSelection = it.Value(); - break; - } - else continue; - } - return aSelection; -} - -const TopoDS_Shape findFaceByName(const std::string& theSubShapeName, std::shared_ptr theDoc) -{ - TopoDS_Shape aFace; - std::string::size_type n, nb = theSubShapeName.rfind('/'); - if (nb == std::string::npos) nb = 0; - std::string aSubString = theSubShapeName.substr(nb + 1); - n = aSubString.rfind('_'); - if (n != std::string::npos) { - std::string aSubStr2 = aSubString.substr(0, n); - aSubString = theSubShapeName.substr(0, nb + 1); - aSubString = aSubString + aSubStr2; - } else - aSubString = theSubShapeName; - - const TDF_Label& aLabel = theDoc->findNamingName(aSubString); - if(aLabel.IsNull()) return aFace; - Handle(TNaming_NamedShape) aNS; - if(aLabel.FindAttribute(TNaming_NamedShape::GetID(), aNS)) { - const TopoDS_Shape& aShape = aNS->Get(); - if(!aShape.IsNull()) { - if(aShape.ShapeType() == TopAbs_COMPOUND) - aFace = getShapeFromCompound(theSubShapeName, aShape); - else - aFace = aShape; - } - } - return aFace; -} - -int ParseName(const std::string& theSubShapeName, std::list& theList) -{ - std::string aName = theSubShapeName; - std::string aLastName; - int n1(0), n2(0); // n1 - start position, n2 - position of the delimiter - while ((n2 = aName.find('|', n1)) != std::string::npos) { - const std::string aName1 = aName.substr(n1, n2 - n1); //name of face - theList.push_back(aName1); - n1 = n2 + 1; - aLastName = aName.substr(n1); - } - if(!aLastName.empty()) - theList.push_back(aLastName); - return theList.size(); -} - -const TopoDS_Shape findCommonShape(const TopAbs_ShapeEnum theType, const TopTools_ListOfShape& theList) -{ - TopoDS_Shape aShape; - std::vector aVec; - TopTools_MapOfShape aMap1, aMap2, aMap3, aMap4; - if(theList.Extent() > 1) { - aVec.push_back(aMap1); - aVec.push_back(aMap2); - } - if(theList.Extent() > 2) - aVec.push_back(aMap3); - if(theList.Extent() == 4) - aVec.push_back(aMap4); - - //fill maps - TopTools_ListIteratorOfListOfShape it(theList); - for(int i = 0;it.More();it.Next(),i++) { - const TopoDS_Shape& aFace = it.Value(); - if(i < 2) { - TopExp_Explorer anExp (aFace, theType); - for(;anExp.More();anExp.Next()) { - const TopoDS_Shape& anEdge = anExp.Current(); - if (!anEdge.IsNull()) - aVec[i].Add(anExp.Current()); - } - } else { - TopExp_Explorer anExp (aFace, TopAbs_VERTEX); - for(;anExp.More();anExp.Next()) { - const TopoDS_Shape& aVertex = anExp.Current(); - if (!aVertex.IsNull()) - aVec[i].Add(anExp.Current()); - } - } - } - //trivial case: 2 faces - TopTools_ListOfShape aList; - TopTools_MapIteratorOfMapOfShape it2(aVec[0]); - for(;it2.More();it2.Next()) { - if(aVec[1].Contains(it2.Key())) { - aShape = it2.Key(); - if(theList.Extent() == 2) - break; - else - aList.Append(it2.Key()); - } - } - if(aList.Extent() && aVec.size() > 3) {// list of common edges ==> search ny neighbors - if(aVec[2].Extent() && aVec[3].Extent()) { - TopTools_ListIteratorOfListOfShape it(aList); - for(;it.More();it.Next()) { - const TopoDS_Shape& aCand = it.Value(); - // not yet completelly implemented, to be rechecked - TopoDS_Vertex aV1, aV2; - TopExp::Vertices(TopoDS::Edge(aCand), aV1, aV2); - int aNum(0); - if(aVec[2].Contains(aV1)) aNum++; - else if(aVec[2].Contains(aV2)) aNum++; - if(aVec[3].Contains(aV1)) aNum++; - else if(aVec[3].Contains(aV2)) aNum++; - if(aNum == 2) { - aShape = aCand; - break; - } - } - } - } - - if(aList.Extent() && aVec.size() == 3) { - - TopTools_ListIteratorOfListOfShape it(aList); - for(;it.More();it.Next()) { - const TopoDS_Shape& aCand = it.Value(); - if(aVec[2].Contains(aCand)) { - aShape = aCand; - break; - } - } - } - return aShape; + Model_SelectionNaming aSelNaming(selectionLabel()); + return aSelNaming.namingName(aCont, aSubSh, theDefaultName); } -std::string getContextName(const std::string& theSubShapeName) -{ - std::string aName; - std::string::size_type n = theSubShapeName.find('/'); - if (n == std::string::npos) return aName; - aName = theSubShapeName.substr(0, n); - return aName; -} // type ::= COMP | COMS | SOLD | SHEL | FACE | WIRE | EDGE | VERT -void Model_AttributeSelection::selectSubShape(const std::string& theType, const std::string& theSubShapeName) +void Model_AttributeSelection::selectSubShape( + const std::string& theType, const std::string& theSubShapeName) { if(theSubShapeName.empty() || theType.empty()) return; - TopAbs_ShapeEnum aType = translateType(theType); - std::shared_ptr aDoc = std::dynamic_pointer_cast(owner()->document());//std::dynamic_pointer_cast(aCont->document()); - std::string aContName = getContextName(theSubShapeName); - if(aContName.empty()) return; - //ResultPtr aCont = context(); - ResultPtr aCont = aDoc->findByName(aContName); - if(!aCont.get() || aCont->shape()->isNull()) return; - TopoDS_Shape aContext = aCont->shape()->impl(); - TopAbs_ShapeEnum aContType = aContext.ShapeType(); - if(aType <= aContType) return; // not applicable - - - TopoDS_Shape aSelection; - switch (aType) - { - case TopAbs_COMPOUND: - break; - case TopAbs_COMPSOLID: - break; - case TopAbs_SOLID: - break; - case TopAbs_SHELL: - break; - case TopAbs_FACE: - { - const TopoDS_Shape aSelection = findFaceByName(theSubShapeName, aDoc); - if(!aSelection.IsNull()) {// Select it - std::shared_ptr aShapeToBeSelected(new GeomAPI_Shape()); - aShapeToBeSelected->setImpl(new TopoDS_Shape(aSelection)); - setValue(aCont, aShapeToBeSelected); - } - } - break; - case TopAbs_WIRE: - break; - case TopAbs_EDGE: - { - TopoDS_Shape aSelection;// = findFaceByName(theSubShapeName, aDoc); - const TDF_Label& aLabel = aDoc->findNamingName(theSubShapeName); - if(!aLabel.IsNull()) { - Handle(TNaming_NamedShape) aNS; - if(aLabel.FindAttribute(TNaming_NamedShape::GetID(), aNS)) { - const TopoDS_Shape& aShape = aNS->Get(); - if(!aShape.IsNull()) { - if(aShape.ShapeType() == TopAbs_COMPOUND) - aSelection = getShapeFromCompound(theSubShapeName, aShape); - else - aSelection = aShape; - } - } - } - if(aSelection.IsNull()) { - std::list aListofNames; - int n = ParseName(theSubShapeName, aListofNames); - if(n > 1 && n < 5) { - TopTools_ListOfShape aList; - for(std::list::iterator it =aListofNames.begin();it != aListofNames.end();it++){ - const TopoDS_Shape aFace = findFaceByName(*it, aDoc); - aList.Append(aFace); - } - aSelection = findCommonShape(TopAbs_EDGE, aList); - } - } - if(!aSelection.IsNull()) {// Select it - std::shared_ptr aShapeToBeSelected(new GeomAPI_Shape()); - aShapeToBeSelected->setImpl(new TopoDS_Shape(aSelection)); - setValue(aCont, aShapeToBeSelected); - } - } - break; - case TopAbs_VERTEX: - { - TopoDS_Shape aSelection; - const TDF_Label& aLabel = aDoc->findNamingName(theSubShapeName); - if(!aLabel.IsNull()) { - Handle(TNaming_NamedShape) aNS; - if(aLabel.FindAttribute(TNaming_NamedShape::GetID(), aNS)) { - const TopoDS_Shape& aShape = aNS->Get(); - if(!aShape.IsNull()) { - if(aShape.ShapeType() == TopAbs_COMPOUND) - aSelection = getShapeFromCompound(theSubShapeName, aShape); - else - aSelection = aShape; - } - } - } - if(aSelection.IsNull()) { - std::list aListofNames; - int n = ParseName(theSubShapeName, aListofNames); - if(n > 1 && n < 4) { // 2 || 3 - TopTools_ListOfShape aList; - for(std::list::iterator it =aListofNames.begin();it != aListofNames.end();it++){ - const TopoDS_Shape aFace = findFaceByName(*it, aDoc); - if(!aFace.IsNull()) - aList.Append(aFace); - } - aSelection = findCommonShape(TopAbs_VERTEX, aList); - } - } - if(!aSelection.IsNull()) {// Select it - std::shared_ptr aShapeToBeSelected(new GeomAPI_Shape()); - aShapeToBeSelected->setImpl(new TopoDS_Shape(aSelection)); - setValue(aCont, aShapeToBeSelected); - } - } - break; - default: //TopAbs_SHAPE - return; + + // check this is Part-name: 2 delimiters in the name + std::size_t aPartEnd = theSubShapeName.find('/'); + if (aPartEnd != 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(aFound); + string aNameInPart = theSubShapeName.substr(aPartEnd + 1); + int anIndex; + std::shared_ptr 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 aDoc = + std::dynamic_pointer_cast(owner()->document()); + std::shared_ptr aShapeToBeSelected; + ResultPtr aCont; + if (aSelNaming.selectSubShape(theType, theSubShapeName, aDoc, aShapeToBeSelected, aCont)) { + setValue(aCont, aShapeToBeSelected); + } } int Model_AttributeSelection::Id() @@ -1061,7 +909,7 @@ int Model_AttributeSelection::Id() const TopoDS_Shape& aSubShape = aSelection->impl(); int anID = 0; if (aSelection && !aSelection->isNull() && - aContext && !aContext->isNull()) + aContext && !aContext->isNull()) { TopTools_IndexedMapOfShape aSubShapesMap; TopExp::MapShapes(aMainShape, aSubShapesMap);