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