1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
3 // File: ModelAPI_ResultConstruction.cpp
4 // Created: 07 Jul 2014
5 // Author: Mikhail PONIKAROV
7 #include <Model_ResultConstruction.h>
9 #include <Model_Data.h>
10 #include <ModelAPI_CompositeFeature.h>
11 #include <Model_SelectionNaming.h>
12 #include <ModelAPI_Events.h>
13 #include <Config_PropManager.h>
14 #include <GeomAPI_PlanarEdges.h>
15 #include <GeomAPI_Shape.h>
16 #include <GeomAlgoAPI_SketchBuilder.h>
17 #include <Events_Loop.h>
19 #include <TDF_Reference.hxx>
20 #include <TDF_ChildIterator.hxx>
21 #include <TNaming_NamedShape.hxx>
22 #include <TNaming_Builder.hxx>
23 #include <TDataStd_Integer.hxx>
24 #include <TDataStd_IntPackedMap.hxx>
25 #include <TDataStd_Name.hxx>
26 #include <TDataStd_UAttribute.hxx>
27 #include <TColStd_MapOfTransient.hxx>
28 #include <TColStd_MapIteratorOfPackedMapOfInteger.hxx>
29 #include <BRep_Tool.hxx>
30 #include <BRep_Builder.hxx>
32 #include <TopoDS_Shape.hxx>
33 #include <TopoDS_Edge.hxx>
34 #include <TopoDS_Vertex.hxx>
35 #include <TopExp_Explorer.hxx>
36 #include <Precision.hxx>
38 // identifier that it is full result selected, but in external document (for internal index is 0)
39 Standard_GUID kFULL_RESULT_ID("ee87e529-da6f-46af-be25-5e0fefde52f7");
42 void Model_ResultConstruction::colorConfigInfo(std::string& theSection, std::string& theName,
43 std::string& theDefault)
45 theSection = "Visualization";
46 theName = "result_construction_color";
47 theDefault = DEFAULT_COLOR();
50 void Model_ResultConstruction::setShape(std::shared_ptr<GeomAPI_Shape> theShape)
52 if (myShape != theShape && (!theShape.get() || !theShape->isEqual(myShape))) {
53 static const Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
54 ModelAPI_EventCreator::get()->sendUpdated(data()->owner(), anEvent);
57 myFacesUpToDate = false;
63 std::shared_ptr<GeomAPI_Shape> Model_ResultConstruction::shape()
68 Model_ResultConstruction::Model_ResultConstruction()
72 myFacesUpToDate = false;
75 void Model_ResultConstruction::setIsInHistory(const bool isInHistory)
77 myIsInHistory = isInHistory;
80 int Model_ResultConstruction::facesNum()
82 if (!myFacesUpToDate) {
83 std::shared_ptr<GeomAPI_PlanarEdges> aWirePtr =
84 std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(myShape);
86 std::list<std::shared_ptr<GeomAPI_Shape> > aFaces;
87 GeomAlgoAPI_SketchBuilder::createFaces(aWirePtr->origin(), aWirePtr->dirX(),
88 aWirePtr->norm(), aWirePtr, aFaces);
89 std::list<std::shared_ptr<GeomAPI_Shape> >::iterator aFIter = aFaces.begin();
90 for(; aFIter != aFaces.end(); aFIter++) {
91 std::shared_ptr<GeomAPI_Face> aFace(new GeomAPI_Face(*aFIter));
92 if (aFace.get() && !aFace->isNull())
93 myFaces.push_back(aFace);
96 myFacesUpToDate = true;
98 return int(myFaces.size());
101 std::shared_ptr<GeomAPI_Face> Model_ResultConstruction::face(const int theIndex)
103 return myFaces[theIndex];
106 bool Model_ResultConstruction::isInfinite()
111 void Model_ResultConstruction::setInfinite(const bool theInfinite)
113 myIsInfinite = theInfinite;
116 void Model_ResultConstruction::setIsConcealed(const bool theValue)
118 // do nothing: the construction element is never consealed
121 static const int kSTART_VERTEX_DELTA = 1000000;
123 static void registerSubShape(TDF_Label theMainLabel, TopoDS_Shape theShape,
124 const int theID, std::shared_ptr<Model_Document> theDoc,
125 bool theSelectionMode,
126 std::map<int, int>& theOrientations,
127 // name of sub-elements by ID to be exported instead of indexes
128 std::map<int, std::string>& theSubNames,
129 Handle(TDataStd_IntPackedMap) theRefs = Handle(TDataStd_IntPackedMap)(),
130 const int theOrientation = 0)
132 TDF_Label aLab = theID == 0 ? theMainLabel : theMainLabel.FindChild(theID);
133 if (theOrientation != 0) { // store the orientation of edge relatively to face if needed
134 TDataStd_Integer::Set(aLab, theOrientation);
136 TNaming_Builder aBuilder(aLab);
137 // wire never happens as sub, it must be generated to be found
138 // by SelectionNaming TNaming_Tool::NamedShape
139 if (theSelectionMode && theShape.ShapeType() != TopAbs_WIRE)
140 aBuilder.Select(theShape, theShape);
142 aBuilder.Generated(theShape);
143 std::stringstream aName;
144 // #1839 : do not store name of the feature in the tree, since this name could be changed
145 //aName<<theContextFeature->name();
146 if (theShape.ShapeType() != TopAbs_COMPOUND) { // compound means the whole result for construction
148 if (theShape.ShapeType() == TopAbs_FACE) aName<<"Face";
149 else if (theShape.ShapeType() == TopAbs_WIRE) aName<<"Wire";
150 else if (theShape.ShapeType() == TopAbs_EDGE) aName<<"Edge";
151 else if (theShape.ShapeType() == TopAbs_VERTEX) aName<<"Vertex";
153 if (theRefs.IsNull()) {
155 if (theOrientation == 1)
157 else if (theOrientation == -1)
159 } else { // make a composite name from all sub-elements indexes: "1_2_3_4"
160 TColStd_MapIteratorOfPackedMapOfInteger aRef(theRefs->GetMap());
161 for(; aRef.More(); aRef.Next()) {
162 aName<<"-"<<theSubNames[aRef.Key()];
163 if (theOrientations.find(aRef.Key()) != theOrientations.end()) {
164 if (theOrientations[aRef.Key()] == 1)
166 else if (theOrientations[aRef.Key()] == -1)
173 theDoc->addNamingName(aLab, aName.str());
174 TDataStd_Name::Set(aLab, aName.str().c_str());
177 TDF_Label Model_ResultConstruction::startLabel(
178 const std::shared_ptr<ModelAPI_Document> theExtDoc, bool& theExternal)
180 theExternal = theExtDoc.get() && theExtDoc != document();
181 if (theExternal) { // external document is used
182 std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(theExtDoc);
183 return aDoc->extConstructionsLabel();
185 std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
186 return aData->label();
189 int Model_ResultConstruction::select(const std::shared_ptr<GeomAPI_Shape>& theSubShape,
190 const std::shared_ptr<ModelAPI_Document> theExtDoc, const int theIndex)
192 int anIndex; // resulting index of the sub-label
193 TopoDS_Shape aSubShape;
194 if (theSubShape.get()) {
195 aSubShape = theSubShape->impl<TopoDS_Shape>();
196 } else if (shape().get()) {
197 aSubShape = shape()->impl<TopoDS_Shape>();
199 // if external document requires this selection, put the naming structures to this doc
200 // to support the naming mechanism in this document correctly
202 TDF_Label aDataLab = startLabel(theExtDoc, anExternal);
203 if (theIndex == -1) {
204 anIndex = anExternal ? 2 : 1; // for the external doc don't mind about the main shape
206 if (theSubShape.get() || anExternal) { // searching for already selected sub (or whole for ext)
207 // iterate all the already presented shapes to see the same
208 TDF_ChildIterator aSubsIter(aDataLab, Standard_False);
209 for(; aSubsIter.More(); aSubsIter.Next()) {
210 const TDF_Label aLab = aSubsIter.Value();
211 if (aLab.Tag() == 1) // skip the root shape label
213 Handle(TNaming_NamedShape) aNS;
214 if (aLab.FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
215 if (aNS->Get().IsSame(aSubShape)) {
216 return aLab.Tag() - 1; // found exactly the needed shape, nothing else to do
219 anIndex = aLab.Tag(); // searching for the latest index
221 anIndex = (anIndex == 1) ? 2 : (anIndex + 1); // next after 1-root, or next after all
224 anIndex = theIndex + 1;
227 // set the naming structure at index
228 TDF_Label aLab = aDataLab.FindChild(anIndex, Standard_True);
230 // if the subshape is part of a result face, select the whole face (#1997)
231 bool isSelectionMode = false; // and other don't set shapes - all the naming is in face label
232 if (!aSubShape.IsNull() && aSubShape.ShapeType() > TopAbs_FACE) {
233 for(int aFaceIndex = 0; aFaceIndex < facesNum(); aFaceIndex++) {
234 TopExp_Explorer anExp(face(aFaceIndex)->impl<TopoDS_Shape>(), aSubShape.ShapeType());
235 for(; anExp.More(); anExp.Next()) {
236 if (aSubShape.IsSame(anExp.Current())) { // this is the case: select the whole face
237 // here just store the face index (to update face if update of edge is needed)
238 TNaming_Builder aBuilder(aLab);
239 aBuilder.Select(aSubShape, aSubShape);
240 int aFaceSelID = select(face(aFaceIndex), theExtDoc, -1);
241 TDF_Reference::Set(aLab, aLab.Father().FindChild(aFaceSelID));
242 isSelectionMode = true;
249 // external full result is not identified by index == 0, so, add here the ID
250 if (!theSubShape.get()) {
251 TDataStd_UAttribute::Set(aLab, kFULL_RESULT_ID);
253 TNaming_Builder aBuilder(aLab);
254 // store all sub-faces naming since faces may be used for extrusion, where all edges are needed
255 Handle(TDataStd_IntPackedMap) anIndices = TDataStd_IntPackedMap::Set(aLab);
256 std::list<int> aFacesIndexes;
257 for(int a = 0; a < facesNum(); a++) {
258 anIndices->Add(select(face(a), theExtDoc, -1));
263 { // this to have erased Builder after the shape was generated (NS on this label may be changed)
264 TNaming_Builder aBuilder(aLab);
265 if (aSubShape.IsNull()) {
266 return anIndex - 1; // just keep empty named shape
268 // wire never happens as sub, it must be generated to be found
269 // by SelectionNaming TNaming_Tool::NamedShape
270 if (isSelectionMode && aSubShape.ShapeType() != TopAbs_WIRE) {
271 aBuilder.Select(aSubShape, aSubShape);
273 aBuilder.Generated(aSubShape);
277 if (anIndex == 1 && isInfinite()) { // infinitive results has no sub-selection
280 ResultPtr aThisPtr = std::dynamic_pointer_cast<ModelAPI_Result>(data()->owner());
281 FeaturePtr aThisFeature = document()->feature(aThisPtr);
282 CompositeFeaturePtr aComposite =
283 std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aThisFeature);
284 if (!aComposite || aComposite->numberOfSubs() == 0) {
285 // saving of context is enough: result construction contains exactly the needed shape
289 // identify the results of sub-object of the composite by edges
290 // save type of the selected shape in integer attribute
291 TopAbs_ShapeEnum aShapeType = aSubShape.ShapeType();
292 TDataStd_Integer::Set(aLab, (int)aShapeType);
294 TColStd_MapOfTransient allCurves;
295 if (aShapeType == TopAbs_VERTEX) { // compare positions
296 aVertexPos = BRep_Tool::Pnt(TopoDS::Vertex(aSubShape));
298 for(TopExp_Explorer anEdgeExp(aSubShape, TopAbs_EDGE); anEdgeExp.More(); anEdgeExp.Next()) {
299 TopoDS_Edge anEdge = TopoDS::Edge(anEdgeExp.Current());
300 Standard_Real aFirst, aLast;
301 Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
302 allCurves.Add(aCurve);
305 std::shared_ptr<Model_Document> aMyDoc =
306 std::dynamic_pointer_cast<Model_Document>(document());
307 // iterate and store the result ids of sub-elements and sub-elements to sub-labels
308 Handle(TDataStd_IntPackedMap) aRefs = TDataStd_IntPackedMap::Set(aLab);
309 std::map<int, int> anOrientations; //map from edges IDs to orientations of these edges in face
310 std::map<int, std::string> aSubNames; //map from edges IDs to names of edges
312 const int aSubNum = aComposite->numberOfSubs();
313 for(int a = 0; a < aSubNum; a++) {
314 FeaturePtr aSub = aComposite->subFeature(a);
315 const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aSub->results();
316 std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRes = aResults.cbegin();
317 // there may be many shapes (circle and center): register if at least one is in selection
318 for(; aRes != aResults.cend(); aRes++) {
319 ResultConstructionPtr aConstr =
320 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aRes);
321 if (!aConstr->shape()) {
324 if (aShapeType == TopAbs_VERTEX) {
325 if (aConstr->shape()->isVertex()) { // compare vertices positions
326 const TopoDS_Shape& aVertex = aConstr->shape()->impl<TopoDS_Shape>();
327 gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aVertex));
328 if (aPnt.IsEqual(aVertexPos, Precision::Confusion())) {
329 aRefs->Add(aComposite->subFeatureId(a));
330 aSubNames[aComposite->subFeatureId(a)] = Model_SelectionNaming::shortName(aConstr);
332 } else { // get first or last vertex of the edge: last is stored with additional delta
333 const TopoDS_Shape& anEdge = aConstr->shape()->impl<TopoDS_Shape>();
334 int aDelta = kSTART_VERTEX_DELTA;
335 for(TopExp_Explorer aVExp(anEdge, TopAbs_VERTEX); aVExp.More(); aVExp.Next()) {
336 gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aVExp.Current()));
337 if (aPnt.IsEqual(aVertexPos, Precision::Confusion())) {
338 aRefs->Add(aDelta + aComposite->subFeatureId(a));
339 aSubNames[aDelta + aComposite->subFeatureId(a)] =
340 Model_SelectionNaming::shortName(aConstr, aDelta / kSTART_VERTEX_DELTA);
343 aDelta += kSTART_VERTEX_DELTA;
347 if (aConstr->shape()->isEdge()) {
348 const TopoDS_Shape& aResShape = aConstr->shape()->impl<TopoDS_Shape>();
349 TopoDS_Edge anEdge = TopoDS::Edge(aResShape);
350 if (!anEdge.IsNull()) {
351 Standard_Real aFirst, aLast;
352 Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
353 if (allCurves.Contains(aCurve)) {
354 int anID = aComposite->subFeatureId(a);
356 aSubNames[anID] = Model_SelectionNaming::shortName(aConstr);
357 if (aShapeType != TopAbs_EDGE) { // face needs the sub-edges on sub-labels
358 // add edges to sub-label to support naming for edges selection
359 TopExp_Explorer anEdgeExp(aSubShape, TopAbs_EDGE);
360 for(; anEdgeExp.More(); anEdgeExp.Next()) {
361 TopoDS_Edge anEdge = TopoDS::Edge(anEdgeExp.Current());
362 Standard_Real aFirst, aLast;
363 Handle(Geom_Curve) aFaceCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
364 if (aFaceCurve == aCurve) {
365 int anOrient = Model_SelectionNaming::edgeOrientation(aSubShape, anEdge);
366 anOrientations[anID] = anOrient;
368 TDF_Label aSubLab = aLab.FindChild(anID);
369 std::string aName = "Edge-" + Model_SelectionNaming::shortName(aConstr, 0);
370 TNaming_Builder aBuilder(aSubLab);
372 aBuilder.Select(anEdge, anEdge);
374 aBuilder.Generated(anEdge);
375 aMyDoc->addNamingName(aSubLab, aName.c_str());
376 TDataStd_Name::Set(aSubLab, aName.c_str());
379 // store the orientation of edge relatively to face if needed
380 TDataStd_Integer::Set(aSubLab, anOrient);
384 } else { // put vertices of the selected edge to sub-labels
385 // add edges to sub-label to support naming for edges selection
386 int aDelta = kSTART_VERTEX_DELTA;
387 int aTagIndex = anID + kSTART_VERTEX_DELTA;
388 for(TopExp_Explorer anEdgeExp(aSubShape, TopAbs_VERTEX);
391 aTagIndex += kSTART_VERTEX_DELTA,
392 aDelta += kSTART_VERTEX_DELTA) {
393 TopoDS_Vertex aV = TopoDS::Vertex(anEdgeExp.Current());
395 TDF_Label aSubLab = aLab.FindChild(aTagIndex);
396 std::string aName = "Vertex-"
397 + Model_SelectionNaming::shortName(aConstr, aDelta / kSTART_VERTEX_DELTA);
398 TNaming_Builder aBuilder(aLab);
400 aBuilder.Select(aV, aV);
402 aBuilder.Generated(aV);
403 aMyDoc->addNamingName(aLab, aName.c_str());
404 TDataStd_Name::Set(aLab, aName.c_str());
413 // store the selected as primitive
414 registerSubShape(aLab, aSubShape, 0, aMyDoc, isSelectionMode, anOrientations, aSubNames, aRefs);
418 std::shared_ptr<GeomAPI_Shape> Model_ResultConstruction::shape(const int theIndex,
419 const std::shared_ptr<ModelAPI_Document> theExtDoc)
421 std::shared_ptr<GeomAPI_Shape> aResult;
423 return aResult; // the whole shape, so, NULL
426 TDF_Label aLab = startLabel(theExtDoc, isExt).FindChild(theIndex + 1);
427 if (!aLab.IsNull()) { // index is not bad
428 Handle(TNaming_NamedShape) aSelection;
429 if (aLab.FindAttribute(TNaming_NamedShape::GetID(), aSelection)) {
430 TopoDS_Shape aSelShape = aSelection->Get();
431 if (aSelShape.IsNull())
432 return aResult; // shape equal to context => null
433 aResult = std::shared_ptr<GeomAPI_Shape>(new GeomAPI_Shape);
434 aResult->setImpl(new TopoDS_Shape(aSelShape));
441 bool Model_ResultConstruction::update(const int theIndex,
442 const std::shared_ptr<ModelAPI_Document> theExtDoc, bool& theModified)
446 TDF_Label aLab = startLabel(theExtDoc, anExt).FindChild(theIndex + 1, Standard_True);
447 if (theIndex == 0 || aLab.IsAttribute(kFULL_RESULT_ID)) { // full for external same as index == 0
448 // it is just reference to construction, not sub-shape
449 // if there is a sketch, the sketch-naming must be updated
451 // update all faces named by the whole result
453 Handle(TDataStd_IntPackedMap) anIndices;
454 if (aLab.FindAttribute(TDataStd_IntPackedMap::GetID(), anIndices)) {
455 NCollection_Map<TopoDS_Shape> aFaces; // collect faces, updated in the tree
456 TColStd_MapIteratorOfPackedMapOfInteger anIndexIter(anIndices->GetMap());
457 Handle(TColStd_HPackedMapOfInteger) aNewPackedMap =
458 new TColStd_HPackedMapOfInteger; // with only faces that are ok
459 // iterate to find existing faces, updated
460 for(; anIndexIter.More(); anIndexIter.Next()) {
461 if (update(anIndexIter.Key(), theExtDoc, theModified)) {
462 GeomShapePtr aFace = shape(anIndexIter.Key(), theExtDoc);
463 if (!aFaces.Contains(aFace->impl<TopoDS_Shape>())) {
464 aNewPackedMap->ChangeMap().Add(anIndexIter.Key());
465 aFaces.Add(aFace->impl<TopoDS_Shape>());
469 // then iterate all existing faces to find new faces
470 int aCurrentFacesNum = facesNum();
471 for(int a = 0; a < aCurrentFacesNum; a++) {
472 GeomShapePtr aFace = face(a);
473 if (!aFaces.Contains(aFace->impl<TopoDS_Shape>())) {
475 int aNewFaceIndex = select(aFace, theExtDoc, -1);
476 if (aNewFaceIndex > 0) {
477 aNewPackedMap->ChangeMap().Add(aNewFaceIndex);
481 anIndices->ChangeMap(aNewPackedMap);
485 // For correct naming selection, put the shape into the naming structure.
486 // It seems sub-shapes are not needed: only this shape is (and can be ) selected.
487 TNaming_Builder aBuilder(aLab);
488 aBuilder.Generated(shape()->impl<TopoDS_Shape>());
490 return shape() && !shape()->isNull();
492 // construction: identification by the results indexes, recompute faces and
493 // take the face that more close by the indexes
494 ResultPtr aThisPtr = std::dynamic_pointer_cast<ModelAPI_Result>(data()->owner());
495 FeaturePtr aContextFeature = document()->feature(aThisPtr);
497 // sketch sub-element
498 if (std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aContextFeature).get())
500 // update the referenced object if it is sub
501 Handle(TDF_Reference) aRef;
502 if (aLab.FindAttribute(TDF_Reference::GetID(), aRef)) {
503 int aFaceIndex = aRef->Get().Tag();
504 // don't check selection ,since face may disappear, but the shape stays correct
505 Model_ResultConstruction::update(aFaceIndex, theExtDoc, theModified);
507 // getting a type of selected shape
508 Handle(TDataStd_Integer) aTypeAttr;
509 if (!aLab.FindAttribute(TDataStd_Integer::GetID(), aTypeAttr)) {
512 TopAbs_ShapeEnum aShapeType = (TopAbs_ShapeEnum)(aTypeAttr->Get());
513 // selected indexes will be needed in each "if"
514 Handle(TDataStd_IntPackedMap) aSubIds;
515 std::shared_ptr<GeomAPI_Shape> aNewSelected;
517 !aLab.FindAttribute(TDataStd_IntPackedMap::GetID(), aSubIds) || aSubIds->Extent() == 0;
518 // for now working only with composite features
519 CompositeFeaturePtr aComposite =
520 std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aContextFeature);
521 if (!aComposite.get() || aComposite->numberOfSubs() == 0) {
525 if (aShapeType == TopAbs_FACE || aShapeType == TopAbs_WIRE) {
526 // compound is for the whole sketch selection
527 // If this is a wire with plane defined then it is a sketch-like object
528 if (!facesNum()) // no faces, update can not work correctly
530 // if there is no edges indexes, any face can be used: take the first
531 std::shared_ptr<GeomAPI_Shape> aNewSelected;
533 aNewSelected = face(0);
534 } else { // searching for most looks-like initial face by the indexes
535 // prepare edges of the current result for the fast searching
536 // curves and orientations of edges
537 NCollection_DataMap<Handle(Geom_Curve), int> allCurves;
538 const int aSubNum = aComposite->numberOfSubs();
539 for(int a = 0; a < aSubNum; a++) {
540 int aSubID = aComposite->subFeatureId(a);
541 if (aSubIds->Contains(aSubID)) {
542 FeaturePtr aSub = aComposite->subFeature(a);
543 const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aSub->results();
544 std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRes;
545 for(aRes = aResults.cbegin(); aRes != aResults.cend(); aRes++) {
546 ResultConstructionPtr aConstr =
547 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aRes);
548 if (aConstr->shape() && aConstr->shape()->isEdge()) {
549 const TopoDS_Shape& aResShape = aConstr->shape()->impl<TopoDS_Shape>();
550 TopoDS_Edge anEdge = TopoDS::Edge(aResShape);
551 if (!anEdge.IsNull()) {
552 Standard_Real aFirst, aLast;
553 Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
554 // searching for orientation information
556 Handle(TDataStd_Integer) anInt;
557 if (aLab.FindChild(aSubID).FindAttribute(TDataStd_Integer::GetID(), anInt)) {
558 anOrient = anInt->Get();
560 allCurves.Bind(aCurve, anOrient);
566 aNewSelected = Model_SelectionNaming::findAppropriateFace(
567 aThisPtr, allCurves, aShapeType == TopAbs_WIRE);
569 if (aNewSelected) { // store this new selection
570 select(aNewSelected, theExtDoc, theIndex);
574 // if the selection is not found, put the empty shape:
575 // it's better to have disappeared shape, than the old, the lost one
576 TNaming_Builder anEmptyBuilder(aLab);
579 } else if (aShapeType == TopAbs_EDGE) {
580 // just reselect the edge by the id
581 const int aSubNum = aComposite->numberOfSubs();
582 for(int a = 0; a < aSubNum; a++) {
583 // if aSubIds take any, the first appropriate
584 if (aSubIds->IsEmpty() || aSubIds->Contains(aComposite->subFeatureId(a))) {
585 // found the appropriate feature
586 FeaturePtr aFeature = aComposite->subFeature(a);
587 std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aResIter =
588 aFeature->results().cbegin();
589 for(;aResIter != aFeature->results().cend(); aResIter++) {
590 ResultConstructionPtr aRes =
591 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aResIter);
592 if (aRes && aRes->shape() && aRes->shape()->isEdge()) { // found!
593 select(aRes->shape(), theExtDoc, theIndex);
600 } else if (aShapeType == TopAbs_VERTEX) {
601 // just reselect the vertex by the id of edge
602 const int aSubNum = aComposite->numberOfSubs();
603 for(int a = 0; a < aSubNum; a++) {
604 // if aSubIds take any, the first appropriate
605 int aFeatureID = aComposite->subFeatureId(a);
606 if (aSubIds->IsEmpty() || aSubIds->Contains(aFeatureID) ||
607 aSubIds->Contains(aFeatureID + kSTART_VERTEX_DELTA) ||
608 aSubIds->Contains(aFeatureID + kSTART_VERTEX_DELTA * 2)) {
609 // searching for deltas
611 if (aSubIds->Contains(aFeatureID + kSTART_VERTEX_DELTA)) aVertexNum = 1;
612 else if (aSubIds->Contains(aFeatureID + kSTART_VERTEX_DELTA * 2)) aVertexNum = 2;
613 // found the feature with appropriate edge
614 FeaturePtr aFeature = aComposite->subFeature(a);
615 std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aResIter =
616 aFeature->results().cbegin();
617 for(;aResIter != aFeature->results().cend(); aResIter++) {
618 ResultConstructionPtr aRes =
619 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aResIter);
620 if (aRes && aRes->shape()) {
621 if (aRes->shape()->isVertex() && aVertexNum == 0) { // found!
622 select(aRes->shape(), theExtDoc, theIndex);
625 } else if (aRes->shape()->isEdge() && aVertexNum > 0) {
626 const TopoDS_Shape& anEdge = aRes->shape()->impl<TopoDS_Shape>();
628 for(TopExp_Explorer aVExp(anEdge, TopAbs_VERTEX); aVExp.More(); aVExp.Next()) {
629 if (aVIndex == aVertexNum) { // found!
630 std::shared_ptr<GeomAPI_Shape> aVertex(new GeomAPI_Shape);
631 aVertex->setImpl(new TopoDS_Shape(aVExp.Current()));
632 select(aVertex, theExtDoc, theIndex);
644 } else { // simple construction element: the selected is that needed
645 select(shape(), theExtDoc, theIndex);
649 return false; // unknown case