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