if (aSelLab.FindAttribute(TNaming_NamedShape::GetID(), aNS))
anOldShape = aNS->Get();
- Selector_Selector aSelector(aSelLab);
- if (ModelAPI_Session::get()->moduleDocument() != owner()->document()) {
- aSelector.setBaseDocument(std::dynamic_pointer_cast<Model_Document>
- (ModelAPI_Session::get()->moduleDocument())->extConstructionsLabel());
- }
- 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))
std::shared_ptr<Model_ResultConstruction> aConstructionContext =
std::dynamic_pointer_cast<Model_ResultConstruction>(aContext);
if (!aConstructionContext->isInfinite()) {
- Selector_Selector aSelector(aSelLab);
- if (ModelAPI_Session::get()->moduleDocument() != owner()->document()) {
- aSelector.setBaseDocument(std::dynamic_pointer_cast<Model_Document>
- (ModelAPI_Session::get()->moduleDocument())->extConstructionsLabel());
- }
-
- 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 {
TopoDS_Shape aNewSub = theSubShape->impl<TopoDS_Shape>();
bool aSelectorOk = true;
- Selector_Selector aSel(aSelLab);
- if (ModelAPI_Session::get()->moduleDocument() != owner()->document()) {
- aSel.setBaseDocument(std::dynamic_pointer_cast<Model_Document>
- (ModelAPI_Session::get()->moduleDocument())->extConstructionsLabel());
- }
+ Selector_Selector aSelector(aSelLab, baseDocumentLab());
try {
- aSelectorOk = aSel.select(aContext, aNewSub, myIsGeometricalSelection);
+ 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);
}
}
}
}
- Selector_Selector aSelector(aSelLab);
- if (ModelAPI_Session::get()->moduleDocument() != owner()->document()) {
- aSelector.setBaseDocument(std::dynamic_pointer_cast<Model_Document>
- (ModelAPI_Session::get()->moduleDocument())->extConstructionsLabel());
- }
+ Selector_Selector aSelector(aSelLab, baseDocumentLab());
std::string aResult;
- if (aSelector.restore())
+ if (aSelector.restore(aCont->shape()->impl<TopoDS_Shape>()))
aResult = aSelector.name(this);
if (aCenterType != NOT_CENTER) {
aResult += centersMap()[aCenterType];
}
}
- Selector_Selector aSelector(selectionLabel());
- if (ModelAPI_Session::get()->moduleDocument() != owner()->document()) {
- aSelector.setBaseDocument(std::dynamic_pointer_cast<Model_Document>
- (ModelAPI_Session::get()->moduleDocument())->extConstructionsLabel());
- }
+ Selector_Selector aSelector(selectionLabel(), baseDocumentLab());
myRestoreDocument = aDoc;
TDF_Label aContextLabel = aSelector.restoreByName(
aSubShapeName, aShapeType, this, myIsGeometricalSelection);
bool aToUnblock = false;
aToUnblock = !owner()->data()->blockSendAttributeUpdated(true);
myRef.setValue(aContext);
- aSelector.store();
- aSelector.solve(aContextShape);
+ aSelector.store(aContextShape);
owner()->data()->sendAttributeUpdated(this);
if (aToUnblock)
owner()->data()->blockSendAttributeUpdated(false);
if (aFeature.get())
return;
- Selector_Selector aSelector(aSelLab);
- if (ModelAPI_Session::get()->moduleDocument() != owner()->document()) {
- aSelector.setBaseDocument(std::dynamic_pointer_cast<Model_Document>
- (ModelAPI_Session::get()->moduleDocument())->extConstructionsLabel());
- }
- if (aSelector.restore()) {
- TopoDS_Shape aContextShape = context()->shape()->impl<TopoDS_Shape>();
+ 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;
+}
return myIsGeometricalSelection;
};
+ /// Returns the module document label if this selection attribute is not in this document.
+ /// Returns null label otherwise.
+ TDF_Label baseDocumentLab();
+
friend class Model_Data;
friend class Model_AttributeSelectionList;
};
SET(PROJECT_HEADERS
Selector.h
Selector_Selector.h
+ Selector_Algo.h
+ Selector_Primitive.h
+ Selector_AlgoWithSubs.h
+ Selector_Intersect.h
+ Selector_Container.h
+ Selector_Modify.h
+ Selector_FilterByNeighbors.h
+ Selector_WeakName.h
Selector_NameGenerator.h
Selector_NExplode.h
)
SET(PROJECT_SOURCES
Selector_Selector.cpp
+ Selector_Algo.cpp
+ Selector_Primitive.cpp
+ Selector_AlgoWithSubs.cpp
+ Selector_Intersect.cpp
+ Selector_Container.cpp
+ Selector_Modify.cpp
+ Selector_FilterByNeighbors.cpp
+ Selector_WeakName.cpp
Selector_NameGenerator.cpp
Selector_NExplode.cpp
)
--- /dev/null
+// Copyright (C) 2014-2017 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
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// 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
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#include <Selector_Algo.h>
+
+#include <Selector_Primitive.h>
+#include <Selector_Intersect.h>
+#include <Selector_Modify.h>
+#include <Selector_Container.h>
+#include <Selector_FilterByNeighbors.h>
+#include <Selector_WeakName.h>
+
+#include <TDF_Tool.hxx>
+#include <TopoDS_Face.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TopoDS.hxx>
+#include <Geom_Surface.hxx>
+#include <BRep_Tool.hxx>
+#include <TNaming_Builder.hxx>
+#include <TNaming_Tool.hxx>
+#include <TNaming_SameShapeIterator.hxx>
+#include <TNaming_Iterator.hxx>
+#include <TDataStd_ReferenceArray.hxx>
+#include <TDataStd_ExtStringList.hxx>
+#include <TDataStd_Integer.hxx>
+
+/// type of the selection, integer keeps the Selector_Type value
+static const Standard_GUID kSEL_TYPE("db174d59-c2e3-4a90-955e-55544df090d6");
+// geometrical naming indicator
+static const Standard_GUID kGEOMETRICAL_NAMING("a5322d02-50fb-43ed-9255-75c7b93f6657");
+
+
+// reference attribute that contains the reference to labels where the "from" or "base" shapes
+// of selection are located
+static const Standard_GUID kBASE_ARRAY("7c515b1a-9549-493d-9946-a4933a22f45f");
+// if the base array contains reference to the root label, this means that it refers to an
+// external document and this list contains a tag in the document
+static const Standard_GUID kBASE_LIST("7c515b1a-9549-493d-9946-a4933a22f45a");
+
+Selector_Algo::Selector_Algo()
+{
+ myGeometricalNaming = false; // default values
+ myAlwaysGeometricalNaming = false;
+}
+
+#define SET_ALGO_FLAGS(algo) \
+ algo->myLab = theAccess; \
+ algo->myBaseDocumentLab = theBaseDocument; \
+ algo->myGeometricalNaming = theGeometricalNaming; \
+ algo->myUseNeighbors = theUseNeighbors; \
+ algo->myUseIntersections = theUseIntersections; \
+ algo->myAlwaysGeometricalNaming = theAlwaysGeometricalNaming;
+
+Selector_Algo* Selector_Algo::select(const TopoDS_Shape theContext, const TopoDS_Shape theValue,
+ const TDF_Label theAccess, const TDF_Label theBaseDocument,
+ const bool theGeometricalNaming, const bool theUseNeighbors, const bool theUseIntersections,
+ const bool theAlwaysGeometricalNaming)
+{
+ Selector_Algo* aResult = NULL;
+ if (theValue.IsNull() || theContext.IsNull())
+ return aResult;
+
+ // check the value shape can be named as it is, or it is needed to construct it from the
+ // higher level shapes (like a box vertex by faces that form this vertex)
+ bool aIsFound = TNaming_Tool::HasLabel(theAccess, theValue);
+ if (aIsFound) { // additional check for selection and delete evolution only: also could not use
+ aIsFound = false;
+ for(TNaming_SameShapeIterator aShapes(theValue, theAccess); aShapes.More(); aShapes.Next())
+ {
+ Handle(TNaming_NamedShape) aNS;
+ if (aShapes.Label().FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
+ if (aNS->Evolution() == TNaming_MODIFY || aNS->Evolution() == TNaming_GENERATED ||
+ aNS->Evolution() == TNaming_PRIMITIVE) {
+ aIsFound = true;
+ break;
+ }
+ }
+ }
+ }
+ // searching in the base document
+ if (!aIsFound && !theBaseDocument.IsNull() && TNaming_Tool::HasLabel(theBaseDocument, theValue))
+ {
+ TNaming_SameShapeIterator aShapes(theValue, theBaseDocument);
+ for(; aShapes.More(); aShapes.Next())
+ {
+ Handle(TNaming_NamedShape) aNS;
+ if (aShapes.Label().FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
+ if (aNS->Evolution() == TNaming_MODIFY || aNS->Evolution() == TNaming_GENERATED ||
+ aNS->Evolution() == TNaming_PRIMITIVE) {
+ aIsFound = true;
+ break;
+ }
+ }
+ }
+ }
+ if (!aIsFound) {
+ TopAbs_ShapeEnum aSelectionType = theValue.ShapeType();
+ if (aSelectionType == TopAbs_COMPOUND || aSelectionType == TopAbs_COMPSOLID ||
+ aSelectionType == TopAbs_SHELL || aSelectionType == TopAbs_WIRE)
+ {
+ Selector_Container* aContainer = new Selector_Container;
+ SET_ALGO_FLAGS(aContainer);
+ if (aContainer->select(theContext, theValue))
+ return aContainer;
+ delete aContainer;
+ return false;
+ }
+ Selector_Intersect* anIntersect = new Selector_Intersect;
+ SET_ALGO_FLAGS(anIntersect);
+ bool aGoodIntersector = anIntersect->select(theContext, theValue);
+ // weak intersector is bad for not use neighbors and has lower priority than neighbors
+ if (aGoodIntersector && anIntersect->myWeakIndex == -1) {
+ return anIntersect;
+ }
+ if (!theUseNeighbors) {
+ delete anIntersect;
+ return false;
+ }
+ // searching by neighbors
+ Selector_FilterByNeighbors* aNBs = new Selector_FilterByNeighbors;
+ SET_ALGO_FLAGS(aNBs);
+ if (aNBs->select(theContext, theValue)) {
+ delete anIntersect;
+ return aNBs;
+ }
+ delete aNBs;
+ if (aGoodIntersector) { // if neighbors are bad, use intersector with weak index
+ return anIntersect;
+ }
+ delete anIntersect;
+
+ // pure weak naming: there is no sense to use pure weak naming for neighbors selection
+ if (theUseNeighbors) {
+ Selector_WeakName* aWeak = new Selector_WeakName;
+ SET_ALGO_FLAGS(aWeak);
+ if (aWeak->select(theContext, theValue)) {
+ return aWeak;
+ }
+ delete aWeak;
+ }
+ return NULL; // not found value in the tree, not found context shape in the tree also
+ }
+ // searching for the base shapes of the value
+ Handle(TNaming_NamedShape) aPrimitiveNS;
+ NCollection_List<Handle(TNaming_NamedShape)> aModifList;
+ for(int aUseExternal = 0; aUseExternal < 2; aUseExternal++) {
+ TDF_Label aLab = aUseExternal == 0 ? theAccess : theBaseDocument;
+ if (aLab.IsNull() || !TNaming_Tool::HasLabel(aLab, theValue))
+ continue;
+ for(TNaming_SameShapeIterator aShapes(theValue, aLab); aShapes.More(); aShapes.Next())
+ {
+ Handle(TNaming_NamedShape) aNS;
+ if (aShapes.Label().FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
+ TNaming_Evolution anEvolution = aNS->Evolution();
+ if (anEvolution == TNaming_PRIMITIVE) { // the value shape is declared as PRIMITIVE
+ aPrimitiveNS = aNS;
+ break;
+ } else if (anEvolution == TNaming_GENERATED || anEvolution == TNaming_MODIFY) {
+ // check this is a new shape
+ TNaming_Iterator aNSIter(aNS);
+ for(; aNSIter.More(); aNSIter.Next())
+ if (aNSIter.NewShape().IsSame(theValue))
+ break;
+ if (aNSIter.More()) // new was found
+ aModifList.Append(aNS);
+ }
+ }
+ }
+ }
+
+ if (!aPrimitiveNS.IsNull()) {
+ Selector_Primitive* aPrimitive = new Selector_Primitive;
+ SET_ALGO_FLAGS(aPrimitive);
+ aPrimitive->select(aPrimitiveNS->Label());
+ return aPrimitive;
+ } else {
+ Selector_Modify* aModify = new Selector_Modify;
+ SET_ALGO_FLAGS(aModify);
+ bool aGoodModify = aModify->select(aModifList, theContext, theValue);
+ // weak intersector is bad for not use neighbors and has lower priority than neighbors
+ if (aGoodModify && aModify->myWeakIndex == -1) {
+ return aModify;
+ }
+ if (!theUseNeighbors) {
+ delete aModify;
+ return false;
+ }
+ // searching by neighbors
+ Selector_FilterByNeighbors* aNBs = new Selector_FilterByNeighbors;
+ SET_ALGO_FLAGS(aNBs);
+ if (aNBs->select(theContext, theValue)) {
+ delete aModify;
+ return aNBs;
+ }
+ delete aNBs;
+
+ if (aGoodModify) { // if neighbors are bad, use modify algo with weak index
+ return aModify;
+ }
+ delete aModify;
+ }
+
+ return NULL; // invalid case
+}
+
+Selector_Algo* Selector_Algo::relesectWithAllGeometry(
+ Selector_Algo* theOldAlgo, const TopoDS_Shape theContext)
+{
+ return select(theContext, theOldAlgo->value(),
+ theOldAlgo->myLab, theOldAlgo->myBaseDocumentLab, true, true, true, true);
+}
+
+void Selector_Algo::storeBaseArray(const TDF_LabelList& theRef, const TDF_Label& theLast)
+{
+ Handle(TDataStd_ReferenceArray) anArray =
+ TDataStd_ReferenceArray::Set(myLab, kBASE_ARRAY, 0, theRef.Extent());
+ Handle(TDataStd_ExtStringList) anEntries; // entries of references to external document
+ const TDF_Label aThisDocRoot = myLab.Root();
+ TDF_LabelList::Iterator aBIter(theRef);
+ for(int anIndex = 0; true; aBIter.Next(), anIndex++) {
+ const TDF_Label& aLab = aBIter.More() ? aBIter.Value() : theLast;
+ // check this is a label of this document
+ if (aLab.Root().IsEqual(aThisDocRoot)) {
+ anArray->SetValue(anIndex, aLab);
+ } else { // store reference to external document as an entry-string
+ if (anEntries.IsNull()) {
+ anEntries = TDataStd_ExtStringList::Set(myLab, kBASE_LIST);
+ }
+ TCollection_AsciiString anEntry;
+ TDF_Tool::Entry(aLab, anEntry);
+ anEntries->Append(anEntry);
+ anArray->SetValue(anIndex, aThisDocRoot); // stored root means it is external reference
+ }
+ if (!aBIter.More())
+ break;
+ }
+}
+
+bool Selector_Algo::restoreBaseArray(TDF_LabelList& theRef, TDF_Label& theLast)
+{
+ const TDF_Label aThisDocRoot = myLab.Root();
+ Handle(TDataStd_ExtStringList) anEntries; // entries of references to external document
+ TDataStd_ListOfExtendedString::Iterator anIter;
+ Handle(TDataStd_ReferenceArray) anArray;
+ if (myLab.FindAttribute(kBASE_ARRAY, anArray)) {
+ int anUpper = anArray->Upper();
+ for(int anIndex = anArray->Lower(); anIndex <= anUpper; anIndex++) {
+ TDF_Label aLab = anArray->Value(anIndex);
+ if (aLab.IsEqual(aThisDocRoot)) { // external document reference
+ if (myBaseDocumentLab.IsNull())
+ return false;
+ if (anEntries.IsNull()) {
+ if (!myLab.FindAttribute(kBASE_LIST, anEntries))
+ return false;
+ anIter.Initialize(anEntries->List());
+ }
+ if (!anIter.More())
+ return false;
+ TDF_Tool::Label(myBaseDocumentLab.Data(), anIter.Value(), aLab);
+ anIter.Next();
+ }
+ if (anIndex == anUpper) {
+ theLast = aLab;
+ } else {
+ theRef.Append(aLab);
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+void Selector_Algo::store(const TopoDS_Shape theShape)
+{
+ TNaming_Builder aBuilder(myLab);
+ aBuilder.Select(theShape, theShape);
+}
+
+bool Selector_Algo::sameGeometry(const TopoDS_Shape theShape1, const TopoDS_Shape theShape2) {
+ if (!theShape1.IsNull() && !theShape2.IsNull() && theShape1.ShapeType() == theShape2.ShapeType())
+ {
+ if (theShape1.ShapeType() == TopAbs_FACE) { // check surfaces
+ TopLoc_Location aLoc1, aLoc2;
+ TopoDS_Face aFace1 = TopoDS::Face(theShape1);
+ Handle(Geom_Surface) aSurf1 = BRep_Tool::Surface(aFace1, aLoc1);
+ TopoDS_Face aFace2 = TopoDS::Face(theShape2);
+ Handle(Geom_Surface) aSurf2 = BRep_Tool::Surface(aFace2, aLoc2);
+ return aSurf1 == aSurf2 && aLoc1.IsEqual(aLoc2);
+ } else if (theShape1.ShapeType() == TopAbs_EDGE) { // check curves
+ TopLoc_Location aLoc1, aLoc2;
+ Standard_Real aFirst, aLast;
+ TopoDS_Edge anEdge1 = TopoDS::Edge(theShape1);
+ Handle(Geom_Curve) aCurve1 = BRep_Tool::Curve(anEdge1, aLoc1, aFirst, aLast);
+ TopoDS_Edge anEdge2 = TopoDS::Edge(theShape2);
+ Handle(Geom_Curve) aCurve2 = BRep_Tool::Curve(anEdge2, aLoc2, aFirst, aLast);
+ return aCurve1 == aCurve2 && aLoc1.IsEqual(aLoc2);
+ }
+ }
+ return false;
+}
+
+TopoDS_Shape Selector_Algo::value()
+{
+ Handle(TNaming_NamedShape) aNS;
+ if (myLab.FindAttribute(TNaming_NamedShape::GetID(), aNS))
+ return aNS->Get();
+ return TopoDS_Shape(); // empty, error shape
+}
+
+Selector_Algo* Selector_Algo::restoreByLab(TDF_Label theLab)
+{
+ Handle(TDataStd_Integer) aTypeAttr;
+ if (!myLab.FindAttribute(kSEL_TYPE, aTypeAttr))
+ return NULL;
+ Selector_Type aType = Selector_Type(aTypeAttr->Get());
+ Selector_Algo* aResult = NULL;
+ switch (aType) {
+ case SELTYPE_CONTAINER: {
+ aResult = new Selector_Container;
+ break;
+ }
+ case SELTYPE_INTERSECT: {
+ aResult = new Selector_Intersect;
+ break;
+ }
+ case SELTYPE_MODIFICATION: {
+ aResult = new Selector_Modify;
+ break;
+ }
+ case SELTYPE_PRIMITIVE: {
+ aResult = new Selector_Primitive;
+ break;
+ }
+ case SELTYPE_FILTER_BY_NEIGHBOR: {
+ aResult = new Selector_FilterByNeighbors;
+ break;
+ }
+ case SELTYPE_WEAK_NAMING: {
+ aResult = new Selector_WeakName;
+ break;
+ }
+ default: { // unknown case
+ }
+ }
+ if (aResult) {
+ bool aGeomNaming = myLab.IsAttribute(kGEOMETRICAL_NAMING);
+ aResult->myLab = theLab;
+ aResult->myBaseDocumentLab = myBaseDocumentLab;
+ aResult->myGeometricalNaming = aGeomNaming;
+ aResult->myUseNeighbors = myUseNeighbors;
+ aResult->myUseIntersections = myUseIntersections;
+ if (!aResult->restore()) {
+ delete aResult;
+ aResult = NULL;
+ }
+ }
+ return aResult;
+}
+
+Selector_Algo* Selector_Algo::restoreByName(TDF_Label theLab, TDF_Label theBaseDocLab,
+ std::string theName, const TopAbs_ShapeEnum theShapeType,
+ Selector_NameGenerator* theNameGenerator, TDF_Label& theContextLab)
+{
+ Selector_Algo* aResult = NULL;
+ if (theName[0] == '[') { // intersection or container
+ switch(theShapeType) {
+ case TopAbs_COMPOUND:
+ case TopAbs_COMPSOLID:
+ case TopAbs_SHELL:
+ case TopAbs_WIRE:
+ aResult = new Selector_Container;
+ break;
+ case TopAbs_VERTEX:
+ case TopAbs_EDGE:
+ case TopAbs_FACE:
+ aResult = new Selector_Intersect;
+ break;
+ default:;
+ }
+ } else if (theName[0] == '(') { // filter by neighbors
+ aResult = new Selector_FilterByNeighbors;
+ } if (theName.find(pureWeakNameID()) == 0) { // weak naming identifier
+ } else if (theName.find('&') != std::string::npos) { // modification
+ aResult = new Selector_Modify;
+ } else { // primitive
+ aResult = new Selector_Primitive;
+ }
+ if (aResult) {
+ aResult->myLab = theLab;
+ aResult->myBaseDocumentLab = theBaseDocLab;
+ theContextLab = aResult->restoreByName(theName, theShapeType, theNameGenerator);
+ if (theContextLab.IsNull()) {
+ delete aResult;
+ aResult = NULL;
+ }
+ }
+ return aResult;
+}
+
+void Selector_Algo::storeType(const Selector_Type theType)
+{
+ TDataStd_Integer::Set(myLab, kSEL_TYPE, (int)(theType));
+}
--- /dev/null
+// Copyright (C) 2014-2017 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
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// 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
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef Selector_Algo_H_
+#define Selector_Algo_H_
+
+#include "Selector.h"
+
+#include <Standard_GUID.hxx>
+#include <TDF_Label.hxx>
+#include <TDF_LabelList.hxx>
+#include <TopoDS_Shape.hxx>
+
+class Selector_NameGenerator;
+
+/**\class Selector_Selector
+ * \ingroup DataModel
+ * \brief Base class for all kinds of selection algorithms.
+ */
+class Selector_Algo
+{
+ TopAbs_ShapeEnum myShapeType; ///< type of this shape
+
+ TDF_Label myLab; ///< label where this also may be located
+ TDF_Label myBaseDocumentLab; ///< an access-label of the document that may contain initial shapes
+ bool myGeometricalNaming; ///< flag that indicates that geometrical naming selection is enabled
+ bool myAlwaysGeometricalNaming; ///< to enable geometrical naming from beginning, at select
+ bool myUseNeighbors; ///< to use neighbors algorithms
+ bool myUseIntersections; ///< to use intersections algorithms
+
+public:
+ /// Type of a selector algorithm: on this type depends what is stored in this label and how to
+ /// restore it on update.
+ enum Selector_Type {
+ SELTYPE_CONTAINER, ///< just a container of sub-elements, keeps the shape type of container
+ SELTYPE_INTERSECT, ///< sub-shape is intersection of higher level objects
+ SELTYPE_PRIMITIVE, ///< sub-shape found as a primitive on some label
+ SELTYPE_MODIFICATION, ///< modification of base shapes to the final label
+ SELTYPE_FILTER_BY_NEIGHBOR, ///< identification by neighbor shapes in context
+ SELTYPE_WEAK_NAMING, ///< pure weak naming by weak index in context
+ };
+
+ /// Initializes the algorithm
+ SELECTOR_EXPORT Selector_Algo();
+
+ /// Initializes the selector structure on the label.
+ /// Stores the name data to restore after modification.
+ /// \param theContext whole shape that contains the selected sub-shape
+ /// \param theValue selected subshape
+ /// \param theGeometricalNaming treats selection with equal surfaces as one
+ /// \param theUseNeighbors enables searching algorithm by neighbors
+ /// \param theUseIntersections enables searching algorithm by intersection of higher level shapes
+ SELECTOR_EXPORT static Selector_Algo* select(
+ const TopoDS_Shape theContext, const TopoDS_Shape theValue,
+ const TDF_Label theAccess, const TDF_Label theBaseDocument,
+ const bool theGeometricalNaming = false,
+ const bool theUseNeighbors = true, const bool theUseIntersections = true,
+ const bool theAlwaysGeometricalNaming = false);
+
+ /// Stores the name to the label and sub-labels tree
+ SELECTOR_EXPORT virtual void store() = 0;
+
+ /// Restores the selected shape by the topological naming kept in the data structure
+ /// Returns true if it can restore structure correctly
+ SELECTOR_EXPORT virtual bool restore() = 0;
+
+ /// Restores the selected shape by the topological name string.
+ /// Returns not empty label of the context.
+ SELECTOR_EXPORT virtual TDF_Label restoreByName(std::string theName,
+ const TopAbs_ShapeEnum theShapeType, Selector_NameGenerator* theNameGenerator) = 0;
+
+ /// Updates the current shape by the stored topological name
+ SELECTOR_EXPORT virtual bool solve(const TopoDS_Shape& theContext) = 0;
+
+ /// Returns the naming name of the selection
+ SELECTOR_EXPORT virtual std::string name(Selector_NameGenerator* theNameGenerator) = 0;
+ /// Returns the current sub-shape value (null if can not resolve)
+ SELECTOR_EXPORT TopoDS_Shape value();
+ /// Restores sub-algorithm of a given type by the storage-label
+ SELECTOR_EXPORT Selector_Algo* restoreByLab(TDF_Label theLab);
+ /// Restores the selected sub-algorithm by the naming name.
+ /// Returns not empty label of the context.
+ SELECTOR_EXPORT static Selector_Algo* restoreByName(
+ TDF_Label theLab, TDF_Label theBaseDocLab, std::string theName,
+ const TopAbs_ShapeEnum theShapeType, Selector_NameGenerator* theNameGenerator,
+ TDF_Label& theContextLab);
+
+ /// Returns true if the given shapes are based on the same geometry
+ static bool sameGeometry(const TopoDS_Shape theShape1, const TopoDS_Shape theShape2);
+
+ /// Creates a new selection algorithm for selection of all topology based on the same geometry
+ SELECTOR_EXPORT static Selector_Algo* relesectWithAllGeometry(
+ Selector_Algo* theOldAlgo, const TopoDS_Shape theContext);
+
+protected:
+ /// Returns label where this algorithm is attached to, or just an access label to the document
+ const TDF_Label& label() const
+ {return myLab;}
+ /// Stores the array of references to theLab: references to elements of ref-list, then the last
+ void storeBaseArray(const TDF_LabelList& theRef, const TDF_Label& theLast);
+ /// Restores references to the labels: references to elements of ref-list, then the last
+ bool restoreBaseArray(TDF_LabelList& theRef, TDF_Label& theLast);
+ /// Stores result of selection at the given label
+ void store(const TopoDS_Shape theShape);
+ /// Returns an access-label of the document that may contain initial shapes
+ const TDF_Label& baseDocument() const
+ {return myBaseDocumentLab;}
+ /// Returns the geometrical naming flag
+ bool geometricalNaming() const
+ {return myGeometricalNaming;}
+ /// Returns always geometrical naming flag
+ bool alwaysGeometricalNaming() const
+ {return myAlwaysGeometricalNaming;}
+ /// Returns use neighbors flag
+ bool useNeighbors() const
+ {return myUseNeighbors;}
+ /// Returns use intersections flag
+ bool useIntersections() const
+ {return myUseIntersections;}
+ /// Returns GUID for the weak index (integer attribute) of the sub-shape
+ static const Standard_GUID& weakID()
+ {
+ static const Standard_GUID kWEAK_INDEX("e9373a61-cabc-4ee8-aabf-aea47c62ed87");
+ return kWEAK_INDEX;
+ }
+ /// Returns GUID for the type of the shape, stored in case it is intersection or container
+ static const Standard_GUID& shapeTypeID()
+ {
+ static const Standard_GUID kSHAPE_TYPE("864b3267-cb9d-4107-bf58-c3ce1775b171");
+ return kSHAPE_TYPE;
+ }
+ /// string identifier of the weak name in modification or intersection types of algorithm
+ static const std::string& weakNameID()
+ {
+ static const std::string kWEAK_NAME_IDENTIFIER = "weak_name_";
+ return kWEAK_NAME_IDENTIFIER;
+ }
+ /// string identifier of the pure weak name
+ static const std::string& pureWeakNameID()
+ {
+ static const std::string kPURE_WEAK_NAME_IDENTIFIER = "_weak_name_";
+ return kPURE_WEAK_NAME_IDENTIFIER;
+ }
+ /// Stores the type of an algorithm in the data tree (in myLab)
+ void storeType(const Selector_Type theType);
+};
+
+#endif
--- /dev/null
+// Copyright (C) 2014-2017 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
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// 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
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#include <Selector_AlgoWithSubs.h>
+
+Selector_AlgoWithSubs::Selector_AlgoWithSubs() : Selector_Algo()
+{}
+
+void Selector_AlgoWithSubs::clearSubAlgos()
+{
+ std::list<Selector_Algo*>::iterator anAlgo = mySubSelList.begin();
+ for(; anAlgo != mySubSelList.end(); anAlgo++) {
+ delete *anAlgo;
+ }
+ mySubSelList.clear();
+}
+
+Selector_AlgoWithSubs::~Selector_AlgoWithSubs()
+{
+ clearSubAlgos();
+}
+
+TDF_Label Selector_AlgoWithSubs::newSubLabel()
+{
+ return label().FindChild(int(mySubSelList.size() + 1));
+}
+
+bool Selector_AlgoWithSubs::append(Selector_Algo* theAlgo, const bool theEraseIfNull)
+{
+ if (theAlgo) {
+ mySubSelList.push_back(theAlgo);
+ return true;
+ }
+ if (theEraseIfNull)
+ clearSubAlgos();
+ return false;
+}
+
+const std::list<Selector_Algo*>& Selector_AlgoWithSubs::list() const
+{
+ return mySubSelList;
+}
--- /dev/null
+// Copyright (C) 2014-2017 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
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// 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
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef Selector_AlgoWithSubs_H_
+#define Selector_AlgoWithSubs_H_
+
+#include "Selector_Algo.h"
+
+#include <list>
+
+/**\class Selector_AlgoWithSubs
+ * \ingroup DataModel
+ * \brief Kind of selection algorithm: generic algorithm that contains sub-algorithms inside.
+ * It is base for Container, Intersection and FilterByNeighbours algorithms.
+ */
+class Selector_AlgoWithSubs: public Selector_Algo
+{
+ std::list<Selector_Algo*> mySubSelList; ///< list of sub-algorithms
+public:
+ /// Initializes selector
+ Selector_AlgoWithSubs();
+ /// Destructor
+ virtual ~Selector_AlgoWithSubs();
+ /// Erases the sub-algorithms stored
+ void clearSubAlgos();
+ /// Returns the next label for a new sub-selector created
+ TDF_Label newSubLabel();
+ /// Appends a new algorithm to the list, erases list if it is null (failed)
+ bool append(Selector_Algo* theAlgo, const bool theEraseIfNull = true);
+ /// Returns the stored list of sub-algorithms.
+ const std::list<Selector_Algo*>& list() const;
+};
+
+#endif
--- /dev/null
+// Copyright (C) 2014-2017 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
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// 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
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#include <Selector_Container.h>
+
+#include <Selector_NameGenerator.h>
+#include <Selector_NExplode.h>
+
+#include <TNaming_NamedShape.hxx>
+#include <TDataStd_Name.hxx>
+#include <TDataStd_Integer.hxx>
+#include <TDF_ChildIterator.hxx>
+#include <TopTools_MapOfShape.hxx>
+#include <TopExp_Explorer.hxx>
+#include <BRep_Tool.hxx>
+#include <TopoDS.hxx>
+#include <TopoDS_Builder.hxx>
+#include <TopoDS_Compound.hxx>
+
+Selector_Container::Selector_Container() : Selector_AlgoWithSubs()
+{}
+
+bool Selector_Container::select(const TopoDS_Shape theContext, const TopoDS_Shape theValue)
+{
+ myShapeType = theValue.ShapeType();
+
+ // iterate all sub-shapes and select them on sublabels
+ for(TopoDS_Iterator aSubIter(theValue); aSubIter.More(); aSubIter.Next()) {
+ Selector_Algo* aSubAlgo = Selector_Algo::select(theContext, aSubIter.Value(),
+ newSubLabel(), baseDocument(),
+ false, useNeighbors(), useIntersections()); //for subs no geometrical naming allowed
+ if (!append(aSubAlgo))
+ return false;
+ }
+ return true;
+}
+
+void Selector_Container::store()
+{
+ storeType(Selector_Algo::SELTYPE_CONTAINER);
+ // store all sub-selectors
+ TDataStd_Integer::Set(label(), shapeTypeID(), (int)myShapeType);
+ std::list<Selector_Algo*>::const_iterator aSubSel = list().cbegin();
+ for(; aSubSel != list().cend(); aSubSel++) {
+ (*aSubSel)->store();
+ }
+ TDataStd_Integer::Set(label(), shapeTypeID(), (int)myShapeType);
+}
+
+bool Selector_Container::restore()
+{
+ Handle(TDataStd_Integer) aShapeTypeAttr;
+ if (!label().FindAttribute(shapeTypeID(), aShapeTypeAttr))
+ return false;
+ myShapeType = TopAbs_ShapeEnum(aShapeTypeAttr->Get());
+ // restore sub-selectors
+ bool aSubResult = true;
+ for(TDF_ChildIterator aSub(label(), false); aSub.More(); aSub.Next()) {
+ Selector_Algo* aSubSel = restoreByLab(aSub.Value());
+ if (!append(aSubSel, false)) {
+ break; // some empty label left in the end
+ }
+ }
+ return true;
+}
+
+TDF_Label Selector_Container::restoreByName(std::string theName,
+ const TopAbs_ShapeEnum theShapeType, Selector_NameGenerator* theNameGenerator)
+{
+ myShapeType = theShapeType;
+ TDF_Label aContext;
+ for(size_t aStart = 0; aStart != std::string::npos; aStart = theName.find('[', aStart + 1)) {
+ size_t anEndPos = theName.find(']', aStart + 1);
+ if (anEndPos != std::string::npos) {
+ std::string aSubStr = theName.substr(aStart + 1, anEndPos - aStart - 1);
+ TopAbs_ShapeEnum aSubShapeType = TopAbs_FACE;
+ switch (myShapeType) {
+ case TopAbs_COMPSOLID: aSubShapeType = TopAbs_SOLID; break;
+ case TopAbs_WIRE: aSubShapeType = TopAbs_EDGE; break;
+ default:;
+ }
+ TDF_Label aSubContext;
+ Selector_Algo* aSubSel =
+ Selector_Algo::restoreByName(
+ label(), baseDocument(), aSubStr, aSubShapeType, theNameGenerator, aSubContext);
+ if (!append(aSubSel))
+ return TDF_Label();
+
+ if (aSubContext.IsNull()) {
+ delete aSubSel;
+ clearSubAlgos();
+ return TDF_Label();
+ }
+ if (!aContext.IsNull() && !aContext.IsEqual(aSubContext)) {
+ if (!theNameGenerator->isLater(aContext, aSubContext))
+ aContext = aSubContext;
+ } else {
+ aContext = aSubContext;
+ }
+ } else
+ return TDF_Label(); // invalid parentheses
+ }
+ return aContext;
+}
+
+bool Selector_Container::solve(const TopoDS_Shape& theContext)
+{
+ TopoDS_Shape aResult;
+
+ TopoDS_Builder aBuilder;
+ switch(myShapeType) {
+ case TopAbs_COMPOUND: {
+ TopoDS_Compound aComp;
+ aBuilder.MakeCompound(aComp);
+ aResult = aComp;
+ break;
+ }
+ case TopAbs_COMPSOLID: {
+ TopoDS_CompSolid aComp;
+ aBuilder.MakeCompSolid(aComp);
+ aResult = aComp;
+ break;
+ }
+ case TopAbs_SHELL: {
+ TopoDS_Shell aShell;
+ aBuilder.MakeShell(aShell);
+ aResult = aShell;
+ break;
+ }
+ case TopAbs_WIRE: {
+ TopoDS_Wire aWire;
+ aBuilder.MakeWire(aWire);
+ aResult = aWire;
+ break;
+ }
+ }
+ TopoDS_ListOfShape aSubSelectorShapes;
+ std::list<Selector_Algo*>::const_iterator aSubSel = list().cbegin();
+ for(; aSubSel != list().cend(); aSubSel++) {
+ if (!(*aSubSel)->solve(theContext)) {
+ return false;
+ }
+ aBuilder.Add(aResult, (*aSubSel)->value());
+ }
+ if (!aResult.IsNull()) {
+ Selector_Algo::store(aResult);
+ return true;
+ }
+ return false;
+}
+
+std::string Selector_Container::name(Selector_NameGenerator* theNameGenerator)
+{
+ std::string aResult;
+ // add names of sub-components one by one in "[]"
+ std::list<Selector_Algo*>::const_iterator aSubSel = list().cbegin();
+ for(; aSubSel != list().cend(); aSubSel++) {
+ aResult += '[';
+ aResult += (*aSubSel)->name(theNameGenerator);
+ aResult += ']';
+ }
+ return aResult;
+}
--- /dev/null
+// Copyright (C) 2014-2017 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
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// 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
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef Selector_Container_H_
+#define Selector_Container_H_
+
+#include "Selector_AlgoWithSubs.h"
+
+#include <list>
+
+/**\class Selector_Container
+ * \ingroup DataModel
+ * \brief Kind of selection algorithm: selected shape is a container of sub-shapes that must
+ * be named one by one.
+ */
+class Selector_Container: public Selector_AlgoWithSubs
+{
+ TopAbs_ShapeEnum myShapeType; ///< type of this container
+public:
+ /// Initializes the selection of this kind
+ SELECTOR_EXPORT bool select(const TopoDS_Shape theContext, const TopoDS_Shape theValue);
+
+ /// Stores the name to the label and sub-labels tree
+ SELECTOR_EXPORT virtual void store() override;
+
+ /// Restores the selected shape by the topological naming kept in the data structure
+ /// Returns true if it can restore structure correctly
+ SELECTOR_EXPORT virtual bool restore() override;
+
+ /// Restores the selected shape by the topological name string.
+ /// Returns not empty label of the context.
+ SELECTOR_EXPORT virtual TDF_Label restoreByName(std::string theName,
+ const TopAbs_ShapeEnum theShapeType, Selector_NameGenerator* theNameGenerator) override;
+
+ /// Updates the current shape by the stored topological name
+ SELECTOR_EXPORT virtual bool solve(const TopoDS_Shape& theContext) override;
+
+ /// Returns the naming name of the selection
+ SELECTOR_EXPORT virtual std::string name(Selector_NameGenerator* theNameGenerator) override;
+private:
+ /// Initializes selector
+ Selector_Container();
+
+ friend class Selector_Algo;
+};
+
+#endif
--- /dev/null
+// Copyright (C) 2014-2017 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
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// 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
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#include <Selector_FilterByNeighbors.h>
+
+#include <Selector_NameGenerator.h>
+
+#include <TopoDS.hxx>
+#include <TopoDS_Builder.hxx>
+#include <TopoDS_Compound.hxx>
+#include <TopTools_MapOfShape.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TDataStd_Integer.hxx>
+#include <TDataStd_IntegerArray.hxx>
+#include <TDF_ChildIterator.hxx>
+
+// array of the neighbor levels
+static const Standard_GUID kLEVELS_ARRAY("ee4c4b45-e859-4e86-aa4f-6eac68e0ca1f");
+
+Selector_FilterByNeighbors::Selector_FilterByNeighbors() : Selector_AlgoWithSubs()
+{}
+
+/// Searches neighbor of theLevel of neighborhood to theValue in theContex
+static void findNeighbors(const TopoDS_Shape theContext, const TopoDS_Shape theValue,
+ const int theLevel, TopTools_MapOfShape& theResult)
+{
+ TopAbs_ShapeEnum aConnectorType = TopAbs_VERTEX; // type of the connector sub-shapes
+ if (theValue.ShapeType() == TopAbs_FACE)
+ aConnectorType = TopAbs_EDGE;
+ TopTools_MapOfShape aNBConnectors; // connector shapes that already belong to neighbors
+ for(TopExp_Explorer aValExp(theValue, aConnectorType); aValExp.More(); aValExp.Next()) {
+ aNBConnectors.Add(aValExp.Current());
+ }
+
+ TopTools_MapOfShape alreadyProcessed;
+ alreadyProcessed.Add(theValue);
+
+ for(int aLevel = 1; aLevel <= theLevel; aLevel++) {
+ TopoDS_ListOfShape aGoodCandidates;
+ TopExp_Explorer aCandidate(theContext, theValue.ShapeType());
+ for(; aCandidate.More(); aCandidate.Next()) {
+ if (alreadyProcessed.Contains(aCandidate.Current()))
+ continue;
+ TopExp_Explorer aCandConnector(aCandidate.Current(), aConnectorType);
+ for(; aCandConnector.More(); aCandConnector.Next()) {
+ if (aNBConnectors.Contains(aCandConnector.Current())) // candidate is neighbor
+ break;
+ }
+ if (aCandConnector.More()) {
+ if (aLevel == theLevel) { // add a NB into result: it is connected to other neighbors
+ theResult.Add(aCandidate.Current());
+ } else { // add to the NB of the current level
+ aGoodCandidates.Append(aCandidate.Current());
+ }
+ }
+ }
+ if (aLevel != theLevel) { // good candidates are added to neighbor of this level by connectors
+ for(TopoDS_ListOfShape::Iterator aGood(aGoodCandidates); aGood.More(); aGood.Next()) {
+ TopExp_Explorer aGoodConnector(aGood.Value(), aConnectorType);
+ for(; aGoodConnector.More(); aGoodConnector.Next()) {
+ aNBConnectors.Add(aGoodConnector.Current());
+ }
+ alreadyProcessed.Add(aGood.Value());
+ }
+ }
+ }
+}
+
+/// Searches the neighbor shape by neighbors defined in theNB in theContext shape
+static const TopoDS_Shape findNeighbor(const TopoDS_Shape theContext,
+ const std::list<std::pair<TopoDS_Shape, int> >& theNB, const bool theGeometrical)
+{
+ // searching for neighbors with minimum level
+ int aMinLevel = 0;
+ std::list<std::pair<TopoDS_Shape, int> >::const_iterator aNBIter = theNB.cbegin();
+ for(; aNBIter != theNB.cend(); aNBIter++) {
+ if (aMinLevel == 0 || aNBIter->second < aMinLevel) {
+ aMinLevel = aNBIter->second;
+ }
+ }
+ // collect all neighbors which are neighbors of sub-shapes with minimum level
+ bool aFirst = true;
+ TopoDS_ListOfShape aMatches;
+ for(aNBIter = theNB.cbegin(); aNBIter != theNB.cend(); aNBIter++) {
+ if (aNBIter->second == aMinLevel) {
+ TopTools_MapOfShape aThisNBs;
+ findNeighbors(theContext, aNBIter->first, aMinLevel, aThisNBs);
+ // aMatches must contain common part of all NBs lists
+ for(TopTools_MapOfShape::Iterator aThisNB(aThisNBs); aThisNB.More(); aThisNB.Next()) {
+ if (aFirst) {
+ aMatches.Append(aThisNB.Value());
+ } else {
+ // remove all in aMatches which are not in this NBs
+ for(TopoDS_ListOfShape::Iterator aMatch(aMatches); aMatch.More(); ) {
+ if (aThisNBs.Contains(aMatch.Value())) {
+ aMatch.Next();
+ } else {
+ aMatches.Remove(aMatch);
+ }
+ }
+ }
+ }
+ aFirst = false;
+ }
+ }
+ if (aMatches.IsEmpty())
+ return TopoDS_Shape(); // not found any candidate
+ if (aMatches.Extent() == 1)
+ return aMatches.First(); // already found good candidate
+ TopoDS_Compound aResultCompound; // in case of geometrical name and many candidates
+ // iterate all matches to find by other (higher level) neighbors the best candidate
+ TopoDS_Shape aGoodCandidate;
+ TopTools_MapOfShape aGoodCandidates; // already added good candidates to the map
+ for(TopoDS_ListOfShape::Iterator aCandidate(aMatches); aCandidate.More(); aCandidate.Next()) {
+ bool aValidCadidate = true;
+ for(int aLevel = aMinLevel + 1; true; aLevel++) {
+ bool aFooundHigherLevel = false;
+ TopoDS_ListOfShape aLevelNBs;
+ for(aNBIter = theNB.cbegin(); aNBIter != theNB.cend(); aNBIter++) {
+ if (aNBIter->second == aLevel)
+ aLevelNBs.Append(aNBIter->first);
+ else if (aNBIter->second >= aLevel)
+ aFooundHigherLevel = true;
+ }
+ if (!aFooundHigherLevel && aLevelNBs.IsEmpty()) { // iterated all, so, good candidate
+ if (aGoodCandidate.IsNull()) {
+ aGoodCandidate = aCandidate.Value();
+ } else { // another good candidate
+ if (theGeometrical && Selector_Algo::sameGeometry(aGoodCandidate, aCandidate.Value())) {
+ if (!aGoodCandidates.Add(aCandidate.Value()))
+ break;
+ static TopoDS_Builder aBuilder;
+ if (aResultCompound.IsNull()) {
+ aBuilder.MakeCompound(aResultCompound);
+ aBuilder.Add(aResultCompound, aGoodCandidate);
+ }
+ aBuilder.Add(aResultCompound, aCandidate.Value());
+ } else
+ return TopoDS_Shape();
+ }
+ }
+ if (!aLevelNBs.IsEmpty()) {
+ TopTools_MapOfShape aNBsOfCandidate;
+ findNeighbors(theContext, aCandidate.Value(), aLevel, aNBsOfCandidate);
+ // check all stored neighbors are in the map of real neighbors
+ for(TopoDS_ListOfShape::Iterator aLevIter(aLevelNBs); aLevIter.More(); aLevIter.Next()) {
+ if (!aNBsOfCandidate.Contains(aLevIter.Value())) {
+ aValidCadidate = false;
+ break;
+ }
+ }
+ }
+ if (!aValidCadidate) // candidate is not valid, break the checking
+ break;
+ }
+ }
+ if (!aResultCompound.IsNull())
+ return aResultCompound;
+ return aGoodCandidate;
+}
+
+bool Selector_FilterByNeighbors::select(const TopoDS_Shape theContext, const TopoDS_Shape theValue)
+{
+ myShapeType = theValue.ShapeType();
+ // searching by neighbors
+ std::list<std::pair<TopoDS_Shape, int> > aNBs; /// neighbor sub-shape -> level of neighborhood
+ for(int aLevel = 1; true; aLevel++) {
+ TopTools_MapOfShape aNewNB;
+ findNeighbors(theContext, theValue, aLevel, aNewNB);
+ if (aNewNB.Extent() == 0) { // there are no neighbors of the given level, stop iteration
+ break;
+ }
+ // iterate by the order in theContext to keep same naming names
+ TopExp_Explorer anOrder(theContext, theValue.ShapeType());
+ for (; anOrder.More(); anOrder.Next()) {
+ if (aNewNB.Contains(anOrder.Current())) {
+ TopoDS_Shape aNewNBShape = anOrder.Current();
+ // check which can be named correctly, without "by neighbors" type
+ Selector_Algo* aSubAlgo = Selector_Algo::select(theContext, aNewNBShape,
+ newSubLabel(), baseDocument(), geometricalNaming(), false, false);
+ if (aSubAlgo) {
+ // add to list of good NBs
+ aNBs.push_back(std::pair<TopoDS_Shape, int>(aNewNBShape, aLevel));
+ }
+ delete aSubAlgo; // don't keep this sub-algo until all subs and whole validity are checked
+ }
+ }
+ TopoDS_Shape aResult = findNeighbor(theContext, aNBs, geometricalNaming());
+ if (!aResult.IsNull() && aResult.IsSame(theValue)) {
+ std::list<std::pair<TopoDS_Shape, int> >::iterator aNBIter = aNBs.begin();
+ for(; aNBIter != aNBs.end(); aNBIter++) {
+ Selector_Algo* aSubAlgo = Selector_Algo::select(theContext, aNBIter->first,
+ newSubLabel(), baseDocument(), geometricalNaming(), false, false);
+ if (append(aSubAlgo)) {
+ myNBLevel.push_back(aNBIter->second);
+ } else {
+ delete aSubAlgo;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+void Selector_FilterByNeighbors::store()
+{
+ storeType(Selector_Algo::SELTYPE_FILTER_BY_NEIGHBOR);
+ TDataStd_Integer::Set(label(), shapeTypeID(), (int)myShapeType);
+ // store numbers of levels corresponded to the neighbors in sub-selectors
+ Handle(TDataStd_IntegerArray) anArray =
+ TDataStd_IntegerArray::Set(label(), kLEVELS_ARRAY, 0, int(myNBLevel.size()) - 1);
+ std::list<int>::iterator aLevel = myNBLevel.begin();
+ for(int anIndex = 0; aLevel != myNBLevel.end(); aLevel++, anIndex++) {
+ anArray->SetValue(anIndex, *aLevel);
+ }
+ // store all sub-selectors
+ std::list<Selector_Algo*>::const_iterator aSubSel = list().cbegin();
+ for(; aSubSel != list().cend(); aSubSel++) {
+ (*aSubSel)->store();
+ }
+}
+
+bool Selector_FilterByNeighbors::restore()
+{
+ Handle(TDataStd_Integer) aShapeTypeAttr;
+ if (!label().FindAttribute(shapeTypeID(), aShapeTypeAttr))
+ return false;
+ myShapeType = TopAbs_ShapeEnum(aShapeTypeAttr->Get());
+ // restore levels indices
+ Handle(TDataStd_IntegerArray) anArray;
+ if (!label().FindAttribute(kLEVELS_ARRAY, anArray))
+ return false;
+ for(int anIndex = 0; anIndex <= anArray->Upper(); anIndex++) {
+ myNBLevel.push_back(anArray->Value(anIndex));
+ }
+ // restore sub-selectors
+ bool aSubResult = true;
+ for(TDF_ChildIterator aSub(label(), false); aSub.More(); aSub.Next()) {
+ Selector_Algo* aSubSel = restoreByLab(aSub.Value());
+ if (!append(aSubSel, false)) {
+ break; // some empty label left in the end
+ }
+ }
+ return true;
+}
+
+TDF_Label Selector_FilterByNeighbors::restoreByName(std::string theName,
+ const TopAbs_ShapeEnum theShapeType, Selector_NameGenerator* theNameGenerator)
+{
+ myShapeType = theShapeType;
+ TDF_Label aContext;
+ for (size_t aStart = 0; aStart != std::string::npos;
+ aStart = theName.find('(', aStart + 1)) {
+ size_t anEndPos = theName.find(')', aStart + 1);
+ if (anEndPos != std::string::npos) {
+ std::string aSubStr = theName.substr(aStart + 1, anEndPos - aStart - 1);
+ TDF_Label aSubContext;
+ Selector_Algo* aSubSel =
+ Selector_Algo::restoreByName(
+ label(), baseDocument(), aSubStr, myShapeType, theNameGenerator, aSubContext);
+ if (!append(aSubSel))
+ return TDF_Label();
+
+ if (aSubContext.IsNull()) {
+ delete aSubSel;
+ clearSubAlgos();
+ return TDF_Label();
+ }
+ if (!aContext.IsNull() && !aContext.IsEqual(aSubContext)) {
+ if (!theNameGenerator->isLater(aContext, aSubContext))
+ aContext = aSubContext;
+ } else {
+ aContext = aSubContext;
+ }
+ if (!aContext.IsNull()) // for filters by neighbor the latest context shape is vital
+ aContext = theNameGenerator->newestContext(aContext);
+
+ // searching for the level index
+ std::string aLevel;
+ for (anEndPos++; anEndPos != std::string::npos &&
+ theName[anEndPos] != '(' && theName[anEndPos] != 0;
+ anEndPos++) {
+ aLevel += theName[anEndPos];
+ }
+ if (aLevel.empty())
+ myNBLevel.push_back(1); // by default it is 1
+ else {
+ int aNum = atoi(aLevel.c_str());
+ if (aNum > 0)
+ myNBLevel.push_back(aNum);
+ else
+ return TDF_Label(); // invalid number
+ }
+ } else
+ return TDF_Label(); // invalid parentheses
+ }
+ return aContext;
+}
+
+bool Selector_FilterByNeighbors::solve(const TopoDS_Shape& theContext)
+{
+ TopoDS_Shape aResult;
+
+ std::list<std::pair<TopoDS_Shape, int> > aNBs; /// neighbor sub-shape -> level of neighborhood
+ std::list<int>::iterator aLevel = myNBLevel.begin();
+ std::list<Selector_Algo*>::const_iterator aSubSel = list().cbegin();
+ for(; aSubSel != list().cend(); aSubSel++, aLevel++) {
+ if (!(*aSubSel)->solve(theContext)) {
+ return false;
+ }
+ aNBs.push_back(std::pair<TopoDS_Shape, int>((*aSubSel)->value(), *aLevel));
+ }
+ aResult = findNeighbor(theContext, aNBs, geometricalNaming());
+ if (!aResult.IsNull()) {
+ Selector_Algo::store(aResult);
+ return true;
+ }
+ return false;
+}
+
+std::string Selector_FilterByNeighbors::name(Selector_NameGenerator* theNameGenerator)
+{
+ // (nb1)level_if_more_than_1(nb2)level_if_more_than_1(nb3)level_if_more_than_1
+ std::string aResult;
+ std::list<int>::iterator aLevel = myNBLevel.begin();
+ std::list<Selector_Algo*>::const_iterator aSubSel = list().cbegin();
+ for(; aSubSel != list().cend(); aSubSel++, aLevel++) {
+ aResult += "(" + (*aSubSel)->name(theNameGenerator) + ")";
+ if (*aLevel > 1) {
+ std::ostringstream aLevelStr;
+ aLevelStr<<*aLevel;
+ aResult += aLevelStr.str();
+ }
+ }
+ return aResult;
+}
--- /dev/null
+// Copyright (C) 2014-2017 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
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// 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
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef Selector_FilterByNeighbors_H_
+#define Selector_FilterByNeighbors_H_
+
+#include "Selector_AlgoWithSubs.h"
+
+#include <list>
+
+/**\class Selector_FilterByNeighbors
+ * \ingroup DataModel
+ * \brief Kind of selection algorithm: selected shape is identified by neighbor faces of
+ * the same type. Or neighbors of neighbors are considered, etc.
+ * be named one by one.
+ */
+class Selector_FilterByNeighbors: public Selector_AlgoWithSubs
+{
+ TopAbs_ShapeEnum myShapeType; ///< type of this shape
+ std::list<int> myNBLevel; ///< list of integers corresponding to subs neighborhood level
+public:
+ /// Initializes the selection of this kind
+ SELECTOR_EXPORT bool select(const TopoDS_Shape theContext, const TopoDS_Shape theValue);
+
+ /// Stores the name to the label and sub-labels tree
+ SELECTOR_EXPORT virtual void store() override;
+
+ /// Restores the selected shape by the topological naming kept in the data structure
+ /// Returns true if it can restore structure correctly
+ SELECTOR_EXPORT virtual bool restore() override;
+
+ /// Restores the selected shape by the topological name string.
+ /// Returns not empty label of the context.
+ SELECTOR_EXPORT virtual TDF_Label restoreByName(std::string theName,
+ const TopAbs_ShapeEnum theShapeType, Selector_NameGenerator* theNameGenerator) override;
+
+ /// Updates the current shape by the stored topological name
+ SELECTOR_EXPORT virtual bool solve(const TopoDS_Shape& theContext) override;
+
+ /// Returns the naming name of the selection
+ SELECTOR_EXPORT virtual std::string name(Selector_NameGenerator* theNameGenerator) override;
+private:
+ /// Initializes selector
+ Selector_FilterByNeighbors();
+
+ friend class Selector_Algo;
+};
+
+#endif
--- /dev/null
+// Copyright (C) 2014-2017 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
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// 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
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#include <Selector_Intersect.h>
+
+#include <Selector_NameGenerator.h>
+#include <Selector_NExplode.h>
+
+#include <TNaming_NamedShape.hxx>
+#include <TDataStd_Name.hxx>
+#include <TDataStd_Integer.hxx>
+#include <TDF_ChildIterator.hxx>
+#include <TopTools_MapOfShape.hxx>
+#include <TopExp_Explorer.hxx>
+#include <BRep_Tool.hxx>
+#include <TopoDS.hxx>
+#include <TopoDS_Builder.hxx>
+#include <TopoDS_Compound.hxx>
+
+Selector_Intersect::Selector_Intersect() : Selector_AlgoWithSubs()
+{
+ myWeakIndex = -1; // no index by default
+}
+
+// returns the sub-shapes of theSubType which belong to all theShapes (so, common or intersection)
+static void commonShapes(const TopoDS_ListOfShape& theShapes, TopAbs_ShapeEnum theSubType,
+ TopoDS_ListOfShape& theResults)
+{
+ TopoDS_ListOfShape::iterator aSubSel = theShapes.begin();
+ for(; aSubSel != theShapes.end(); aSubSel++) {
+ TopTools_MapOfShape aCurrentMap;
+ for(TopExp_Explorer anExp(*aSubSel, theSubType); anExp.More(); anExp.Next()) {
+ if (aCurrentMap.Add(anExp.Current()) && aSubSel == theShapes.begin())
+ theResults.Append(anExp.Current());
+ }
+ if (aSubSel != theShapes.begin()) { // remove from common shapes not in aCurrentMap
+ for(TopoDS_ListOfShape::Iterator aComIter(theResults); aComIter.More(); ) {
+ if (aCurrentMap.Contains(aComIter.Value()))
+ aComIter.Next();
+ else
+ theResults.Remove(aComIter);
+ }
+ }
+ }
+}
+
+bool Selector_Intersect::select(const TopoDS_Shape theContext, const TopoDS_Shape theValue)
+{
+ myShapeType = theValue.ShapeType();
+ TopAbs_ShapeEnum aSelectionType = myShapeType;
+ // try to find the shape of the higher level type in the context shape
+ bool aFacesTried = false; // for identification of vertices, faces are tried, then edges
+ TopoDS_ListOfShape aLastCommon; // store not good commons, but which may be used for weak naming
+ TopoDS_ListOfShape aLastIntersectors;
+ while(aSelectionType != TopAbs_FACE || !aFacesTried) {
+ if (aSelectionType == TopAbs_FACE) {
+ if (theValue.ShapeType() != TopAbs_VERTEX)
+ break;
+ aFacesTried = true;
+ aSelectionType = TopAbs_EDGE;
+ } else
+ aSelectionType = TopAbs_FACE;
+ TopTools_MapOfShape anIntersectors; // shapes of aSelectionType that contain theValue
+ TopoDS_ListOfShape anIntList; // same as anIntersectors
+ for(TopExp_Explorer aSelExp(theContext, aSelectionType); aSelExp.More(); aSelExp.Next()) {
+ if (aSelectionType == TopAbs_EDGE &&
+ BRep_Tool::Degenerated(TopoDS::Edge(aSelExp.Current())))
+ continue;
+ TopExp_Explorer aSubExp(aSelExp.Current(), theValue.ShapeType());
+ for(; aSubExp.More(); aSubExp.Next()) {
+ if (aSubExp.Current().IsSame(theValue)) {
+ if (anIntersectors.Add(aSelExp.Current()))
+ anIntList.Append(aSelExp.Current());
+ break;
+ }
+ }
+ }
+ // check that solution is only one
+ TopoDS_ListOfShape aCommon;
+ commonShapes(anIntList, theValue.ShapeType(), aCommon);
+ if (aCommon.Extent() == 1 && aCommon.First().IsSame(theValue)) {
+ // name the intersectors
+ TopoDS_ListOfShape::Iterator anInt(anIntList);
+ for (; anInt.More(); anInt.Next()) {
+ Selector_Algo* aSubAlgo = Selector_Algo::select(theContext, anInt.Value(),
+ newSubLabel(), baseDocument(), geometricalNaming(), useNeighbors(), false);
+ if (!append(aSubAlgo))
+ break; // if some selector is failed, stop and search another solution
+ }
+ if (!anInt.More()) { // all intersectors were correctly named
+ return true;
+ }
+ } else if (aCommon.Extent() > 1 && aLastCommon.IsEmpty()) {
+ aLastCommon = aCommon;
+ aLastIntersectors = anIntList;
+ }
+ }
+ if (aLastCommon.Extent() > 1) {
+ if (alwaysGeometricalNaming()) {
+ TopoDS_ListOfShape::Iterator aCommonIter(aLastCommon);
+ TopoDS_Shape aFirst = aCommonIter.Value();
+ for(aCommonIter.Next(); aCommonIter.More(); aCommonIter.Next()) {
+ if (!sameGeometry(aFirst, aCommonIter.Value()))
+ break;
+ }
+ if (!aCommonIter.More()) { // all geometry is same, result is a compound
+ return true;
+ }
+ }
+ // weak naming to distinguish commons coming from intersection
+ Selector_NExplode aNexp(aLastCommon);
+ myWeakIndex = aNexp.index(theValue);
+ if (myWeakIndex != -1) {
+ // name the intersectors
+ TopoDS_ListOfShape::Iterator anInt(aLastIntersectors);
+ for (; anInt.More(); anInt.Next()) {
+ Selector_Algo* aSubAlgo = Selector_Algo::select(theContext, anInt.Value(),
+ newSubLabel(), baseDocument(), geometricalNaming(), useNeighbors(), useIntersections());
+ if (!append(aSubAlgo))
+ break; // if some selector is failed, stop and search another solution
+ }
+ if (!anInt.More()) { // all intersectors were correctly named
+ return true;
+ }
+ }
+ }
+ return false; // solution does not found
+}
+
+void Selector_Intersect::store()
+{
+ storeType(Selector_Algo::SELTYPE_INTERSECT);
+ // store all sub-selectors
+ TDataStd_Integer::Set(label(), shapeTypeID(), (int)myShapeType);
+ std::list<Selector_Algo*>::const_iterator aSubSel = list().cbegin();
+ for(; aSubSel != list().cend(); aSubSel++) {
+ (*aSubSel)->store();
+ }
+ TDataStd_Integer::Set(label(), shapeTypeID(), (int)myShapeType);
+ if (myWeakIndex != -1) {
+ TDataStd_Integer::Set(label(), weakID(), myWeakIndex);
+ }
+}
+
+bool Selector_Intersect::restore()
+{
+ Handle(TDataStd_Integer) aShapeTypeAttr;
+ if (!label().FindAttribute(shapeTypeID(), aShapeTypeAttr))
+ return false;
+ myShapeType = TopAbs_ShapeEnum(aShapeTypeAttr->Get());
+ // restore sub-selectors
+ bool aSubResult = true;
+ for(TDF_ChildIterator aSub(label(), false); aSub.More(); aSub.Next()) {
+ Selector_Algo* aSubSel = restoreByLab(aSub.Value());
+ if (!append(aSubSel, false)) {
+ break; // some empty label left in the end
+ }
+ }
+ Handle(TDataStd_Integer) aWeakInt;
+ if (label().FindAttribute(weakID(), aWeakInt)) {
+ myWeakIndex = aWeakInt->Get();
+ }
+ return true;
+}
+
+TDF_Label Selector_Intersect::restoreByName(std::string theName,
+ const TopAbs_ShapeEnum theShapeType, Selector_NameGenerator* theNameGenerator)
+{
+ myShapeType = theShapeType;
+ TDF_Label aContext;
+ for(size_t aStart = 0; aStart != std::string::npos; aStart = theName.find('[', aStart + 1)) {
+ size_t anEndPos = theName.find(']', aStart + 1);
+ if (anEndPos != std::string::npos) {
+ std::string aSubStr = theName.substr(aStart + 1, anEndPos - aStart - 1);
+ if (aSubStr.find(weakNameID()) == 0) { // weak name identifier
+ std::string aWeakIndex = aSubStr.substr(weakNameID().size());
+ myWeakIndex = atoi(aWeakIndex.c_str());
+ continue;
+ }
+ TopAbs_ShapeEnum aSubShapeType = TopAbs_FACE;
+ if (anEndPos != std::string::npos && anEndPos + 1 < theName.size()) {
+ char aShapeChar = theName[anEndPos + 1];
+ if (theName[anEndPos + 1] != '[') {
+ switch(aShapeChar) {
+ case 'c': aSubShapeType = TopAbs_COMPOUND; break;
+ case 'o': aSubShapeType = TopAbs_COMPSOLID; break;
+ case 's': aSubShapeType = TopAbs_SOLID; break;
+ case 'h': aSubShapeType = TopAbs_SHELL; break;
+ case 'w': aSubShapeType = TopAbs_WIRE; break;
+ case 'e': aSubShapeType = TopAbs_EDGE; break;
+ case 'v': aSubShapeType = TopAbs_VERTEX; break;
+ default:;
+ }
+ }
+ }
+ TDF_Label aSubContext;
+ Selector_Algo* aSubSel =
+ Selector_Algo::restoreByName(
+ label(), baseDocument(), aSubStr, aSubShapeType, theNameGenerator, aSubContext);
+ if (!append(aSubSel))
+ return TDF_Label();
+
+ if (aSubContext.IsNull()) {
+ delete aSubSel;
+ clearSubAlgos();
+ return TDF_Label();
+ }
+ if (!aContext.IsNull() && !aContext.IsEqual(aSubContext)) {
+ if (!theNameGenerator->isLater(aContext, aSubContext))
+ aContext = aSubContext;
+ } else {
+ aContext = aSubContext;
+ }
+ } else
+ return TDF_Label(); // invalid parentheses
+ }
+ return aContext;
+}
+
+bool Selector_Intersect::solve(const TopoDS_Shape& theContext)
+{
+ TopoDS_Shape aResult;
+ TopoDS_ListOfShape aSubSelectorShapes;
+ std::list<Selector_Algo*>::const_iterator aSubSel = list().cbegin();
+ for(; aSubSel != list().cend(); aSubSel++) {
+ if (!(*aSubSel)->solve(theContext)) {
+ return false;
+ }
+ aSubSelectorShapes.Append((*aSubSel)->value());
+ }
+ TopoDS_ListOfShape aCommon; // common sub shapes in each sub-selector (a result)
+ commonShapes(aSubSelectorShapes, myShapeType, aCommon);
+ if (aCommon.Extent() != 1) {
+ if (myWeakIndex != -1) {
+ Selector_NExplode aNexp(aCommon);
+ aResult = aNexp.shape(myWeakIndex);
+ } else if (geometricalNaming() && aCommon.Extent() > 1) {
+ // check results are on the same geometry, create compound
+ TopoDS_ListOfShape::Iterator aCommonIter(aCommon);
+ TopoDS_Shape aFirst = aCommonIter.Value();
+ for(aCommonIter.Next(); aCommonIter.More(); aCommonIter.Next()) {
+ if (!sameGeometry(aFirst, aCommonIter.Value()))
+ break;
+ }
+ if (!aCommonIter.More()) { // all geometry is same, create a result compound
+ TopoDS_Builder aBuilder;
+ TopoDS_Compound aCompound;
+ aBuilder.MakeCompound(aCompound);
+ for(aCommonIter.Initialize(aCommon); aCommonIter.More(); aCommonIter.Next()) {
+ aBuilder.Add(aCompound, aCommonIter.Value());
+ }
+ aResult = aCompound;
+ }
+ } else {
+ return false;
+ }
+ } else {
+ aResult = aCommon.First();
+ }
+ if (!aResult.IsNull()) {
+ Selector_Algo::store(aResult);
+ return true;
+ }
+ return false;
+}
+
+std::string Selector_Intersect::name(Selector_NameGenerator* theNameGenerator)
+{
+ std::string aResult;
+ // add names of sub-components one by one in "[]" +optionally [weak_name_1]
+ std::list<Selector_Algo*>::const_iterator aSubSel = list().cbegin();
+ for(; aSubSel != list().cend(); aSubSel++) {
+ aResult += '[';
+ aResult += (*aSubSel)->name(theNameGenerator);
+ aResult += ']';
+ TopoDS_Shape aSubVal = (*aSubSel)->value();
+ if (!aSubVal.IsNull()) {
+ TopAbs_ShapeEnum aSubType = aSubVal.ShapeType();
+ if (aSubType != TopAbs_FACE) { // in case the sub shape type must be stored
+ switch(aSubType) {
+ case TopAbs_COMPOUND: aResult += "c"; break;
+ case TopAbs_COMPSOLID: aResult += "o"; break;
+ case TopAbs_SOLID: aResult += "s"; break;
+ case TopAbs_SHELL: aResult += "h"; break;
+ case TopAbs_WIRE: aResult += "w"; break;
+ case TopAbs_EDGE: aResult += "e"; break;
+ case TopAbs_VERTEX: aResult += "v"; break;
+ default:;
+ }
+ }
+ }
+ }
+ if (myWeakIndex != -1) {
+ std::ostringstream aWeakStr;
+ aWeakStr<<"["<<weakNameID()<<myWeakIndex<<"]";
+ aResult += aWeakStr.str();
+ }
+ return aResult;
+}
--- /dev/null
+// Copyright (C) 2014-2017 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
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// 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
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef Selector_Intersect_H_
+#define Selector_Intersect_H_
+
+#include "Selector_AlgoWithSubs.h"
+
+#include <list>
+
+/**\class Selector_Intersect
+ * \ingroup DataModel
+ * \brief Kind of selection algorithm: sub-shape is intersection of higher level objects.
+ */
+class Selector_Intersect: public Selector_AlgoWithSubs
+{
+ TopAbs_ShapeEnum myShapeType; ///< type of this shape
+ int myWeakIndex; ///< weak index in case intersection produces several shapes
+public:
+ /// Initializes the selection of this kind
+ SELECTOR_EXPORT bool select(const TopoDS_Shape theContext, const TopoDS_Shape theValue);
+
+ /// Stores the name to the label and sub-labels tree
+ SELECTOR_EXPORT virtual void store() override;
+
+ /// Restores the selected shape by the topological naming kept in the data structure
+ /// Returns true if it can restore structure correctly
+ SELECTOR_EXPORT virtual bool restore() override;
+
+ /// Restores the selected shape by the topological name string.
+ /// Returns not empty label of the context.
+ SELECTOR_EXPORT virtual TDF_Label restoreByName(std::string theName,
+ const TopAbs_ShapeEnum theShapeType, Selector_NameGenerator* theNameGenerator) override;
+
+ /// Updates the current shape by the stored topological name
+ SELECTOR_EXPORT virtual bool solve(const TopoDS_Shape& theContext) override;
+
+ /// Returns the naming name of the selection
+ SELECTOR_EXPORT virtual std::string name(Selector_NameGenerator* theNameGenerator) override;
+private:
+ /// Initializes selector
+ Selector_Intersect();
+
+ friend class Selector_Algo;
+};
+
+#endif
--- /dev/null
+// Copyright (C) 2014-2017 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
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// 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
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#include <Selector_Modify.h>
+
+#include <Selector_NameGenerator.h>
+#include <Selector_NExplode.h>
+
+#include <TNaming_NamedShape.hxx>
+#include <TNaming_Iterator.hxx>
+#include <TNaming_SameShapeIterator.hxx>
+#include <TNaming_NewShapeIterator.hxx>
+#include <TNaming_Tool.hxx>
+#include <TDataStd_Name.hxx>
+#include <TDataStd_Integer.hxx>
+#include <TDF_ChildIterator.hxx>
+#include <TopTools_MapOfShape.hxx>
+#include <TopExp_Explorer.hxx>
+#include <BRep_Tool.hxx>
+#include <TopoDS.hxx>
+#include <TopoDS_Builder.hxx>
+#include <TopoDS_Compound.hxx>
+
+Selector_Modify::Selector_Modify() : Selector_Algo()
+{
+ myWeakIndex = -1; // no index by default
+}
+
+// adds to theResult all labels that contain initial shapes for theValue located in theFinal
+static void findBases(TDF_Label theAccess, Handle(TNaming_NamedShape) theFinal,
+ const TopoDS_Shape& theValue,
+ bool aMustBeAtFinal, const TDF_Label& theAdditionalDocument, TDF_LabelList& theResult)
+{
+ bool aFoundAnyShape = false;
+ TNaming_SameShapeIterator aLabIter(theValue, theAccess);
+ for(; aLabIter.More(); aLabIter.Next()) {
+ Handle(TNaming_NamedShape) aNS;
+ if (aLabIter.Label().FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
+ if (aMustBeAtFinal && aNS != theFinal)
+ continue; // looking for old at the same final label only
+ TNaming_Evolution anEvolution = aNS->Evolution();
+ if (anEvolution == TNaming_PRIMITIVE) {
+ // check that this is not in the results already
+ const TDF_Label aResult = aNS->Label();
+ TDF_LabelList::Iterator aResIter(theResult);
+ for(; aResIter.More(); aResIter.Next()) {
+ if (aResIter.Value().IsEqual(aResult))
+ break;
+ }
+ if (!aResIter.More()) // not found, so add this new
+ theResult.Append(aResult);
+ aFoundAnyShape = true;
+ }
+ if (anEvolution == TNaming_GENERATED || anEvolution == TNaming_MODIFY) {
+ for(TNaming_Iterator aThisIter(aNS); aThisIter.More(); aThisIter.Next()) {
+ if (aThisIter.NewShape().IsSame(theValue)) {
+ // continue recursively, null NS means that any NS are ok
+ findBases(theAccess, theFinal, aThisIter.OldShape(),
+ false, theAdditionalDocument, theResult);
+ aFoundAnyShape = true;
+ }
+ }
+ }
+ }
+ }
+ if (!aFoundAnyShape && !theAdditionalDocument.IsNull()) { // try to find in additional document
+ static TDF_Label anEmpty;
+ if (TNaming_Tool::HasLabel(theAdditionalDocument, theValue))
+ findBases(theAdditionalDocument, Handle(TNaming_NamedShape)(), theValue,
+ false, anEmpty, theResult);
+ }
+}
+
+/// Returns in theResults all shapes with history started in theBase and ended in theFinal
+static void findFinals(const TDF_Label& anAccess, const TopoDS_Shape& theBase,
+ const TDF_Label& theFinal,
+ const TDF_Label& theAdditionalDoc, TopTools_MapOfShape& theResults)
+{
+ if (TNaming_Tool::HasLabel(anAccess, theBase)) {
+ for(TNaming_NewShapeIterator aBaseIter(theBase, anAccess); aBaseIter.More(); aBaseIter.Next())
+ {
+ TNaming_Evolution anEvolution = aBaseIter.NamedShape()->Evolution();
+ if (anEvolution == TNaming_GENERATED || anEvolution == TNaming_MODIFY) {
+ if (aBaseIter.NamedShape()->Label().IsEqual(theFinal)) {
+ theResults.Add(aBaseIter.Shape());
+ } else {
+ findFinals(anAccess, aBaseIter.Shape(), theFinal, theAdditionalDoc, theResults);
+ }
+ }
+ }
+ }
+ if (!theAdditionalDoc.IsNull()) { // search additionally by the additional access label
+ static TDF_Label anEmpty;
+ findFinals(theAdditionalDoc, theBase, theFinal, anEmpty, theResults);
+ }
+}
+
+void Selector_Modify::findModificationResult(TopoDS_ListOfShape& theCommon) {
+ for(TDF_LabelList::Iterator aBase(myBases); aBase.More(); aBase.Next()) {
+ TDF_Label anAdditionalDoc; // this document if base is started in extra document
+ if (aBase.Value().Root() != label().Root()) {
+ anAdditionalDoc = label();
+ }
+ TopTools_MapOfShape aFinals;
+ for(TNaming_Iterator aBaseShape(aBase.Value()); aBaseShape.More(); aBaseShape.Next()) {
+ findFinals(aBase.Value(), aBaseShape.NewShape(), myFinal, anAdditionalDoc, aFinals);
+ }
+ if (!aFinals.IsEmpty()) {
+ if (theCommon.IsEmpty()) { // just copy all to common
+ for(TopTools_MapOfShape::Iterator aFinal(aFinals); aFinal.More(); aFinal.Next()) {
+ theCommon.Append(aFinal.Key());
+ }
+ } else { // keep only shapes presented in both lists
+ for(TopoDS_ListOfShape::Iterator aCommon(theCommon); aCommon.More(); ) {
+ if (aFinals.Contains(aCommon.Value())) {
+ aCommon.Next();
+ } else { // common is not found, remove it
+ theCommon.Remove(aCommon);
+ }
+ }
+ }
+ }
+ }
+}
+
+bool Selector_Modify::select(NCollection_List<Handle(TNaming_NamedShape)>& theModifList,
+ const TopoDS_Shape theContext, const TopoDS_Shape theValue)
+{
+ if (theModifList.Extent() > 1) { // searching for the best modification result: by context
+ Handle(TNaming_NamedShape) aCandidate;
+ NCollection_List<Handle(TNaming_NamedShape)>::Iterator aModIter(theModifList);
+ for (; !theModifList.IsEmpty() && aModIter.More(); aModIter.Next()) {
+ aCandidate = aModIter.Value();
+ TDF_Label aFatherLab = aCandidate->Label().Father();
+ Handle(TNaming_NamedShape) aFatherNS;
+ if (aFatherLab.FindAttribute(TNaming_NamedShape::GetID(), aFatherNS)) {
+ for (TNaming_Iterator anIter(aFatherNS); anIter.More(); anIter.Next()) {
+ if (theContext.IsSame(anIter.NewShape())) { // found the best modification
+ theModifList.Clear();
+ break;
+ }
+ }
+ }
+ }
+ // take the best candidate, or the last in the iteration
+ theModifList.Clear();
+ theModifList.Append(aCandidate);
+ }
+
+ if (!theModifList.IsEmpty()) {
+ // searching for all the base shapes of this modification
+ findBases(label(), theModifList.First(), theValue, true, baseDocument(), myBases);
+ if (!myBases.IsEmpty()) {
+ myFinal = theModifList.First()->Label();
+ TopoDS_ListOfShape aCommon;
+ findModificationResult(aCommon);
+ // trying to search by neighbors
+ if (aCommon.Extent() > 1) { // more complicated selection
+ if (alwaysGeometricalNaming()) {
+ TopoDS_ListOfShape::Iterator aCommonIter(aCommon);
+ TopoDS_Shape aFirst = aCommonIter.Value();
+ for (aCommonIter.Next(); aCommonIter.More(); aCommonIter.Next()) {
+ if (!sameGeometry(aFirst, aCommonIter.Value()))
+ break;
+ }
+ if (!aCommonIter.More()) { // all geometry is same, result is a compound
+ return true;
+ }
+ }
+ }
+ }
+ // weak naming case
+ TopoDS_ListOfShape aCommon;
+ myFinal = theModifList.First()->Label();
+ Handle(TNaming_NamedShape) aNS;
+ if (myFinal.FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
+ for(TNaming_Iterator aFinalIter(aNS); aFinalIter.More(); aFinalIter.Next()) {
+ const TopoDS_Shape& aNewShape = aFinalIter.NewShape();
+ if (!aNewShape.IsNull())
+ aCommon.Append(aNewShape);
+ }
+ }
+ Selector_NExplode aNexp(aCommon);
+ myWeakIndex = aNexp.index(theValue);
+ return myWeakIndex != -1;
+ }
+ return false;
+}
+
+void Selector_Modify::store()
+{
+ storeType(Selector_Algo::SELTYPE_MODIFICATION);
+ storeBaseArray(myBases, myFinal);
+ if (myWeakIndex != -1) {
+ TDataStd_Integer::Set(label(), weakID(), myWeakIndex);
+ }
+}
+
+bool Selector_Modify::restore()
+{
+ if (restoreBaseArray(myBases, myFinal)) {
+ Handle(TDataStd_Integer) aWeakInt;
+ if (label().FindAttribute(weakID(), aWeakInt)) {
+ myWeakIndex = aWeakInt->Get();
+ }
+ return true;
+ }
+ return false;
+}
+
+TDF_Label Selector_Modify::restoreByName(std::string theName,
+ const TopAbs_ShapeEnum theShapeType, Selector_NameGenerator* theNameGenerator)
+{
+ TDF_Label aContext;
+ for(size_t anEnd, aStart = 0; aStart != std::string::npos; aStart = anEnd) {
+ if (aStart != 0)
+ aStart++;
+ anEnd = theName.find('&', aStart);
+ std::string aSubStr =
+ theName.substr(aStart, anEnd == std::string::npos ? anEnd : anEnd - aStart);
+ if (aSubStr.find(weakNameID()) == 0) { // weak name identifier
+ std::string aWeakIndex = aSubStr.substr(weakNameID().size());
+ myWeakIndex = atoi(aWeakIndex.c_str());
+ continue;
+ }
+ TDF_Label aSubContext, aValue;
+ if (!theNameGenerator->restoreContext(aSubStr, aSubContext, aValue))
+ return TDF_Label(); // can not restore
+ if(aSubContext.IsNull() || aValue.IsNull())
+ return TDF_Label(); // can not restore
+ if (myFinal.IsNull()) {
+ myFinal = aValue;
+ aContext = aSubContext;
+ } else
+ myBases.Append(aValue);
+ }
+ return aContext;
+}
+
+bool Selector_Modify::solve(const TopoDS_Shape& theContext)
+{
+ TopoDS_Shape aResult;
+ if (myBases.IsEmpty() && myWeakIndex > 0) { // weak name by the final shapes index
+ TopoDS_ListOfShape aCommon;
+ Handle(TNaming_NamedShape) aNS;
+ if (myFinal.FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
+ for(TNaming_Iterator aFinalIter(aNS); aFinalIter.More(); aFinalIter.Next()) {
+ const TopoDS_Shape& aNewShape = aFinalIter.NewShape();
+ if (!aNewShape.IsNull())
+ aCommon.Append(aNewShape);
+ }
+ }
+ Selector_NExplode aNexp(aCommon);
+ aResult = aNexp.shape(myWeakIndex);
+ } else { // standard case
+ TopoDS_ListOfShape aFinalsCommon; // final shapes presented in all results from bases
+ findModificationResult(aFinalsCommon);
+ if (aFinalsCommon.Extent() == 1) { // result is valid: found only one shape
+ aResult = aFinalsCommon.First();
+ } else if (aFinalsCommon.Extent() > 1 && myWeakIndex > 0) {
+ Selector_NExplode aNExp(aFinalsCommon);
+ aResult = aNExp.shape(myWeakIndex);
+ } else if (aFinalsCommon.Extent() > 1 && geometricalNaming()) {// if same geometry - compound
+ TopoDS_ListOfShape::Iterator aCommonIter(aFinalsCommon);
+ TopoDS_Shape aFirst = aCommonIter.Value();
+ for(aCommonIter.Next(); aCommonIter.More(); aCommonIter.Next()) {
+ if (!sameGeometry(aFirst, aCommonIter.Value()))
+ break;
+ }
+ if (!aCommonIter.More()) { // all geometry is same, create a result compound
+ TopoDS_Builder aBuilder;
+ TopoDS_Compound aCompound;
+ aBuilder.MakeCompound(aCompound);
+ for(aCommonIter.Initialize(aFinalsCommon); aCommonIter.More(); aCommonIter.Next()) {
+ aBuilder.Add(aCompound, aCommonIter.Value());
+ }
+ aResult = aCompound;
+ }
+
+ }
+ }
+
+ if (!aResult.IsNull()) {
+ Selector_Algo::store(aResult);
+ return true;
+ }
+ return false;
+}
+
+std::string Selector_Modify::name(Selector_NameGenerator* theNameGenerator)
+{
+ // final&base1&base2 +optionally: [weak_name_1]
+ std::string aResult;
+ Handle(TDataStd_Name) aName;
+ if (!myFinal.FindAttribute(TDataStd_Name::GetID(), aName))
+ return "";
+ aResult += theNameGenerator->contextName(myFinal) + "/" +
+ std::string(TCollection_AsciiString(aName->Get()).ToCString());
+ for(TDF_LabelList::iterator aBase = myBases.begin(); aBase != myBases.end(); aBase++) {
+ if (!aBase->FindAttribute(TDataStd_Name::GetID(), aName))
+ return "";
+ aResult += "&";
+ aResult += theNameGenerator->contextName(*aBase) + "/" +
+ std::string(TCollection_AsciiString(aName->Get()).ToCString());
+ }
+ if (myWeakIndex != -1) {
+ std::ostringstream aWeakStr;
+ aWeakStr<<"&"<<weakNameID()<<myWeakIndex;
+ aResult += aWeakStr.str();
+ }
+ return aResult;
+}
--- /dev/null
+// Copyright (C) 2014-2017 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
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// 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
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef Selector_Modify_H_
+#define Selector_Modify_H_
+
+#include "Selector_Algo.h"
+
+#include <TNaming_NamedShape.hxx>
+
+#include <list>
+
+/**\class Selector_Modify
+ * \ingroup DataModel
+ * \brief Kind of selection algorithm: sub-shape is modification of primitive at some
+ * final stage.
+ */
+class Selector_Modify: public Selector_Algo
+{
+ TDF_Label myFinal; ///< final label of the primitive or generation, where the value is
+ TDF_LabelList myBases; ///< initial labels that contain shapes that produce the modification
+ int myWeakIndex; ///< weak index in case modification produces several shapes
+public:
+ /// Initializes the selection of this kind by list of named shapes where the modification results
+ /// are presented and the selected value.
+ SELECTOR_EXPORT bool select(NCollection_List<Handle(TNaming_NamedShape)>& theModifList,
+ const TopoDS_Shape theContext, const TopoDS_Shape theValue);
+
+ /// Stores the name to the label and sub-labels tree
+ SELECTOR_EXPORT virtual void store() override;
+
+ /// Restores the selected shape by the topological naming kept in the data structure
+ /// Returns true if it can restore structure correctly
+ SELECTOR_EXPORT virtual bool restore() override;
+
+ /// Restores the selected shape by the topological name string.
+ /// Returns not empty label of the context.
+ SELECTOR_EXPORT virtual TDF_Label restoreByName(std::string theName,
+ const TopAbs_ShapeEnum theShapeType, Selector_NameGenerator* theNameGenerator) override;
+
+ /// Updates the current shape by the stored topological name
+ SELECTOR_EXPORT virtual bool solve(const TopoDS_Shape& theContext) override;
+
+ /// Returns the naming name of the selection
+ SELECTOR_EXPORT virtual std::string name(Selector_NameGenerator* theNameGenerator) override;
+
+private:
+ /// Initializes selector
+ Selector_Modify();
+ /// Searches the final shapes presented in all results from bases basing on modification fields
+ void findModificationResult(TopoDS_ListOfShape& theCommon);
+
+ friend class Selector_Algo;
+};
+
+#endif
SELECTOR_EXPORT TopoDS_Shape shape(const int theIndex);
protected:
- TopoDS_ListOfShape mySorted; ///< keepthe the ordered list of shapes
+ TopoDS_ListOfShape mySorted; ///< keep the ordered list of shapes
};
#endif
--- /dev/null
+// Copyright (C) 2014-2017 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
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// 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
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#include <Selector_Primitive.h>
+
+#include <Selector_NameGenerator.h>
+
+#include <TNaming_NamedShape.hxx>
+#include <TDataStd_Name.hxx>
+
+
+Selector_Primitive::Selector_Primitive() : Selector_Algo()
+{
+}
+
+void Selector_Primitive::select(const TDF_Label theFinalLabel)
+{
+ myFinal = theFinalLabel;
+}
+
+void Selector_Primitive::store()
+{
+ storeType(Selector_Algo::SELTYPE_PRIMITIVE);
+ static const TDF_LabelList anEmptyRefList;
+ storeBaseArray(anEmptyRefList, myFinal);
+}
+
+bool Selector_Primitive::restore()
+{
+ static TDF_LabelList anEmptyRefList;
+ return restoreBaseArray(anEmptyRefList, myFinal);
+}
+
+TDF_Label Selector_Primitive::restoreByName(std::string theName,
+ const TopAbs_ShapeEnum theShapeType, Selector_NameGenerator* theNameGenerator)
+{
+ TDF_Label aContext;
+ if (theNameGenerator->restoreContext(theName, aContext, myFinal)) {
+ if (myFinal.IsNull())
+ aContext.Nullify();
+ }
+ return aContext;
+}
+
+bool Selector_Primitive::solve(const TopoDS_Shape& theContext)
+{
+ Handle(TNaming_NamedShape) aNS;
+ if (myFinal.FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
+ Selector_Algo::store(aNS->Get());
+ return true;
+ }
+ return false;
+}
+
+std::string Selector_Primitive::name(Selector_NameGenerator* theNameGenerator)
+{
+ Handle(TDataStd_Name) aName;
+ if (!myFinal.FindAttribute(TDataStd_Name::GetID(), aName))
+ return "";
+ std::string aResult = theNameGenerator->contextName(myFinal);
+ if (!aResult.empty())
+ aResult += "/" + std::string(TCollection_AsciiString(aName->Get()).ToCString());
+ return aResult;
+}
--- /dev/null
+// Copyright (C) 2014-2017 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
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// 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
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef Selector_Primitive_H_
+#define Selector_Primitive_H_
+
+#include "Selector_Algo.h"
+
+/**\class Selector_Primitive
+ * \ingroup DataModel
+ * \brief Kind of selection algorithm: exact referencing to alone shape in the data structure.
+ */
+class Selector_Primitive: public Selector_Algo
+{
+ TDF_Label myFinal; ///< final label of the where the value is
+public:
+ /// Initializes the selection of this kind
+ /// \param theLabel the final label with the primitive shape
+ SELECTOR_EXPORT void select(const TDF_Label theFinalLabel);
+
+ /// Stores the name to the label and sub-labels tree
+ SELECTOR_EXPORT virtual void store() override;
+
+ /// Restores the selected shape by the topological naming kept in the data structure
+ /// Returns true if it can restore structure correctly
+ SELECTOR_EXPORT virtual bool restore() override;
+
+ /// Restores the selected shape by the topological name string.
+ /// Returns not empty label of the context.
+ SELECTOR_EXPORT virtual TDF_Label restoreByName(std::string theName,
+ const TopAbs_ShapeEnum theShapeType, Selector_NameGenerator* theNameGenerator) override;
+
+ /// Updates the current shape by the stored topological name
+ SELECTOR_EXPORT virtual bool solve(const TopoDS_Shape& theContext) override;
+
+ /// Returns the naming name of the selection
+ SELECTOR_EXPORT virtual std::string name(Selector_NameGenerator* theNameGenerator) override;
+private:
+ /// Initializes selector
+ Selector_Primitive();
+
+ friend class Selector_Algo;
+};
+
+#endif
-// Copyright (C) 2014-2017 CEA/DEN, EDF R&D
+ // Copyright (C) 2014-2017 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
#include <Selector_Selector.h>
#include <Selector_NameGenerator.h>
-#include <Selector_NExplode.h>
+#include <Selector_Algo.h>
-#include <TopoDS_Iterator.hxx>
-#include <TopoDS_Builder.hxx>
-#include <TopoDS.hxx>
-#include <TopExp_Explorer.hxx>
-#include <TopoDS_Edge.hxx>
-#include <TopoDS_Face.hxx>
-#include <TNaming_Tool.hxx>
-#include <TNaming_NewShapeIterator.hxx>
-#include <TNaming_OldShapeIterator.hxx>
-#include <TNaming_SameShapeIterator.hxx>
-#include <TNaming_Iterator.hxx>
-#include <TNaming_Builder.hxx>
#include <TopTools_MapOfShape.hxx>
-#include <BRep_Tool.hxx>
-
-#include <TDF_ChildIDIterator.hxx>
-#include <TDF_Tool.hxx>
-#include <TDataStd_Integer.hxx>
-#include <TDataStd_ReferenceArray.hxx>
-#include <TDataStd_IntegerArray.hxx>
-#include <TDataStd_Name.hxx>
-#include <TDataStd_UAttribute.hxx>
-#include <TDataStd_ExtStringList.hxx>
-
-#include <list>
-
-/// type of the selection, integer keeps the Selector_Type value
-static const Standard_GUID kSEL_TYPE("db174d59-c2e3-4a90-955e-55544df090d6");
-/// type of the shape, stored in case it is intersection or container
-static const Standard_GUID kSHAPE_TYPE("864b3267-cb9d-4107-bf58-c3ce1775b171");
-// reference attribute that contains the reference to labels where the "from" or "base" shapes
-// of selection are located
-static const Standard_GUID kBASE_ARRAY("7c515b1a-9549-493d-9946-a4933a22f45f");
-// if the base array contains reference to the root label, this means that it refers to an
-// external document and this list contains a tag in the document
-static const Standard_GUID kBASE_LIST("7c515b1a-9549-493d-9946-a4933a22f45a");
-// array of the neighbor levels
-static const Standard_GUID kLEVELS_ARRAY("ee4c4b45-e859-4e86-aa4f-6eac68e0ca1f");
-// weak index (integer) of the sub-shape
-static const Standard_GUID kWEAK_INDEX("e9373a61-cabc-4ee8-aabf-aea47c62ed87");
-// geometrical naming indicator
-static const Standard_GUID kGEOMETRICAL_NAMING("a5322d02-50fb-43ed-9255-75c7b93f6657");
-
-// string identifier of the weak name in modification or intersection types of algorithm
-static const std::string kWEAK_NAME_IDENTIFIER = "weak_name_";
-// string identifier of the pure weak name algorithm
-static const std::string kPUREWEAK_NAME_IDENTIFIER = "_weak_name_";
-
-
-Selector_Selector::Selector_Selector(TDF_Label theLab) : myLab(theLab)
-{
- myWeakIndex = -1;
- myAlwaysGeometricalNaming = false;
-}
-
-TDF_Label Selector_Selector::label()
-{
- return myLab;
-}
-
-void Selector_Selector::setBaseDocument(const TDF_Label theAccess)
-{
- myBaseDocumentLab = theAccess;
-}
-
-// adds to theResult all labels that contain initial shapes for theValue located in theFinal
-static void findBases(TDF_Label theAccess, Handle(TNaming_NamedShape) theFinal,
- const TopoDS_Shape& theValue,
- bool aMustBeAtFinal, const TDF_Label& theAdditionalDocument, TDF_LabelList& theResult)
-{
- bool aFoundAnyShape = false;
- TNaming_SameShapeIterator aLabIter(theValue, theAccess);
- for(; aLabIter.More(); aLabIter.Next()) {
- Handle(TNaming_NamedShape) aNS;
- if (aLabIter.Label().FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
- if (aMustBeAtFinal && aNS != theFinal)
- continue; // looking for old at the same final label only
- TNaming_Evolution anEvolution = aNS->Evolution();
- if (anEvolution == TNaming_PRIMITIVE) {
- // check that this is not in the results already
- const TDF_Label aResult = aNS->Label();
- TDF_LabelList::Iterator aResIter(theResult);
- for(; aResIter.More(); aResIter.Next()) {
- if (aResIter.Value().IsEqual(aResult))
- break;
- }
- if (!aResIter.More()) // not found, so add this new
- theResult.Append(aResult);
- aFoundAnyShape = true;
- }
- if (anEvolution == TNaming_GENERATED || anEvolution == TNaming_MODIFY) {
- for(TNaming_Iterator aThisIter(aNS); aThisIter.More(); aThisIter.Next()) {
- if (aThisIter.NewShape().IsSame(theValue)) {
- // continue recursively, null NS means that any NS are ok
- findBases(theAccess, theFinal, aThisIter.OldShape(),
- false, theAdditionalDocument, theResult);
- aFoundAnyShape = true;
- }
- }
- }
- }
- }
- if (!aFoundAnyShape && !theAdditionalDocument.IsNull()) { // try to find in additional document
- static TDF_Label anEmpty;
- if (TNaming_Tool::HasLabel(theAdditionalDocument, theValue))
- findBases(theAdditionalDocument, Handle(TNaming_NamedShape)(), theValue,
- false, anEmpty, theResult);
- }
-}
-
-// returns the sub-shapes of theSubType which belong to all theShapes (so, common or intersection)
-static void commonShapes(const TopoDS_ListOfShape& theShapes, TopAbs_ShapeEnum theSubType,
- TopoDS_ListOfShape& theResults)
-{
- TopoDS_ListOfShape::iterator aSubSel = theShapes.begin();
- for(; aSubSel != theShapes.end(); aSubSel++) {
- TopTools_MapOfShape aCurrentMap;
- for(TopExp_Explorer anExp(*aSubSel, theSubType); anExp.More(); anExp.Next()) {
- if (aCurrentMap.Add(anExp.Current()) && aSubSel == theShapes.begin())
- theResults.Append(anExp.Current());
- }
- if (aSubSel != theShapes.begin()) { // remove from common shapes not in aCurrentMap
- for(TopoDS_ListOfShape::Iterator aComIter(theResults); aComIter.More(); ) {
- if (aCurrentMap.Contains(aComIter.Value()))
- aComIter.Next();
- else
- theResults.Remove(aComIter);
- }
- }
- }
-}
-
-/// Searches neighbor of theLevel of neighborhood to theValue in theContex
-static void findNeighbors(const TopoDS_Shape theContext, const TopoDS_Shape theValue,
- const int theLevel, TopTools_MapOfShape& theResult)
-{
- TopAbs_ShapeEnum aConnectorType = TopAbs_VERTEX; // type of the connector sub-shapes
- if (theValue.ShapeType() == TopAbs_FACE)
- aConnectorType = TopAbs_EDGE;
- TopTools_MapOfShape aNBConnectors; // connector shapes that already belong to neighbors
- for(TopExp_Explorer aValExp(theValue, aConnectorType); aValExp.More(); aValExp.Next()) {
- aNBConnectors.Add(aValExp.Current());
- }
-
- TopTools_MapOfShape alreadyProcessed;
- alreadyProcessed.Add(theValue);
-
- for(int aLevel = 1; aLevel <= theLevel; aLevel++) {
- TopoDS_ListOfShape aGoodCandidates;
- TopExp_Explorer aCandidate(theContext, theValue.ShapeType());
- for(; aCandidate.More(); aCandidate.Next()) {
- if (alreadyProcessed.Contains(aCandidate.Current()))
- continue;
- TopExp_Explorer aCandConnector(aCandidate.Current(), aConnectorType);
- for(; aCandConnector.More(); aCandConnector.Next()) {
- if (aNBConnectors.Contains(aCandConnector.Current())) // candidate is neighbor
- break;
- }
- if (aCandConnector.More()) {
- if (aLevel == theLevel) { // add a NB into result: it is connected to other neighbors
- theResult.Add(aCandidate.Current());
- } else { // add to the NB of the current level
- aGoodCandidates.Append(aCandidate.Current());
- }
- }
- }
- if (aLevel != theLevel) { // good candidates are added to neighbor of this level by connectors
- for(TopoDS_ListOfShape::Iterator aGood(aGoodCandidates); aGood.More(); aGood.Next()) {
- TopExp_Explorer aGoodConnector(aGood.Value(), aConnectorType);
- for(; aGoodConnector.More(); aGoodConnector.Next()) {
- aNBConnectors.Add(aGoodConnector.Current());
- }
- alreadyProcessed.Add(aGood.Value());
- }
- }
- }
-}
+#include <TopExp_Explorer.hxx>
+#include <TopoDS_Builder.hxx>
+#include <TopoDS_Compound.hxx>
+#include <TNaming_NamedShape.hxx>
-/// Returns true if the given shapes are based on the same geometry
-static bool sameGeometry(const TopoDS_Shape theShape1, const TopoDS_Shape theShape2) {
- if (!theShape1.IsNull() && !theShape2.IsNull() && theShape1.ShapeType() == theShape2.ShapeType())
- {
- if (theShape1.ShapeType() == TopAbs_FACE) { // check surfaces
- TopLoc_Location aLoc1, aLoc2;
- TopoDS_Face aFace1 = TopoDS::Face(theShape1);
- Handle(Geom_Surface) aSurf1 = BRep_Tool::Surface(aFace1, aLoc1);
- TopoDS_Face aFace2 = TopoDS::Face(theShape2);
- Handle(Geom_Surface) aSurf2 = BRep_Tool::Surface(aFace2, aLoc2);
- return aSurf1 == aSurf2 && aLoc1.IsEqual(aLoc2);
- } else if (theShape1.ShapeType() == TopAbs_EDGE) { // check curves
- TopLoc_Location aLoc1, aLoc2;
- Standard_Real aFirst, aLast;
- TopoDS_Edge anEdge1 = TopoDS::Edge(theShape1);
- Handle(Geom_Curve) aCurve1 = BRep_Tool::Curve(anEdge1, aLoc1, aFirst, aLast);
- TopoDS_Edge anEdge2 = TopoDS::Edge(theShape2);
- Handle(Geom_Curve) aCurve2 = BRep_Tool::Curve(anEdge2, aLoc2, aFirst, aLast);
- return aCurve1 == aCurve2 && aLoc1.IsEqual(aLoc2);
- }
- }
- return false;
-}
+Selector_Selector::Selector_Selector(TDF_Label theLab, TDF_Label theBaseDocLab) :
+ myLab(theLab), myBaseDocumentLab(theBaseDocLab), myAlgo(NULL)
+{}
-/// Searches the neighbor shape by neighbors defined in theNB in theContext shape
-static const TopoDS_Shape findNeighbor(const TopoDS_Shape theContext,
- const std::list<std::pair<TopoDS_Shape, int> >& theNB, const bool theGeometrical)
+Selector_Selector::~Selector_Selector()
{
- // searching for neighbors with minimum level
- int aMinLevel = 0;
- std::list<std::pair<TopoDS_Shape, int> >::const_iterator aNBIter = theNB.cbegin();
- for(; aNBIter != theNB.cend(); aNBIter++) {
- if (aMinLevel == 0 || aNBIter->second < aMinLevel) {
- aMinLevel = aNBIter->second;
- }
- }
- // collect all neighbors which are neighbors of sub-shapes with minimum level
- bool aFirst = true;
- TopoDS_ListOfShape aMatches;
- for(aNBIter = theNB.cbegin(); aNBIter != theNB.cend(); aNBIter++) {
- if (aNBIter->second == aMinLevel) {
- TopTools_MapOfShape aThisNBs;
- findNeighbors(theContext, aNBIter->first, aMinLevel, aThisNBs);
- // aMatches must contain common part of all NBs lists
- for(TopTools_MapOfShape::Iterator aThisNB(aThisNBs); aThisNB.More(); aThisNB.Next()) {
- if (aFirst) {
- aMatches.Append(aThisNB.Value());
- } else {
- // remove all in aMatches which are not in this NBs
- for(TopoDS_ListOfShape::Iterator aMatch(aMatches); aMatch.More(); ) {
- if (aThisNBs.Contains(aMatch.Value())) {
- aMatch.Next();
- } else {
- aMatches.Remove(aMatch);
- }
- }
- }
- }
- aFirst = false;
- }
- }
- if (aMatches.IsEmpty())
- return TopoDS_Shape(); // not found any candidate
- if (aMatches.Extent() == 1)
- return aMatches.First(); // already found good candidate
- TopoDS_Compound aResultCompound; // in case of geometrical name and many candidates
- // iterate all matches to find by other (higher level) neighbors the best candidate
- TopoDS_Shape aGoodCandidate;
- TopTools_MapOfShape aGoodCandidates; // already added good candidates to the map
- for(TopoDS_ListOfShape::Iterator aCandidate(aMatches); aCandidate.More(); aCandidate.Next()) {
- bool aValidCadidate = true;
- for(int aLevel = aMinLevel + 1; true; aLevel++) {
- bool aFooundHigherLevel = false;
- TopoDS_ListOfShape aLevelNBs;
- for(aNBIter = theNB.cbegin(); aNBIter != theNB.cend(); aNBIter++) {
- if (aNBIter->second == aLevel)
- aLevelNBs.Append(aNBIter->first);
- else if (aNBIter->second >= aLevel)
- aFooundHigherLevel = true;
- }
- if (!aFooundHigherLevel && aLevelNBs.IsEmpty()) { // iterated all, so, good candidate
- if (aGoodCandidate.IsNull()) {
- aGoodCandidate = aCandidate.Value();
- } else { // another good candidate
- if (theGeometrical && sameGeometry(aGoodCandidate, aCandidate.Value())) {
- if (!aGoodCandidates.Add(aCandidate.Value()))
- break;
- static TopoDS_Builder aBuilder;
- if (aResultCompound.IsNull()) {
- aBuilder.MakeCompound(aResultCompound);
- aBuilder.Add(aResultCompound, aGoodCandidate);
- }
- aBuilder.Add(aResultCompound, aCandidate.Value());
- } else
- return TopoDS_Shape();
- }
- }
- if (!aLevelNBs.IsEmpty()) {
- TopTools_MapOfShape aNBsOfCandidate;
- findNeighbors(theContext, aCandidate.Value(), aLevel, aNBsOfCandidate);
- // check all stored neighbors are in the map of real neighbors
- for(TopoDS_ListOfShape::Iterator aLevIter(aLevelNBs); aLevIter.More(); aLevIter.Next()) {
- if (!aNBsOfCandidate.Contains(aLevIter.Value())) {
- aValidCadidate = false;
- break;
- }
- }
- }
- if (!aValidCadidate) // candidate is not valid, break the checking
- break;
- }
- }
- if (!aResultCompound.IsNull())
- return aResultCompound;
- return aGoodCandidate;
+ if (myAlgo)
+ delete myAlgo;
}
bool Selector_Selector::select(const TopoDS_Shape theContext, const TopoDS_Shape theValue,
- const bool theGeometricalNaming, const bool theUseNeighbors, const bool theUseIntersections)
+ const bool theGeometricalNaming)
{
if (theValue.IsNull() || theContext.IsNull())
return false;
- myGeometricalNaming = theGeometricalNaming;
- // check the value shape can be named as it is, or it is needed to construct it from the
- // higher level shapes (like a box vertex by faces that form this vertex)
- bool aIsFound = TNaming_Tool::HasLabel(myLab, theValue);
- if (aIsFound) { // additional check for selection and delete evolution only: also could not use
- aIsFound = false;
- for(TNaming_SameShapeIterator aShapes(theValue, myLab); aShapes.More(); aShapes.Next())
- {
- Handle(TNaming_NamedShape) aNS;
- if (aShapes.Label().FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
- if (aNS->Evolution() == TNaming_MODIFY || aNS->Evolution() == TNaming_GENERATED ||
- aNS->Evolution() == TNaming_PRIMITIVE) {
- aIsFound = true;
- break;
- }
- }
- }
- }
- // searching in the base document
- if (!aIsFound && !myBaseDocumentLab.IsNull() &&
- TNaming_Tool::HasLabel(myBaseDocumentLab, theValue))
- {
- TNaming_SameShapeIterator aShapes(theValue, myBaseDocumentLab);
- for(; aShapes.More(); aShapes.Next())
- {
- Handle(TNaming_NamedShape) aNS;
- if (aShapes.Label().FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
- if (aNS->Evolution() == TNaming_MODIFY || aNS->Evolution() == TNaming_GENERATED ||
- aNS->Evolution() == TNaming_PRIMITIVE) {
- aIsFound = true;
- break;
- }
- }
- }
- }
- if (!aIsFound) {
- TopAbs_ShapeEnum aSelectionType = theValue.ShapeType();
- myShapeType = aSelectionType;
- if (aSelectionType == TopAbs_COMPOUND || aSelectionType == TopAbs_COMPSOLID ||
- aSelectionType == TopAbs_SHELL || aSelectionType == TopAbs_WIRE)
- { // iterate all sub-shapes and select them on sublabels
- for(TopoDS_Iterator aSubIter(theValue); aSubIter.More(); aSubIter.Next()) {
- if (!selectBySubSelector(theContext, aSubIter.Value(),
- false, theUseNeighbors, theUseIntersections)) {//for subs no geometrical naming allowed
- return false; // if some selector is failed, everything is failed
- }
- }
- myType = SELTYPE_CONTAINER;
- return true;
- }
-
- // try to find the shape of the higher level type in the context shape
- bool aFacesTried = false; // for identification of vertices, faces are tried, then edges
- TopoDS_ListOfShape aLastCommon; // to store the commons not good, but may be used for weak
- TopoDS_ListOfShape aLastIntersectors;
- while(theUseIntersections && (aSelectionType != TopAbs_FACE || !aFacesTried)) {
- if (aSelectionType == TopAbs_FACE) {
- if (theValue.ShapeType() != TopAbs_VERTEX)
- break;
- aFacesTried = true;
- aSelectionType = TopAbs_EDGE;
- } else
- aSelectionType = TopAbs_FACE;
- TopTools_MapOfShape anIntersectors; // shapes of aSelectionType that contain theValue
- TopoDS_ListOfShape anIntList; // same as anIntersectors
- for(TopExp_Explorer aSelExp(theContext, aSelectionType); aSelExp.More(); aSelExp.Next()) {
- if (aSelectionType == TopAbs_EDGE &&
- BRep_Tool::Degenerated(TopoDS::Edge(aSelExp.Current())))
- continue;
- TopExp_Explorer aSubExp(aSelExp.Current(), theValue.ShapeType());
- for(; aSubExp.More(); aSubExp.Next()) {
- if (aSubExp.Current().IsSame(theValue)) {
- if (anIntersectors.Add(aSelExp.Current()))
- anIntList.Append(aSelExp.Current());
- break;
- }
- }
- }
- // check that solution is only one
- TopoDS_ListOfShape aCommon;
- commonShapes(anIntList, theValue.ShapeType(), aCommon);
- if (aCommon.Extent() == 1 && aCommon.First().IsSame(theValue)) {
- // name the intersectors
- mySubSelList.clear();
- TopoDS_ListOfShape::Iterator anInt(anIntList);
- for (; anInt.More(); anInt.Next()) {
- if (!selectBySubSelector(theContext, anInt.Value(),
- theGeometricalNaming, theUseNeighbors, false)) {
- break; // if some selector is failed, stop and search another solution
- }
- }
- if (!anInt.More()) { // all intersectors were correctly named
- myType = SELTYPE_INTERSECT;
- return true;
- }
- } else if (aCommon.Extent() > 1 && aLastCommon.IsEmpty()) {
- aLastCommon = aCommon;
- aLastIntersectors = anIntList;
- }
- }
-
- if (!theUseNeighbors)
- return false;
-
- // searching by neighbors
- std::list<std::pair<TopoDS_Shape, int> > aNBs; /// neighbor sub-shape -> level of neighborhood
- for(int aLevel = 1; true; aLevel++) {
- TopTools_MapOfShape aNewNB;
- findNeighbors(theContext, theValue, aLevel, aNewNB);
- if (aNewNB.Extent() == 0) { // there are no neighbors of the given level, stop iteration
- break;
- }
- // iterate by the order in theContext to keep same naming names
- TopExp_Explorer anOrder(theContext, theValue.ShapeType());
- for (; anOrder.More(); anOrder.Next()) {
- if (aNewNB.Contains(anOrder.Current())) {
- TopoDS_Shape aNewNBShape = anOrder.Current();
- // check which can be named correctly, without "by neighbors" type
- Selector_Selector aSelector(myLab.FindChild(1));
- aSelector.setBaseDocument(myBaseDocumentLab);
- if (aSelector.select(theContext, aNewNBShape, theGeometricalNaming, false, false)) {
- // add to list of good NBs
- aNBs.push_back(std::pair<TopoDS_Shape, int>(aNewNBShape, aLevel));
- }
- }
- }
- TopoDS_Shape aResult = findNeighbor(theContext, aNBs, theGeometricalNaming);
- if (!aResult.IsNull() && aResult.IsSame(theValue)) {
- std::list<std::pair<TopoDS_Shape, int> >::iterator aNBIter = aNBs.begin();
- for(; aNBIter != aNBs.end(); aNBIter++) {
- if (!selectBySubSelector(theContext, aNBIter->first,
- theGeometricalNaming, false, false)) {
- return false; // something is wrong because before this selection was ok
- }
- myNBLevel.push_back(aNBIter->second);
-
- }
- myType = SELTYPE_FILTER_BY_NEIGHBOR;
- return true;
- }
- }
-
- if (aLastCommon.Extent() > 1) {
- if (myAlwaysGeometricalNaming) {
- TopoDS_ListOfShape::Iterator aCommonIter(aLastCommon);
- TopoDS_Shape aFirst = aCommonIter.Value();
- for(aCommonIter.Next(); aCommonIter.More(); aCommonIter.Next()) {
- if (!sameGeometry(aFirst, aCommonIter.Value()))
- break;
- }
- if (!aCommonIter.More()) { // all geometry is same, result is a compound
- myType = SELTYPE_INTERSECT;
- return true;
- }
- }
- // weak naming to distinguish commons coming from intersection
- Selector_NExplode aNexp(aLastCommon);
- myWeakIndex = aNexp.index(theValue);
- if (myWeakIndex != -1) {
- // name the intersectors
- mySubSelList.clear();
- TopoDS_ListOfShape::Iterator anInt(aLastIntersectors);
- for (; anInt.More(); anInt.Next()) {
- if (!selectBySubSelector(theContext, anInt.Value(),
- theGeometricalNaming, theUseNeighbors, theUseIntersections)) {
- break; // if some selector is failed, stop and search another solution
- }
- }
- if (!anInt.More()) { // all intersectors were correctly named
- myType = SELTYPE_INTERSECT;
- return true;
- }
- }
- }
-
- // pure weak naming: there is no sense to use pure weak naming for neighbors selection
- if (theUseNeighbors) {
- myType = SELTYPE_WEAK_NAMING;
- Selector_NExplode aNexp(theContext, theValue.ShapeType());
- myWeakIndex = aNexp.index(theValue);
- if (myWeakIndex != -1) {
- myShapeType = theValue.ShapeType();
- // searching for context shape label to store in myFinal
- myFinal.Nullify();
- if (TNaming_Tool::HasLabel(myLab, theContext)) {
- for(TNaming_SameShapeIterator aShapes(theContext, myLab); aShapes.More(); aShapes.Next())
- {
- Handle(TNaming_NamedShape) aNS;
- if (aShapes.Label().FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
- TNaming_Evolution anEvolution = aNS->Evolution();
- if (anEvolution == TNaming_PRIMITIVE || anEvolution == TNaming_GENERATED ||
- anEvolution == TNaming_MODIFY) {
- // check this is a new shape
- for(TNaming_Iterator aNSIter(aNS); aNSIter.More(); aNSIter.Next()) {
- if (aNSIter.NewShape().IsSame(theContext)) {
- myFinal = aNS->Label();
- break;
- }
- }
- }
- }
- }
- }
- return true; // could be final empty (in case it is called recursively) or not
- }
- }
-
- return false;
- }
- // searching for the base shapes of the value
- Handle(TNaming_NamedShape) aPrimitiveNS;
- NCollection_List<Handle(TNaming_NamedShape)> aModifList;
- for(int aUseExternal = 0; aUseExternal < 2; aUseExternal++) {
- TDF_Label aLab = aUseExternal == 0 ? myLab : myBaseDocumentLab;
- if (aLab.IsNull() || !TNaming_Tool::HasLabel(aLab, theValue))
- continue;
- for(TNaming_SameShapeIterator aShapes(theValue, aLab); aShapes.More(); aShapes.Next())
- {
- Handle(TNaming_NamedShape) aNS;
- if (aShapes.Label().FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
- TNaming_Evolution anEvolution = aNS->Evolution();
- if (anEvolution == TNaming_PRIMITIVE) { // the value shape is declared as PRIMITIVE
- aPrimitiveNS = aNS;
- break;
- } else if (anEvolution == TNaming_GENERATED || anEvolution == TNaming_MODIFY) {
- // check this is a new shape
- TNaming_Iterator aNSIter(aNS);
- for(; aNSIter.More(); aNSIter.Next())
- if (aNSIter.NewShape().IsSame(theValue))
- break;
- if (aNSIter.More()) // new was found
- aModifList.Append(aNS);
- }
- }
- }
- }
- if (!aPrimitiveNS.IsNull()) {
- myType = SELTYPE_PRIMITIVE;
- myFinal = aPrimitiveNS->Label();
- return true;
- }
-
- if (aModifList.Extent() > 1) { // searching for the best modification result: by context
- Handle(TNaming_NamedShape) aCandidate;
- NCollection_List<Handle(TNaming_NamedShape)>::Iterator aModIter(aModifList);
- for(; !aModifList.IsEmpty() && aModIter.More(); aModIter.Next()) {
- aCandidate = aModIter.Value();
- TDF_Label aFatherLab = aCandidate->Label().Father();
- Handle(TNaming_NamedShape) aFatherNS;
- if (aFatherLab.FindAttribute(TNaming_NamedShape::GetID(), aFatherNS)) {
- for(TNaming_Iterator anIter(aFatherNS); anIter.More(); anIter.Next()) {
- if (theContext.IsSame(anIter.NewShape())) { // found the best modification
- aModifList.Clear();
- break;
- }
- }
- }
- }
- // take the best candidate, or the last in the iteration
- aModifList.Clear();
- aModifList.Append(aCandidate);
- }
-
- if (!aModifList.IsEmpty()) {
- // searching for all the base shapes of this modification
- findBases(myLab, aModifList.First(), theValue, true, myBaseDocumentLab, myBases);
- if (!myBases.IsEmpty()) {
- myFinal = aModifList.First()->Label();
- TopoDS_ListOfShape aCommon;
- findModificationResult(aCommon);
- // trying to search by neighbors
- if (aCommon.Extent() > 1) { // more complicated selection
- if (myAlwaysGeometricalNaming) {
- TopoDS_ListOfShape::Iterator aCommonIter(aCommon);
- TopoDS_Shape aFirst = aCommonIter.Value();
- for(aCommonIter.Next(); aCommonIter.More(); aCommonIter.Next()) {
- if (!sameGeometry(aFirst, aCommonIter.Value()))
- break;
- }
- if (!aCommonIter.More()) { // all geometry is same, result is a compound
- myType = SELTYPE_MODIFICATION;
- return true;
- }
- }
- if (!theUseNeighbors)
- return false;
-
- // searching by neighbors
- std::list<std::pair<TopoDS_Shape, int> > aNBs;//neighbor sub-shape -> level of neighborhood
- for(int aLevel = 1; true; aLevel++) {
- TopTools_MapOfShape aNewNB;
- findNeighbors(theContext, theValue, aLevel, aNewNB);
- if (aNewNB.Extent() == 0) { // there are no neighbors of the given level, stop iteration
- break;
- }
- // iterate by the order in theContext to keep same naming names
- TopExp_Explorer anOrder(theContext, theValue.ShapeType());
- for (; anOrder.More(); anOrder.Next()) {
- if (aNewNB.Contains(anOrder.Current())) {
- TopoDS_Shape aNewNBShape = anOrder.Current();
- // check which can be named correctly, without "by neighbors" type
- Selector_Selector aSelector(myLab.FindChild(1));
- if (!myBaseDocumentLab.IsNull())
- aSelector.setBaseDocument(myBaseDocumentLab);
- if (aSelector.select(theContext, aNewNBShape, theGeometricalNaming, false)) {
- // add to list of good NBs
- aNBs.push_back(std::pair<TopoDS_Shape, int>(aNewNBShape, aLevel));
- }
- }
- }
- TopoDS_Shape aResult = findNeighbor(theContext, aNBs, theGeometricalNaming);
- if (!aResult.IsNull() && aResult.IsSame(theValue)) {
- std::list<std::pair<TopoDS_Shape, int> >::iterator aNBIter = aNBs.begin();
- for(; aNBIter != aNBs.end(); aNBIter++) {
- if (!selectBySubSelector(theContext, aNBIter->first,
- theGeometricalNaming, theUseNeighbors, theUseIntersections)) {
- return false; // something is wrong because before this selection was ok
- }
- myNBLevel.push_back(aNBIter->second);
-
- }
- myType = SELTYPE_FILTER_BY_NEIGHBOR;
- return true;
- }
- }
- // filter by neighbors did not help
- if (aCommon.Extent() > 1) {
- if (myAlwaysGeometricalNaming) {
- TopoDS_ListOfShape::Iterator aCommonIter(aCommon);
- TopoDS_Shape aFirst = aCommonIter.Value();
- for(aCommonIter.Next(); aCommonIter.More(); aCommonIter.Next()) {
- if (!sameGeometry(aFirst, aCommonIter.Value()))
- break;
- }
- if (!aCommonIter.More()) { // all geometry is same, result is a compound
- myType = SELTYPE_FILTER_BY_NEIGHBOR;
- return true;
- }
- }
- // weak naming between the common results
- Selector_NExplode aNexp(aCommon);
- myWeakIndex = aNexp.index(theValue);
- if (myWeakIndex == -1)
- return false;
- }
- }
- }
- myType = SELTYPE_MODIFICATION;
- if (myBases.IsEmpty()) { // selection based on the external shape, weak name by finals compound
- TopoDS_ListOfShape aCommon;
- myFinal = aModifList.First()->Label();
- Handle(TNaming_NamedShape) aNS;
- if (myFinal.FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
- for(TNaming_Iterator aFinalIter(aNS); aFinalIter.More(); aFinalIter.Next()) {
- const TopoDS_Shape& aNewShape = aFinalIter.NewShape();
- if (!aNewShape.IsNull())
- aCommon.Append(aNewShape);
- }
- }
- Selector_NExplode aNexp(aCommon);
- myWeakIndex = aNexp.index(theValue);
- if (myWeakIndex == -1)
- return false;
- }
- return true;
- }
+ myAlgo = Selector_Algo::select(theContext, theValue, myLab, myBaseDocumentLab,
+ theGeometricalNaming, true, true);
- // not found a good result
- return false;
-}
-
-/// Stores the array of references to the label: references to elements of ref-list, then the last
-static void storeBaseArray(const TDF_Label& theLab,
- const TDF_LabelList& theRef, const TDF_Label& theLast)
-{
- Handle(TDataStd_ReferenceArray) anArray =
- TDataStd_ReferenceArray::Set(theLab, kBASE_ARRAY, 0, theRef.Extent());
- Handle(TDataStd_ExtStringList) anEntries; // entries of references to external document
- const TDF_Label aThisDocRoot = theLab.Root();
- TDF_LabelList::Iterator aBIter(theRef);
- for(int anIndex = 0; true; aBIter.Next(), anIndex++) {
- const TDF_Label& aLab = aBIter.More() ? aBIter.Value() : theLast;
- // check this is a label of this document
- if (aLab.Root().IsEqual(aThisDocRoot)) {
- anArray->SetValue(anIndex, aLab);
- } else { // store reference to external document as an entry-string
- if (anEntries.IsNull()) {
- anEntries = TDataStd_ExtStringList::Set(theLab, kBASE_LIST);
- }
- TCollection_AsciiString anEntry;
- TDF_Tool::Entry(aLab, anEntry);
- anEntries->Append(anEntry);
- anArray->SetValue(anIndex, aThisDocRoot); // stored root means it is external reference
- }
- if (!aBIter.More())
- break;
- }
-}
-
-void Selector_Selector::store()
-{
- static const TDF_LabelList anEmptyRefList;
- myLab.ForgetAllAttributes(true); // remove old naming data
- TDataStd_Integer::Set(myLab, kSEL_TYPE, (int)myType);
- if (myGeometricalNaming)
- TDataStd_UAttribute::Set(myLab, kGEOMETRICAL_NAMING);
- switch(myType) {
- case SELTYPE_CONTAINER:
- case SELTYPE_INTERSECT: {
- TDataStd_Integer::Set(myLab, kSHAPE_TYPE, (int)myShapeType);
- // store also all sub-selectors
- std::list<Selector_Selector>::iterator aSubSel = mySubSelList.begin();
- for(; aSubSel != mySubSelList.end(); aSubSel++) {
- aSubSel->store();
- }
- if (myWeakIndex != -1) {
- TDataStd_Integer::Set(myLab, kWEAK_INDEX, myWeakIndex);
- }
- break;
- }
- case SELTYPE_PRIMITIVE: {
- storeBaseArray(myLab, anEmptyRefList, myFinal);
- break;
- }
- case SELTYPE_MODIFICATION: {
- storeBaseArray(myLab, myBases, myFinal);
- if (myWeakIndex != -1) {
- TDataStd_Integer::Set(myLab, kWEAK_INDEX, myWeakIndex);
- }
- break;
- }
- case SELTYPE_FILTER_BY_NEIGHBOR: {
- TDataStd_Integer::Set(myLab, kSHAPE_TYPE, (int)myShapeType);
- // store numbers of levels corresponded to the neighbors in sub-selectors
- Handle(TDataStd_IntegerArray) anArray =
- TDataStd_IntegerArray::Set(myLab, kLEVELS_ARRAY, 0, int(myNBLevel.size()) - 1);
- std::list<int>::iterator aLevel = myNBLevel.begin();
- for(int anIndex = 0; aLevel != myNBLevel.end(); aLevel++, anIndex++) {
- anArray->SetValue(anIndex, *aLevel);
- }
- // store all sub-selectors
- std::list<Selector_Selector>::iterator aSubSel = mySubSelList.begin();
- for(; aSubSel != mySubSelList.end(); aSubSel++) {
- aSubSel->store();
- }
- break;
- }
- case SELTYPE_WEAK_NAMING: {
- TDataStd_Integer::Set(myLab, kWEAK_INDEX, myWeakIndex);
- TDataStd_Integer::Set(myLab, kSHAPE_TYPE, (int)myShapeType);
- if (!myFinal.IsNull()) {
- storeBaseArray(myLab, anEmptyRefList, myFinal);
- }
- break;
- }
- default: { // unknown case
- break;
- }
- }
+ return myAlgo != NULL;
}
-/// Restores references to the labels: references to elements of ref-list, then the last
-static bool restoreBaseArray(const TDF_Label& theLab, const TDF_Label& theBaseDocumetnLab,
- TDF_LabelList& theRef, TDF_Label& theLast)
+bool Selector_Selector::store(const TopoDS_Shape theContext)
{
- const TDF_Label aThisDocRoot = theLab.Root();
- Handle(TDataStd_ExtStringList) anEntries; // entries of references to external document
- TDataStd_ListOfExtendedString::Iterator anIter;
- Handle(TDataStd_ReferenceArray) anArray;
- if (theLab.FindAttribute(kBASE_ARRAY, anArray)) {
- int anUpper = anArray->Upper();
- for(int anIndex = anArray->Lower(); anIndex <= anUpper; anIndex++) {
- TDF_Label aLab = anArray->Value(anIndex);
- if (aLab.IsEqual(aThisDocRoot)) { // external document reference
- if (theBaseDocumetnLab.IsNull())
- return false;
- if (anEntries.IsNull()) {
- if (!theLab.FindAttribute(kBASE_LIST, anEntries))
- return false;
- anIter.Initialize(anEntries->List());
- }
- if (!anIter.More())
- return false;
- TDF_Tool::Label(theBaseDocumetnLab.Data(), anIter.Value(), aLab);
- anIter.Next();
- }
- if (anIndex == anUpper) {
- theLast = aLab;
- } else {
- theRef.Append(aLab);
- }
- }
- return true;
- }
- return false;
+ myAlgo->store();
+ return myAlgo->solve(theContext); // to update the selection shape on the label
}
-
-bool Selector_Selector::restore()
+bool Selector_Selector::restore(const TopoDS_Shape theContext)
{
- Handle(TDataStd_Integer) aTypeAttr;
- if (!myLab.FindAttribute(kSEL_TYPE, aTypeAttr))
- return false;
- myGeometricalNaming = myLab.IsAttribute(kGEOMETRICAL_NAMING);
- myType = Selector_Type(aTypeAttr->Get());
- switch(myType) {
- case SELTYPE_CONTAINER:
- case SELTYPE_INTERSECT: {
- Handle(TDataStd_Integer) aShapeTypeAttr;
- if (!myLab.FindAttribute(kSHAPE_TYPE, aShapeTypeAttr))
- return false;
- myShapeType = TopAbs_ShapeEnum(aShapeTypeAttr->Get());
- // restore sub-selectors
- bool aSubResult = true;
- mySubSelList.clear();
- for(TDF_ChildIDIterator aSub(myLab, kSEL_TYPE, false); aSub.More(); aSub.Next()) {
- mySubSelList.push_back(Selector_Selector(aSub.Value()->Label()));
- mySubSelList.back().setBaseDocument(myBaseDocumentLab);
- if (!mySubSelList.back().restore())
- aSubResult = false;
- }
- Handle(TDataStd_Integer) aWeakInt;
- if (myLab.FindAttribute(kWEAK_INDEX, aWeakInt)) {
- myWeakIndex = aWeakInt->Get();
- }
- return aSubResult;
- }
- case SELTYPE_PRIMITIVE: {
- return restoreBaseArray(myLab, myBaseDocumentLab, myBases, myFinal);
- }
- case SELTYPE_MODIFICATION: {
- if (restoreBaseArray(myLab, myBaseDocumentLab, myBases, myFinal)) {
- Handle(TDataStd_Integer) aWeakInt;
- if (myLab.FindAttribute(kWEAK_INDEX, aWeakInt)) {
- myWeakIndex = aWeakInt->Get();
- }
- return true;
- }
- return false;
- }
- case SELTYPE_FILTER_BY_NEIGHBOR: {
- Handle(TDataStd_Integer) aShapeTypeAttr;
- if (!myLab.FindAttribute(kSHAPE_TYPE, aShapeTypeAttr))
- return false;
- myShapeType = TopAbs_ShapeEnum(aShapeTypeAttr->Get());
- // restore sub-selectors
- bool aSubResult = true;
- mySubSelList.clear();
- for(TDF_ChildIDIterator aSub(myLab, kSEL_TYPE, false); aSub.More(); aSub.Next()) {
- mySubSelList.push_back(Selector_Selector(aSub.Value()->Label()));
- mySubSelList.back().setBaseDocument(myBaseDocumentLab);
- if (!mySubSelList.back().restore())
- aSubResult = false;
- }
- // restore levels indices
- Handle(TDataStd_IntegerArray) anArray;
- if (!myLab.FindAttribute(kLEVELS_ARRAY, anArray))
- return false;
- for(int anIndex = 0; anIndex <= anArray->Upper(); anIndex++) {
- myNBLevel.push_back(anArray->Value(anIndex));
- }
- return true;
- }
- case SELTYPE_WEAK_NAMING: {
- Handle(TDataStd_Integer) aWeakInt;
- if (!myLab.FindAttribute(kWEAK_INDEX, aWeakInt))
- return false;
- myWeakIndex = aWeakInt->Get();
- Handle(TDataStd_Integer) aShapeTypeAttr;
- if (!myLab.FindAttribute(kSHAPE_TYPE, aShapeTypeAttr))
- return false;
- myShapeType = TopAbs_ShapeEnum(aShapeTypeAttr->Get());
- if (!restoreBaseArray(myLab, myBaseDocumentLab, myBases, myFinal))
- return false;
+ if (myAlgo->restoreByLab(myLab)) {
+ myAlgo->solve(theContext); // to update the selection shape on the label
return true;
}
- default: { // unknown case
- }
- }
return false;
}
-/// Returns in theResults all shapes with history started in theBase and ended in theFinal
-static void findFinals(const TDF_Label& anAccess, const TopoDS_Shape& theBase,
- const TDF_Label& theFinal,
- const TDF_Label& theAdditionalDoc, TopTools_MapOfShape& theResults)
-{
- if (TNaming_Tool::HasLabel(anAccess, theBase)) {
- for(TNaming_NewShapeIterator aBaseIter(theBase, anAccess); aBaseIter.More(); aBaseIter.Next())
- {
- TNaming_Evolution anEvolution = aBaseIter.NamedShape()->Evolution();
- if (anEvolution == TNaming_GENERATED || anEvolution == TNaming_MODIFY) {
- if (aBaseIter.NamedShape()->Label().IsEqual(theFinal)) {
- theResults.Add(aBaseIter.Shape());
- } else {
- findFinals(anAccess, aBaseIter.Shape(), theFinal, theAdditionalDoc, theResults);
- }
- }
- }
- }
- if (!theAdditionalDoc.IsNull()) { // search additionally by the additional access label
- static TDF_Label anEmpty;
- findFinals(theAdditionalDoc, theBase, theFinal, anEmpty, theResults);
- }
-}
-
-void Selector_Selector::findModificationResult(TopoDS_ListOfShape& theCommon) {
- for(TDF_LabelList::Iterator aBase(myBases); aBase.More(); aBase.Next()) {
- TDF_Label anAdditionalDoc; // this document if base is started in extra document
- if (aBase.Value().Root() != myLab.Root()) {
- anAdditionalDoc = myLab;
- }
- TopTools_MapOfShape aFinals;
- for(TNaming_Iterator aBaseShape(aBase.Value()); aBaseShape.More(); aBaseShape.Next()) {
- findFinals(aBase.Value(), aBaseShape.NewShape(), myFinal, anAdditionalDoc, aFinals);
- }
- if (!aFinals.IsEmpty()) {
- if (theCommon.IsEmpty()) { // just copy all to common
- for(TopTools_MapOfShape::Iterator aFinal(aFinals); aFinal.More(); aFinal.Next()) {
- theCommon.Append(aFinal.Key());
- }
- } else { // keep only shapes presented in both lists
- for(TopoDS_ListOfShape::Iterator aCommon(theCommon); aCommon.More(); ) {
- if (aFinals.Contains(aCommon.Value())) {
- aCommon.Next();
- } else { // common is not found, remove it
- theCommon.Remove(aCommon);
- }
- }
- }
- }
- }
-}
-
-bool Selector_Selector::solve(const TopoDS_Shape& theContext)
-{
- TopoDS_Shape aResult; // null if invalid
- switch(myType) {
- case SELTYPE_CONTAINER: {
- TopoDS_Builder aBuilder;
- switch(myShapeType) {
- case TopAbs_COMPOUND: {
- TopoDS_Compound aComp;
- aBuilder.MakeCompound(aComp);
- aResult = aComp;
- break;
- }
- case TopAbs_COMPSOLID: {
- TopoDS_CompSolid aComp;
- aBuilder.MakeCompSolid(aComp);
- aResult = aComp;
- break;
- }
- case TopAbs_SHELL: {
- TopoDS_Shell aShell;
- aBuilder.MakeShell(aShell);
- aResult = aShell;
- break;
- }
- case TopAbs_WIRE: {
- TopoDS_Wire aWire;
- aBuilder.MakeWire(aWire);
- aResult = aWire;
- break;
- }
- }
- std::list<Selector_Selector>::iterator aSubSel = mySubSelList.begin();
- for(; aSubSel != mySubSelList.end(); aSubSel++) {
- if (!aSubSel->solve(theContext)) {
- return false;
- }
- aBuilder.Add(aResult, aSubSel->value());
- }
- break;
- }
- case SELTYPE_INTERSECT: {
- TopoDS_ListOfShape aSubSelectorShapes;
- std::list<Selector_Selector>::iterator aSubSel = mySubSelList.begin();
- for(; aSubSel != mySubSelList.end(); aSubSel++) {
- if (!aSubSel->solve(theContext)) {
- return false;
- }
- aSubSelectorShapes.Append(aSubSel->value());
- }
- TopoDS_ListOfShape aCommon; // common sub shapes in each sub-selector (a result)
- commonShapes(aSubSelectorShapes, myShapeType, aCommon);
- if (aCommon.Extent() != 1) {
- if (myWeakIndex != -1) {
- Selector_NExplode aNexp(aCommon);
- aResult = aNexp.shape(myWeakIndex);
- } else if (myGeometricalNaming && aCommon.Extent() > 1) {
- // check results are on the same geometry, create compound
- TopoDS_ListOfShape::Iterator aCommonIter(aCommon);
- TopoDS_Shape aFirst = aCommonIter.Value();
- for(aCommonIter.Next(); aCommonIter.More(); aCommonIter.Next()) {
- if (!sameGeometry(aFirst, aCommonIter.Value()))
- break;
- }
- if (!aCommonIter.More()) { // all geometry is same, create a result compound
- TopoDS_Builder aBuilder;
- TopoDS_Compound aCompound;
- aBuilder.MakeCompound(aCompound);
- for(aCommonIter.Initialize(aCommon); aCommonIter.More(); aCommonIter.Next()) {
- aBuilder.Add(aCompound, aCommonIter.Value());
- }
- aResult = aCompound;
- }
- } else {
- return false;
- }
- } else {
- aResult = aCommon.First();
- }
- break;
- }
- case SELTYPE_PRIMITIVE: {
- Handle(TNaming_NamedShape) aNS;
- if (myFinal.FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
- aResult = aNS->Get();
- }
- break;
- }
- case SELTYPE_MODIFICATION: {
- if (myBases.IsEmpty() && myWeakIndex > 0) { // weak name by the final shapes index
- TopoDS_ListOfShape aCommon;
- Handle(TNaming_NamedShape) aNS;
- if (myFinal.FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
- for(TNaming_Iterator aFinalIter(aNS); aFinalIter.More(); aFinalIter.Next()) {
- const TopoDS_Shape& aNewShape = aFinalIter.NewShape();
- if (!aNewShape.IsNull())
- aCommon.Append(aNewShape);
- }
- }
- Selector_NExplode aNexp(aCommon);
- aResult = aNexp.shape(myWeakIndex);
- } else { // standard case
- TopoDS_ListOfShape aFinalsCommon; // final shapes presented in all results from bases
- findModificationResult(aFinalsCommon);
- if (aFinalsCommon.Extent() == 1) { // result is valid: found only one shape
- aResult = aFinalsCommon.First();
- } else if (aFinalsCommon.Extent() > 1 && myWeakIndex > 0) {
- Selector_NExplode aNExp(aFinalsCommon);
- aResult = aNExp.shape(myWeakIndex);
- } else if (aFinalsCommon.Extent() > 1 && myGeometricalNaming) {// if same geometry - compound
- TopoDS_ListOfShape::Iterator aCommonIter(aFinalsCommon);
- TopoDS_Shape aFirst = aCommonIter.Value();
- for(aCommonIter.Next(); aCommonIter.More(); aCommonIter.Next()) {
- if (!sameGeometry(aFirst, aCommonIter.Value()))
- break;
- }
- if (!aCommonIter.More()) { // all geometry is same, create a result compound
- TopoDS_Builder aBuilder;
- TopoDS_Compound aCompound;
- aBuilder.MakeCompound(aCompound);
- for(aCommonIter.Initialize(aFinalsCommon); aCommonIter.More(); aCommonIter.Next()) {
- aBuilder.Add(aCompound, aCommonIter.Value());
- }
- aResult = aCompound;
- }
-
- }
- }
- break;
- }
- case SELTYPE_FILTER_BY_NEIGHBOR: {
- std::list<std::pair<TopoDS_Shape, int> > aNBs; /// neighbor sub-shape -> level of neighborhood
- std::list<int>::iterator aLevel = myNBLevel.begin();
- std::list<Selector_Selector>::iterator aSubSel = mySubSelList.begin();
- for(; aSubSel != mySubSelList.end(); aSubSel++, aLevel++) {
- if (!aSubSel->solve(theContext)) {
- return false;
- }
- aNBs.push_back(std::pair<TopoDS_Shape, int>(aSubSel->value(), *aLevel));
- }
- aResult = findNeighbor(theContext, aNBs, myGeometricalNaming);
- break;
- }
- case SELTYPE_WEAK_NAMING: {
- TopoDS_Shape aContext;
- if (myFinal.IsNull()) {
- aContext = theContext;
- } else {
- Handle(TNaming_NamedShape) aNS;
- if (myFinal.FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
- aContext = aNS->Get();
- }
- }
- if (!aContext.IsNull()) {
- Selector_NExplode aNexp(aContext, myShapeType);
- aResult = aNexp.shape(myWeakIndex);
- }
- }
- default: { // unknown case
- }
- }
-
- TNaming_Builder aBuilder(myLab);
- if (!aResult.IsNull()) {
- aBuilder.Select(aResult, aResult);
- return true;
- }
- return false; // builder just erases the named shape in case of error
-}
-
TopoDS_Shape Selector_Selector::value()
{
Handle(TNaming_NamedShape) aNS;
}
std::string Selector_Selector::name(Selector_NameGenerator* theNameGenerator) {
- switch(myType) {
- case SELTYPE_CONTAINER:
- case SELTYPE_INTERSECT: {
- std::string aResult;
- // add names of sub-components one by one in "[]" +optionally [weak_name_1]
- std::list<Selector_Selector>::iterator aSubSel = mySubSelList.begin();
- for(; aSubSel != mySubSelList.end(); aSubSel++) {
- aResult += '[';
- aResult += aSubSel->name(theNameGenerator);
- aResult += ']';
- TopoDS_Shape aSubVal = aSubSel->value();
- if (!aSubVal.IsNull()) {
- TopAbs_ShapeEnum aSubType = aSubVal.ShapeType();
- if (aSubType != TopAbs_FACE) { // in case the sub shape type must be stored
- switch(aSubType) {
- case TopAbs_COMPOUND: aResult += "c"; break;
- case TopAbs_COMPSOLID: aResult += "o"; break;
- case TopAbs_SOLID: aResult += "s"; break;
- case TopAbs_SHELL: aResult += "h"; break;
- case TopAbs_WIRE: aResult += "w"; break;
- case TopAbs_EDGE: aResult += "e"; break;
- case TopAbs_VERTEX: aResult += "v"; break;
- default:
- ;
- }
- }
- }
- }
- if (myWeakIndex != -1) {
- std::ostringstream aWeakStr;
- aWeakStr<<"["<<kWEAK_NAME_IDENTIFIER<<myWeakIndex<<"]";
- aResult += aWeakStr.str();
- }
- return aResult;
- }
- case SELTYPE_PRIMITIVE: {
- Handle(TDataStd_Name) aName;
- if (!myFinal.FindAttribute(TDataStd_Name::GetID(), aName))
- return "";
- return theNameGenerator->contextName(myFinal) + "/" +
- std::string(TCollection_AsciiString(aName->Get()).ToCString());
- }
- case SELTYPE_MODIFICATION: {
- // final&base1&base2 +optionally: [weak_name_1]
- std::string aResult;
- Handle(TDataStd_Name) aName;
- if (!myFinal.FindAttribute(TDataStd_Name::GetID(), aName))
- return "";
- aResult += theNameGenerator->contextName(myFinal) + "/" +
- std::string(TCollection_AsciiString(aName->Get()).ToCString());
- for(TDF_LabelList::iterator aBase = myBases.begin(); aBase != myBases.end(); aBase++) {
- if (!aBase->FindAttribute(TDataStd_Name::GetID(), aName))
- return "";
- aResult += "&";
- aResult += theNameGenerator->contextName(*aBase) + "/" +
- std::string(TCollection_AsciiString(aName->Get()).ToCString());
- }
- if (myWeakIndex != -1) {
- std::ostringstream aWeakStr;
- aWeakStr<<"&"<<kWEAK_NAME_IDENTIFIER<<myWeakIndex;
- aResult += aWeakStr.str();
- }
- return aResult;
- }
- case SELTYPE_FILTER_BY_NEIGHBOR: {
- // (nb1)level_if_more_than_1(nb2)level_if_more_than_1(nb3)level_if_more_than_1
- std::string aResult;
- std::list<int>::iterator aLevel = myNBLevel.begin();
- std::list<Selector_Selector>::iterator aSubSel = mySubSelList.begin();
- for(; aSubSel != mySubSelList.end(); aSubSel++, aLevel++) {
- aResult += "(" + aSubSel->name(theNameGenerator) + ")";
- if (*aLevel > 1) {
- std::ostringstream aLevelStr;
- aLevelStr<<*aLevel;
- aResult += aLevelStr.str();
- }
- }
- return aResult;
- }
- case SELTYPE_WEAK_NAMING: {
- // _weak_naming_1_Context
- std::ostringstream aWeakStr;
- aWeakStr<<kPUREWEAK_NAME_IDENTIFIER<<myWeakIndex;
- std::string aResult = aWeakStr.str();
- if (!myFinal.IsNull())
- aResult += "_" + theNameGenerator->contextName(myFinal);
- return aResult;
- }
- default: { // unknown case
- }
- };
- return "";
+ return myAlgo->name(theNameGenerator);
}
TDF_Label Selector_Selector::restoreByName(
std::string theName, const TopAbs_ShapeEnum theShapeType,
Selector_NameGenerator* theNameGenerator, const bool theGeometricalNaming)
{
- myGeometricalNaming = theGeometricalNaming;
- if (theName[0] == '[') { // intersection or container
- switch(theShapeType) {
- case TopAbs_COMPOUND:
- case TopAbs_COMPSOLID:
- case TopAbs_SHELL:
- case TopAbs_WIRE:
- myType = SELTYPE_CONTAINER;
- break;
- case TopAbs_VERTEX:
- case TopAbs_EDGE:
- case TopAbs_FACE:
- myType = SELTYPE_INTERSECT;
- break;
- default:
- return TDF_Label(); // unknown case
- }
- myShapeType = theShapeType;
- TDF_Label aContext;
- for(size_t aStart = 0; aStart != std::string::npos;
- aStart = theName.find('[', aStart + 1)) {
- size_t anEndPos = theName.find(']', aStart + 1);
- if (anEndPos != std::string::npos) {
- std::string aSubStr = theName.substr(aStart + 1, anEndPos - aStart - 1);
- if (aSubStr.find(kWEAK_NAME_IDENTIFIER) == 0) { // weak name identifier
- std::string aWeakIndex = aSubStr.substr(kWEAK_NAME_IDENTIFIER.size());
- myWeakIndex = atoi(aWeakIndex.c_str());
- continue;
- }
- TopAbs_ShapeEnum aSubShapeType = TopAbs_FACE;
- if (anEndPos != std::string::npos && anEndPos + 1 < theName.size()) {
- char aShapeChar = theName[anEndPos + 1];
- if (theName[anEndPos + 1] != '[') {
- switch(aShapeChar) {
- case 'c': aSubShapeType = TopAbs_COMPOUND; break;
- case 'o': aSubShapeType = TopAbs_COMPSOLID; break;
- case 's': aSubShapeType = TopAbs_SOLID; break;
- case 'h': aSubShapeType = TopAbs_SHELL; break;
- case 'w': aSubShapeType = TopAbs_WIRE; break;
- case 'e': aSubShapeType = TopAbs_EDGE; break;
- case 'v': aSubShapeType = TopAbs_VERTEX; break;
- default:;
- }
- }
- }
- mySubSelList.push_back(Selector_Selector(myLab.FindChild(int(mySubSelList.size()) + 1)));
- mySubSelList.back().setBaseDocument(myBaseDocumentLab);
- TDF_Label aSubContext = mySubSelList.back().restoreByName(
- aSubStr, aSubShapeType, theNameGenerator, theGeometricalNaming);
- if (aSubContext.IsNull())
- return aSubContext; // invalid sub-selection parsing
- if (!aContext.IsNull() && !aContext.IsEqual(aSubContext)) {
- if (!theNameGenerator->isLater(aContext, aSubContext))
- aContext = aSubContext;
- } else {
- aContext = aSubContext;
- }
- } else
- return TDF_Label(); // invalid parentheses
- }
- return aContext;
- } else if (theName[0] == '(') { // filter by neighbors
- myType = SELTYPE_FILTER_BY_NEIGHBOR;
- TDF_Label aContext;
- for(size_t aStart = 0; aStart != std::string::npos;
- aStart = theName.find('(', aStart + 1)) {
- size_t anEndPos = theName.find(')', aStart + 1);
- if (anEndPos != std::string::npos) {
- std::string aSubStr = theName.substr(aStart + 1, anEndPos - aStart - 1);
- mySubSelList.push_back(Selector_Selector(myLab.FindChild(int(mySubSelList.size()) + 1)));
- mySubSelList.back().setBaseDocument(myBaseDocumentLab);
- TDF_Label aSubContext = mySubSelList.back().restoreByName(
- aSubStr, theShapeType, theNameGenerator, theGeometricalNaming);
- if (aSubContext.IsNull())
- return aSubContext; // invalid sub-selection parsing
- if (!aContext.IsNull() && !aContext.IsEqual(aSubContext)) {
- if (!theNameGenerator->isLater(aContext, aSubContext))
- aContext = aSubContext;
- } else {
- aContext = aSubContext;
- }
- if (!aContext.IsNull()) // for filters by neighbor the latest context shape is vital
- aContext = theNameGenerator->newestContext(aContext);
-
- // searching for the level index
- std::string aLevel;
- for(anEndPos++; anEndPos != std::string::npos &&
- theName[anEndPos] != '(' && theName[anEndPos] != 0;
- anEndPos++) {
- aLevel += theName[anEndPos];
- }
- if (aLevel.empty())
- myNBLevel.push_back(1); // by default it is 1
- else {
- int aNum = atoi(aLevel.c_str());
- if (aNum > 0)
- myNBLevel.push_back(aNum);
- else
- return TDF_Label(); // invalid number
- }
- } else
- return TDF_Label(); // invalid parentheses
- }
- return aContext;
- } if (theName.find(kPUREWEAK_NAME_IDENTIFIER) == 0) { // weak naming identifier
- myType = SELTYPE_WEAK_NAMING;
- std::string aWeakIndex = theName.substr(kPUREWEAK_NAME_IDENTIFIER.size());
- std::size_t aContextPosition = aWeakIndex.find("_");
- myWeakIndex = atoi(aWeakIndex.c_str());
- myShapeType = theShapeType;
- TDF_Label aContext;
- if (aContextPosition != std::string::npos) { // context is also defined
- std::string aContextName = aWeakIndex.substr(aContextPosition + 1);
- theNameGenerator->restoreContext(aContextName, aContext, myFinal);
- }
- return aContext;
- } else if (theName.find('&') == std::string::npos) { // without '&' it can be only primitive
- myType = SELTYPE_PRIMITIVE;
- TDF_Label aContext;
- if (theNameGenerator->restoreContext(theName, aContext, myFinal)) {
- if (!myFinal.IsNull())
- return aContext;
- }
- } else { // modification
- myType = SELTYPE_MODIFICATION;
- TDF_Label aContext;
- for(size_t anEnd, aStart = 0; aStart != std::string::npos; aStart = anEnd) {
- if (aStart != 0)
- aStart++;
- anEnd = theName.find('&', aStart);
- std::string aSubStr =
- theName.substr(aStart, anEnd == std::string::npos ? anEnd : anEnd - aStart);
- if (aSubStr.find(kWEAK_NAME_IDENTIFIER) == 0) { // weak name identifier
- std::string aWeakIndex = aSubStr.substr(kWEAK_NAME_IDENTIFIER.size());
- myWeakIndex = atoi(aWeakIndex.c_str());
- continue;
- }
- TDF_Label aSubContext, aValue;
- if (!theNameGenerator->restoreContext(aSubStr, aSubContext, aValue))
- return TDF_Label(); // can not restore
- if(aSubContext.IsNull() || aValue.IsNull())
- return TDF_Label(); // can not restore
- if (myFinal.IsNull()) {
- myFinal = aValue;
- aContext = aSubContext;
- } else
- myBases.Append(aValue);
- }
- return aContext;
+ TDF_Label aResult;
+ myAlgo = Selector_Algo::restoreByName(
+ myLab, myBaseDocumentLab, theName, theShapeType, theNameGenerator, aResult);
+ if (myAlgo) {
+ return aResult;
}
return TDF_Label();
}
-bool Selector_Selector::selectBySubSelector(const TopoDS_Shape theContext,
- const TopoDS_Shape theValue, const bool theGeometricalNaming,
- const bool theUseNeighbors, const bool theUseIntersections)
-{
- mySubSelList.push_back(Selector_Selector(myLab.FindChild(int(mySubSelList.size()) + 1)));
- if (!myBaseDocumentLab.IsNull())
- mySubSelList.back().setBaseDocument(myBaseDocumentLab);
- if (!mySubSelList.back().select(theContext, theValue,
- theGeometricalNaming, theUseNeighbors, theUseIntersections)) {
- mySubSelList.clear(); // if one of the selector is failed, all become invalid
- return false;
- }
- return true;
-}
-
void Selector_Selector::combineGeometrical(const TopoDS_Shape theContext)
{
TopoDS_Shape aValue = value();
if (aValue.IsNull() || aValue.ShapeType() == TopAbs_COMPOUND)
return;
- myAlwaysGeometricalNaming = true;
- mySubSelList.clear();
- myBases.Clear();
- myWeakIndex = -1;
- if (select(theContext, aValue, true)) {
- store();
- solve(theContext);
- return;
- }
- // if can not select, select the compound in a custom way
- TopTools_MapOfShape aMap;
- TopoDS_ListOfShape aList;
- for(TopExp_Explorer anExp(theContext, aValue.ShapeType()); anExp.More(); anExp.Next()) {
- if (aMap.Add(anExp.Current())) {
- if (sameGeometry(aValue, anExp.Current()))
- aList.Append(anExp.Current());
- }
- }
- if (aList.Size() > 1) {
- TopoDS_Builder aBuilder;
- TopoDS_Compound aCompound;
- aBuilder.MakeCompound(aCompound);
- for(TopoDS_ListIteratorOfListOfShape aListIter(aList); aListIter.More(); aListIter.Next()) {
- aBuilder.Add(aCompound, aListIter.Value());
+
+ Selector_Algo* aNewAlgo = Selector_Algo::relesectWithAllGeometry(myAlgo, theContext);
+ if (aNewAlgo) {
+ aNewAlgo->store();
+ aNewAlgo->solve(theContext);
+ delete myAlgo;
+ myAlgo = aNewAlgo;
+ } else {
+ // if can not select, select the compound in a custom way
+ TopTools_MapOfShape aMap;
+ TopoDS_ListOfShape aList;
+ for(TopExp_Explorer anExp(theContext, aValue.ShapeType()); anExp.More(); anExp.Next()) {
+ if (aMap.Add(anExp.Current())) {
+ if (myAlgo->sameGeometry(aValue, anExp.Current()))
+ aList.Append(anExp.Current());
+ }
}
- if (select(theContext, aCompound, true)) {
- store();
- solve(theContext);
+ if (aList.Size() > 1) {
+ TopoDS_Builder aBuilder;
+ TopoDS_Compound aCompound;
+ aBuilder.MakeCompound(aCompound);
+ for(TopoDS_ListIteratorOfListOfShape aListIter(aList); aListIter.More(); aListIter.Next()) {
+ aBuilder.Add(aCompound, aListIter.Value());
+ }
+ Selector_Algo* aNewAlgo = Selector_Algo::relesectWithAllGeometry(myAlgo, theContext);
+ if (aNewAlgo) {
+ aNewAlgo->store();
+ aNewAlgo->solve(theContext);
+ delete myAlgo;
+ myAlgo = aNewAlgo;
+ }
}
}
}
+
+bool Selector_Selector::solve(const TopoDS_Shape theContext)
+{
+ return myAlgo->solve(theContext);
+}
#include "Selector.h"
#include <TDF_Label.hxx>
-#include <TDF_LabelList.hxx>
#include <TopoDS_Shape.hxx>
-#include <list>
class Selector_NameGenerator;
+class Selector_Algo;
/**\class Selector_Selector
* \ingroup DataModel
*/
class Selector_Selector
{
- /// Type of a selector: on this type depends what is stored in this label and how to
- /// restore it on update.
- enum Selector_Type {
- SELTYPE_CONTAINER, ///< just a container of sub-elements, keeps the shape type of container
- SELTYPE_INTERSECT, ///< sub-shape is intersection of higher level objects
- SELTYPE_PRIMITIVE, ///< sub-shape found as a primitive on some label
- SELTYPE_MODIFICATION, ///< modification of base shapes to the final label
- SELTYPE_FILTER_BY_NEIGHBOR, ///< identification by neighbor shapes in context
- SELTYPE_WEAK_NAMING, ///< pure weak naming by weak index in context
- };
-
- Selector_Type myType; ///< Type of this selector.
- TopAbs_ShapeEnum myShapeType; ///< type of this shape: in container, intersection or neighbors
- std::list<Selector_Selector> mySubSelList; ///< list of sub-selectors if needed
- TDF_Label myFinal; ///< final label of the primitive or generation, where the value is
- TDF_LabelList myBases; ///< initial labels that contain shapes that produce the modification
- int myWeakIndex; ///< index of the shape among commons for the modification type (-1 - not set)
-
- std::list<int> myNBLevel; ///< list of integers corresponding to mySubSelList neighborhood level
-
TDF_Label myLab; ///< main label where selector is performed
-
TDF_Label myBaseDocumentLab; ///< an access-label to the document that may contain initial shapes
-
- bool myGeometricalNaming; ///< flag that indicates that geometrical naming selection is enabled
- bool myAlwaysGeometricalNaming; /// to enable geometrical naming from beginning, at select
+ Selector_Algo* myAlgo; ///< root algorithm of the selector
public:
/// Initializes selector on the label
- SELECTOR_EXPORT Selector_Selector(TDF_Label theLab);
- /// Returns label of this selector
- SELECTOR_EXPORT TDF_Label label();
+ SELECTOR_EXPORT Selector_Selector(TDF_Label theLab, TDF_Label theBaseDocLab = TDF_Label());
- /// Sets the base document access label.
- SELECTOR_EXPORT void setBaseDocument(const TDF_Label theAccess);
+ /// Destructor
+ SELECTOR_EXPORT ~Selector_Selector();
/// Initializes the selector structure on the label.
/// Stores the name data to restore after modification.
/// \param theUseNeighbors enables searching algorithm by neighbors
/// \param theUseIntersections enables searching algorithm by intersection of higher level shapes
SELECTOR_EXPORT bool select(const TopoDS_Shape theContext, const TopoDS_Shape theValue,
- const bool theGeometricalNaming = false,
- const bool theUseNeighbors = true, const bool theUseIntersections = true);
+ const bool theGeometricalNaming = false);
/// Stores the name to the label and sub-labels tree
- SELECTOR_EXPORT void store();
+ SELECTOR_EXPORT bool store(const TopoDS_Shape theContext);
/// Restores the selected shape by the topological naming kept in the data structure
/// Returns true if it can restore structure correctly
- SELECTOR_EXPORT bool restore();
+ SELECTOR_EXPORT bool restore(const TopoDS_Shape theContext);
/// Restores the selected shape by the topological name string.
/// Returns not empty label of the context.
std::string theName, const TopAbs_ShapeEnum theShapeType,
Selector_NameGenerator* theNameGenerator, const bool theGeometricalNaming = false);
- /// Updates the current shape by the stored topological name
- SELECTOR_EXPORT bool solve(const TopoDS_Shape& theContext);
-
/// Returns the current sub-shape value (null if can not resolve)
SELECTOR_EXPORT TopoDS_Shape value();
/// Makes the current local selection becomes all sub-shapes with same base geometry.
SELECTOR_EXPORT void combineGeometrical(const TopoDS_Shape theContext);
-private:
-
- /// Create and keep in the list the sub-selector that select the given value.
- /// Returns true if selection is correct.
- bool selectBySubSelector(const TopoDS_Shape theContext, const TopoDS_Shape theValue,
- const bool theGeometricalNaming = false, const bool theUseNeighbors = true,
- const bool theUseIntersections = true);
- /// Searches the final shapes presented in all results from bases basing on modification fields
- void findModificationResult(TopoDS_ListOfShape& theCommon);
+ /// Stores the selected shape in he tree and returns true if shape found correctly
+ SELECTOR_EXPORT bool solve(const TopoDS_Shape theContext);
};
#endif
--- /dev/null
+// Copyright (C) 2014-2017 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
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// 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
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#include <Selector_WeakName.h>
+
+#include <Selector_NameGenerator.h>
+#include <Selector_NExplode.h>
+
+#include <TNaming_Tool.hxx>
+#include <TNaming_SameShapeIterator.hxx>
+#include <TNaming_Iterator.hxx>
+#include <TDataStd_Integer.hxx>
+
+Selector_WeakName::Selector_WeakName() : Selector_Algo()
+{
+}
+
+bool Selector_WeakName::select(const TopoDS_Shape theContext, const TopoDS_Shape theValue)
+{
+ myShapeType = theValue.ShapeType();
+ Selector_NExplode aNexp(theContext, myShapeType);
+ myWeakIndex = aNexp.index(theValue);
+ if (myWeakIndex != -1) {
+ // searching for context shape label to store in myFinal
+ if (TNaming_Tool::HasLabel(label(), theContext)) {
+ for(TNaming_SameShapeIterator aShapes(theContext, label()); aShapes.More(); aShapes.Next())
+ {
+ Handle(TNaming_NamedShape) aNS;
+ if (aShapes.Label().FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
+ TNaming_Evolution anEvolution = aNS->Evolution();
+ if (anEvolution == TNaming_PRIMITIVE || anEvolution == TNaming_GENERATED ||
+ anEvolution == TNaming_MODIFY) {
+ // check this is a new shape
+ for(TNaming_Iterator aNSIter(aNS); aNSIter.More(); aNSIter.Next()) {
+ if (aNSIter.NewShape().IsSame(theContext)) {
+ myContext = aNS->Label();
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+void Selector_WeakName::store()
+{
+ static const TDF_LabelList anEmptyRefList;
+ storeType(Selector_Algo::SELTYPE_WEAK_NAMING);
+ storeBaseArray(anEmptyRefList, myContext);
+ TDataStd_Integer::Set(label(), weakID(), myWeakIndex);
+ TDataStd_Integer::Set(label(), shapeTypeID(), (int)myShapeType);
+}
+
+bool Selector_WeakName::restore()
+{
+ Handle(TDataStd_Integer) aWeakInt;
+ if (!label().FindAttribute(weakID(), aWeakInt))
+ return false;
+ myWeakIndex = aWeakInt->Get();
+ Handle(TDataStd_Integer) aShapeTypeAttr;
+ if (!label().FindAttribute(shapeTypeID(), aShapeTypeAttr))
+ return false;
+ myShapeType = TopAbs_ShapeEnum(aShapeTypeAttr->Get());
+ static TDF_LabelList anEmptyRefList;
+ return restoreBaseArray(anEmptyRefList, myContext);
+}
+
+TDF_Label Selector_WeakName::restoreByName(std::string theName,
+ const TopAbs_ShapeEnum theShapeType, Selector_NameGenerator* theNameGenerator)
+{
+ std::string aWeakIndex = theName.substr(pureWeakNameID().size());
+ std::size_t aContextPosition = aWeakIndex.find("_");
+ myWeakIndex = atoi(aWeakIndex.c_str());
+ myShapeType = theShapeType;
+ TDF_Label aContext;
+ if (aContextPosition != std::string::npos) { // context is also defined
+ std::string aContextName = aWeakIndex.substr(aContextPosition + 1);
+ if (theNameGenerator->restoreContext(aContextName, aContext, myContext)) {
+ if (myContext.IsNull())
+ aContext.Nullify();
+ }
+ }
+ return aContext;
+}
+
+bool Selector_WeakName::solve(const TopoDS_Shape& theContext)
+{
+
+ TopoDS_Shape aContext;
+ if (myContext.IsNull()) {
+ aContext = theContext;
+ } else {
+ Handle(TNaming_NamedShape) aNS;
+ if (myContext.FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
+ aContext = aNS->Get();
+ }
+ }
+ if (!aContext.IsNull()) {
+ Selector_NExplode aNexp(aContext, myShapeType);
+ TopoDS_Shape aResult = aNexp.shape(myWeakIndex);
+ if (!aResult.IsNull()) {
+ Selector_Algo::store(aResult);
+ return true;
+ }
+ }
+ return false;
+}
+
+std::string Selector_WeakName::name(Selector_NameGenerator* theNameGenerator)
+{
+ // _weak_naming_1_Context
+ std::ostringstream aWeakStr;
+ aWeakStr<<pureWeakNameID()<<myWeakIndex;
+ std::string aResult = aWeakStr.str();
+ if (!myContext.IsNull())
+ aResult += "_" + theNameGenerator->contextName(myContext);
+ return aResult;
+}
--- /dev/null
+// Copyright (C) 2014-2017 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
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// 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
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef Selector_WeakName_H_
+#define Selector_WeakName_H_
+
+#include "Selector_Algo.h"
+
+/**\class Selector_WeakName
+ * \ingroup DataModel
+ * \brief Kind of selection algorithm: if other algorithms fail, this stores the geometrical
+ * index of the selected shape. Pure weak naming approach.
+ */
+class Selector_WeakName: public Selector_Algo
+{
+ TopAbs_ShapeEnum myShapeType; ///< type of this shape
+ int myWeakIndex; ///< weak index in case modification produces several shapes
+ TDF_Label myContext; ///< context shape label
+public:
+ /// Initializes the selection of this kind
+ SELECTOR_EXPORT bool select(const TopoDS_Shape theContext, const TopoDS_Shape theValue);
+
+ /// Stores the name to the label and sub-labels tree
+ SELECTOR_EXPORT virtual void store() override;
+
+ /// Restores the selected shape by the topological naming kept in the data structure
+ /// Returns true if it can restore structure correctly
+ SELECTOR_EXPORT virtual bool restore() override;
+
+ /// Restores the selected shape by the topological name string.
+ /// Returns not empty label of the context.
+ SELECTOR_EXPORT virtual TDF_Label restoreByName(std::string theName,
+ const TopAbs_ShapeEnum theShapeType, Selector_NameGenerator* theNameGenerator) override;
+
+ /// Updates the current shape by the stored topological name
+ SELECTOR_EXPORT virtual bool solve(const TopoDS_Shape& theContext) override;
+
+ /// Returns the naming name of the selection
+ SELECTOR_EXPORT virtual std::string name(Selector_NameGenerator* theNameGenerator) override;
+private:
+ /// Initializes selector
+ Selector_WeakName();
+
+ friend class Selector_Algo;
+};
+
+#endif
}
void SketchPlugin_Point::attributeChanged(const std::string& theID) {
- // the second condition for unability to move external point anywhere
+ // the second condition for inability to move external point anywhere
if (theID == EXTERNAL_ID() || isFixed()) {
std::shared_ptr<GeomAPI_Shape> aSelection = data()->selection(EXTERNAL_ID())->value();
if (!aSelection) {