Salome HOME
Get rid of compilation warnings. Part I.
[modules/shaper.git] / src / Model / Model_ResultConstruction.cpp
1 // Copyright (C) 2014-2020  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include <Model_ResultConstruction.h>
21
22 #include <Model_Data.h>
23 #include <ModelAPI_CompositeFeature.h>
24 #include <GeomAlgoAPI_SketchBuilder.h>
25 #include <GeomAPI_Tools.h>
26 #include <ModelAPI_Events.h>
27 #include <Model_Document.h>
28 #include <GeomAPI_PlanarEdges.h>
29 #include <GeomAPI_Shape.h>
30 #include <Events_Loop.h>
31 #include <GeomDataAPI_Point.h>
32 #include <GeomDataAPI_Dir.h>
33
34 #include <TDF_ChildIDIterator.hxx>
35 #include <TNaming_NamedShape.hxx>
36 #include <TNaming_Builder.hxx>
37 #include <TDataStd_IntPackedMap.hxx>
38 #include <TDataStd_Name.hxx>
39 #include <TDataStd_UAttribute.hxx>
40 #include <BRep_Builder.hxx>
41 #include <TopoDS.hxx>
42 #include <TopoDS_Edge.hxx>
43 #include <TopoDS_Vertex.hxx>
44 #include <TopoDS_ListOfShape.hxx>
45 #include <TopExp_Explorer.hxx>
46 #include <TopTools_MapOfShape.hxx>
47 #include <NCollection_IndexedDataMap.hxx>
48
49 #include <algorithm>
50
51 typedef NCollection_IndexedDataMap<TopoDS_Face, TColStd_ListOfInteger> MapFaceToEdgeIndices;
52
53 /// Convert each edge of sketch to corresponding integer value
54 /// \param[in]  theComposite      sketch feature
55 /// \param[out] theCurvesIndices  map curve to its index
56 /// \param[out] theEdgesIndices   indexed edge
57 /// \param[out] theEdgesNames     indexed name for edge
58 static void indexingSketchEdges(
59     const CompositeFeaturePtr& theComposite,
60     NCollection_DataMap<Handle(Geom_Curve), int>& theCurvesIndices,
61     NCollection_DataMap<int, TopoDS_Edge>& theEdgesIndices,
62     std::map<int, std::string>& theEdgesNames);
63
64 /// Convert each face to the list of indices of its edges
65 /// \param[in]  theFaces          list of faces to proceed
66 /// \param[in]  theCurvesIndices  index of each curve
67 /// \param[out] theFaceEdges      map face to indices of its edges
68 static void faceToEdgeIndices(
69     const ListOfShape& theFaces,
70     const NCollection_DataMap<Handle(Geom_Curve), int>& theCurvesIndices,
71     MapFaceToEdgeIndices& theFaceEdges);
72
73 /// Assign faces to tags for the specified label
74 /// \param theDocument        current document
75 /// \param theShapeLabel      label to store shapes
76 /// \param theName            name of the object
77 /// \param theShape           shape to be stored to the label
78 /// \param theFacesOrder      faces to be assigned to specified tag
79 /// \param theUnorderedFaces  faces which may be stored to any tag
80 /// \param theFaceEdges       indices of edges for each face
81 /// \param theEdgesIndices    indices of edges
82 /// \param theEdgesNames      named of edges
83 static void storeFacesOnLabel(std::shared_ptr<Model_Document>& theDocument,
84                               TDF_Label& theShapeLabel,
85                               const std::string& theName,
86                               const TopoDS_Shape& theShape,
87                               NCollection_DataMap<int, TopoDS_Face>& theFacesOrder,
88                               NCollection_List<TopoDS_Face>& theUnorderedFaces,
89                               const MapFaceToEdgeIndices& theFaceEdges,
90                               const NCollection_DataMap<int, TopoDS_Edge>& theEdgesIndices,
91                               const std::map<int, std::string>& theEdgesNames);
92
93
94 // identifier of the infinite result
95 Standard_GUID kIS_INFINITE("dea8cc5a-53f2-49c1-94e8-a947bed20a9f");
96 // identifier of the result not in history
97 Standard_GUID kIS_IN_HISTORY("a9aec01c-805e-44d1-b5d2-a63f06522f8a");
98
99 void Model_ResultConstruction::colorConfigInfo(std::string& theSection, std::string& theName,
100                                        std::string& theDefault)
101 {
102   theSection = "Visualization";
103   theName = "result_construction_color";
104   theDefault = DEFAULT_COLOR();
105 }
106
107 void Model_ResultConstruction::setShape(std::shared_ptr<GeomAPI_Shape> theShape)
108 {
109   if (myShape != theShape) {
110     storeShape(theShape);
111     if (!theShape.get() || !theShape->isEqual(myShape)) {
112       static const Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
113       ModelAPI_EventCreator::get()->sendUpdated(data()->owner(), anEvent);
114     }
115     myShape = theShape;
116   }
117 }
118
119 std::shared_ptr<GeomAPI_Shape> Model_ResultConstruction::shape()
120 {
121   return myShape;
122 }
123
124 static std::string shortName(
125   std::shared_ptr<ModelAPI_ResultConstruction>& theConstr)
126 {
127   std::string aName = theConstr->data()->name();
128   // remove "-", "/" and "&" command-symbols
129   aName.erase(std::remove(aName.begin(), aName.end(), '-'), aName.end());
130   aName.erase(std::remove(aName.begin(), aName.end(), '/'), aName.end());
131   aName.erase(std::remove(aName.begin(), aName.end(), '&'), aName.end());
132   // remove the last 's', 'e', 'f' and 'r' symbols:
133   // they are used as markers of start/end/forward/reversed indicators
134   static const std::string aSyms("sefr");
135   std::string::iterator aSuffix = aName.end() - 1;
136   while(aSyms.find(*aSuffix) != std::string::npos) {
137     --aSuffix;
138   }
139   aName.erase(aSuffix + 1, aName.end());
140   return aName;
141 }
142
143 bool Model_ResultConstruction::updateShape()
144 {
145   std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
146   if (aData && aData->isValid()) {
147     TDF_Label aShapeLab = aData->shapeLab();
148     Handle(TNaming_NamedShape) aNS;
149     if (aShapeLab.FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
150       TopoDS_Shape aShape = aNS->Get();
151       if (!aShape.IsNull()) {
152         if (aShape.ShapeType() == TopAbs_COMPOUND) {
153           // restore the sketch planar edges object
154           std::shared_ptr<GeomAPI_PlanarEdges> aBigWire(new GeomAPI_PlanarEdges);
155           aBigWire->setImpl<TopoDS_Shape>(new TopoDS_Shape(aShape));
156           FeaturePtr aSketch =
157             document()->feature(std::dynamic_pointer_cast<ModelAPI_Result>(data()->owner()));
158           std::shared_ptr<GeomDataAPI_Point> anOrigin =
159             std::dynamic_pointer_cast<GeomDataAPI_Point>(aSketch->data()->attribute("Origin"));
160           std::shared_ptr<GeomDataAPI_Dir> aDirX =
161             std::dynamic_pointer_cast<GeomDataAPI_Dir>(aSketch->data()->attribute("DirX"));
162           std::shared_ptr<GeomDataAPI_Dir> aNorm =
163             std::dynamic_pointer_cast<GeomDataAPI_Dir>(aSketch->data()->attribute("Norm"));
164           if (anOrigin.get() && aDirX.get() && aNorm.get()) {
165             aBigWire->setPlane(anOrigin->pnt(), aDirX->dir(), aNorm->dir());
166             myShape = aBigWire;
167             return true;
168           }
169         }
170         // just restore shape
171         GeomShapePtr aGShape(new GeomAPI_Shape);
172         aGShape->setImpl<TopoDS_Shape>(new TopoDS_Shape(aShape));
173         myShape = GeomAPI_Tools::getTypedShape(aGShape); // restore the sketch sub-components
174         return true;
175       }
176     }
177   }
178   return false;
179 }
180
181 Model_ResultConstruction::Model_ResultConstruction()
182 {
183 }
184
185 bool Model_ResultConstruction::isInHistory()
186 {
187   std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
188   if (aData.get() && aData->isValid()) {
189     return !aData->label().IsAttribute(kIS_IN_HISTORY); // by default no attribute, but in history
190   }
191   return true;  // unknown case
192 }
193
194 void Model_ResultConstruction::setIsInHistory(const bool isInHistory)
195 {
196   std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
197   if (aData.get() && aData->isValid()) {
198     if (!isInHistory)
199       TDataStd_UAttribute::Set(aData->label(), kIS_IN_HISTORY);
200     else
201       aData->label().ForgetAttribute(kIS_IN_HISTORY);
202   }
203 }
204
205 bool Model_ResultConstruction::isInfinite()
206 {
207   std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
208   if (aData.get() && aData->isValid()) {
209     return aData->label().IsAttribute(kIS_INFINITE);
210   }
211   return false;  // unknown case
212 }
213
214 void Model_ResultConstruction::setInfinite(const bool theInfinite)
215 {
216   std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
217   if (aData.get() && aData->isValid()) {
218     if (theInfinite)
219       TDataStd_UAttribute::Set(aData->label(), kIS_INFINITE);
220     else
221       aData->label().ForgetAttribute(kIS_INFINITE);
222   }
223 }
224
225 int Model_ResultConstruction::facesNum(const bool theUpdateNaming)
226 {
227   int aResult = 0;
228   std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
229   if (aData.get() && aData->isValid()) {
230     TDF_Label aShapeLab = aData->shapeLab();
231     TDF_ChildIDIterator anOldIter(aShapeLab, TDataStd_IntPackedMap::GetID());
232     for (; anOldIter.More(); anOldIter.Next()) {
233       aResult++;
234     }
235   }
236   return aResult;
237 }
238
239 std::shared_ptr<GeomAPI_Face> Model_ResultConstruction::face(const int theIndex)
240 {
241   std::shared_ptr<GeomAPI_Face> aResult;
242   int anIndex = 0;
243   std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
244   if (aData.get() && aData->isValid()) {
245     TDF_Label aShapeLab = aData->shapeLab();
246     TDF_ChildIDIterator anOldIter(aShapeLab, TDataStd_IntPackedMap::GetID());
247     for (; anOldIter.More(); anOldIter.Next()) {
248       if (anIndex == theIndex) {
249         Handle(TNaming_NamedShape) aNS;
250         anOldIter.Value()->Label().FindAttribute(TNaming_NamedShape::GetID(), aNS);
251         aResult.reset(new GeomAPI_Face);
252         aResult->setImpl(new TopoDS_Shape(aNS->Get()));
253         break;
254       }
255       anIndex++;
256     }
257   }
258   return aResult;
259 }
260
261 void Model_ResultConstruction::setIsConcealed(const bool theValue, const bool theForced)
262 {
263   // the construction element may be concealed only by "delete" feature
264   if (!theValue || theForced) {
265     ModelAPI_ResultConstruction::setIsConcealed(theValue, theForced);
266   }
267 }
268
269 void Model_ResultConstruction::storeShape(std::shared_ptr<GeomAPI_Shape> theShape)
270 {
271   std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
272   if (aData && aData->isValid()) {
273     std::string aMyName = data()->name();
274     TDF_Label aShapeLab = aData->shapeLab();
275     if (!theShape.get() || theShape->isNull()) {
276       aShapeLab.ForgetAllAttributes();
277       TDataStd_Name::Set(aShapeLab, aMyName.c_str()); // restore name forgotten
278       return;
279     }
280     std::shared_ptr<Model_Document> aMyDoc =
281       std::dynamic_pointer_cast<Model_Document>(document());
282     const TopoDS_Shape& aShape = theShape->impl<TopoDS_Shape>();
283     if (isInfinite() || aShape.ShapeType() == TopAbs_VERTEX) {
284       aShapeLab.ForgetAllAttributes(); // clear all previously stored
285       TNaming_Builder aBuilder(aShapeLab);
286       aBuilder.Generated(aShape);
287       TDataStd_Name::Set(aShapeLab, aMyName.c_str());
288       aMyDoc->addNamingName(aShapeLab, aMyName);
289     } else if (aShape.ShapeType() == TopAbs_EDGE) { // store sub-vertices on sub-labels
290       aShapeLab.ForgetAllAttributes(); // clear all previously stored
291       TNaming_Builder aBuilder(aShapeLab);
292       aBuilder.Generated(aShape);
293
294       TopExp_Explorer anExp(aShape, TopAbs_VERTEX);
295       for(int anIndex = 1; anExp.More(); anExp.Next(), anIndex++) {
296         TDF_Label aSubLab = aShapeLab.FindChild(anIndex);
297         TNaming_Builder aBuilder(aSubLab);
298         aBuilder.Generated(anExp.Current());
299         std::string aVertexName = aMyName + "_" + (anIndex == 1 ? "StartVertex" : "EndVertex");
300         TDataStd_Name::Set(aSubLab, aVertexName.c_str());
301         aMyDoc->addNamingName(aSubLab, aVertexName);
302       }
303       TDataStd_Name::Set(aShapeLab, aMyName.c_str());
304       aMyDoc->addNamingName(aShapeLab, aMyName);
305     } else { // this is probably sketch, so, work with it as with composite
306       std::shared_ptr<GeomAPI_PlanarEdges> aWirePtr =
307         std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(theShape);
308       if (!aWirePtr.get())
309         return; // unknown case
310       ResultPtr aThisPtr = std::dynamic_pointer_cast<ModelAPI_Result>(data()->owner());
311       FeaturePtr aThisFeature = aMyDoc->feature(aThisPtr);
312       CompositeFeaturePtr aComposite =
313         std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aThisFeature);
314       if (!aComposite || aComposite->numberOfSubs() == 0)
315         return; // unknown case
316       // collect indices of curves of current composite
317       NCollection_DataMap<Handle(Geom_Curve), int> aCurvesIndices;
318       NCollection_DataMap<int, TopoDS_Edge> anEdgeIndices;
319       std::map<int, std::string> aComponentsNames; // names of components that lay on index
320       indexingSketchEdges(aComposite, aCurvesIndices, anEdgeIndices, aComponentsNames);
321
322       GeomAlgoAPI_SketchBuilder aSketchBuilder(aWirePtr->origin(), aWirePtr->dirX(),
323                                                aWirePtr->norm(), aWirePtr);
324       const ListOfShape& aFaces = aSketchBuilder.faces();
325       // order is important to store faces in the same order if sketch is created from scratch
326       MapFaceToEdgeIndices aNewIndices; // edges indices
327       faceToEdgeIndices(aFaces, aCurvesIndices, aNewIndices);
328
329       NCollection_DataMap<int, TopoDS_Face> aFacesOrder; // faces -> tag where they must be set
330       NCollection_List<TopoDS_Face> anUnorderedFaces; // faces that may be located at any index
331       // searching for the best new candidate to old location
332       MapFaceToEdgeIndices::Iterator aNewIter(aNewIndices);
333       for (; aNewIter.More(); aNewIter.Next()) {
334         double aBestFound = 0, aBestNotFound = 1.e+100;
335         int aBestTag = 0;
336         const TColStd_ListOfInteger& aNewInd = aNewIter.Value();
337         // old faces indices where they where located
338         TDF_ChildIDIterator anOldIter(aShapeLab, TDataStd_IntPackedMap::GetID());
339         for (; anOldIter.More(); anOldIter.Next()) {
340           int aTag = anOldIter.Value()->Label().Tag();
341           if (aFacesOrder.IsBound(aTag))
342             continue; // already found a best candidate
343           Handle(TDataStd_IntPackedMap) anOldIndices =
344             Handle(TDataStd_IntPackedMap)::DownCast(anOldIter.Value());
345           double aFound = 0, aNotFound = 0;
346           TColStd_ListOfInteger::Iterator aNewIndIter(aNewInd);
347           for (; aNewIndIter.More(); aNewIndIter.Next()) {
348             if (anOldIndices->Contains(aNewIndIter.Value())) {
349               aFound += 1.;
350             }
351             else if (anOldIndices->Contains(-aNewIndIter.Value())) { // different orientation
352               aFound += 0.001;
353             }
354             else {
355               aNotFound += 1.;
356             }
357           }
358           if (aNotFound <= aBestNotFound) { // less and equal to find better "found": #2859
359             if (aFound > aBestFound) {
360               aBestNotFound = aNotFound;
361               aBestFound = aFound;
362               aBestTag = aTag;
363             }
364           }
365         }
366         if (aBestTag != 0) { // found an appropriate face
367           aFacesOrder.Bind(aBestTag, aNewIter.Key());
368         } else {
369           anUnorderedFaces.Append(aNewIter.Key());
370         }
371       }
372       storeFacesOnLabel(aMyDoc, aShapeLab, aMyName, aShape, aFacesOrder, anUnorderedFaces,
373                         aNewIndices, anEdgeIndices, aComponentsNames);
374     }
375   }
376 }
377
378 void Model_ResultConstruction::setFacesOrder(const std::list<GeomFacePtr>& theFaces)
379 {
380   std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
381   if (aData && aData->isValid()) {
382     std::string aMyName = data()->name();
383     TDF_Label aShapeLab = aData->shapeLab();
384     GeomShapePtr aResShape = shape();
385     if (!aResShape.get() || aResShape->isNull()) {
386       // do nothing
387       return;
388     }
389     std::shared_ptr<Model_Document> aMyDoc =
390         std::dynamic_pointer_cast<Model_Document>(document());
391     const TopoDS_Shape& aShape = aResShape->impl<TopoDS_Shape>();
392     if (aShape.ShapeType() != TopAbs_VERTEX &&
393         aShape.ShapeType() != TopAbs_EDGE) {
394       ResultPtr aThisPtr = std::dynamic_pointer_cast<ModelAPI_Result>(data()->owner());
395       FeaturePtr aThisFeature = aMyDoc->feature(aThisPtr);
396       CompositeFeaturePtr aComposite =
397         std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aThisFeature);
398       if (!aComposite || aComposite->numberOfSubs() == 0)
399         return; // unknown case
400       // collect indices of curves of current composite
401       NCollection_DataMap<Handle(Geom_Curve), int> aCurvesIndices;
402       NCollection_DataMap<int, TopoDS_Edge> anEdgeIndices;
403       std::map<int, std::string> aComponentsNames; // names of components that lay on index
404       indexingSketchEdges(aComposite, aCurvesIndices, anEdgeIndices, aComponentsNames);
405
406       ListOfShape aFaces;
407       NCollection_DataMap<int, TopoDS_Face> aFacesOrder; // faces -> tag where they must be set
408       NCollection_List<TopoDS_Face> anUnorderedFaces; // unordered faces are empty in this case
409       int aTagId = 0;
410       for (std::list<GeomFacePtr>::const_iterator aFIt = theFaces.begin();
411            aFIt != theFaces.end(); ++aFIt) {
412         aFaces.push_back(*aFIt);
413         aFacesOrder.Bind(++aTagId, (*aFIt)->impl<TopoDS_Face>());
414       }
415
416       MapFaceToEdgeIndices aNewIndices; // edges indices
417       faceToEdgeIndices(aFaces, aCurvesIndices, aNewIndices);
418
419       storeFacesOnLabel(aMyDoc, aShapeLab, aMyName, aShape, aFacesOrder, anUnorderedFaces,
420                         aNewIndices, anEdgeIndices, aComponentsNames);
421     }
422   }
423 }
424
425 // ==========================     Auxiliary functions     =========================================
426
427 void storeFacesOnLabel(std::shared_ptr<Model_Document>& theDocument,
428                        TDF_Label& theShapeLabel,
429                        const std::string& theName,
430                        const TopoDS_Shape& theShape,
431                        NCollection_DataMap<int, TopoDS_Face>& theFacesOrder,
432                        NCollection_List<TopoDS_Face>& theUnorderedFaces,
433                        const MapFaceToEdgeIndices& theFaceEdges,
434                        const NCollection_DataMap<int, TopoDS_Edge>& theEdgesIndices,
435                        const std::map<int, std::string>& theEdgesNames)
436 {
437   theShapeLabel.ForgetAllAttributes(); // clear all previously stored
438   TDataStd_Name::Set(theShapeLabel, theName.c_str()); // restore name forgotten
439   TNaming_Builder aBuilder(theShapeLabel); // store the compound to get it ready on open of document
440   aBuilder.Generated(theShape);
441   theDocument->addNamingName(theShapeLabel, theName);
442   // set new faces to the labels
443   NCollection_List<TopoDS_Face>::Iterator anUnordered(theUnorderedFaces);
444   for (int aCurrentTag = 1; !theFacesOrder.IsEmpty() || anUnordered.More(); aCurrentTag++) {
445     TopoDS_Face aFaceToPut;
446     if (theFacesOrder.IsBound(aCurrentTag)) {
447       aFaceToPut = theFacesOrder.Find(aCurrentTag);
448       theFacesOrder.UnBind(aCurrentTag);
449     }
450     else if (anUnordered.More()) {
451       aFaceToPut = anUnordered.Value();
452       anUnordered.Next();
453     }
454
455     if (aFaceToPut.IsNull())
456       continue;
457
458     TopTools_MapOfShape aFaceEdges;
459     for (TopExp_Explorer anEdges(aFaceToPut, TopAbs_EDGE); anEdges.More(); anEdges.Next())
460       aFaceEdges.Add(anEdges.Current());
461
462     TDF_Label aLab = theShapeLabel.FindChild(aCurrentTag);
463     TNaming_Builder aFaceBuilder(aLab);
464     aFaceBuilder.Generated(aFaceToPut);
465     // store also indices of the new face edges
466     Handle(TDataStd_IntPackedMap) aNewMap = TDataStd_IntPackedMap::Set(aLab);
467     const TColStd_ListOfInteger& aNewInd = theFaceEdges.FindFromKey(aFaceToPut);
468     std::stringstream aName;
469     aName<<"Face";
470     TopExp_Explorer aPutEdges(aFaceToPut, TopAbs_EDGE);
471     TNaming_Builder *anEdgesBuilder = 0, *aVerticesBuilder = 0;
472     for(TColStd_ListOfInteger::Iterator anIter(aNewInd); anIter.More(); anIter.Next()) {
473       int anIndex = anIter.Value();
474       int aModIndex = anIndex > 0 ? anIndex : -anIndex;
475       aNewMap->Add(anIndex);
476       aName<<"-"<<theEdgesNames.find(aModIndex)->second;
477       if (anIter.Value() > 0)
478         aName<<"f";
479       else
480         aName<<"r";
481       // collect all edges of the face which are modified in sub-label of the face
482       if (theEdgesIndices.IsBound(aModIndex) &&
483           !aFaceEdges.Contains(theEdgesIndices.Find(aModIndex))) {
484         if (!anEdgesBuilder) {
485           TDF_Label anEdgesLabel = aLab.FindChild(1);
486           anEdgesBuilder = new TNaming_Builder(anEdgesLabel);
487           std::ostringstream aSubName;
488           // tag is needed for Test1922 to distinguish sub-edges of different faces
489           aSubName<<"SubEdge_"<<aCurrentTag;
490           TDataStd_Name::Set(anEdgesLabel, aSubName.str().c_str());
491         }
492         anEdgesBuilder->Modify(theEdgesIndices.Find(aModIndex), aPutEdges.Current());
493       }
494       // put also modified vertices, otherwise vertex of original edge has no history
495       if (theEdgesIndices.IsBound(aModIndex)) {
496         TopExp_Explorer aVExpOld(theEdgesIndices.Find(aModIndex), TopAbs_VERTEX);
497         TopExp_Explorer aVExpNew(aPutEdges.Current(), TopAbs_VERTEX);
498         for(; aVExpNew.More() && aVExpOld.More(); aVExpNew.Next(), aVExpOld.Next()) {
499           if (!aVExpOld.Current().IsSame(aVExpNew.Current())) {
500             if (!aVerticesBuilder) {
501               TDF_Label aVertLabel = aLab.FindChild(2);
502               aVerticesBuilder = new TNaming_Builder(aVertLabel);
503               std::ostringstream aSubName;
504               // tag is needed for Test1922 to distinguish sub-edges of different faces
505               aSubName<<"SubVertex_"<<aCurrentTag;
506               TDataStd_Name::Set(aVertLabel, aSubName.str().c_str());
507             }
508             aVerticesBuilder->Modify(aVExpOld.Current(), aVExpNew.Current());
509
510           }
511         }
512       }
513       aPutEdges.Next();
514     }
515     if (anEdgesBuilder)
516       delete anEdgesBuilder;
517     if (aVerticesBuilder)
518       delete aVerticesBuilder;
519     TDataStd_Name::Set(aLab, TCollection_ExtendedString(aName.str().c_str()));
520     theDocument->addNamingName(aLab, aName.str());
521     // put also wires to sub-labels to correctly select them instead of collection by edges
522     int aWireTag = 3; // first tag is for SubEdge-s, second - for vertices
523     for(TopExp_Explorer aWires(aFaceToPut, TopAbs_WIRE); aWires.More(); aWires.Next()) {
524       TDF_Label aWireLab = aLab.FindChild(aWireTag);
525       TNaming_Builder aWireBuilder(aWireLab);
526       aWireBuilder.Generated(aWires.Current());
527       std::ostringstream aWireName;
528       aWireName<<aName.str()<<"_wire";
529       if (aWireTag > 3)
530         aWireName<<"_"<<aWireTag - 2;
531       TDataStd_Name::Set(aWireLab, aWireName.str().c_str());
532       theDocument->addNamingName(aWireLab, aWireName.str());
533       aWireTag++;
534     }
535   }
536 }
537
538 void indexingSketchEdges(const CompositeFeaturePtr& theComposite,
539                          NCollection_DataMap<Handle(Geom_Curve), int>& theCurvesIndices,
540                          NCollection_DataMap<int, TopoDS_Edge>& theEdgesIndices,
541                          std::map<int, std::string>& theEdgesNames)
542 {
543   const int aSubNum = theComposite->numberOfSubs();
544   for (int a = 0; a < aSubNum; a++) {
545     FeaturePtr aSub = theComposite->subFeature(a);
546     const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aSub->results();
547     std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRes = aResults.cbegin();
548     for (; aRes != aResults.cend(); aRes++) {
549       ResultConstructionPtr aConstr =
550         std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aRes);
551       if (aConstr->shape() && aConstr->shape()->isEdge()) {
552         TopoDS_Edge anEdge = TopoDS::Edge(aConstr->shape()->impl<TopoDS_Shape>());
553         Standard_Real aFirst, aLast;
554         Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
555         theCurvesIndices.Bind(aCurve, a);
556         theEdgesIndices.Bind(a, anEdge);
557         theEdgesNames[a] = shortName(aConstr);
558       }
559     }
560   }
561 }
562
563 void faceToEdgeIndices(const ListOfShape& theFaces,
564                        const NCollection_DataMap<Handle(Geom_Curve), int>& theCurvesIndices,
565                        MapFaceToEdgeIndices& theFaceEdges)
566 {
567   std::list<std::shared_ptr<GeomAPI_Shape> >::const_iterator aFIter = theFaces.begin();
568   for (; aFIter != theFaces.end(); aFIter++) {
569     std::shared_ptr<GeomAPI_Face> aFace(new GeomAPI_Face(*aFIter));
570     // put them to a label, trying to keep the same faces on the same labels
571     if (aFace.get() && !aFace->isNull()) {
572       TopoDS_Face aTopoFace = TopoDS::Face(aFace->impl<TopoDS_Shape>());
573       theFaceEdges.Add(aTopoFace, TColStd_ListOfInteger());
574       // keep new indices of sub-elements used in this face
575       for (TopExp_Explorer anEdges(aTopoFace, TopAbs_EDGE); anEdges.More(); anEdges.Next()) {
576         TopoDS_Edge anEdge = TopoDS::Edge(anEdges.Current());
577         Standard_Real aFirst, aLast;
578         Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
579         if (theCurvesIndices.IsBound(aCurve)) {
580           int anIndex = theCurvesIndices.Find(aCurve);
581           if ((aFirst > aLast) != (anEdge.Orientation() == TopAbs_REVERSED))
582             anIndex = -anIndex;
583           theFaceEdges.ChangeFromKey(aTopoFace).Append(anIndex);
584         }
585       }
586     }
587   }
588 }