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