Salome HOME
Join modifications from branch OCC_development_for_3_2_0a2
[modules/geom.git] / src / GEOMImpl / GEOMImpl_Block6Explorer.cxx
1 // Copyright (C) 2005  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
3 // 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either 
7 // version 2.1 of the License.
8 // 
9 // This library is distributed in the hope that it will be useful 
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
12 // Lesser General Public License for more details.
13 //
14 // You should have received a copy of the GNU Lesser General Public  
15 // License along with this library; if not, write to the Free Software 
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17 //
18 // See http://www.salome-platform.org/
19 //
20 #include <Standard_Stream.hxx>
21
22 #include <BRepOffsetAPI_MakeFilling.hxx>
23
24 #include <GEOMImpl_Block6Explorer.hxx>
25
26 #include "utilities.h"
27
28 #include <BRep_Tool.hxx>
29 #include <BRep_TFace.hxx>
30 #include <BRep_Builder.hxx>
31 #include <BRepLib.hxx>
32 #include <BRepLib_FindSurface.hxx>
33 #include <BRepTools.hxx>
34 #include <BRepTools_WireExplorer.hxx>
35 #include <BRepOffsetAPI_ThruSections.hxx>
36 #include <BRepBuilderAPI_Copy.hxx>
37 #include <BRepBuilderAPI_MakeEdge.hxx>
38 #include <BRepBuilderAPI_MakeWire.hxx>
39 #include <BRepBuilderAPI_MakeFace.hxx>
40 #include <BRepBuilderAPI_Transform.hxx>
41
42 #include <TopAbs.hxx>
43 #include <TopoDS.hxx>
44 #include <TopoDS_Shape.hxx>
45 #include <TopoDS_Edge.hxx>
46 #include <TopoDS_Wire.hxx>
47 #include <TopoDS_Solid.hxx>
48 #include <TopExp.hxx>
49 #include <TopExp_Explorer.hxx>
50 #include <TopTools_MapOfShape.hxx>
51 #include <TopTools_ListOfShape.hxx>
52 #include <TopTools_ListIteratorOfListOfShape.hxx>
53 #include <TopTools_IndexedMapOfShape.hxx>
54 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
55
56 #include <Geom_Curve.hxx>
57 #include <Geom_TrimmedCurve.hxx>
58 #include <GeomFill_Generator.hxx>
59
60 #include <Precision.hxx>
61 #include <gp_Pnt.hxx>
62 #include <TColgp_Array1OfPnt.hxx>
63
64 #include <StdFail_NotDone.hxx>
65 #include <Standard_NullObject.hxx>
66 #include <Standard_TypeMismatch.hxx>
67 #include <Standard_ConstructionError.hxx>
68 #include <Standard_NoSuchObject.hxx>
69
70 #define NBFACES 6
71 #define NBEDGES 12
72 #define NBVERTS 8
73
74 static Standard_Integer mod4 (Standard_Integer nb)
75 {
76   if (nb <= 0) return nb + 4;
77   if (nb > 4)  return nb - 4;
78   return nb;
79 }
80
81 static Standard_Integer edge_id (const Standard_Integer theFaceID,
82                                  const Standard_Integer theEdgeNB)
83 {
84   static Standard_Integer edge_ids[NBFACES][4] = {
85     {  1,  2,  3,  4 },   // face 1
86     {  5,  6,  7,  8 },   // face 2
87     {  9,  5, 10,  1 },   // face 3
88     { 12,  7, 11,  3 },   // face 4
89     {  4, 12,  8,  9 },   // face 5
90     {  2, 11,  6, 10 } }; // face 6
91
92   return edge_ids[theFaceID - 1][theEdgeNB - 1];
93 }
94
95 static Standard_Integer side_edge_id (const Standard_Integer theEdgeNB)
96 {
97   static Standard_Integer side_edge_ids[4] = {9, 10, 11, 12};
98
99   return side_edge_ids[theEdgeNB - 1];
100 }
101
102 static Standard_Integer vertex_id (const Standard_Integer theFaceID,
103                                    const Standard_Integer theVertexNB)
104 {
105   static Standard_Integer vertex_ids[NBFACES][4] = {
106     { 1, 2, 3, 4 },   // face 1
107     { 5, 6, 7, 8 },   // face 2
108     { 1, 5, 6, 2 },   // face 3
109     { 4, 8, 7, 3 },   // face 4
110     { 1, 4, 8, 5 },   // face 5
111     { 2, 3, 7, 6 } }; // face 6
112
113   return vertex_ids[theFaceID - 1][theVertexNB - 1];
114 }
115
116 static Standard_Integer vertex_id_edge (const Standard_Integer theEdgeID, // [1,12]
117                                         const Standard_Integer theVertexNB) // [1,2]
118 {
119   static Standard_Integer vertex_ids_edge[NBEDGES][2] = {
120     {1, 2},   // edge 1
121     {2, 3},   // edge 2
122     {3, 4},   // edge 3
123     {4, 1},   // edge 4
124     {5, 6},   // edge 5
125     {6, 7},   // edge 6
126     {7, 8},   // edge 7
127     {8, 5},   // edge 8
128     {1, 5},   // edge 9
129     {2, 6},   // edge 10
130     {3, 7},   // edge 11
131     {4, 8} }; // edge 12
132
133   return vertex_ids_edge[theEdgeID - 1][theVertexNB - 1];
134 }
135
136 static Standard_Integer face_id_edges (const Standard_Integer theEdge1ID, // [1,12]
137                                        const Standard_Integer theEdge2ID) // [1,12]
138 {
139   static Standard_Integer face_ids_edges[NBEDGES][NBEDGES] = {
140     // 1  2  3  4  5  6  7  8  9  10 11 12
141     {  0, 1, 1, 1, 3, 0, 0, 0, 3, 3, 0, 0  },   // edge 1
142     {  1, 0, 1, 1, 0, 6, 0, 0, 0, 6, 6, 0  },   // edge 2
143     {  1, 1, 0, 1, 0, 0, 4, 0, 0, 0, 4, 4  },   // edge 3
144     {  1, 1, 1, 0, 0, 0, 0, 5, 5, 0, 0, 5  },   // edge 4
145     {  3, 0, 0, 0, 0, 2, 2, 2, 3, 3, 0, 0  },   // edge 5
146     {  0, 6, 0, 0, 2, 0, 2, 2, 0, 6, 6, 0  },   // edge 6
147     {  0, 0, 4, 0, 2, 2, 0, 2, 0, 0, 4, 4  },   // edge 7
148     {  0, 0, 0, 5, 2, 2, 2, 0, 5, 0, 0, 5  },   // edge 8
149     {  3, 0, 0, 5, 3, 0, 0, 5, 0, 3, 0, 5  },   // edge 9
150     {  3, 6, 0, 0, 3, 6, 0, 0, 3, 0, 6, 0  },   // edge 10
151     {  0, 6, 4, 0, 0, 6, 4, 0, 0, 6, 0, 4  },   // edge 11
152     {  0, 0, 4, 5, 0, 0, 4, 5, 5, 0, 4, 0  } }; // edge 12
153
154   return face_ids_edges[theEdge1ID - 1][theEdge2ID - 1];
155 }
156
157 static Standard_Integer edge_id_vertices (const Standard_Integer theVertex1ID, // [1,8]
158                                           const Standard_Integer theVertex2ID) // [1,8]
159 {
160   static Standard_Integer edge_ids_vertices[NBVERTS][NBVERTS] = {
161     // 1   2   3   4   5   6   7   8
162     {  0,  1,  0,  4,  9,  0,  0,  0},   // vertex 1
163     {  1,  0,  2,  0,  0, 10,  0,  0},   // vertex 2
164     {  0,  2,  0,  3,  0,  0, 11,  0},   // vertex 3
165     {  4,  0,  3,  0,  0,  0,  0, 12},   // vertex 4
166     {  9,  0,  0,  0,  0,  5,  0,  8},   // vertex 5
167     {  0, 10,  0,  0,  5,  0,  6,  0},   // vertex 6
168     {  0,  0, 11,  0,  0,  6,  0,  7},   // vertex 7
169     {  0,  0,  0, 12,  8,  0,  7,  0} }; // vertex 8
170
171   return edge_ids_vertices[theVertex1ID - 1][theVertex2ID - 1];
172 }
173
174 static Standard_Integer edge_id_faces (const Standard_Integer theFace1ID, // [1,6]
175                                        const Standard_Integer theFace2ID) // [1,6]
176 {
177   static Standard_Integer edge_ids_faces[NBFACES][NBFACES] = {
178     // 1   2   3   4   5   6
179     {  0,  0,  1,  3,  4,  2  },   // face 1
180     {  0,  0,  5,  7,  8,  6  },   // face 2
181     {  1,  5,  0,  0,  9, 10  },   // face 3
182     {  3,  7,  0,  0, 12, 11  },   // face 4
183     {  4,  8,  9, 12,  0,  0  },   // face 5
184     {  2,  6, 10, 11,  0,  0  } }; // face 6
185
186   return edge_ids_faces[theFace1ID - 1][theFace2ID - 1];
187 }
188
189 //=======================================================================
190 //function : GEOMImpl_Block6Explorer
191 //purpose  : Constructor
192 //=======================================================================
193 GEOMImpl_Block6Explorer::GEOMImpl_Block6Explorer ()
194      : myFaces(1,NBFACES), myEdges(1,NBEDGES), myVertices(1,NBVERTS)
195 {
196 }
197
198 //=======================================================================
199 //function : GetVertex
200 //purpose  :
201 //=======================================================================
202 TopoDS_Shape GEOMImpl_Block6Explorer::GetVertex (const Standard_Integer theVertexID)
203 {
204   TopoDS_Shape aNullShape;
205   if (theVertexID < 1 || theVertexID > NBVERTS) return aNullShape;
206   return myVertices(theVertexID);
207 }
208
209 //=======================================================================
210 //function : GetVertexID
211 //purpose  :
212 //=======================================================================
213 Standard_Integer GEOMImpl_Block6Explorer::GetVertexID (const TopoDS_Shape& theVertex)
214 {
215   for (Standard_Integer id = 1; id <= NBVERTS; id++) {
216     if (theVertex.IsSame(myVertices(id))) return id;
217   }
218   Standard_NoSuchObject::Raise("The Vertex does not belong to the Block");
219   return 0;
220 }
221
222 //=======================================================================
223 //function : GetVertexID
224 //purpose  :
225 //=======================================================================
226 Standard_Integer GEOMImpl_Block6Explorer::GetVertexID (const Standard_Integer theFaceID,
227                                                        const Standard_Integer theVertexNB)
228 {
229   return vertex_id(theFaceID, theVertexNB);
230 }
231
232 //=======================================================================
233 //function : GetVertexOnEdgeID
234 //purpose  :
235 //=======================================================================
236 Standard_Integer GEOMImpl_Block6Explorer::GetVertexOnEdgeID
237                                      (const Standard_Integer theEdgeID,
238                                       const Standard_Integer theVertexNB)
239 {
240   return vertex_id_edge(theEdgeID, theVertexNB);
241 }
242
243 //=======================================================================
244 //function : GetEdge
245 //purpose  :
246 //=======================================================================
247 TopoDS_Shape GEOMImpl_Block6Explorer::GetEdge (const Standard_Integer theEdgeID,
248                                                const Standard_Boolean doMake)
249 {
250   TopoDS_Shape aNullShape;
251   if (theEdgeID < 1 || theEdgeID > NBEDGES) return aNullShape;
252   if (myEdges(theEdgeID).IsNull() && doMake) {
253     // Create the required edge as a linear segment between
254     // corresponding vertices and put it in the Block's edges
255     BRepBuilderAPI_MakeEdge ME (TopoDS::Vertex(myVertices(vertex_id_edge(theEdgeID, 1))),
256                                 TopoDS::Vertex(myVertices(vertex_id_edge(theEdgeID, 2))));
257     if (!ME.IsDone()) {
258       Standard_ConstructionError::Raise("Edge construction failed");
259     }
260     myEdges(theEdgeID) = ME.Shape();
261   }
262
263   return myEdges(theEdgeID);
264 }
265
266 //=======================================================================
267 //function : GetEdgeID
268 //purpose  :
269 //=======================================================================
270 Standard_Integer GEOMImpl_Block6Explorer::GetEdgeID (const TopoDS_Shape& theEdge)
271 {
272   for (Standard_Integer id = 1; id <= NBEDGES; id++) {
273     if (theEdge.IsSame(myEdges(id))) return id;
274   }
275   Standard_NoSuchObject::Raise("The Edge does not belong to the Block");
276   return 0;
277 }
278
279 //=======================================================================
280 //function : GetEdgeID
281 //purpose  :
282 //=======================================================================
283 Standard_Integer GEOMImpl_Block6Explorer::GetEdgeID (const Standard_Integer theFaceID,
284                                                      const Standard_Integer theEdgeNB)
285 {
286   return edge_id(theFaceID, theEdgeNB);
287 }
288
289 //=======================================================================
290 //function : FindEdgeID
291 //purpose  :
292 //=======================================================================
293 Standard_Integer GEOMImpl_Block6Explorer::FindEdgeID (const Standard_Integer theVertex1ID,
294                                                       const Standard_Integer theVertex2ID)
295 {
296   return edge_id_vertices(theVertex1ID, theVertex2ID);
297 }
298
299 //=======================================================================
300 //function : FindCommonEdgeID
301 //purpose  :
302 //=======================================================================
303 Standard_Integer GEOMImpl_Block6Explorer::FindCommonEdgeID
304                                       (const Standard_Integer theFace1ID,
305                                        const Standard_Integer theFace2ID)
306 {
307   return edge_id_faces(theFace1ID, theFace2ID);
308 }
309
310 //=======================================================================
311 //function : GetFace
312 //purpose  :
313 //=======================================================================
314 TopoDS_Shape GEOMImpl_Block6Explorer::GetFace (const Standard_Integer theFaceID,
315                                                const Standard_Boolean doMake)
316 {
317   TopoDS_Shape aNullShape;
318   if (theFaceID < 1 || theFaceID > NBFACES) return aNullShape;
319
320   if (myFaces(theFaceID).IsNull() && doMake) {
321
322     // Create the required face between
323     // corresponding edges and put it in the Block's faces
324
325     TopoDS_Shape E1 = GetEdge(edge_id(theFaceID, 1), doMake);
326     TopoDS_Shape E2 = GetEdge(edge_id(theFaceID, 2), doMake);
327     TopoDS_Shape E3 = GetEdge(edge_id(theFaceID, 3), doMake);
328     TopoDS_Shape E4 = GetEdge(edge_id(theFaceID, 4), doMake);
329
330     BRepBuilderAPI_MakeWire MW (TopoDS::Edge(E1),
331                                 TopoDS::Edge(E2),
332                                 TopoDS::Edge(E3),
333                                 TopoDS::Edge(E4));
334     if (!MW.IsDone()) {
335       Standard_ConstructionError::Raise("Wire construction failed");
336     }
337     TopoDS_Shape aFace;
338     MakeFace(MW, Standard_False, aFace);
339     if (aFace.IsNull()) {
340       Standard_ConstructionError::Raise("Face construction failed");
341     }
342     myFaces(theFaceID) = aFace;
343   }
344
345   return myFaces(theFaceID);
346 }
347
348 //=======================================================================
349 //function : GetFaceID
350 //purpose  :
351 //=======================================================================
352 Standard_Integer GEOMImpl_Block6Explorer::GetFaceID (const TopoDS_Shape& theFace)
353 {
354   for (Standard_Integer id = 1; id <= NBFACES; id++) {
355     if (theFace.IsSame(myFaces(id))) return id;
356   }
357   Standard_NoSuchObject::Raise("The Face does not belong to the Block");
358   return 0;
359 }
360
361 //=======================================================================
362 //function : FindFaceID
363 //purpose  :
364 //=======================================================================
365 Standard_Integer GEOMImpl_Block6Explorer::FindFaceID (const Standard_Integer theEdge1ID,
366                                                       const Standard_Integer theEdge2ID)
367 {
368   return face_id_edges(theEdge1ID, theEdge2ID);
369 }
370
371 //=======================================================================
372 //function : GetOppositeFaceID
373 //purpose  :
374 //=======================================================================
375 Standard_Integer GEOMImpl_Block6Explorer::GetOppositeFaceID (const Standard_Integer theFaceID)
376 {
377   Standard_Integer opp_face_id[NBFACES + 1] = {
378     0,
379     2,  // to 1 face
380     1,  // to 2 face
381     4,  // to 3 face
382     3,  // to 4 face
383     6,  // to 5 face
384     5}; // to 6 face
385
386   return opp_face_id[theFaceID];
387 }
388
389 //=======================================================================
390 //function : IsSimilarFaces
391 //purpose  :
392 //=======================================================================
393 Standard_Boolean GEOMImpl_Block6Explorer::IsSimilarFaces (const Standard_Integer theFace1ID,
394                                                           const Standard_Integer theFace2ID,
395                                                           const gp_Trsf          theTransformation)
396 {
397   Standard_Integer common_edge_id = FindCommonEdgeID(theFace1ID, theFace2ID);
398
399   if (common_edge_id == 0) { // opposite faces
400     for (Standard_Integer id = 1; id <= 4; id++) {
401       TopoDS_Shape E1 = GetEdge(edge_id(theFace1ID, id));
402       TopoDS_Shape E2 = GetEdge(edge_id(theFace2ID, id));
403
404       BRepBuilderAPI_Transform aTrsf (E1, theTransformation, Standard_False);
405       if (!IsSimilarEdges(aTrsf.Shape(), E2))
406         return Standard_False;
407     }
408   } else { // the faces have common edge
409     TopTools_Array1OfShape aVerts1 (1,4);
410     TopTools_Array1OfShape aVerts2 (1,4);
411
412     Standard_Integer common_vertex1 = GetVertexOnEdgeID(common_edge_id, 1);
413     Standard_Integer common_vertex2 = GetVertexOnEdgeID(common_edge_id, 2);
414     aVerts1(1) = myVertices(common_vertex1);
415     aVerts1(2) = myVertices(common_vertex2);
416     aVerts2(1) = myVertices(common_vertex1);
417     aVerts2(2) = myVertices(common_vertex2);
418
419     Standard_Integer not_common_v11 = 0, not_common_v12 = 0;
420     Standard_Integer vnb, vid;
421     for (vnb = 1; vnb <= 4; vnb++) {
422       vid = GetVertexID(theFace1ID, vnb);
423       if (vid != common_vertex1 && FindEdgeID(vid, common_vertex1) == 0) {
424         not_common_v12 = vid;
425       } else {
426         if (vid != common_vertex2 && FindEdgeID(vid, common_vertex2) == 0) {
427           not_common_v11 = vid;
428         }
429       }
430     }
431
432     Standard_Integer not_common_v21 = 0, not_common_v22 = 0;
433     for (vnb = 1; vnb <= 4; vnb++) {
434       vid = GetVertexID(theFace2ID, vnb);
435       if (vid != common_vertex1 && FindEdgeID(vid, common_vertex1) == 0) {
436         not_common_v22 = vid;
437       } else {
438         if (vid != common_vertex2 && FindEdgeID(vid, common_vertex2) == 0) {
439           not_common_v21 = vid;
440         }
441       }
442     }
443     aVerts1(3) = myVertices(not_common_v11);
444     aVerts1(4) = myVertices(not_common_v12);
445     aVerts2(3) = myVertices(not_common_v21);
446     aVerts2(4) = myVertices(not_common_v22);
447
448     for (Standard_Integer id = 1; id <= 4; id++) {
449       BRepBuilderAPI_Transform aTrsf (aVerts1(id), theTransformation, Standard_False);
450       TopoDS_Vertex V1 = TopoDS::Vertex(aTrsf.Shape());
451       TopoDS_Vertex V2 = TopoDS::Vertex(aVerts2(id));
452       if (!BRepTools::Compare(V1, V2)) {
453         return Standard_False;
454       }
455     }
456   }
457
458   return Standard_True;
459 }
460
461 //============ Initialization methods ===================================
462
463 //=======================================================================
464 //function : InitByBlock
465 //purpose  :
466 //=======================================================================
467 void GEOMImpl_Block6Explorer::InitByBlock (const TopoDS_Shape& theBlock)
468 {
469   // 1. Find any one face of the block
470   TopExp_Explorer faces (theBlock, TopAbs_FACE);
471   if (!faces.More()) {
472     Standard_ConstructionError::Raise("The block has no faces");
473   }
474   TopoDS_Shape aFirstFace = faces.Current();
475
476   // 2. Store all elements of the block relatively aFirstFace
477   InitByBlockAndFace(theBlock, aFirstFace);
478 }
479
480 //=======================================================================
481 //function : InitByBlockAndFace
482 //purpose  :
483 //=======================================================================
484 void GEOMImpl_Block6Explorer::InitByBlockAndFace (const TopoDS_Shape& theBlock,
485                                                   const TopoDS_Shape& theFace)
486 {
487   myFaces(1) = theFace;
488
489   // 2. Get wire of the first face
490   TopExp_Explorer wires (myFaces(1), TopAbs_WIRE);
491   if (!wires.More()) {
492     Standard_ConstructionError::Raise("A face of the block has no wires");
493   }
494   TopoDS_Shape aWire = wires.Current();
495   wires.Next();
496   if (wires.More()) {
497     Standard_ConstructionError::Raise("A face of the block has more than one wires");
498   }
499
500   // 3. Explore wire to init edges and vertices of the first face
501   BRepTools_WireExplorer aWE (TopoDS::Wire(aWire), TopoDS::Face(myFaces(1)));
502   Standard_Integer nb = 1;
503   for (; aWE.More(); aWE.Next(), nb++) {
504     if (nb > 4) {
505       Standard_ConstructionError::Raise("A face of the block has more than four edges");
506     }
507     myEdges(edge_id(1, nb)) = aWE.Current();
508     myVertices(vertex_id(1, nb)) = aWE.CurrentVertex();
509   }
510   if (nb < 5) {
511     Standard_ConstructionError::Raise("A face of the block has less than four edges");
512   }
513
514   // 2. Store all other elements of the block
515   InitByBlockAndVertices (theBlock,
516                           myVertices(vertex_id(1,1)),
517                           myVertices(vertex_id(1,2)),
518                           myVertices(vertex_id(1,3)));
519 }
520
521 //=======================================================================
522 //function : InitByBlockAndEdges
523 //purpose  :
524 //=======================================================================
525 void GEOMImpl_Block6Explorer::InitByBlockAndEdges (const TopoDS_Shape& theBlock,
526                                                    const TopoDS_Shape& theEdge1,
527                                                    const TopoDS_Shape& theEdge3)
528 {
529   // 1. Store vertices and edges of the first face
530
531   // 1.1. Store two given edges
532   myEdges(edge_id(1, 1)) = theEdge1;
533   myEdges(edge_id(1, 3)) = theEdge3;
534
535   // 1.2. Find and store the first face
536   TopTools_IndexedDataMapOfShapeListOfShape MEF;
537   MapShapesAndAncestors(theBlock, TopAbs_EDGE, TopAbs_FACE, MEF);
538   if (MEF.Extent() != NBEDGES) {
539     Standard_TypeMismatch::Raise("Block has wrong number of edges");
540   }
541   const TopTools_ListOfShape& aFacesOfE1 = MEF.FindFromKey(theEdge1);
542   const TopTools_ListOfShape& aFacesOfE3 = MEF.FindFromKey(theEdge3);
543
544   Standard_Boolean isFound = Standard_False;
545   TopTools_ListIteratorOfListOfShape anIterF1 (aFacesOfE1);
546   for (; anIterF1.More() && !isFound; anIterF1.Next()) {
547
548     TopTools_ListIteratorOfListOfShape anIterF3 (aFacesOfE3);
549     for (; anIterF3.More() && !isFound; anIterF3.Next()) {
550
551       if (anIterF1.Value().IsSame(anIterF3.Value())) {
552         isFound = Standard_True;
553
554         // Store the face, defined by two opposite edges
555         myFaces(1) = anIterF1.Value();
556       }
557     }
558   }
559   if (!isFound) {
560     Standard_ConstructionError::Raise
561       ("Edges 1 and 2 do not belong to one face of the block");
562   }
563
564   // 1.3. Make vertices of the first edge the first and the
565   //      second vertices of the first face. Order is free.
566   TopoDS_Edge E = TopoDS::Edge(theEdge1);
567   TopoDS_Vertex V1, V2;
568   TopExp::Vertices(E, V1, V2, Standard_True);
569   myVertices(vertex_id(1,1)) = V1;
570   myVertices(vertex_id(1,2)) = V2;
571
572   // Init maps vertex->list_of_edges for the face
573   TopTools_IndexedDataMapOfShapeListOfShape M1;
574   MapShapesAndAncestors(myFaces(1), TopAbs_VERTEX, TopAbs_EDGE, M1);
575   if (M1.Extent() != 4) {
576     Standard_TypeMismatch::Raise("The first face of block has wrong number of vertices");
577   }
578
579   // 1.4. Find and store others elements of the first face
580
581   // edges of the first vertex
582   TopoDS_Shape E1_f = M1.FindFromKey(V1).First();
583   TopoDS_Shape E1_l = M1.FindFromKey(V1).Last();
584
585   if (E1_f.IsSame(theEdge1)) {
586     myEdges(edge_id(1, 4)) = E1_l;
587   } else {
588     myEdges(edge_id(1, 4)) = E1_f;
589   }
590
591   // fourth vertex
592   TopoDS_Edge E4 = TopoDS::Edge(myEdges(edge_id(1, 4)));
593   TopoDS_Vertex V41, V42;
594   TopExp::Vertices(E4, V41, V42, Standard_True);
595   if (V41.IsSame(V1)) {
596     myVertices(vertex_id(1,4)) = V42;
597   } else {
598     myVertices(vertex_id(1,4)) = V41;
599   }
600
601   // edges of the second vertex
602   TopoDS_Shape E2_f = M1.FindFromKey(V2).First();
603   TopoDS_Shape E2_l = M1.FindFromKey(V2).Last();
604
605   if (E2_f.IsSame(theEdge1)) {
606     myEdges(edge_id(1, 2)) = E2_l;
607   } else {
608     myEdges(edge_id(1, 2)) = E2_f;
609   }
610
611   // fird vertex
612   TopoDS_Edge E2 = TopoDS::Edge(myEdges(edge_id(1, 2)));
613   TopoDS_Vertex V21, V22;
614   TopExp::Vertices(E2, V21, V22, Standard_True);
615   if (V21.IsSame(V2)) {
616     myVertices(vertex_id(1,3)) = V22;
617   } else {
618     myVertices(vertex_id(1,3)) = V21;
619   }
620
621   // 2. Store all other elements of the block
622   InitByBlockAndVertices (theBlock,
623                           myVertices(vertex_id(1,1)),
624                           myVertices(vertex_id(1,2)),
625                           myVertices(vertex_id(1,3)));
626 }
627
628 //=======================================================================
629 //function : InitByBlockAndVertices
630 //purpose  :
631 //=======================================================================
632 void GEOMImpl_Block6Explorer::InitByBlockAndVertices (const TopoDS_Shape& theBlock,
633                                                       const TopoDS_Shape& theVertex1,
634                                                       const TopoDS_Shape& theVertex2,
635                                                       const TopoDS_Shape& theVertex3)
636 {
637   // Here we suppose, that vertices are ordered, i.e. exists edge between
638   // theVertex1 and theVertex2 and edge between theVertex2 and theVertex3
639
640   // 1. Store vertices and edges of the first face.
641   //    If the first face is initialized, it means, that this
642   //    method is called from another initialization method, and all
643   //    vertices and edges of the first face are also initialized
644   if (myFaces(1).IsNull()) {
645
646     // 1.1. Store first three vertices
647     myVertices(vertex_id(1, 1)) = theVertex1;
648     myVertices(vertex_id(1, 2)) = theVertex2;
649     myVertices(vertex_id(1, 3)) = theVertex3;
650
651     // 1.2. Find and store the first face
652     TopTools_IndexedDataMapOfShapeListOfShape MVF;
653     MapShapesAndAncestors(theBlock, TopAbs_VERTEX, TopAbs_FACE, MVF);
654     if (MVF.Extent() != NBVERTS) {
655       Standard_TypeMismatch::Raise("Block has wrong number of vertices");
656     }
657     const TopTools_ListOfShape& aFacesOfV1 = MVF.FindFromKey(theVertex1);
658     const TopTools_ListOfShape& aFacesOfV3 = MVF.FindFromKey(theVertex3);
659
660     Standard_Boolean isFound = Standard_False;
661     TopTools_ListIteratorOfListOfShape anIterF1 (aFacesOfV1);
662     for (; anIterF1.More() && !isFound; anIterF1.Next()) {
663
664       TopTools_ListIteratorOfListOfShape anIterF3 (aFacesOfV3);
665       for (; anIterF3.More() && !isFound; anIterF3.Next()) {
666
667         if (anIterF1.Value().IsSame(anIterF3.Value())) {
668           isFound = Standard_True;
669
670           // Store the face, defined by two opposite vertices
671           myFaces(1) = anIterF1.Value();
672         }
673       }
674     }
675     if (!isFound) {
676       Standard_ConstructionError::Raise
677         ("Vertices 1 and 3 do not belong to one face of the block");
678     }
679
680     // Init maps vertex->list_of_edges for the face
681     TopTools_IndexedDataMapOfShapeListOfShape M1;
682     MapShapesAndAncestors(myFaces(1), TopAbs_VERTEX, TopAbs_EDGE, M1);
683     if (M1.Extent() != 4) {
684       Standard_TypeMismatch::Raise("The first face of block has wrong number of vertices");
685     }
686
687     // 1.3. Find and store edges and last vertex of the first face
688     const TopTools_ListOfShape& anEdgesOfV1 = M1.FindFromKey(theVertex1);
689     const TopTools_ListOfShape& anEdgesOfV2 = M1.FindFromKey(theVertex2);
690     const TopTools_ListOfShape& anEdgesOfV3 = M1.FindFromKey(theVertex3);
691
692     TopTools_ListIteratorOfListOfShape anIterE2 (anEdgesOfV2);
693     for (; anIterE2.More(); anIterE2.Next()) {
694
695       TopTools_ListIteratorOfListOfShape anIterE1 (anEdgesOfV1);
696       for (; anIterE1.More(); anIterE1.Next()) {
697
698         if (anIterE1.Value().IsSame(anIterE2.Value())) {
699           // Store the first edge, defined by two vertices
700           myEdges(edge_id(1,1)) = anIterE1.Value();
701
702         } else {
703           // Store the last edge
704           myEdges(edge_id(1,4)) = anIterE1.Value();
705
706           // Find and store the last vertex
707           TopoDS_Edge E = TopoDS::Edge(myEdges(4));
708           TopoDS_Vertex V1, V2;
709           TopExp::Vertices(E, V1, V2, Standard_True);
710
711           if (V1.IsSame(theVertex1)) {
712             myVertices(vertex_id(1,4)) = V2;
713           } else {
714             myVertices(vertex_id(1,4)) = V1;
715           }
716         }
717       }
718
719       TopTools_ListIteratorOfListOfShape anIterE3 (anEdgesOfV3);
720       for (; anIterE3.More(); anIterE3.Next()) {
721
722         if (anIterE3.Value().IsSame(anIterE2.Value())) {
723           // Store the second edge, defined by two vertices
724           myEdges(edge_id(1,2)) = anIterE3.Value();
725
726         } else {
727           // Store the fird edge
728           myEdges(edge_id(1,3)) = anIterE3.Value();
729         }
730       }
731     }
732   }
733
734   // Init map vertex->list_of_edges for the block
735   TopTools_IndexedDataMapOfShapeListOfShape MB;
736   MapShapesAndAncestors(theBlock, TopAbs_VERTEX, TopAbs_EDGE, MB);
737   if (MB.Extent() != NBVERTS) {
738     Standard_TypeMismatch::Raise("Block has wrong number of vertices");
739   }
740
741   // 2. Store edges, linking the first face with the second one
742   //    and vertices of the second face
743   TopTools_IndexedMapOfShape aFaceEdges;
744   TopExp::MapShapes(myFaces(1), TopAbs_EDGE, aFaceEdges);
745
746   Standard_Integer i = 1;
747   for (; i <= 4; i++) {
748     // Get i-th vertex of the face 1
749     TopoDS_Shape Vi = myVertices(vertex_id(1, i));
750     if (!MB.Contains(Vi)) {
751       Standard_ConstructionError::Raise("Face does not belong to the block");
752     }
753
754     // Get list of block's edges, sharing this Vertex
755     const TopTools_ListOfShape& anEdgesOfVi = MB.FindFromKey(Vi);
756     TopTools_ListIteratorOfListOfShape anEdgesIter (anEdgesOfVi);
757
758     // Get Edge (from the List), not belonging to the face 1
759     Standard_Boolean isFound = Standard_False;
760     for (; anEdgesIter.More() && !isFound; anEdgesIter.Next()) {
761       if (!aFaceEdges.Contains(anEdgesIter.Value())) {
762         isFound = Standard_True;
763
764         // Store the linking edge
765         TopoDS_Shape aLinkEdge = anEdgesIter.Value();
766         myEdges(side_edge_id(i)) = aLinkEdge;
767
768         // Get another vertex of the linking edge
769         TopoDS_Edge E = TopoDS::Edge(aLinkEdge);
770         TopoDS_Vertex V1, V2;
771         TopExp::Vertices(E, V1, V2, Standard_True);
772
773         // Store the i-th vertex of the second (opposite to the first) face
774         if (V1.IsSame(Vi)) {
775           myVertices(vertex_id(2, i)) = V2;
776         } else {
777           myVertices(vertex_id(2, i)) = V1;
778         }
779       }
780     }
781   }
782
783   // 3. Store edges of the second (opposite to the first) face
784   for (i = 1; i <= 4; i++) {
785     // Get i-th and (i+1)-th vertices of the face 2
786     TopoDS_Shape Vi = myVertices(vertex_id(2, i));
787     TopoDS_Shape Vj = myVertices(vertex_id(2, mod4(i + 1)));
788
789     // Get list of block's edges, sharing Vi
790     const TopTools_ListOfShape& anEdgesOfVi = MB.FindFromKey(Vi);
791     // Get list of block's edges, sharing Vj
792     const TopTools_ListOfShape& anEdgesOfVj = MB.FindFromKey(Vj);
793
794     // Get Edge (from the List), linking this vertex with the next one
795     Standard_Boolean isFound = Standard_False;
796     TopTools_ListIteratorOfListOfShape anEdgesIteri (anEdgesOfVi);
797     for (; anEdgesIteri.More() && !isFound; anEdgesIteri.Next()) {
798
799       TopTools_ListIteratorOfListOfShape anEdgesIterj (anEdgesOfVj);
800       for (; anEdgesIterj.More() && !isFound; anEdgesIterj.Next()) {
801
802         if (anEdgesIteri.Value().IsSame(anEdgesIterj.Value())) {
803           isFound = Standard_True;
804
805           // Store the linking edge
806           myEdges(edge_id(2, i)) = anEdgesIteri.Value();
807         }
808       }
809     }
810   }
811
812   // 4. Store faces of the block
813   TopTools_IndexedDataMapOfShapeListOfShape MBE;
814   MapShapesAndAncestors(theBlock, TopAbs_EDGE, TopAbs_FACE, MBE);
815   if (MBE.Extent() != NBEDGES) {
816     Standard_TypeMismatch::Raise("Block has wrong number of edges");
817   }
818
819   for (i = 2; i <= NBFACES; i++) {
820     TopoDS_Shape Ei1 = myEdges(edge_id(i, 1));
821     TopoDS_Shape Ei2 = myEdges(edge_id(i, 2));
822     const TopTools_ListOfShape& aFacesOfEi1 = MBE.FindFromKey(Ei1);
823     const TopTools_ListOfShape& aFacesOfEi2 = MBE.FindFromKey(Ei2);
824
825     Standard_Boolean isFound = Standard_False;
826     TopTools_ListIteratorOfListOfShape anIterEi1 (aFacesOfEi1);
827     for (; anIterEi1.More() && !isFound; anIterEi1.Next()) {
828
829       TopTools_ListIteratorOfListOfShape anIterEi2 (aFacesOfEi2);
830       for (; anIterEi2.More() && !isFound; anIterEi2.Next()) {
831
832         if (anIterEi1.Value().IsSame(anIterEi2.Value())) {
833           isFound = Standard_True;
834
835           // Store the face, defined by two edges
836           myFaces(i) = anIterEi1.Value();
837         }
838       }
839     }
840   }
841 }
842
843 //=======================================================================
844 //function : InitByTwoFaces
845 //purpose  :
846 //=======================================================================
847 void GEOMImpl_Block6Explorer::InitByTwoFaces (const TopoDS_Shape& theFace1,
848                                               const TopoDS_Shape& theFace2)
849 {
850   if (theFace1.IsSame(theFace2)) {
851     Standard_ConstructionError::Raise("The faces must be different");
852   }
853
854   // Add two given faces in the structure
855   myFaces(1) = theFace1;
856   myFaces(2) = theFace2;
857
858   // Step 1. Order vertices (and edges)
859
860   // 1.1. Ordered vertices and edges of the first face we put in <myVertices>
861
862   // Get wire of the first face
863   TopExp_Explorer wires1 (myFaces(1), TopAbs_WIRE);
864   if (!wires1.More()) {
865     Standard_ConstructionError::Raise("A face for the block has no wires");
866   }
867   TopoDS_Shape aWire1 = wires1.Current();
868   wires1.Next();
869   if (wires1.More()) {
870     Standard_ConstructionError::Raise("A face for the block has more than one wire");
871   }
872
873   BRepTools_WireExplorer aWE1 (TopoDS::Wire(aWire1), TopoDS::Face(myFaces(1)));
874   Standard_Integer nb;
875   for (nb = 1; aWE1.More(); aWE1.Next(), nb++) {
876     if (nb > 4) {
877       Standard_ConstructionError::Raise("A face for the block has more than four edges");
878     }
879     myEdges(edge_id(1, nb)) = aWE1.Current();
880     myVertices(vertex_id(1, nb)) = aWE1.CurrentVertex();
881   }
882   if (nb < 5) {
883     Standard_ConstructionError::Raise("A face for the block has less than four edges");
884   }
885
886   // 1.2. Ordered vertices and edges of the second face we temporarily store
887   // in arrays, to find for them rigth location in <myVertices> on the Step 2.
888
889   // declare arrays
890   TopTools_Array1OfShape aVertis2(1,4); // ordered vertices of the second face
891   TopTools_Array1OfShape anEdges2(1,4); // anEdges2(i) links aVertis2(i) and aVertis2(i+1)
892
893   // Get wire of the second face
894   TopExp_Explorer wires2 (myFaces(2), TopAbs_WIRE);
895   if (!wires2.More()) {
896     Standard_ConstructionError::Raise("A face for the block has no wires");
897   }
898   TopoDS_Shape aWire2 = wires2.Current();
899   wires2.Next();
900   if (wires2.More()) {
901     Standard_ConstructionError::Raise("A face for the block has more than one wire");
902   }
903
904   BRepTools_WireExplorer aWE2 (TopoDS::Wire(aWire2), TopoDS::Face(myFaces(2)));
905   for (nb = 1; aWE2.More(); aWE2.Next(), nb++) {
906     if (nb > 4) {
907       Standard_ConstructionError::Raise("A face for the block has more than four edges");
908     }
909     anEdges2(nb) = aWE2.Current();
910     aVertis2(nb) = aWE2.CurrentVertex();
911   }
912   if (nb < 5) {
913     Standard_ConstructionError::Raise("A face for the block has less than four edges");
914   }
915
916   // Step 2. Find right place in <myVertices> for the <aVertis2>,
917   //         so as to minimize common length of linking edges
918   //         between face 1 and face 2.
919   //         Each linking edge (of four) will link vertices of the
920   //         faces 1 and 2 with equal local numbers.
921   // The right place is defined by:
922   //  - vertex <aVertis2(i_min)>, which will become the first vertex
923   //         of the second face <myVertices(vertex_id(2,1))>
924   //  - orientation of <aVertis2> relatively their future location
925   //         in <myVertices> (s_min = 1 if direct, s_min = -1 if reversed)
926   Standard_Integer i_min = 0, s_min = 0;
927
928   TColgp_Array1OfPnt aPnts1 (1,4); // points of the first face
929   aPnts1(1) = BRep_Tool::Pnt(TopoDS::Vertex(myVertices(vertex_id(1, 1))));
930   aPnts1(2) = BRep_Tool::Pnt(TopoDS::Vertex(myVertices(vertex_id(1, 2))));
931   aPnts1(3) = BRep_Tool::Pnt(TopoDS::Vertex(myVertices(vertex_id(1, 3))));
932   aPnts1(4) = BRep_Tool::Pnt(TopoDS::Vertex(myVertices(vertex_id(1, 4))));
933
934   TColgp_Array1OfPnt aPnts2 (1,4); // points of the second face
935   aPnts2(1) = BRep_Tool::Pnt(TopoDS::Vertex(aVertis2(1)));
936   aPnts2(2) = BRep_Tool::Pnt(TopoDS::Vertex(aVertis2(2)));
937   aPnts2(3) = BRep_Tool::Pnt(TopoDS::Vertex(aVertis2(3)));
938   aPnts2(4) = BRep_Tool::Pnt(TopoDS::Vertex(aVertis2(4)));
939
940   Standard_Real Dist_min = RealLast();
941   // try all possible locations to find the best (with minimum sum distance)
942   Standard_Integer i = 1;
943   for (; i <= 4; i++) {
944     // try direct orientation
945     Standard_Real Dist_plus = aPnts1(1).Distance(aPnts2(i)) +
946                               aPnts1(2).Distance(aPnts2(mod4(i + 1))) +
947                               aPnts1(3).Distance(aPnts2(mod4(i + 2))) +
948                               aPnts1(4).Distance(aPnts2(mod4(i + 3)));
949     if (Dist_plus < Dist_min) {
950       Dist_min = Dist_plus;
951       i_min = i;
952       s_min = 1;
953     }
954
955     // try reversed orientation
956     Standard_Real Dist_minus = aPnts1(1).Distance(aPnts2(i)) +
957                                aPnts1(2).Distance(aPnts2(mod4(i - 1))) +
958                                aPnts1(3).Distance(aPnts2(mod4(i - 2))) +
959                                aPnts1(4).Distance(aPnts2(mod4(i - 3)));
960     if (Dist_minus < Dist_min) {
961       Dist_min = Dist_minus;
962       i_min = i;
963       s_min = - 1;
964     }
965   }
966
967   // 3. Put vertices and edges of the second face to they
968   //    permanent location in <myVertices> and <myEdges>
969   for (i = 1; i <= 4; i++) {
970     Standard_Integer nb = mod4(i_min + s_min*(i - 1));
971
972     if (aPnts1(i).Distance(aPnts2(nb)) < Precision::Confusion()) {
973       Standard_ConstructionError::Raise("The faces are too close");
974     }
975
976     myVertices(vertex_id(2, i)) = aVertis2(nb);
977
978     if (s_min == -1) nb = mod4(nb - 1);
979     myEdges(edge_id(2, i)) = anEdges2(nb);
980   }
981
982   // 4. Generate side surface
983   if (!aWire1.Closed() || !aWire2.Closed()) {
984     // BRepOffsetAPI_ThruSections is not applicable on not closed wires
985     GetFace(3, Standard_True);
986     GetFace(4, Standard_True);
987     GetFace(5, Standard_True);
988     GetFace(6, Standard_True);
989   } else {
990     // try to build faces on native surfaces of edges or planar
991     Standard_Boolean tryThru = Standard_False;
992     for (Standard_Integer i = 3; i <= 6 && !tryThru; i++) {
993       Standard_Boolean doMake = Standard_True;
994       TopoDS_Shape E1 = GetEdge(edge_id(i, 1), doMake);
995       TopoDS_Shape E2 = GetEdge(edge_id(i, 2), doMake);
996       TopoDS_Shape E3 = GetEdge(edge_id(i, 3), doMake);
997       TopoDS_Shape E4 = GetEdge(edge_id(i, 4), doMake);
998
999       BRepBuilderAPI_MakeWire MW (TopoDS::Edge(E1),
1000                                   TopoDS::Edge(E2),
1001                                   TopoDS::Edge(E3),
1002                                   TopoDS::Edge(E4));
1003       if (!MW.IsDone()) {
1004         Standard_ConstructionError::Raise("Wire construction failed");
1005       }
1006
1007       BRepBuilderAPI_MakeFace MF (MW, Standard_False);
1008       if (MF.IsDone()) {
1009         myFaces(i) = MF.Shape();
1010       } else {
1011         tryThru = Standard_True;
1012       }
1013     }
1014
1015     // Build side surface by ThruSections algorithm
1016     if (tryThru) {
1017       BRepOffsetAPI_ThruSections THS;
1018       THS.AddWire(TopoDS::Wire(aWire1));
1019       THS.AddWire(TopoDS::Wire(aWire2));
1020       THS.Build();
1021       if (!THS.IsDone()) {
1022         StdFail_NotDone::Raise("Side surface generation failed");
1023       }
1024       for (Standard_Integer i = 1; i <= 4; i++) {
1025         // fill face
1026         myFaces(i+2) = THS.GeneratedFace(myEdges(i));
1027
1028         // fill edge
1029         Standard_Integer ee = side_edge_id(i);
1030         TopTools_IndexedDataMapOfShapeListOfShape MVE;
1031         MapShapesAndAncestors(myFaces(i+2), TopAbs_VERTEX, TopAbs_EDGE, MVE);
1032         FindEdge(myEdges(ee),
1033                  myVertices(vertex_id_edge(ee, 1)),
1034                  myVertices(vertex_id_edge(ee, 2)),
1035                  MVE);
1036       }
1037     }
1038   }
1039 }
1040
1041 //=======================================================================
1042 //function : MapShapesAndAncestors
1043 //purpose  :
1044 //=======================================================================
1045 void GEOMImpl_Block6Explorer::MapShapesAndAncestors (const TopoDS_Shape& S,
1046                                                      const TopAbs_ShapeEnum TS,
1047                                                      const TopAbs_ShapeEnum TA,
1048                                                      TopTools_IndexedDataMapOfShapeListOfShape& M)
1049 {
1050   TopTools_ListOfShape empty;
1051   TopTools_MapOfShape mapA;
1052
1053   // visit ancestors
1054   TopExp_Explorer exa (S,TA);
1055   for (; exa.More(); exa.Next()) {
1056     // visit shapes
1057     const TopoDS_Shape& anc = exa.Current();
1058     if (mapA.Add(anc)) {
1059       TopExp_Explorer exs (anc,TS);
1060       TopTools_MapOfShape mapS;
1061       for (; exs.More(); exs.Next()) {
1062         if (mapS.Add(exs.Current())) {
1063           Standard_Integer index = M.FindIndex(exs.Current());
1064           if (index == 0) index = M.Add(exs.Current(),empty);
1065           M(index).Append(anc);
1066         }
1067       }
1068     }
1069   }
1070
1071   // visit shapes not under ancestors
1072   TopExp_Explorer ex (S,TS,TA);
1073   for (; ex.More(); ex.Next()) {
1074     Standard_Integer index = M.FindIndex(ex.Current());
1075     if (index == 0) index = M.Add(ex.Current(),empty);
1076   }
1077 }
1078
1079 //=======================================================================
1080 //function : IsSimilarEdges
1081 //purpose  :
1082 //=======================================================================
1083 Standard_Boolean GEOMImpl_Block6Explorer::IsSimilarEdges (const TopoDS_Shape& E1,
1084                                                           const TopoDS_Shape& E2)
1085 {
1086   TopoDS_Edge E1e = TopoDS::Edge(E1);
1087   TopoDS_Edge E2e = TopoDS::Edge(E2);
1088   TopoDS_Vertex V11, V12, V21, V22;
1089   TopExp::Vertices(E1e, V11, V12, Standard_True);
1090   TopExp::Vertices(E2e, V21, V22, Standard_True);
1091   if (BRepTools::Compare(V11, V21) && BRepTools::Compare(V12, V22))
1092     return Standard_True;
1093   if (BRepTools::Compare(V11, V22) && BRepTools::Compare(V12, V21))
1094     return Standard_True;
1095
1096   return Standard_False;
1097 }
1098
1099 //=======================================================================
1100 //function : FindEdge
1101 //purpose  :
1102 //=======================================================================
1103 Standard_Integer GEOMImpl_Block6Explorer::FindEdge
1104                    (TopoDS_Shape&       theResult,
1105                     const TopoDS_Shape& V1,
1106                     const TopoDS_Shape& V2,
1107                     const TopTools_IndexedDataMapOfShapeListOfShape& MVE,
1108                     const Standard_Boolean findAll)
1109 {
1110   Standard_Integer isFound = 0;
1111
1112   const TopTools_ListOfShape& anEdgesOfV1 = MVE.FindFromKey(V1);
1113   const TopTools_ListOfShape& anEdgesOfV2 = MVE.FindFromKey(V2);
1114
1115   TopTools_ListIteratorOfListOfShape it1 (anEdgesOfV1);
1116   for (; it1.More(); it1.Next()) {
1117     TopTools_ListIteratorOfListOfShape it2 (anEdgesOfV2);
1118     for (; it2.More(); it2.Next()) {
1119       if (it1.Value().IsSame(it2.Value())) {
1120         isFound++;
1121         theResult = it1.Value();
1122         if (!findAll) return isFound;
1123       }
1124     }
1125   }
1126
1127   return isFound;
1128 }
1129
1130 //=======================================================================
1131 //function : FindFace
1132 //purpose  :
1133 //=======================================================================
1134 Standard_Integer GEOMImpl_Block6Explorer::FindFace
1135                    (TopoDS_Shape&       theResult,
1136                     const TopoDS_Shape& V1,
1137                     const TopoDS_Shape& V2,
1138                     const TopoDS_Shape& V3,
1139                     const TopoDS_Shape& V4,
1140                     const TopTools_IndexedDataMapOfShapeListOfShape& MVF,
1141                     const Standard_Boolean findAll)
1142 {
1143   Standard_Integer isFound = Standard_False;
1144
1145   const TopTools_ListOfShape& aFacesOfV1 = MVF.FindFromKey(V1);
1146   const TopTools_ListOfShape& aFacesOfV2 = MVF.FindFromKey(V2);
1147   const TopTools_ListOfShape& aFacesOfV3 = MVF.FindFromKey(V3);
1148   const TopTools_ListOfShape& aFacesOfV4 = MVF.FindFromKey(V4);
1149
1150   TopTools_ListIteratorOfListOfShape it1 (aFacesOfV1);
1151   for (; it1.More(); it1.Next()) {
1152     TopTools_ListIteratorOfListOfShape it2 (aFacesOfV2);
1153     for (; it2.More(); it2.Next()) {
1154       if (it1.Value().IsSame(it2.Value())) {
1155         TopTools_ListIteratorOfListOfShape it3 (aFacesOfV3);
1156         for (; it3.More(); it3.Next()) {
1157           if (it1.Value().IsSame(it3.Value())) {
1158             TopTools_ListIteratorOfListOfShape it4 (aFacesOfV4);
1159             for (; it4.More(); it4.Next()) {
1160               if (it1.Value().IsSame(it4.Value())) {
1161                 isFound++;
1162                 theResult = it1.Value();
1163                 if (!findAll) return isFound;
1164               }
1165             }
1166           }
1167         }
1168       }
1169     }
1170   }
1171
1172   return isFound;
1173 }
1174
1175 //=======================================================================
1176 //function : MakeFace
1177 //purpose  :
1178 //=======================================================================
1179 void GEOMImpl_Block6Explorer::MakeFace (const TopoDS_Wire&     theWire,
1180                                         const Standard_Boolean isPlanarWanted,
1181                                         TopoDS_Shape&          theResult)
1182 {
1183   // try to build face on plane or on any surface under the edges of the wire
1184   BRepBuilderAPI_MakeFace MK (theWire, isPlanarWanted);
1185   if (MK.IsDone()) {
1186     theResult = MK.Shape();
1187     return;
1188   }
1189
1190   if (!isPlanarWanted) {
1191     // try to construct filling surface
1192     BRepOffsetAPI_MakeFilling MF;
1193
1194     Standard_Integer nbEdges = 0;
1195     BRepTools_WireExplorer aWE (theWire);
1196     for (; aWE.More(); aWE.Next(), nbEdges++) {
1197       MF.Add(TopoDS::Edge(aWE.Current()), GeomAbs_C0);
1198     }
1199
1200     MF.Build();
1201     if (MF.IsDone()) {
1202       // Result of filling
1203       TopoDS_Shape aFace = MF.Shape();
1204
1205       // Update tolerance
1206       Standard_Real aTol = MF.G0Error();
1207
1208       TColgp_Array1OfPnt aPnts (1,nbEdges); // points of the given wire
1209       BRepTools_WireExplorer aWE1 (theWire);
1210       Standard_Integer vi = 1;
1211       for (; aWE1.More() && vi <= nbEdges; aWE1.Next(), vi++) {
1212         aPnts(vi) = BRep_Tool::Pnt(TopoDS::Vertex(aWE1.CurrentVertex()));
1213       }
1214
1215       // Find maximum deviation in vertices
1216       TopExp_Explorer exp (aFace, TopAbs_VERTEX);
1217       TopTools_MapOfShape mapShape;
1218       for (; exp.More(); exp.Next()) {
1219         if (mapShape.Add(exp.Current())) {
1220           TopoDS_Vertex aV = TopoDS::Vertex(exp.Current());
1221           Standard_Real aTolV = BRep_Tool::Tolerance(aV);
1222           gp_Pnt aP = BRep_Tool::Pnt(aV);
1223           Standard_Real min_dist = aP.Distance(aPnts(1));
1224           for (vi = 2; vi <= nbEdges; vi++) {
1225             min_dist = Min(min_dist, aP.Distance(aPnts(vi)));
1226           }
1227           aTol = Max(aTol, aTolV);
1228           aTol = Max(aTol, min_dist);
1229         }
1230       }
1231
1232       if ((*((Handle(BRep_TFace)*)&aFace.TShape()))->Tolerance() < aTol) {
1233         (*((Handle(BRep_TFace)*)&aFace.TShape()))->Tolerance(aTol);
1234       }
1235       theResult = aFace;
1236     }
1237   } else {
1238     // try to update wire tolerances to build a planar face
1239
1240     // With OCCT6.0 or lower
1241
1242     // Find a deviation
1243     Standard_Real aToleranceReached, aTol;
1244     BRepLib_FindSurface aFS;
1245     aFS.Init(theWire, -1., isPlanarWanted);
1246     aToleranceReached = aFS.ToleranceReached();
1247     aTol = aFS.Tolerance();
1248
1249     if (!aFS.Found()) {
1250       aFS.Init(theWire, aToleranceReached, isPlanarWanted);
1251       if (!aFS.Found()) return;
1252       aToleranceReached = aFS.ToleranceReached();
1253       aTol = aFS.Tolerance();
1254     }
1255     aTol = Max(1.2 * aToleranceReached, aTol);
1256
1257     // Copy the wire, bacause it can be updated with very-very big tolerance here
1258     BRepBuilderAPI_Copy aMC (theWire);
1259     if (!aMC.IsDone()) return;
1260     TopoDS_Wire aWire = TopoDS::Wire(aMC.Shape());
1261     // Update tolerances to <aTol>
1262     BRep_Builder B;
1263     for (TopExp_Explorer expE (aWire, TopAbs_EDGE); expE.More(); expE.Next()) {
1264       TopoDS_Edge anE = TopoDS::Edge(expE.Current());
1265       B.UpdateEdge(anE, aTol);
1266     }
1267     for (TopExp_Explorer expV (aWire, TopAbs_VERTEX); expV.More(); expV.Next()) {
1268       TopoDS_Vertex aV = TopoDS::Vertex(expV.Current());
1269       B.UpdateVertex(aV, aTol);
1270     }
1271     //BRepLib::UpdateTolerances(aWire);
1272     // Build face
1273     BRepBuilderAPI_MakeFace MK1 (aWire, isPlanarWanted);
1274     if (MK1.IsDone()) {
1275       theResult = MK1.Shape();
1276       return;
1277     }
1278
1279     // After migration on OCCT version higher than 6.0
1280     //BRepLib_MakeFace aBMF;
1281     //aBMF.Init(theWire, isPlanarWanted, Standard_True);
1282     //if (aBMF.Error() == BRepLib_FaceDone) {
1283     //  theResult = aBMF.Shape();
1284     //  return;
1285     //}
1286   }
1287 }