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