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