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