aShapeTypeToExplode == GeomAPI_Shape::COMPOUND) {
theResultBody->loadGeneratedShapes(theMakeShape, theBaseShape, GeomAPI_Shape::EDGE);
}
- // issue #2197: make naming of edges generated from vertices
- if (aShapeTypeToExplode == GeomAPI_Shape::EDGE) {
- GeomAPI_DataMapOfShapeShape aFacesFromFromEdges;
- GeomAPI_ShapeExplorer anEdgeExp(theBaseShape, GeomAPI_Shape::EDGE);
- for(; anEdgeExp.more(); anEdgeExp.next()) {
- ListOfShape aGenerated;
- theMakeShape->generated(anEdgeExp.current(), aGenerated);
- ListOfShape::iterator aGenIter = aGenerated.begin();
- for(; aGenIter != aGenerated.end(); aGenIter++) {
- GeomShapePtr aGen = *aGenIter;
- if (aGen.get() && !aGen->isNull()) {
- if ((*aGenIter)->shapeType() == GeomAPI_Shape::FACE) { // normal case
- aFacesFromFromEdges.bind(aGen, anEdgeExp.current());
- }
- }
- }
- }
-
- // closed revolution of 1-3 faces can not distinguish lateral and base edges
- if (aFacesFromFromEdges.size() <= 3) {
- bool isClosed = false; // lateral edges are closed (in full revolution)
- GeomAPI_DataMapOfShapeShape anEdgesFromVertices;
- GeomAPI_ShapeExplorer aVertExp(theBaseShape, GeomAPI_Shape::VERTEX);
- for(; aVertExp.more(); aVertExp.next()) {
- ListOfShape aGenerated;
- theMakeShape->generated(aVertExp.current(), aGenerated);
- ListOfShape::iterator aGenIter = aGenerated.begin();
- for(; aGenIter != aGenerated.end(); aGenIter++) {
- std::shared_ptr<GeomAPI_Shape> aGenerated = *aGenIter;
- if (anEdgesFromVertices.isBound(aGenerated)) // already here
- continue;
- std::ostringstream aStream;
- aStream << "Lateral_" << aLateralIndex++;
- theResultBody->generated(aGenerated, aStream.str());
-
- anEdgesFromVertices.bind(aGenerated, aVertExp.current());
- std::shared_ptr<GeomAPI_Edge> anEdge(new GeomAPI_Edge(aGenerated));
- isClosed = isClosed || anEdge->isClosed();
- }
- }
- if (isClosed) {
- GeomAPI_ShapeExplorer anEdgesExp(theMakeShape->shape(), GeomAPI_Shape::EDGE);
- for(; anEdgesExp.more(); anEdgesExp.next()) {
- if (!anEdgesFromVertices.isBound(anEdgesExp.current())) {
- // found a base edge
- std::ostringstream aStream;
- aStream << "Base_Edge_" << aBaseEdgeIndex++;
- theResultBody->generated(anEdgesExp.current(), aStream.str());
- // only one orientation is needed
- anEdgesFromVertices.bind(anEdgesExp.current(), anEdgesExp.current());
- }
- }
- } else if (aFacesFromFromEdges.size() == 1) { // 2233: sphere created by the revolution:
- // vertices at degenerated edges will have the same name
- GeomAPI_DataMapOfShapeShape aVertices;
- GeomAPI_ShapeExplorer aVertExp(theMakeShape->shape(), GeomAPI_Shape::VERTEX);
- for(int anIndex = 1; aVertExp.more(); aVertExp.next()) {
- if (!aVertices.isBound(aVertExp.current())) {
- // found a base edge
- std::ostringstream aStream;
- aStream << "Vertex_" << aVertexIndex++;
- theResultBody->generated(aVertExp.current(), aStream.str());
- // only one orientation is needed
- aVertices.bind(aVertExp.current(), aVertExp.current());
- }
- }
- }
- } else { // issue #2197, test case 4 : edges that produce fully-revolved face,
- // but contain only 2 edges (on apex of revolution)
- GeomAPI_ShapeExplorer anEdgeExp(theBaseShape, GeomAPI_Shape::EDGE);
- for(; anEdgeExp.more(); anEdgeExp.next()) {
- ListOfShape aGenerated;
- theMakeShape->generated(anEdgeExp.current(), aGenerated);
- ListOfShape::iterator aGenIter = aGenerated.begin();
- for(; aGenIter != aGenerated.end(); aGenIter++) {
- GeomShapePtr aGen = (*aGenIter);
- if (aGen.get() && !aGen->isNull()) {
- GeomAPI_ShapeExplorer aFaceEdgeExp(aGen, GeomAPI_Shape::EDGE);
- int aNumEdges = 0;
- int aNumClosed = 0;
- GeomShapePtr aNotClosedEdge;
- GeomEdgePtr aDegenerateEdge;
- GeomAPI_DataMapOfShapeShape alreadyIterated;
- for(; aFaceEdgeExp.more(); aFaceEdgeExp.next()) {
- std::shared_ptr<GeomAPI_Edge> anEdge(new GeomAPI_Edge(aFaceEdgeExp.current()));
- if (anEdge->isDegenerated()) {
- aDegenerateEdge = anEdge;
- continue;
- }
- if (alreadyIterated.isBound(anEdge))
- continue;
- alreadyIterated.bind(anEdge, anEdge);
- aNumEdges++;
- if (anEdge->isClosed()) {
- aNumClosed++;
- } else {
- aNotClosedEdge = anEdge;
- }
- }
- if (aNumEdges == 2 && aNumClosed == 1) {
- std::ostringstream aStream;
- aStream << "Base_Edge_" << aBaseEdgeIndex++;
- theResultBody->generated(aNotClosedEdge, aStream.str());
- if (aDegenerateEdge.get()) { // export vertex of the degenerated edge (apex) #2520
- GeomAPI_ShapeExplorer anEdgeExp(aDegenerateEdge, GeomAPI_Shape::VERTEX);
- if (anEdgeExp.more()) {
- std::ostringstream aStream;
- aStream << "Base_Vertex_" << aBaseVertexIndex++;
- theResultBody->generated(anEdgeExp.current(), aStream.str());
- }
- }
- }
- }
- }
- }
- }
- }
std::shared_ptr<GeomAlgoAPI_MakeSweep> aMakeSweep =
std::dynamic_pointer_cast<GeomAlgoAPI_MakeSweep>(theMakeShape);
for(; aRefIter != aRefs.end(); aRefIter++) {
std::shared_ptr<ModelAPI_CompositeFeature> aComposite =
std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(*aRefIter);
- if (aComposite.get() && aComposite->isSub(theFeature)) {
+ if (aComposite.get() && aComposite->data()->isValid() && aComposite->isSub(theFeature)) {
aComposite->removeFeature(theFeature);
}
}
}
}
+Selector_NExplode::Selector_NExplode(const TopoDS_Shape& theShape, const TopAbs_ShapeEnum theType)
+{
+ std::vector<TopoDS_Shape> aShapesVec;
+ TopTools_MapOfShape anAdded; // to avoid same shapes duplication
+ for(TopExp_Explorer anExp(theShape, theType); anExp.More(); anExp.Next()) {
+ if (anAdded.Add(anExp.Current()))
+ aShapesVec.push_back(anExp.Current());
+ }
+
+ CompareShapes::DataMapOfShapeDouble aCash;
+ CompareShapes shComp(&aCash);
+ std::stable_sort(aShapesVec.begin(), aShapesVec.end(), shComp);
+
+ std::vector<TopoDS_Shape>::const_iterator anIter = aShapesVec.begin();
+ for (; anIter != aShapesVec.end(); ++anIter) {
+ mySorted.Append(*anIter);
+ }
+}
+
+
int Selector_NExplode::index(const TopoDS_Shape& theSubShape)
{
TopoDS_ListOfShape::Iterator anIter(mySorted);
class Selector_NExplode
{
public:
- /// \brief Initializes the sorted list of shapes by the context shape and type of sub-shapes.
+ /// \brief Initializes the sorted list of shapes by the shapes list.
SELECTOR_EXPORT Selector_NExplode(const TopoDS_ListOfShape& theShapes);
+ /// \brief Initializes the sorted list of shapes by the context shape and type of sub-shapes.
+ SELECTOR_EXPORT Selector_NExplode(const TopoDS_Shape& theShape, const TopAbs_ShapeEnum theType);
/// Returns an index (started from one) of sub-shape in the sorted list. Returns 0 if not found.
SELECTOR_EXPORT int index(const TopoDS_Shape& theSubShape);
// 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
+ TopTools_MapOfShape aLastIntersectors;
while(aSelectionType != TopAbs_FACE || !aFacesTried) {
if (aSelectionType == TopAbs_FACE) {
if (theValue.ShapeType() != TopAbs_VERTEX)
commonShapes(anIntList, theValue.ShapeType(), aCommon);
if (aCommon.Extent() == 1 && aCommon.First().IsSame(theValue)) {
// name the intersectors
- std::list<Selector_Selector> aSubSelList;
+ mySubSelList.clear();
TopTools_MapOfShape::Iterator anInt(anIntersectors);
for (; anInt.More(); anInt.Next()) {
if (!selectBySubSelector(theContext, anInt.Value())) {
if (!anInt.More()) { // all intersectors were correctly named
myType = SELTYPE_INTERSECT;
return true;
- }
+ }
+ } else if (aCommon.Extent() > 1 && aLastCommon.IsEmpty()) {
+ aLastCommon = aCommon;
+ aLastIntersectors = anIntersectors;
}
}
return true;
}
}
+
+ // weak naming to distinguish commons coming from intersection
+ if (aLastCommon.Extent() > 1) {
+ Selector_NExplode aNexp(aLastCommon);
+ myWeakIndex = aNexp.index(theValue);
+ if (myWeakIndex != -1) {
+ // name the intersectors
+ mySubSelList.clear();
+ TopTools_MapOfShape::Iterator anInt(aLastIntersectors);
+ for (; anInt.More(); anInt.Next()) {
+ if (!selectBySubSelector(theContext, anInt.Value())) {
+ 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
+ myType = SELTYPE_WEAK_NAMING;
+ Selector_NExplode aNexp(theContext, theValue.ShapeType());
+ myWeakIndex = aNexp.index(theValue);
+ if (myWeakIndex != -1) {
+ myShapeType = theValue.ShapeType();
+ return true;
+ }
+
return false;
}
// searching for the base shapes of the value
for(; aSubSel != mySubSelList.end(); aSubSel++) {
aSubSel->store();
}
+ if (myWeakIndex != -1) {
+ TDataStd_Integer::Set(myLab, kWEAK_INDEX, myWeakIndex);
+ }
break;
}
case SELTYPE_PRIMITIVE: {
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);
+ break;
}
default: { // unknown case
break;
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 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());
+ return myWeakIndex != -1;
+ }
default: { // unknown case
}
}
}
TopoDS_ListOfShape aCommon; // common sub shapes in each sub-selector (a result)
commonShapes(aSubSelectorShapes, myShapeType, aCommon);
- if (aCommon.Extent() != 1)
- return false;
- aResult = aCommon.First();
+ if (aCommon.Extent() != 1) {
+ if (myWeakIndex != -1) {
+ Selector_NExplode aNexp(aCommon);
+ aResult = aNexp.shape(myWeakIndex);
+ } else {
+ return false;
+ }
+ } else {
+ aResult = aCommon.First();
+ }
break;
}
case SELTYPE_PRIMITIVE: {
aNBs.push_back(std::pair<TopoDS_Shape, int>(aSubSel->value(), *aLevel));
}
aResult = findNeighbor(theContext, aNBs);
+ break;
+ }
+ case SELTYPE_WEAK_NAMING: {
+ Selector_NExplode aNexp(theContext, myShapeType);
+ aResult = aNexp.shape(myWeakIndex);
}
default: { // unknown case
}
case SELTYPE_CONTAINER:
case SELTYPE_INTERSECT: {
std::string aResult;
- // add names of sub-components one by one in "[]"
+ // 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 += ']';
}
+ if (myWeakIndex != -1) {
+ std::ostringstream aWeakStr;
+ aWeakStr<<"["<<kWEAK_NAME_IDENTIFIER<<myWeakIndex<<"]";
+ aResult += aWeakStr.str();
+ }
return aResult;
}
case SELTYPE_PRIMITIVE: {
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());
}
}
return aResult;
}
+ case SELTYPE_WEAK_NAMING: {
+ // weak_naming_1
+ std::ostringstream aWeakStr;
+ aWeakStr<<kWEAK_NAME_IDENTIFIER<<myWeakIndex;
+ std::string aResult = aWeakStr.str();
+ return aResult;
+ }
default: { // unknown case
}
};
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;
+ }
mySubSelList.push_back(Selector_Selector(myLab.FindChild(int(mySubSelList.size()) + 1)));
TDF_Label aSubContext =
mySubSelList.back().restoreByName(aSubStr, theShapeType, theNameGenerator);
if (!myFinal.IsNull())
return aContext;
}
+ } if (theName.find(kWEAK_NAME_IDENTIFIER) == 0) { // weak naming identifier
+ myType = SELTYPE_WEAK_NAMING;
+ std::string aWeakIndex = theName.substr(kWEAK_NAME_IDENTIFIER.size());
+ myWeakIndex = atoi(aWeakIndex.c_str());
+ myShapeType = theShapeType;
+ return myLab;
} else { // modification
myType = SELTYPE_MODIFICATION;
TDF_Label aContext;
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.