#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>
-/// type of the selection, integerm keeps the Selector_Type value
+/// 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(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;
- 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 (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 (!aResIter.More()) // not found, so add this new
- theResult.Append(aResult);
- }
- 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);
+ 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)
}
}
+/// 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 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)) {
+ if (!selectBySubSelector(theContext, aSubIter.Value(),
+ false, theUseNeighbors, theUseIntersections)) {//for subs no geometrical naming allowed
return false; // if some selector is failed, everything is failed
}
}
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(aSelectionType != TopAbs_FACE || !aFacesTried) {
+ while(theUseIntersections && (aSelectionType != TopAbs_FACE || !aFacesTried)) {
if (aSelectionType == TopAbs_FACE) {
if (theValue.ShapeType() != TopAbs_VERTEX)
break;
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())))
+ if (aSelectionType == TopAbs_EDGE &&
+ BRep_Tool::Degenerated(TopoDS::Edge(aSelExp.Current())))
continue;
TopExp_Explorer aSubExp(aSelExp.Current(), theValue.ShapeType());
for(; aSubExp.More(); aSubExp.Next()) {
mySubSelList.clear();
TopoDS_ListOfShape::Iterator anInt(anIntList);
for (; anInt.More(); anInt.Next()) {
- if (!selectBySubSelector(theContext, anInt.Value(), theUseNeighbors)) {
+ if (!selectBySubSelector(theContext, anInt.Value(),
+ theGeometricalNaming, theUseNeighbors, false)) {
break; // if some selector is failed, stop and search another solution
}
}
if (!theUseNeighbors)
return false;
- // searching by neighbours
+ // 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;
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 the 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)) {
+ 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)) {
+ if (!selectBySubSelector(theContext, anInt.Value(),
+ theGeometricalNaming, theUseNeighbors, theUseIntersections)) {
break; // if some selector is failed, stop and search another solution
}
}
}
}
- // pure weak naming
- 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;
+ // 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 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(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 neighbours
+ // 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 neighbours
+ // 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;
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)) {
+ if (!selectBySubSelector(theContext, aNBIter->first,
+ theGeometricalNaming, theUseNeighbors, theUseIntersections)) {
return false; // something is wrong because before this selection was ok
}
myNBLevel.push_back(aNBIter->second);
return true;
}
}
- // filter by neighbours did not help
- if (aCommon.Extent() > 1) { // weak naming between the common results
+ // 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)
TopoDS_ListOfShape aCommon;
myFinal = aModifList.First()->Label();
Handle(TNaming_NamedShape) aNS;
- 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);
+ 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 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;
- 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);
+ 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) // 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:
aResult += '[';
aResult += aSubSel->name(theNameGenerator);
aResult += ']';
- TopAbs_ShapeEnum aSubType = aSubSel->value().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:
- ;
+ 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:
+ ;
+ }
}
}
}
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:
continue;
}
TopAbs_ShapeEnum aSubShapeType = TopAbs_FACE;
- if (anEndPos != std::string::npos && anEndPos + 1 > theName.size()) {
+ if (anEndPos != std::string::npos && anEndPos + 1 < theName.size()) {
char aShapeChar = theName[anEndPos + 1];
if (theName[anEndPos + 1] != '[') {
switch(aShapeChar) {
}
}
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)) {
return TDF_Label(); // invalid parentheses
}
return aContext;
- } else if (theName[0] == '(') { // filter by neighbours
+ } else if (theName[0] == '(') { // filter by neighbors
myType = SELTYPE_FILTER_BY_NEIGHBOR;
TDF_Label aContext;
for(size_t aStart = 0; aStart != std::string::npos;
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)) {
} else {
aContext = aSubContext;
}
- if (!aContext.IsNull()) // for filters by neighbour the latest context shape is vital
+ if (!aContext.IsNull()) // for filters by neighbor the latest context shape is vital
aContext = theNameGenerator->newestContext(aContext);
// searching for the level index
theNameGenerator->restoreContext(aContextName, aContext, myFinal);
}
return aContext;
- } else if (theName.find('&') == std::string::npos) { // wihtout '&' it can be only primitive
+ } 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)) {
return TDF_Label();
}
-bool Selector_Selector::selectBySubSelector(
- const TopoDS_Shape theContext, const TopoDS_Shape theValue, const bool theUseNeighbors)
+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)) {
+ 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);
+ }
+ }
+}