#include "Model_SelectionNaming.h"
#include "Model_Document.h"
#include <ModelAPI_Feature.h>
-#include <Events_Error.h>
+#include <Events_InfoMessage.h>
#include <TopoDS_Iterator.hxx>
#include <TopoDS.hxx>
#include <TNaming_NamedShape.hxx>
#include <TNaming_Localizer.hxx>
#include <TDataStd_Name.hxx>
+#include <ModelAPI_ResultConstruction.h>
+#include <ModelAPI_CompositeFeature.h>
+#include <TColStd_MapOfTransient.hxx>
+#include <algorithm>
#ifdef DEB_NAMING
#include <BRepTools.hxx>
#endif
+/// added to the index in the packed map to signalize that the vertex of edge is selected
+/// (multiplied by the index of the edge)
+static const int kSTART_VERTEX_DELTA = 1000000;
+
Model_SelectionNaming::Model_SelectionNaming(TDF_Label theSelectionLab)
{
myLab = theSelectionLab;
TopoDS_Shape aContext = theContext->shape()->impl<TopoDS_Shape>();
#ifdef DEB_NAMING
if(aSubShape.ShapeType() == TopAbs_COMPOUND) {
- BRepTools::Write(aSubShape, "Selection.brep");
- BRepTools::Write(aContext, "Context.brep");
+ BRepTools::Write(aSubShape, "Selection.brep");
+ BRepTools::Write(aContext, "Context.brep");
}
#endif
std::shared_ptr<Model_Document> aDoc =
switch (aType) {
case TopAbs_FACE:
// the Face should be in DF. If it is not the case, it is an error ==> to be debugged
- break;
- case TopAbs_EDGE:
- {
- // name structure: F1 | F2 [| F3 | F4], where F1 & F2 the faces which gives the Edge in trivial case
- // if it is not atrivial case we use localization by neighbours. F3 & F4 - neighbour faces
- if (BRep_Tool::Degenerated(TopoDS::Edge(aSubShape))) {
- aName = "Degenerated_Edge";
- break;
- }
- TopTools_IndexedDataMapOfShapeListOfShape aMap;
- TopExp::MapShapesAndAncestors(aContext, TopAbs_EDGE, TopAbs_FACE, aMap);
- TopTools_IndexedMapOfShape aSMap; // map for ancestors of the sub-shape
- bool isTrivialCase(true);
-/* for (int i = 1; i <= aMap.Extent(); i++) {
- const TopoDS_Shape& aKey = aMap.FindKey(i);
- //if (aKey.IsNotEqual(aSubShape)) continue; // find exactly the selected key
- if (aKey.IsSame(aSubShape)) continue;
- const TopTools_ListOfShape& anAncestors = aMap.FindFromIndex(i);
- // check that it is not a trivial case (F1 & F2: aNumber = 1)
- isTrivialCase = isTrivial(anAncestors, aSMap);
- break;
- }*/
- if(aMap.Contains(aSubShape)) {
- const TopTools_ListOfShape& anAncestors = aMap.FindFromKey(aSubShape);
- // check that it is not a trivial case (F1 & F2: aNumber = 1)
- isTrivialCase = isTrivial(anAncestors, aSMap);
- } else
- break;
- TopTools_ListOfShape aListOfNbs;
- if(!isTrivialCase) { // find Neighbors
- TNaming_Localizer aLocalizer;
- TopTools_MapOfShape aMap3;
- aLocalizer.FindNeighbourg(aContext, aSubShape, aMap3);
- //int n = aMap3.Extent();
- TopTools_MapIteratorOfMapOfShape it(aMap3);
- for(;it.More();it.Next()) {
- const TopoDS_Shape& aNbShape = it.Key(); // neighbor edge
- //TopAbs_ShapeEnum aType = aNbShape.ShapeType();
- const TopTools_ListOfShape& aList = aMap.FindFromKey(aNbShape);
- TopTools_ListIteratorOfListOfShape it2(aList);
- for(;it2.More();it2.Next()) {
- if(aSMap.Contains(it2.Value())) continue; // skip this Face
- aListOfNbs.Append(it2.Value());
- }
- }
- } // else a trivial case
-
- // build name of the sub-shape Edge
- for(int i=1; i <= aSMap.Extent(); i++) {
- const TopoDS_Shape& aFace = aSMap.FindKey(i);
- std::string aFaceName = getShapeName(aDoc, aFace);
- if(i == 1)
- aName = aFaceName;
- else
- aName += "|" + aFaceName;
- }
- TopTools_ListIteratorOfListOfShape itl(aListOfNbs);
- for (;itl.More();itl.Next()) {
- std::string aFaceName = getShapeName(aDoc, itl.Value());
- aName += "|" + aFaceName;
- }
- }
- break;
+ break;
+ case TopAbs_EDGE:
+ {
+ // name structure: F1 & F2 [& F3 & F4], where F1 & F2 the faces which gives the Edge in trivial case
+ // if it is not atrivial case we use localization by neighbours. F3 & F4 - neighbour faces
+ if (BRep_Tool::Degenerated(TopoDS::Edge(aSubShape))) {
+ aName = "Degenerated_Edge";
+ break;
+ }
+ TopTools_IndexedDataMapOfShapeListOfShape aMap;
+ TopExp::MapShapesAndAncestors(aContext, TopAbs_EDGE, TopAbs_FACE, aMap);
+ TopTools_IndexedMapOfShape aSMap; // map for ancestors of the sub-shape
+ bool isTrivialCase(true);
+ if(aMap.Contains(aSubShape)) {
+ const TopTools_ListOfShape& anAncestors = aMap.FindFromKey(aSubShape);
+ // check that it is not a trivial case (F1 & F2: aNumber = 1)
+ isTrivialCase = isTrivial(anAncestors, aSMap);
+ } else
+ break;
+ TopTools_ListOfShape aListOfNbs;
+ if(!isTrivialCase) { // find Neighbors
+ TNaming_Localizer aLocalizer;
+ TopTools_MapOfShape aMap3;
+ aLocalizer.FindNeighbourg(aContext, aSubShape, aMap3);
+ //int n = aMap3.Extent();
+ TopTools_MapIteratorOfMapOfShape it(aMap3);
+ for(;it.More();it.Next()) {
+ const TopoDS_Shape& aNbShape = it.Key(); // neighbor edge
+ //TopAbs_ShapeEnum aType = aNbShape.ShapeType();
+ const TopTools_ListOfShape& aList = aMap.FindFromKey(aNbShape);
+ TopTools_ListIteratorOfListOfShape it2(aList);
+ for(;it2.More();it2.Next()) {
+ if(aSMap.Contains(it2.Value())) continue; // skip this Face
+ aListOfNbs.Append(it2.Value());
+ }
+ }
+ } // else a trivial case
+
+ // build name of the sub-shape Edge
+ for(int i=1; i <= aSMap.Extent(); i++) {
+ const TopoDS_Shape& aFace = aSMap.FindKey(i);
+ std::string aFaceName = getShapeName(aDoc, aFace);
+ if(i == 1)
+ aName = aFaceName;
+ else
+ aName += "&" + aFaceName;
+ }
+ TopTools_ListIteratorOfListOfShape itl(aListOfNbs);
+ for (;itl.More();itl.Next()) {
+ std::string aFaceName = getShapeName(aDoc, itl.Value());
+ aName += "&" + aFaceName;
+ }
+ }
+ break;
case TopAbs_VERTEX:
// name structure (Monifold Topology):
const TopTools_ListOfShape& aList2 = aMap.FindFromKey(aSubShape);
TopTools_ListOfShape aList;
TopTools_MapOfShape aFMap;
- //int n = aList2.Extent(); //bug! duplication
// fix is below
TopTools_ListIteratorOfListOfShape itl2(aList2);
for (int i = 1;itl2.More();itl2.Next(),i++) {
if(aFMap.Add(itl2.Value()))
aList.Append(itl2.Value());
}
- //n = aList.Extent();
int n = aList.Extent();
- if(n < 3) { // open topology case or Compound case => via edges
+ bool isByFaces = n >= 3;
+ if(!isByFaces) { // open topology case or Compound case => via edges
TopTools_IndexedDataMapOfShapeListOfShape aMap;
TopExp::MapShapesAndAncestors(aContext, TopAbs_VERTEX, TopAbs_EDGE, aMap);
const TopTools_ListOfShape& aList22 = aMap.FindFromKey(aSubShape);
for (int i = 1;itl.More();itl.Next(),i++) {
const TopoDS_Shape& anEdge = itl.Value();
std::string anEdgeName = getShapeName(aDoc, anEdge);
+ if (anEdgeName.empty()) { // edge is not in DS, trying by faces anyway
+ isByFaces = true;
+ aName.clear();
+ break;
+ }
if(i == 1)
aName = anEdgeName;
else
- aName += "|" + anEdgeName;
+ aName += "&" + anEdgeName;
}
}//reg
else { // dangle vertex: if(aList22.Extent() == 1)
//it should be already in DF
}
}
- else {
+ if (isByFaces) {
TopTools_ListIteratorOfListOfShape itl(aList);
for (int i = 1;itl.More();itl.Next(),i++) {
const TopoDS_Shape& aFace = itl.Value();
if(i == 1)
aName = aFaceName;
else
- aName += "|" + aFaceName;
+ aName += "&" + aFaceName;
}
}
}
TopAbs_ShapeEnum translateType (const std::string& theType)
{
// map from the textual shape types to OCCT enumeration
- static std::map<std::string, TopAbs_ShapeEnum> MyShapeTypes;
- if (MyShapeTypes.size() == 0) {
- MyShapeTypes["face"] = TopAbs_FACE;
- MyShapeTypes["faces"] = TopAbs_FACE;
- MyShapeTypes["vertex"] = TopAbs_VERTEX;
- MyShapeTypes["vertices"] = TopAbs_VERTEX;
- MyShapeTypes["wire"] = TopAbs_WIRE;
- MyShapeTypes["edge"] = TopAbs_EDGE;
- MyShapeTypes["edges"] = TopAbs_EDGE;
- MyShapeTypes["shell"] = TopAbs_SHELL;
- MyShapeTypes["solid"] = TopAbs_SOLID;
- MyShapeTypes["solids"] = TopAbs_SOLID;
- MyShapeTypes["FACE"] = TopAbs_FACE;
- MyShapeTypes["FACES"] = TopAbs_FACE;
- MyShapeTypes["VERTEX"] = TopAbs_VERTEX;
- MyShapeTypes["VERTICES"] = TopAbs_VERTEX;
- MyShapeTypes["WIRE"] = TopAbs_WIRE;
- MyShapeTypes["EDGE"] = TopAbs_EDGE;
- MyShapeTypes["EDGES"] = TopAbs_EDGE;
- MyShapeTypes["SHELL"] = TopAbs_SHELL;
- MyShapeTypes["SOLID"] = TopAbs_SOLID;
- MyShapeTypes["SOLIDS"] = TopAbs_SOLID;
+ static std::map<std::string, TopAbs_ShapeEnum> aShapeTypes;
+
+ if(aShapeTypes.size() == 0) {
+ aShapeTypes["compound"] = TopAbs_COMPOUND;
+ aShapeTypes["compounds"] = TopAbs_COMPOUND;
+ aShapeTypes["compsolid"] = TopAbs_COMPSOLID;
+ aShapeTypes["compsolids"] = TopAbs_COMPSOLID;
+ aShapeTypes["solid"] = TopAbs_SOLID;
+ aShapeTypes["solids"] = TopAbs_SOLID;
+ aShapeTypes["shell"] = TopAbs_SHELL;
+ aShapeTypes["shells"] = TopAbs_SHELL;
+ aShapeTypes["face"] = TopAbs_FACE;
+ aShapeTypes["faces"] = TopAbs_FACE;
+ aShapeTypes["wire"] = TopAbs_WIRE;
+ aShapeTypes["wires"] = TopAbs_WIRE;
+ aShapeTypes["edge"] = TopAbs_EDGE;
+ aShapeTypes["edges"] = TopAbs_EDGE;
+ aShapeTypes["vertex"] = TopAbs_VERTEX;
+ aShapeTypes["vertices"] = TopAbs_VERTEX;
+ aShapeTypes["COMPOUND"] = TopAbs_COMPOUND;
+ aShapeTypes["COMPOUNDS"] = TopAbs_COMPOUND;
+ aShapeTypes["COMPSOLID"] = TopAbs_COMPSOLID;
+ aShapeTypes["COMPSOLIDS"] = TopAbs_COMPSOLID;
+ aShapeTypes["SOLID"] = TopAbs_SOLID;
+ aShapeTypes["SOLIDS"] = TopAbs_SOLID;
+ aShapeTypes["SHELL"] = TopAbs_SHELL;
+ aShapeTypes["SHELLS"] = TopAbs_SHELL;
+ aShapeTypes["FACE"] = TopAbs_FACE;
+ aShapeTypes["FACES"] = TopAbs_FACE;
+ aShapeTypes["WIRE"] = TopAbs_WIRE;
+ aShapeTypes["WIRES"] = TopAbs_WIRE;
+ aShapeTypes["EDGE"] = TopAbs_EDGE;
+ aShapeTypes["EDGES"] = TopAbs_EDGE;
+ aShapeTypes["VERTEX"] = TopAbs_VERTEX;
+ aShapeTypes["VERTICES"] = TopAbs_VERTEX;
}
- if (MyShapeTypes.find(theType) != MyShapeTypes.end())
- return MyShapeTypes[theType];
- Events_Error::send("Shape type defined in XML is not implemented!");
+ if (aShapeTypes.find(theType) != aShapeTypes.end())
+ return aShapeTypes[theType];
+ Events_InfoMessage("Model_SelectionNaming", "Shape type defined in XML is not implemented!").send();
return TopAbs_SHAPE;
}
return aFace;
}
-int ParseName(const std::string& theSubShapeName, std::list<std::string>& theList)
+size_t ParseName(const std::string& theSubShapeName, std::list<std::string>& theList)
{
std::string aName = theSubShapeName;
std::string aLastName;
- int n1(0), n2(0); // n1 - start position, n2 - position of the delimiter
- while ((n2 = aName.find('|', n1)) != std::string::npos) {
+ size_t n1(0), n2(0); // n1 - start position, n2 - position of the delimiter
+ while ((n2 = aName.find('&', n1)) != std::string::npos) {
const std::string aName1 = aName.substr(n1, n2 - n1); //name of face
theList.push_back(aName1);
n1 = n2 + 1;
{
std::string aName;
std::string::size_type n = theSubShapeName.find('/');
- if (n == std::string::npos) return aName;
+ if (n == std::string::npos) return theSubShapeName;
aName = theSubShapeName.substr(0, n);
return aName;
}
+/// Parses naming name of sketch sub-elements: takes indices and orientation
+/// (if theOriented = true) from this name. Map theIDs constains indices ->
+/// orientations and start/end vertices: negative is reversed, 2 - start, 3 - end
+bool parseSubIndices(CompositeFeaturePtr theComp, //< to iterate names
+ const std::string& theName, const char* theShapeType,
+ std::map<int, int>& theIDs, const bool theOriented = false)
+{
+ // collect all IDs in the name
+ std::map<std::string, int> aNames; // short name of sub -> ID of sub of theComp
+ const int aSubNum = theComp->numberOfSubs();
+ for(int a = 0; a < aSubNum; a++) {
+ FeaturePtr aSub = theComp->subFeature(a);
+ const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aSub->results();
+ std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRes = aResults.cbegin();
+ // there may be many shapes (circle and center)
+ for(; aRes != aResults.cend(); aRes++) {
+ ResultConstructionPtr aConstr =
+ std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aRes);
+ if (aConstr.get()) {
+ aNames[Model_SelectionNaming::shortName(aConstr)] = theComp->subFeatureId(a);
+ }
+ }
+ }
+
+ size_t aPrevPos = theName.find("/") + 1, aLastNamePos;
+ bool isShape = false; // anyway the first world must be 'Vertex'
+ do {
+ aLastNamePos = theName.find('-', aPrevPos);
+ std::string anID = theName.substr(aPrevPos, aLastNamePos - aPrevPos);
+ if (!isShape) {
+ if (anID != theShapeType)
+ return false;
+ isShape = true;
+ } else {
+ int anOrientation = 1; // default
+ if (theOriented) { // here must be a symbol in the end of digit 'f' or 'r'
+ const char aSymbol = anID.back();
+ if (aSymbol == 'r') anOrientation = -1;
+ anID.pop_back();
+ }
+ // check start/end symbols
+ if (anID.back() == 's') {
+ anOrientation *= 2;
+ anID.pop_back();
+ } else if (anID.back() == 'e') {
+ anOrientation *= 3;
+ anID.pop_back();
+ }
+
+ if (aNames.find(anID) != aNames.end()) {
+ theIDs[aNames[anID]] = anOrientation;
+ }
+ }
+ aPrevPos = aLastNamePos + 1;
+ } while (aLastNamePos != std::string::npos);
+ return true;
+}
+
+/// produces theEdge orientation relatively to theContext face
+int Model_SelectionNaming::edgeOrientation(const TopoDS_Shape& theContext, TopoDS_Edge& theEdge)
+{
+ if (theContext.ShapeType() != TopAbs_FACE)
+ return 0;
+ TopoDS_Face aContext = TopoDS::Face(theContext);
+ if (theEdge.Orientation() == TopAbs_FORWARD)
+ return 1;
+ if (theEdge.Orientation() == TopAbs_REVERSED)
+ return -1;
+ return 0; // unknown
+}
+
+std::shared_ptr<GeomAPI_Shape> Model_SelectionNaming::findAppropriateFace(
+ std::shared_ptr<ModelAPI_Result>& theConstr,
+ NCollection_DataMap<Handle(Geom_Curve), int>& theCurves)
+{
+ int aBestFound = 0; // best number of found edges (not percentage: issue 1019)
+ int aBestOrient = 0; // for the equal "BestFound" additional parameter is orientation
+ std::shared_ptr<GeomAPI_Shape> aResult;
+ ResultConstructionPtr aConstructionContext =
+ std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(theConstr);
+ if (!aConstructionContext.get())
+ return aResult;
+ for(int aFaceIndex = 0; aFaceIndex < aConstructionContext->facesNum(); aFaceIndex++) {
+ int aFound = 0, aNotFound = 0, aSameOrientation = 0;
+ TopoDS_Face aFace =
+ TopoDS::Face(aConstructionContext->face(aFaceIndex)->impl<TopoDS_Shape>());
+ TopExp_Explorer anEdgesExp(aFace, TopAbs_EDGE);
+ TColStd_MapOfTransient alreadyProcessed; // to avoid counting edges with same curved (841)
+ for(; anEdgesExp.More(); anEdgesExp.Next()) {
+ TopoDS_Edge anEdge = TopoDS::Edge(anEdgesExp.Current());
+ if (!anEdge.IsNull()) {
+ Standard_Real aFirst, aLast;
+ Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
+ if (alreadyProcessed.Contains(aCurve))
+ continue;
+ alreadyProcessed.Add(aCurve);
+ if (theCurves.IsBound(aCurve)) {
+ aFound++;
+ int anOrient = theCurves.Find(aCurve);
+ if (anOrient != 0) { // extra comparision score is orientation
+ if (edgeOrientation(aFace, anEdge) == anOrient)
+ aSameOrientation++;
+ }
+ } else {
+ aNotFound++;
+ }
+ }
+ }
+ if (aFound + aNotFound != 0) {
+ if (aFound > aBestFound ||
+ (aFound == aBestFound && aSameOrientation > aBestOrient)) {
+ aBestFound = aFound;
+ aBestOrient = aSameOrientation;
+ aResult = aConstructionContext->face(aFaceIndex);
+ }
+ }
+ }
+ return aResult;
+}
+
+std::string Model_SelectionNaming::shortName(
+ std::shared_ptr<ModelAPI_ResultConstruction>& theConstr, const int theEdgeVertexPos)
+{
+ std::string aName = theConstr->data()->name();
+ // remove "-", "/" and "&" command-symbols
+ aName.erase(std::remove(aName.begin(), aName.end(), '-'), aName.end());
+ aName.erase(std::remove(aName.begin(), aName.end(), '/'), aName.end());
+ aName.erase(std::remove(aName.begin(), aName.end(), '&'), aName.end());
+ // remove the last 's', 'e', 'f' and 'r' symbols: they are used as markers of start/end/forward/rewersed indicators
+ static const std::string aSyms("sefr");
+ while(aSyms.find(aName.back()) != std::string::npos) {
+ aName.pop_back();
+ }
+ if (theEdgeVertexPos == 1) {
+ aName += "s"; // start
+ } else if (theEdgeVertexPos == 2) {
+ aName += "e"; // end
+ }
+ return aName;
+}
+
// type ::= COMP | COMS | SOLD | SHEL | FACE | WIRE | EDGE | VERT
bool Model_SelectionNaming::selectSubShape(const std::string& theType,
const std::string& theSubShapeName, std::shared_ptr<Model_Document> theDoc,
std::string aContName = getContextName(theSubShapeName);
if(aContName.empty()) return false;
ResultPtr aCont = theDoc->findByName(aContName);
- if(!aCont.get() || aCont->shape()->isNull()) return false;
- TopoDS_Shape aContext = aCont->shape()->impl<TopoDS_Shape>();
- TopAbs_ShapeEnum aContType = aContext.ShapeType();
- if(aType <= aContType) return false; // not applicable
+ // possible this is body where postfix is added to distinguish several shapes on the same label
+ int aSubShapeId = -1; // -1 means sub shape not found
+ if (!aCont.get() && aContName == theSubShapeName) {
+ size_t aPostIndex = aContName.rfind('_');
+ if (aPostIndex != std::string::npos) {
+ std::string aSubContName = aContName.substr(0, aPostIndex);
+ aCont = theDoc->findByName(aSubContName);
+ if (aCont.get()) {
+ try {
+ std::string aNum = aContName.substr(aPostIndex + 1);
+ aSubShapeId = std::stoi(aNum);
+ } catch (std::invalid_argument&) {
+ aSubShapeId = -1;
+ }
+ if (aSubShapeId > 0)
+ aContName = aSubContName;
+ }
+ }
+ }
TopoDS_Shape aSelection;
switch (aType)
{
- case TopAbs_COMPOUND:
- break;
- case TopAbs_COMPSOLID:
- break;
- case TopAbs_SOLID:
- break;
- case TopAbs_SHELL:
- break;
case TopAbs_FACE:
{
- const TopoDS_Shape aSelection = findFaceByName(theSubShapeName, theDoc);
- if(!aSelection.IsNull()) {// Select it
- std::shared_ptr<GeomAPI_Shape> aShapeToBeSelected(new GeomAPI_Shape());
- aShapeToBeSelected->setImpl(new TopoDS_Shape(aSelection));
- theShapeToBeSelected = aShapeToBeSelected;
- theCont = aCont;
- return true;
- }
+ aSelection = findFaceByName(theSubShapeName, theDoc);
}
break;
- case TopAbs_WIRE:
- break;
case TopAbs_EDGE:
{
- TopoDS_Shape aSelection;// = findFaceByName(theSubShapeName, aDoc);
const TDF_Label& aLabel = theDoc->findNamingName(theSubShapeName);
if(!aLabel.IsNull()) {
Handle(TNaming_NamedShape) aNS;
aSelection = getShapeFromNS(theSubShapeName, aNS);
}
}
- if(aSelection.IsNull()) {
- std::list<std::string> aListofNames;
- int n = ParseName(theSubShapeName, aListofNames);
- if(n > 1 && n < 5) {
- TopTools_ListOfShape aList;
- std::list<std::string>::iterator it =aListofNames.begin();
- for(;it != aListofNames.end();it++){
- const TopoDS_Shape aFace = findFaceByName(*it, theDoc);
- aList.Append(aFace);
- }
- aSelection = findCommonShape(TopAbs_EDGE, aList);
- }
- }
- if(!aSelection.IsNull()) {// Select it
- std::shared_ptr<GeomAPI_Shape> aShapeToBeSelected(new GeomAPI_Shape());
- aShapeToBeSelected->setImpl(new TopoDS_Shape(aSelection));
- theShapeToBeSelected = aShapeToBeSelected;
- theCont = aCont;
- return true;
- }
}
break;
case TopAbs_VERTEX:
{
- TopoDS_Shape aSelection;
const TDF_Label& aLabel = theDoc->findNamingName(theSubShapeName);
if(!aLabel.IsNull()) {
Handle(TNaming_NamedShape) aNS;
aSelection = getShapeFromNS(theSubShapeName, aNS);
}
}
- if(aSelection.IsNull()) {
- std::list<std::string> aListofNames;
- int n = ParseName(theSubShapeName, aListofNames);
- if(n > 1 && n < 4) { // 2 || 3
- TopTools_ListOfShape aList;
- std::list<std::string>::iterator it = aListofNames.begin();
- for(; it != aListofNames.end(); it++){
- const TopoDS_Shape aFace = findFaceByName(*it, theDoc);
- if(!aFace.IsNull())
- aList.Append(aFace);
- }
- aSelection = findCommonShape(TopAbs_VERTEX, aList);
- }
- }
- if(!aSelection.IsNull()) {// Select it
- std::shared_ptr<GeomAPI_Shape> aShapeToBeSelected(new GeomAPI_Shape());
- aShapeToBeSelected->setImpl(new TopoDS_Shape(aSelection));
- theShapeToBeSelected = aShapeToBeSelected;
+ }
+ break;
+ case TopAbs_COMPOUND:
+ case TopAbs_COMPSOLID:
+ case TopAbs_SOLID:
+ case TopAbs_SHELL:
+ case TopAbs_WIRE:
+ default: {//TopAbs_SHAPE
+ /// case when the whole sketch is selected, so, selection type is compound, but there is no value
+ if (aCont.get() && aCont->shape().get()) {
+ if (aCont->shape()->impl<TopoDS_Shape>().ShapeType() == aType) {
theCont = aCont;
return true;
+ } else if (aSubShapeId > 0) { // try to find sub-shape by the index
+ TopExp_Explorer anExp(aCont->shape()->impl<TopoDS_Shape>(), aType);
+ for(; aSubShapeId > 0 && anExp.More(); aSubShapeId--) {
+ anExp.Next();
+ }
+ if (anExp.More()) {
+ std::shared_ptr<GeomAPI_Shape> aShapeToBeSelected(new GeomAPI_Shape());
+ aShapeToBeSelected->setImpl(new TopoDS_Shape(anExp.Current()));
+ theShapeToBeSelected = aShapeToBeSelected;
+ theCont = aCont;
+ return true;
+ }
}
}
- break;
- default: //TopAbs_SHAPE
return false;
+ }
+ }
+ // another try to find edge or vertex by faces
+ std::list<std::string> aListofNames;
+ size_t aN = aSelection.IsNull() ? ParseName(theSubShapeName, aListofNames) : 0;
+ if (aSelection.IsNull() && (aType == TopAbs_EDGE || aType == TopAbs_VERTEX)) {
+ if(aN > 1 && (aN < 4 || (aType == TopAbs_EDGE && aN < 5))) { // 2 || 3 or 4 for EDGE
+ TopTools_ListOfShape aList;
+ std::list<std::string>::iterator it = aListofNames.begin();
+ for(; it != aListofNames.end(); it++){
+ const TopoDS_Shape aFace = findFaceByName(*it, theDoc);
+ if(!aFace.IsNull())
+ aList.Append(aFace);
+ }
+ aSelection = findCommonShape(aType, aList);
+ }
+ }
+ if (!aSelection.IsNull()) {// Select it
+ std::shared_ptr<GeomAPI_Shape> aShapeToBeSelected(new GeomAPI_Shape());
+ aShapeToBeSelected->setImpl(new TopoDS_Shape(aSelection));
+ theShapeToBeSelected = aShapeToBeSelected;
+ theCont = aCont;
+ return true;
+ }
+ // in case of construction, there is no registered names for all sub-elements,
+ // even for the main element; so, trying to find them by name (without "&" intersections)
+ if (aN == 0) {
+ size_t aConstrNamePos = theSubShapeName.find("/");
+ bool isFullName = aConstrNamePos == std::string::npos;
+ std::string aContrName = aContName;
+ // isFullName ? theSubShapeName : theSubShapeName.substr(0, aConstrNamePos);
+ ResultPtr aConstr = theDoc->findByName(aContrName);
+ if (aConstr.get() && aConstr->groupName() == ModelAPI_ResultConstruction::group()) {
+ theCont = aConstr;
+ if (isFullName) {
+ theShapeToBeSelected = aConstr->shape();
+ return true;
+ }
+ // for sketch sub-elements selected
+ CompositeFeaturePtr aComposite =
+ std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theDoc->feature(aConstr));
+ if (aComposite.get()) {
+ if (aType == TopAbs_VERTEX || aType == TopAbs_EDGE) {
+ // collect all IDs in the name
+ std::map<int, int> anIDs;
+ if (!parseSubIndices(aComposite, theSubShapeName,
+ aType == TopAbs_EDGE ? "Edge" : "Vertex", anIDs))
+ return false;
+
+ const int aSubNum = aComposite->numberOfSubs();
+ for(int a = 0; a < aSubNum; a++) {
+ int aCompID = aComposite->subFeatureId(a);
+ if (anIDs.find(aCompID) != anIDs.end()) { // found the vertex/edge shape
+ FeaturePtr aSub = aComposite->subFeature(a);
+ const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aSub->results();
+ std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIt = aResults.cbegin();
+ // there may be many shapes (circle and center)
+ for(; aRIt != aResults.cend(); aRIt++) {
+ ResultConstructionPtr aRes =
+ std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aRIt);
+ if (aRes) {
+ int anOrientation = abs(anIDs[aCompID]);
+ TopoDS_Shape aShape = aRes->shape()->impl<TopoDS_Shape>();
+ if (anOrientation == 1) {
+ if (aType == aShape.ShapeType()) {
+ theShapeToBeSelected = aRes->shape();
+ return true;
+ }
+ } else { // take first or second vertex of the edge
+ TopoDS_Shape aShape = aRes->shape()->impl<TopoDS_Shape>();
+ TopExp_Explorer anExp(aShape, aType);
+ for(; anExp.More() && anOrientation != 2; anOrientation--)
+ anExp.Next();
+ if (anExp.More()) {
+ std::shared_ptr<GeomAPI_Shape> aShapeToBeSelected(new GeomAPI_Shape());
+ aShapeToBeSelected->setImpl(new TopoDS_Shape(anExp.Current()));
+ theShapeToBeSelected = aShapeToBeSelected;
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+ } else if (aType == TopAbs_FACE) { // sketch faces is identified by format "Sketch_1/Face-2f-8f-11r"
+ std::map<int, int> anIDs;
+ if (!parseSubIndices(aComposite, theSubShapeName, "Face", anIDs, true))
+ return false;
+
+ NCollection_DataMap<Handle(Geom_Curve), int> allCurves; // curves and orientations of edges
+ const int aSubNum = aComposite->numberOfSubs();
+ for(int a = 0; a < aSubNum; a++) {
+ int aSubID = aComposite->subFeatureId(a);
+ if (anIDs.find(aSubID) != anIDs.end()) {
+ FeaturePtr aSub = aComposite->subFeature(a);
+ const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aSub->results();
+ std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRes;
+ for(aRes = aResults.cbegin(); aRes != aResults.cend(); aRes++) {
+ ResultConstructionPtr aConstr =
+ std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aRes);
+ if (aConstr->shape() && aConstr->shape()->isEdge()) {
+ const TopoDS_Shape& aResShape = aConstr->shape()->impl<TopoDS_Shape>();
+ TopoDS_Edge anEdge = TopoDS::Edge(aResShape);
+ if (!anEdge.IsNull()) {
+ Standard_Real aFirst, aLast;
+ Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
+ allCurves.Bind(aCurve, anIDs[aSubID] > 0 ? 1 : -1);
+ }
+ }
+ }
+ }
+ }
+ std::shared_ptr<GeomAPI_Shape> aFoundFace = findAppropriateFace(aConstr, allCurves);
+ if (aFoundFace.get()) {
+ theShapeToBeSelected = aFoundFace;
+ return true;
+ }
+ }
+ }
+ }
}
return false;
}
-