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