#include <Selector_NameGenerator.h>
#include <Selector_NExplode.h>
-#include <TDF_ChildIDIterator.hxx>
#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 <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>
// 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(Handle(TNaming_NamedShape) theFinal, const TopoDS_Shape& theValue,
- bool aMustBeAtFinal, TDF_LabelList& theResult)
+static void findBases(TDF_Label theAccess, Handle(TNaming_NamedShape) theFinal,
+ const TopoDS_Shape& theValue,
+ bool aMustBeAtFinal, const TDF_Label& theAdditionalDocument, TDF_LabelList& theResult)
{
- TNaming_SameShapeIterator aLabIter(theValue, theFinal->Label());
+ 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 (!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(theFinal, aThisIter.OldShape(), false, theResult);
+ 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)
}
}
+/// 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;
+}
+
/// 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 std::list<std::pair<TopoDS_Shape, int> >& theNB, const bool theGeometrical)
{
// searching for neighbors with minimum level
int aMinLevel = 0;
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;
for(TopoDS_ListOfShape::Iterator aCandidate(aMatches); aCandidate.More(); aCandidate.Next()) {
if (!aFooundHigherLevel && aLevelNBs.IsEmpty()) { // iterated all, so, good candidate
if (aGoodCandidate.IsNull()) {
aGoodCandidate = aCandidate.Value();
- } else { // too many good candidates
- return TopoDS_Shape();
+ } else { // another good candidate
+ if (theGeometrical && sameGeometry(aGoodCandidate, aCandidate.Value())) {
+ 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()) {
break;
}
}
+ if (!aResultCompound.IsNull())
+ return aResultCompound;
return aGoodCandidate;
}
bool Selector_Selector::select(const TopoDS_Shape theContext, const TopoDS_Shape theValue,
- const bool theUseNeighbors, const bool theUseIntersections)
+ const bool theGeometricalNaming, const bool theUseNeighbors, const bool theUseIntersections)
{
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);
}
}
}
+ // 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;
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(), theUseNeighbors, theUseIntersections)) {
+ if (!selectBySubSelector(theContext, aSubIter.Value(),
+ false, theUseNeighbors, theUseIntersections)) {//for subs no geometrical naming allowed
return false; // if some selector is failed, everything is failed
}
}
mySubSelList.clear();
TopoDS_ListOfShape::Iterator anInt(anIntList);
for (; anInt.More(); anInt.Next()) {
- if (!selectBySubSelector(theContext, anInt.Value(), theUseNeighbors, false)) {
+ if (!selectBySubSelector(theContext, anInt.Value(),
+ theGeometricalNaming, theUseNeighbors, false)) {
break; // if some selector is failed, stop and search another solution
}
}
TopoDS_Shape aNewNBShape = anOrder.Current();
// check which can be named correctly, without "by neighbors" type
Selector_Selector aSelector(myLab.FindChild(1));
- if (aSelector.select(theContext, aNewNBShape, false, false)) { // add to list of good NBs
+ 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);
+ 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, false, false)) {
+ if (!selectBySubSelector(theContext, aNBIter->first,
+ theGeometricalNaming, false, false)) {
return false; // something is wrong because before this selection was ok
}
myNBLevel.push_back(aNBIter->second);
}
}
- // weak naming to distinguish commons coming from intersection
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) {
mySubSelList.clear();
TopoDS_ListOfShape::Iterator anInt(aLastIntersectors);
for (; anInt.More(); anInt.Next()) {
- if (!selectBySubSelector(
- theContext, anInt.Value(), theUseNeighbors, theUseIntersections)) {
+ if (!selectBySubSelector(theContext, anInt.Value(),
+ theGeometricalNaming, theUseNeighbors, theUseIntersections)) {
break; // if some selector is failed, stop and search another solution
}
}
// searching for the base shapes of the value
Handle(TNaming_NamedShape) aPrimitiveNS;
NCollection_List<Handle(TNaming_NamedShape)> aModifList;
- for(TNaming_SameShapeIterator aShapes(theValue, 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) { // 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);
+ 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 (!aModifList.IsEmpty()) {
// searching for all the base shapes of this modification
- findBases(aModifList.First(), theValue, true, myBases);
+ 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;
TopoDS_Shape aNewNBShape = anOrder.Current();
// check which can be named correctly, without "by neighbors" type
Selector_Selector aSelector(myLab.FindChild(1));
- if (aSelector.select(theContext, aNewNBShape, false)) {// add to list of good NBs
+ 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);
+ 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, theUseNeighbors, theUseIntersections)) {
+ if (!selectBySubSelector(theContext, aNBIter->first,
+ theGeometricalNaming, theUseNeighbors, theUseIntersections)) {
return false; // something is wrong because before this selection was ok
}
myNBLevel.push_back(aNBIter->second);
}
}
// filter by neighbors did not help
- if (aCommon.Extent() > 1) { // weak naming between the common results
+ 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;
}
+/// 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: {
break;
}
case SELTYPE_PRIMITIVE: {
- Handle(TDataStd_ReferenceArray) anArray =
- TDataStd_ReferenceArray::Set(myLab, kBASE_ARRAY, 0, 0);
- anArray->SetValue(0, myFinal);
+ storeBaseArray(myLab, anEmptyRefList, myFinal);
break;
}
case SELTYPE_MODIFICATION: {
- Handle(TDataStd_ReferenceArray) anArray =
- TDataStd_ReferenceArray::Set(myLab, kBASE_ARRAY, 0, myBases.Extent());
- TDF_LabelList::Iterator aBIter(myBases);
- for(int anIndex = 0; aBIter.More(); aBIter.Next(), anIndex++) {
- anArray->SetValue(anIndex, aBIter.Value());
- }
- anArray->SetValue(myBases.Extent(), myFinal); // final is in the end of array
+ storeBaseArray(myLab, myBases, myFinal);
if (myWeakIndex != -1) {
TDataStd_Integer::Set(myLab, kWEAK_INDEX, myWeakIndex);
}
case SELTYPE_WEAK_NAMING: {
TDataStd_Integer::Set(myLab, kWEAK_INDEX, myWeakIndex);
TDataStd_Integer::Set(myLab, kSHAPE_TYPE, (int)myShapeType);
- // store myFinal in the base array
if (!myFinal.IsNull()) {
- Handle(TDataStd_ReferenceArray) anArray =
- TDataStd_ReferenceArray::Set(myLab, kBASE_ARRAY, 0, 0);
- anArray->SetValue(0, myFinal);
+ storeBaseArray(myLab, anEmptyRefList, myFinal);
}
break;
}
}
}
+/// 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)
+{
+ 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;
+}
+
+
bool Selector_Selector::restore()
{
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:
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;
}
return aSubResult;
}
case SELTYPE_PRIMITIVE: {
- Handle(TDataStd_ReferenceArray) anArray;
- if (myLab.FindAttribute(kBASE_ARRAY, anArray)) {
- myFinal = anArray->Value(0);
- return true;
- }
- return false;
+ return restoreBaseArray(myLab, myBaseDocumentLab, myBases, myFinal);
}
case SELTYPE_MODIFICATION: {
- Handle(TDataStd_ReferenceArray) anArray;
- if (myLab.FindAttribute(kBASE_ARRAY, anArray)) {
- int anUpper = anArray->Upper();
- for(int anIndex = 0; anIndex < anUpper; anIndex++) {
- myBases.Append(anArray->Value(anIndex));
- }
- myFinal = anArray->Value(anUpper);
+ if (restoreBaseArray(myLab, myBaseDocumentLab, myBases, myFinal)) {
Handle(TDataStd_Integer) aWeakInt;
if (myLab.FindAttribute(kWEAK_INDEX, aWeakInt)) {
myWeakIndex = aWeakInt->Get();
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;
}
if (!myLab.FindAttribute(kSHAPE_TYPE, aShapeTypeAttr))
return false;
myShapeType = TopAbs_ShapeEnum(aShapeTypeAttr->Get());
- Handle(TDataStd_ReferenceArray) anArray;
- if (myLab.FindAttribute(kBASE_ARRAY, anArray)) {
- myFinal = anArray->Value(0);
- }
+ if (!restoreBaseArray(myLab, myBaseDocumentLab, myBases, myFinal))
+ return false;
return true;
}
default: { // unknown case
}
/// Returns in theResults all shapes with history started in theBase and ended in theFinal
-static void findFinals(const TopoDS_Shape& theBase, const TDF_Label& theFinal,
- TopTools_MapOfShape& theResults)
+static void findFinals(const TDF_Label& anAccess, const TopoDS_Shape& theBase,
+ const TDF_Label& theFinal,
+ const TDF_Label& theAdditionalDoc, TopTools_MapOfShape& theResults)
{
- for(TNaming_NewShapeIterator aBaseIter(theBase, theFinal); 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(aBaseIter.Shape(), theFinal, 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(aBaseShape.NewShape(), myFinal, 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()) {
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;
}
break;
}
case SELTYPE_MODIFICATION: {
- if (myBases.IsEmpty() && myWeakIndex) { // weak name by the final shapes index
+ 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)) {
} else { // standard case
TopoDS_ListOfShape aFinalsCommon; // final shapes presented in all results from bases
findModificationResult(aFinalsCommon);
- if (aFinalsCommon.Extent() == 1) // only in this case result is valid: found only one shape
+ if (aFinalsCommon.Extent() == 1) { // result is valid: found only one shape
aResult = aFinalsCommon.First();
- else if (aFinalsCommon.Extent() > 1 && myWeakIndex) {
+ } 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;
}
aNBs.push_back(std::pair<TopoDS_Shape, int>(aSubSel->value(), *aLevel));
}
- aResult = findNeighbor(theContext, aNBs);
+ aResult = findNeighbor(theContext, aNBs, myGeometricalNaming);
break;
}
case SELTYPE_WEAK_NAMING: {
return TopoDS_Shape(); // empty, error shape
}
-static const std::string kWEAK_NAME_IDENTIFIER = "weak_name_";
-static const std::string kPUREWEAK_NAME_IDENTIFIER = "_weak_name_";
-
std::string Selector_Selector::name(Selector_NameGenerator* theNameGenerator) {
switch(myType) {
case SELTYPE_CONTAINER:
TDF_Label Selector_Selector::restoreByName(
std::string theName, const TopAbs_ShapeEnum theShapeType,
- Selector_NameGenerator* theNameGenerator)
+ Selector_NameGenerator* theNameGenerator, const bool theGeometricalNaming)
{
+ myGeometricalNaming = theGeometricalNaming;
if (theName[0] == '[') { // intersection or container
switch(theShapeType) {
case TopAbs_COMPOUND:
}
}
mySubSelList.push_back(Selector_Selector(myLab.FindChild(int(mySubSelList.size()) + 1)));
- TDF_Label aSubContext =
- mySubSelList.back().restoreByName(aSubStr, aSubShapeType, theNameGenerator);
+ 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 (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)));
- TDF_Label aSubContext =
- mySubSelList.back().restoreByName(aSubStr, theShapeType, theNameGenerator);
+ 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)) {
return TDF_Label();
}
-bool Selector_Selector::selectBySubSelector(
- const TopoDS_Shape theContext, const TopoDS_Shape theValue,
+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 (!mySubSelList.back().select(theContext, theValue, theUseNeighbors, theUseIntersections)) {
+ 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());
+ }
+ if (select(theContext, aCompound, true)) {
+ store();
+ solve(theContext);
+ }
+ }
+}