+
+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;
+ }
+ if (MyShapeTypes.find(theType) != MyShapeTypes.end())
+ return MyShapeTypes[theType];
+ Events_Error::send("Shape type defined in XML is not implemented!");
+ return TopAbs_SHAPE;
+}
+
+const TopoDS_Shape getShapeFromCompound(const std::string& theSubShapeName, const TopoDS_Shape& theCompound)
+{
+ TopoDS_Shape aSelection;
+ std::string::size_type n = theSubShapeName.rfind('/');
+ if (n == std::string::npos) n = 0;
+ std::string aSubString = theSubShapeName.substr(n + 1);
+ n = aSubString.rfind('_');
+ if (n == std::string::npos) return aSelection;
+ aSubString = aSubString.substr(n+1);
+ int indx = atoi(aSubString.c_str());
+ TopoDS_Iterator it(theCompound);
+ for (int i = 1;it.More();it.Next(), i++) {
+ if(i == indx) {
+ aSelection = it.Value();
+ break;
+ }
+ else continue;
+ }
+ return aSelection;
+}
+
+const TopoDS_Shape findFaceByName(const std::string& theSubShapeName, std::shared_ptr<Model_Document> theDoc)
+{
+ TopoDS_Shape aFace;
+ std::string::size_type n, nb = theSubShapeName.rfind('/');
+ if (nb == std::string::npos) nb = 0;
+ std::string aSubString = theSubShapeName.substr(nb + 1);
+ n = aSubString.rfind('_');
+ if (n != std::string::npos) {
+ std::string aSubStr2 = aSubString.substr(0, n);
+ aSubString = theSubShapeName.substr(0, nb + 1);
+ aSubString = aSubString + aSubStr2;
+ } else
+ aSubString = theSubShapeName;
+
+ const TDF_Label& aLabel = theDoc->findNamingName(aSubString);
+ if(aLabel.IsNull()) return aFace;
+ Handle(TNaming_NamedShape) aNS;
+ if(aLabel.FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
+ const TopoDS_Shape& aShape = aNS->Get();
+ if(!aShape.IsNull()) {
+ if(aShape.ShapeType() == TopAbs_COMPOUND)
+ aFace = getShapeFromCompound(theSubShapeName, aShape);
+ else
+ aFace = aShape;
+ }
+ }
+ return aFace;
+}
+
+int 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) {
+ const std::string aName1 = aName.substr(n1, n2 - n1); //name of face
+ theList.push_back(aName1);
+ n1 = n2 + 1;
+ aLastName = aName.substr(n1);
+ }
+ if(!aLastName.empty())
+ theList.push_back(aLastName);
+ return theList.size();
+}
+
+const TopoDS_Shape findCommonShape(const TopAbs_ShapeEnum theType, const TopTools_ListOfShape& theList)
+{
+ TopoDS_Shape aShape;
+ std::vector<TopTools_MapOfShape> aVec;
+ TopTools_MapOfShape aMap1, aMap2, aMap3, aMap4;
+ if(theList.Extent() > 1) {
+ aVec.push_back(aMap1);
+ aVec.push_back(aMap2);
+ }
+ if(theList.Extent() > 2)
+ aVec.push_back(aMap3);
+ if(theList.Extent() == 4)
+ aVec.push_back(aMap4);
+
+ //fill maps
+ TopTools_ListIteratorOfListOfShape it(theList);
+ for(int i = 0;it.More();it.Next(),i++) {
+ const TopoDS_Shape& aFace = it.Value();
+ if(i < 2) {
+ TopExp_Explorer anExp (aFace, theType);
+ for(;anExp.More();anExp.Next()) {
+ const TopoDS_Shape& anEdge = anExp.Current();
+ if (!anEdge.IsNull())
+ aVec[i].Add(anExp.Current());
+ }
+ } else {
+ TopExp_Explorer anExp (aFace, TopAbs_VERTEX);
+ for(;anExp.More();anExp.Next()) {
+ const TopoDS_Shape& aVertex = anExp.Current();
+ if (!aVertex.IsNull())
+ aVec[i].Add(anExp.Current());
+ }
+ }
+ }
+ //trivial case: 2 faces
+ TopTools_ListOfShape aList;
+ TopTools_MapIteratorOfMapOfShape it2(aVec[0]);
+ for(;it2.More();it2.Next()) {
+ if(aVec[1].Contains(it2.Key())) {
+ aShape = it2.Key();
+ if(theList.Extent() == 2)
+ break;
+ else
+ aList.Append(it2.Key());
+ }
+ }
+ if(aList.Extent() && aVec.size() > 3) {// list of common edges ==> search ny neighbors
+ if(aVec[2].Extent() && aVec[3].Extent()) {
+ TopTools_ListIteratorOfListOfShape it(aList);
+ for(;it.More();it.Next()) {
+ const TopoDS_Shape& aCand = it.Value();
+ // not yet completelly implemented, to be rechecked
+ TopoDS_Vertex aV1, aV2;
+ TopExp::Vertices(TopoDS::Edge(aCand), aV1, aV2);
+ int aNum(0);
+ if(aVec[2].Contains(aV1)) aNum++;
+ else if(aVec[2].Contains(aV2)) aNum++;
+ if(aVec[3].Contains(aV1)) aNum++;
+ else if(aVec[3].Contains(aV2)) aNum++;
+ if(aNum == 2) {
+ aShape = aCand;
+ break;
+ }
+ }
+ }
+ }
+
+ if(aList.Extent() && aVec.size() == 3) {
+
+ TopTools_ListIteratorOfListOfShape it(aList);
+ for(;it.More();it.Next()) {
+ const TopoDS_Shape& aCand = it.Value();
+ if(aVec[2].Contains(aCand)) {
+ aShape = aCand;
+ break;
+ }
+ }
+ }
+ return aShape;
+}
+
+std::string getContextName(const std::string& theSubShapeName)
+{
+ std::string aName;
+ std::string::size_type n = theSubShapeName.find('/');
+ if (n == std::string::npos) return aName;
+ aName = theSubShapeName.substr(0, n);
+ return aName;
+}
+// type ::= COMP | COMS | SOLD | SHEL | FACE | WIRE | EDGE | VERT
+void Model_AttributeSelection::selectSubShape(const std::string& theType, const std::string& theSubShapeName)
+{
+ if(theSubShapeName.empty() || theType.empty()) return;
+ TopAbs_ShapeEnum aType = translateType(theType);
+ std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(owner()->document());//std::dynamic_pointer_cast<Model_Document>(aCont->document());
+ std::string aContName = getContextName(theSubShapeName);
+ if(aContName.empty()) return;
+ //ResultPtr aCont = context();
+ ResultPtr aCont = aDoc->findByName(aContName);
+ if(!aCont.get() || aCont->shape()->isNull()) return;
+ TopoDS_Shape aContext = aCont->shape()->impl<TopoDS_Shape>();
+ TopAbs_ShapeEnum aContType = aContext.ShapeType();
+ if(aType <= aContType) return; // not applicable
+
+
+ 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, aDoc);
+ if(!aSelection.IsNull()) {// Select it
+ std::shared_ptr<GeomAPI_Shape> aShapeToBeSelected(new GeomAPI_Shape());
+ aShapeToBeSelected->setImpl(new TopoDS_Shape(aSelection));
+ setValue(aCont, aShapeToBeSelected);
+ }
+ }
+ break;
+ case TopAbs_WIRE:
+ break;
+ case TopAbs_EDGE:
+ {
+ TopoDS_Shape aSelection;// = findFaceByName(theSubShapeName, aDoc);
+ const TDF_Label& aLabel = aDoc->findNamingName(theSubShapeName);
+ if(!aLabel.IsNull()) {
+ Handle(TNaming_NamedShape) aNS;
+ if(aLabel.FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
+ const TopoDS_Shape& aShape = aNS->Get();
+ if(!aShape.IsNull()) {
+ if(aShape.ShapeType() == TopAbs_COMPOUND)
+ aSelection = getShapeFromCompound(theSubShapeName, aShape);
+ else
+ aSelection = aShape;
+ }
+ }
+ }
+ if(aSelection.IsNull()) {
+ std::list<std::string> aListofNames;
+ int n = ParseName(theSubShapeName, aListofNames);
+ if(n > 1 && n < 5) {
+ TopTools_ListOfShape aList;
+ for(std::list<std::string>::iterator it =aListofNames.begin();it != aListofNames.end();it++){
+ const TopoDS_Shape aFace = findFaceByName(*it, aDoc);
+ 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));
+ setValue(aCont, aShapeToBeSelected);
+ }
+ }
+ break;
+ case TopAbs_VERTEX:
+ {
+ TopoDS_Shape aSelection;
+ const TDF_Label& aLabel = aDoc->findNamingName(theSubShapeName);
+ if(!aLabel.IsNull()) {
+ Handle(TNaming_NamedShape) aNS;
+ if(aLabel.FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
+ const TopoDS_Shape& aShape = aNS->Get();
+ if(!aShape.IsNull()) {
+ if(aShape.ShapeType() == TopAbs_COMPOUND)
+ aSelection = getShapeFromCompound(theSubShapeName, aShape);
+ else
+ aSelection = aShape;
+ }
+ }
+ }
+ if(aSelection.IsNull()) {
+ std::list<std::string> aListofNames;
+ int n = ParseName(theSubShapeName, aListofNames);
+ if(n > 1 && n < 4) { // 2 || 3
+ TopTools_ListOfShape aList;
+ for(std::list<std::string>::iterator it =aListofNames.begin();it != aListofNames.end();it++){
+ const TopoDS_Shape aFace = findFaceByName(*it, aDoc);
+ 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));
+ setValue(aCont, aShapeToBeSelected);
+ }
+ }
+ break;
+ default: //TopAbs_SHAPE
+ return;
+ }
+
+}
+
+int Model_AttributeSelection::Id()
+{
+ std::shared_ptr<GeomAPI_Shape> aSelection = value();
+ std::shared_ptr<GeomAPI_Shape> aContext = context()->shape();
+ const TopoDS_Shape& aMainShape = aContext->impl<TopoDS_Shape>();
+ const TopoDS_Shape& aSubShape = aSelection->impl<TopoDS_Shape>();
+ int anID = 0;
+ if (aSelection && !aSelection->isNull() &&
+ aContext && !aContext->isNull())
+ {
+ TopTools_IndexedMapOfShape aSubShapesMap;
+ TopExp::MapShapes(aMainShape, aSubShapesMap);
+ anID = aSubShapesMap.FindIndex(aSubShape);
+ }
+ return anID;
+}