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