Back to index

salome-geom  6.5.0
GEOMImpl_Block6Explorer.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
00004 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
00005 //
00006 // This library is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 2.1 of the License.
00010 //
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // Lesser General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public
00017 // License along with this library; if not, write to the Free Software
00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00019 //
00020 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00021 //
00022 
00023 #include <Standard_Stream.hxx>
00024 
00025 #include <GEOMImpl_Block6Explorer.hxx>
00026 
00027 #include <ShHealOper_ShapeProcess.hxx>
00028 
00029 #include "utilities.h"
00030 
00031 #include <Basics_OCCTVersion.hxx>
00032 
00033 #include <BRep_Tool.hxx>
00034 #include <BRep_TFace.hxx>
00035 #include <BRep_Builder.hxx>
00036 #include <BRepLib.hxx>
00037 #include <BRepLib_FindSurface.hxx>
00038 #include <BRepTools.hxx>
00039 #include <BRepTools_WireExplorer.hxx>
00040 #include <BRepOffsetAPI_ThruSections.hxx>
00041 #include <BRepOffsetAPI_MakeFilling.hxx>
00042 #include <BRepCheck_Analyzer.hxx>
00043 #include <BRepBuilderAPI_Copy.hxx>
00044 #include <BRepBuilderAPI_MakeEdge.hxx>
00045 #include <BRepBuilderAPI_MakeWire.hxx>
00046 #include <BRepBuilderAPI_MakeFace.hxx>
00047 #include <BRepBuilderAPI_Transform.hxx>
00048 
00049 #include <TopAbs.hxx>
00050 #include <TopoDS.hxx>
00051 #include <TopoDS_Shape.hxx>
00052 #include <TopoDS_Edge.hxx>
00053 #include <TopoDS_Wire.hxx>
00054 #include <TopoDS_Solid.hxx>
00055 #include <TopExp.hxx>
00056 #include <TopExp_Explorer.hxx>
00057 #include <TopTools_MapOfShape.hxx>
00058 #include <TopTools_ListOfShape.hxx>
00059 #include <TopTools_ListIteratorOfListOfShape.hxx>
00060 #include <TopTools_IndexedMapOfShape.hxx>
00061 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
00062 
00063 #include <Geom_Curve.hxx>
00064 #include <Geom_TrimmedCurve.hxx>
00065 #include <GeomFill_Generator.hxx>
00066 
00067 #include <gce_MakePln.hxx>
00068 
00069 #include <Precision.hxx>
00070 #include <gp_Pnt.hxx>
00071 #include <gp_Pln.hxx>
00072 #include <TColgp_Array1OfPnt.hxx>
00073 
00074 #include <StdFail_NotDone.hxx>
00075 #include <Standard_NullObject.hxx>
00076 #include <Standard_TypeMismatch.hxx>
00077 #include <Standard_ConstructionError.hxx>
00078 #include <Standard_NoSuchObject.hxx>
00079 
00080 #define NBFACES 6
00081 #define NBEDGES 12
00082 #define NBVERTS 8
00083 
00084 #define PLANAR_FACE_MAX_TOLERANCE 1e-06
00085 
00086 static Standard_Integer mod4 (Standard_Integer nb)
00087 {
00088   if (nb <= 0) return nb + 4;
00089   if (nb > 4)  return nb - 4;
00090   return nb;
00091 }
00092 
00093 static Standard_Integer edge_id (const Standard_Integer theFaceID,
00094                                  const Standard_Integer theEdgeNB)
00095 {
00096   static Standard_Integer edge_ids[NBFACES][4] = {
00097     {  1,  2,  3,  4 },   // face 1
00098     {  5,  6,  7,  8 },   // face 2
00099     {  9,  5, 10,  1 },   // face 3
00100     { 12,  7, 11,  3 },   // face 4
00101     {  4, 12,  8,  9 },   // face 5
00102     {  2, 11,  6, 10 } }; // face 6
00103 
00104   return edge_ids[theFaceID - 1][theEdgeNB - 1];
00105 }
00106 
00107 static Standard_Integer side_edge_id (const Standard_Integer theEdgeNB)
00108 {
00109   static Standard_Integer side_edge_ids[4] = {9, 10, 11, 12};
00110 
00111   return side_edge_ids[theEdgeNB - 1];
00112 }
00113 
00114 static Standard_Integer vertex_id (const Standard_Integer theFaceID,
00115                                    const Standard_Integer theVertexNB)
00116 {
00117   static Standard_Integer vertex_ids[NBFACES][4] = {
00118     { 1, 2, 3, 4 },   // face 1
00119     { 5, 6, 7, 8 },   // face 2
00120     { 1, 5, 6, 2 },   // face 3
00121     { 4, 8, 7, 3 },   // face 4
00122     { 1, 4, 8, 5 },   // face 5
00123     { 2, 3, 7, 6 } }; // face 6
00124 
00125   return vertex_ids[theFaceID - 1][theVertexNB - 1];
00126 }
00127 
00128 static Standard_Integer vertex_id_edge (const Standard_Integer theEdgeID, // [1,12]
00129                                         const Standard_Integer theVertexNB) // [1,2]
00130 {
00131   static Standard_Integer vertex_ids_edge[NBEDGES][2] = {
00132     {1, 2},   // edge 1
00133     {2, 3},   // edge 2
00134     {3, 4},   // edge 3
00135     {4, 1},   // edge 4
00136     {5, 6},   // edge 5
00137     {6, 7},   // edge 6
00138     {7, 8},   // edge 7
00139     {8, 5},   // edge 8
00140     {1, 5},   // edge 9
00141     {2, 6},   // edge 10
00142     {3, 7},   // edge 11
00143     {4, 8} }; // edge 12
00144 
00145   return vertex_ids_edge[theEdgeID - 1][theVertexNB - 1];
00146 }
00147 
00148 static Standard_Integer face_id_edges (const Standard_Integer theEdge1ID, // [1,12]
00149                                        const Standard_Integer theEdge2ID) // [1,12]
00150 {
00151   static Standard_Integer face_ids_edges[NBEDGES][NBEDGES] = {
00152     // 1  2  3  4  5  6  7  8  9  10 11 12
00153     {  0, 1, 1, 1, 3, 0, 0, 0, 3, 3, 0, 0  },   // edge 1
00154     {  1, 0, 1, 1, 0, 6, 0, 0, 0, 6, 6, 0  },   // edge 2
00155     {  1, 1, 0, 1, 0, 0, 4, 0, 0, 0, 4, 4  },   // edge 3
00156     {  1, 1, 1, 0, 0, 0, 0, 5, 5, 0, 0, 5  },   // edge 4
00157     {  3, 0, 0, 0, 0, 2, 2, 2, 3, 3, 0, 0  },   // edge 5
00158     {  0, 6, 0, 0, 2, 0, 2, 2, 0, 6, 6, 0  },   // edge 6
00159     {  0, 0, 4, 0, 2, 2, 0, 2, 0, 0, 4, 4  },   // edge 7
00160     {  0, 0, 0, 5, 2, 2, 2, 0, 5, 0, 0, 5  },   // edge 8
00161     {  3, 0, 0, 5, 3, 0, 0, 5, 0, 3, 0, 5  },   // edge 9
00162     {  3, 6, 0, 0, 3, 6, 0, 0, 3, 0, 6, 0  },   // edge 10
00163     {  0, 6, 4, 0, 0, 6, 4, 0, 0, 6, 0, 4  },   // edge 11
00164     {  0, 0, 4, 5, 0, 0, 4, 5, 5, 0, 4, 0  } }; // edge 12
00165 
00166   return face_ids_edges[theEdge1ID - 1][theEdge2ID - 1];
00167 }
00168 
00169 static Standard_Integer edge_id_vertices (const Standard_Integer theVertex1ID, // [1,8]
00170                                           const Standard_Integer theVertex2ID) // [1,8]
00171 {
00172   static Standard_Integer edge_ids_vertices[NBVERTS][NBVERTS] = {
00173     // 1   2   3   4   5   6   7   8
00174     {  0,  1,  0,  4,  9,  0,  0,  0},   // vertex 1
00175     {  1,  0,  2,  0,  0, 10,  0,  0},   // vertex 2
00176     {  0,  2,  0,  3,  0,  0, 11,  0},   // vertex 3
00177     {  4,  0,  3,  0,  0,  0,  0, 12},   // vertex 4
00178     {  9,  0,  0,  0,  0,  5,  0,  8},   // vertex 5
00179     {  0, 10,  0,  0,  5,  0,  6,  0},   // vertex 6
00180     {  0,  0, 11,  0,  0,  6,  0,  7},   // vertex 7
00181     {  0,  0,  0, 12,  8,  0,  7,  0} }; // vertex 8
00182 
00183   return edge_ids_vertices[theVertex1ID - 1][theVertex2ID - 1];
00184 }
00185 
00186 static Standard_Integer edge_id_faces (const Standard_Integer theFace1ID, // [1,6]
00187                                        const Standard_Integer theFace2ID) // [1,6]
00188 {
00189   static Standard_Integer edge_ids_faces[NBFACES][NBFACES] = {
00190     // 1   2   3   4   5   6
00191     {  0,  0,  1,  3,  4,  2  },   // face 1
00192     {  0,  0,  5,  7,  8,  6  },   // face 2
00193     {  1,  5,  0,  0,  9, 10  },   // face 3
00194     {  3,  7,  0,  0, 12, 11  },   // face 4
00195     {  4,  8,  9, 12,  0,  0  },   // face 5
00196     {  2,  6, 10, 11,  0,  0  } }; // face 6
00197 
00198   return edge_ids_faces[theFace1ID - 1][theFace2ID - 1];
00199 }
00200 
00201 //=======================================================================
00202 //function : GEOMImpl_Block6Explorer
00203 //purpose  : Constructor
00204 //=======================================================================
00205 GEOMImpl_Block6Explorer::GEOMImpl_Block6Explorer ()
00206      : myFaces(1,NBFACES), myEdges(1,NBEDGES), myVertices(1,NBVERTS)
00207 {
00208 }
00209 
00210 //=======================================================================
00211 //function : GetVertex
00212 //purpose  :
00213 //=======================================================================
00214 TopoDS_Shape GEOMImpl_Block6Explorer::GetVertex (const Standard_Integer theVertexID)
00215 {
00216   TopoDS_Shape aNullShape;
00217   if (theVertexID < 1 || theVertexID > NBVERTS) return aNullShape;
00218   return myVertices(theVertexID);
00219 }
00220 
00221 //=======================================================================
00222 //function : GetVertexID
00223 //purpose  :
00224 //=======================================================================
00225 Standard_Integer GEOMImpl_Block6Explorer::GetVertexID (const TopoDS_Shape& theVertex)
00226 {
00227   for (Standard_Integer id = 1; id <= NBVERTS; id++) {
00228     if (theVertex.IsSame(myVertices(id))) return id;
00229   }
00230   Standard_NoSuchObject::Raise("The Vertex does not belong to the Block");
00231   return 0;
00232 }
00233 
00234 //=======================================================================
00235 //function : GetVertexID
00236 //purpose  :
00237 //=======================================================================
00238 Standard_Integer GEOMImpl_Block6Explorer::GetVertexID (const Standard_Integer theFaceID,
00239                                                        const Standard_Integer theVertexNB)
00240 {
00241   return vertex_id(theFaceID, theVertexNB);
00242 }
00243 
00244 //=======================================================================
00245 //function : GetVertexOnEdgeID
00246 //purpose  :
00247 //=======================================================================
00248 Standard_Integer GEOMImpl_Block6Explorer::GetVertexOnEdgeID
00249                                      (const Standard_Integer theEdgeID,
00250                                       const Standard_Integer theVertexNB)
00251 {
00252   return vertex_id_edge(theEdgeID, theVertexNB);
00253 }
00254 
00255 //=======================================================================
00256 //function : GetEdge
00257 //purpose  :
00258 //=======================================================================
00259 TopoDS_Shape GEOMImpl_Block6Explorer::GetEdge (const Standard_Integer theEdgeID,
00260                                                const Standard_Boolean doMake)
00261 {
00262   TopoDS_Shape aNullShape;
00263   if (theEdgeID < 1 || theEdgeID > NBEDGES) return aNullShape;
00264   if (myEdges(theEdgeID).IsNull() && doMake) {
00265     // Create the required edge as a linear segment between
00266     // corresponding vertices and put it in the Block's edges
00267     BRepBuilderAPI_MakeEdge ME (TopoDS::Vertex(myVertices(vertex_id_edge(theEdgeID, 1))),
00268                                 TopoDS::Vertex(myVertices(vertex_id_edge(theEdgeID, 2))));
00269     if (!ME.IsDone()) {
00270       Standard_ConstructionError::Raise("Edge construction failed");
00271     }
00272     myEdges(theEdgeID) = ME.Shape();
00273   }
00274 
00275   return myEdges(theEdgeID);
00276 }
00277 
00278 //=======================================================================
00279 //function : GetEdgeID
00280 //purpose  :
00281 //=======================================================================
00282 Standard_Integer GEOMImpl_Block6Explorer::GetEdgeID (const TopoDS_Shape& theEdge)
00283 {
00284   for (Standard_Integer id = 1; id <= NBEDGES; id++) {
00285     if (theEdge.IsSame(myEdges(id))) return id;
00286   }
00287   Standard_NoSuchObject::Raise("The Edge does not belong to the Block");
00288   return 0;
00289 }
00290 
00291 //=======================================================================
00292 //function : GetEdgeID
00293 //purpose  :
00294 //=======================================================================
00295 Standard_Integer GEOMImpl_Block6Explorer::GetEdgeID (const Standard_Integer theFaceID,
00296                                                      const Standard_Integer theEdgeNB)
00297 {
00298   return edge_id(theFaceID, theEdgeNB);
00299 }
00300 
00301 //=======================================================================
00302 //function : FindEdgeID
00303 //purpose  :
00304 //=======================================================================
00305 Standard_Integer GEOMImpl_Block6Explorer::FindEdgeID (const Standard_Integer theVertex1ID,
00306                                                       const Standard_Integer theVertex2ID)
00307 {
00308   return edge_id_vertices(theVertex1ID, theVertex2ID);
00309 }
00310 
00311 //=======================================================================
00312 //function : FindCommonEdgeID
00313 //purpose  :
00314 //=======================================================================
00315 Standard_Integer GEOMImpl_Block6Explorer::FindCommonEdgeID
00316                                       (const Standard_Integer theFace1ID,
00317                                        const Standard_Integer theFace2ID)
00318 {
00319   return edge_id_faces(theFace1ID, theFace2ID);
00320 }
00321 
00322 //=======================================================================
00323 //function : GetFace
00324 //purpose  :
00325 //=======================================================================
00326 TopoDS_Shape GEOMImpl_Block6Explorer::GetFace (const Standard_Integer theFaceID,
00327                                                const Standard_Boolean doMake)
00328 {
00329   TopoDS_Shape aNullShape;
00330   if (theFaceID < 1 || theFaceID > NBFACES) return aNullShape;
00331 
00332   if (myFaces(theFaceID).IsNull() && doMake) {
00333 
00334     // Create the required face between
00335     // corresponding edges and put it in the Block's faces
00336 
00337     TopoDS_Shape E1 = GetEdge(edge_id(theFaceID, 1), doMake);
00338     TopoDS_Shape E2 = GetEdge(edge_id(theFaceID, 2), doMake);
00339     TopoDS_Shape E3 = GetEdge(edge_id(theFaceID, 3), doMake);
00340     TopoDS_Shape E4 = GetEdge(edge_id(theFaceID, 4), doMake);
00341 
00342     BRepBuilderAPI_MakeWire MW (TopoDS::Edge(E1),
00343                                 TopoDS::Edge(E2),
00344                                 TopoDS::Edge(E3),
00345                                 TopoDS::Edge(E4));
00346     if (!MW.IsDone()) {
00347       Standard_ConstructionError::Raise("Wire construction failed");
00348     }
00349     TopoDS_Shape aFace;
00350     MakeFace(MW, Standard_False, aFace);
00351     if (aFace.IsNull()) {
00352       Standard_ConstructionError::Raise("Face construction failed");
00353     }
00354     myFaces(theFaceID) = aFace;
00355   }
00356 
00357   return myFaces(theFaceID);
00358 }
00359 
00360 //=======================================================================
00361 //function : GetFaceID
00362 //purpose  :
00363 //=======================================================================
00364 Standard_Integer GEOMImpl_Block6Explorer::GetFaceID (const TopoDS_Shape& theFace)
00365 {
00366   for (Standard_Integer id = 1; id <= NBFACES; id++) {
00367     if (theFace.IsSame(myFaces(id))) return id;
00368   }
00369   Standard_NoSuchObject::Raise("The Face does not belong to the Block");
00370   return 0;
00371 }
00372 
00373 //=======================================================================
00374 //function : FindFaceID
00375 //purpose  :
00376 //=======================================================================
00377 Standard_Integer GEOMImpl_Block6Explorer::FindFaceID (const Standard_Integer theEdge1ID,
00378                                                       const Standard_Integer theEdge2ID)
00379 {
00380   return face_id_edges(theEdge1ID, theEdge2ID);
00381 }
00382 
00383 //=======================================================================
00384 //function : GetOppositeFaceID
00385 //purpose  :
00386 //=======================================================================
00387 Standard_Integer GEOMImpl_Block6Explorer::GetOppositeFaceID (const Standard_Integer theFaceID)
00388 {
00389   Standard_Integer opp_face_id[NBFACES + 1] = {
00390     0,
00391     2,  // to 1 face
00392     1,  // to 2 face
00393     4,  // to 3 face
00394     3,  // to 4 face
00395     6,  // to 5 face
00396     5}; // to 6 face
00397 
00398   return opp_face_id[theFaceID];
00399 }
00400 
00401 //=======================================================================
00402 //function : IsSimilarFaces
00403 //purpose  :
00404 //=======================================================================
00405 Standard_Boolean GEOMImpl_Block6Explorer::IsSimilarFaces (const Standard_Integer theFace1ID,
00406                                                           const Standard_Integer theFace2ID,
00407                                                           const gp_Trsf          theTransformation)
00408 {
00409   Standard_Integer common_edge_id = FindCommonEdgeID(theFace1ID, theFace2ID);
00410 
00411   if (common_edge_id == 0) { // opposite faces
00412     for (Standard_Integer id = 1; id <= 4; id++) {
00413       TopoDS_Shape E1 = GetEdge(edge_id(theFace1ID, id));
00414       TopoDS_Shape E2 = GetEdge(edge_id(theFace2ID, id));
00415 
00416       BRepBuilderAPI_Transform aTrsf (E1, theTransformation, Standard_False);
00417       if (!IsSimilarEdges(aTrsf.Shape(), E2))
00418         return Standard_False;
00419     }
00420   } else { // the faces have common edge
00421     TopTools_Array1OfShape aVerts1 (1,4);
00422     TopTools_Array1OfShape aVerts2 (1,4);
00423 
00424     Standard_Integer common_vertex1 = GetVertexOnEdgeID(common_edge_id, 1);
00425     Standard_Integer common_vertex2 = GetVertexOnEdgeID(common_edge_id, 2);
00426     aVerts1(1) = myVertices(common_vertex1);
00427     aVerts1(2) = myVertices(common_vertex2);
00428     aVerts2(1) = myVertices(common_vertex1);
00429     aVerts2(2) = myVertices(common_vertex2);
00430 
00431     Standard_Integer not_common_v11 = 0, not_common_v12 = 0;
00432     Standard_Integer vnb, vid;
00433     for (vnb = 1; vnb <= 4; vnb++) {
00434       vid = GetVertexID(theFace1ID, vnb);
00435       if (vid != common_vertex1 && FindEdgeID(vid, common_vertex1) == 0) {
00436         not_common_v12 = vid;
00437       } else {
00438         if (vid != common_vertex2 && FindEdgeID(vid, common_vertex2) == 0) {
00439           not_common_v11 = vid;
00440         }
00441       }
00442     }
00443 
00444     Standard_Integer not_common_v21 = 0, not_common_v22 = 0;
00445     for (vnb = 1; vnb <= 4; vnb++) {
00446       vid = GetVertexID(theFace2ID, vnb);
00447       if (vid != common_vertex1 && FindEdgeID(vid, common_vertex1) == 0) {
00448         not_common_v22 = vid;
00449       } else {
00450         if (vid != common_vertex2 && FindEdgeID(vid, common_vertex2) == 0) {
00451           not_common_v21 = vid;
00452         }
00453       }
00454     }
00455     aVerts1(3) = myVertices(not_common_v11);
00456     aVerts1(4) = myVertices(not_common_v12);
00457     aVerts2(3) = myVertices(not_common_v21);
00458     aVerts2(4) = myVertices(not_common_v22);
00459 
00460     for (Standard_Integer id = 1; id <= 4; id++) {
00461       BRepBuilderAPI_Transform aTrsf (aVerts1(id), theTransformation, Standard_False);
00462       TopoDS_Vertex V1 = TopoDS::Vertex(aTrsf.Shape());
00463       TopoDS_Vertex V2 = TopoDS::Vertex(aVerts2(id));
00464       if (!BRepTools::Compare(V1, V2)) {
00465         return Standard_False;
00466       }
00467     }
00468   }
00469 
00470   return Standard_True;
00471 }
00472 
00473 //============ Initialization methods ===================================
00474 
00475 //=======================================================================
00476 //function : InitByBlock
00477 //purpose  :
00478 //=======================================================================
00479 void GEOMImpl_Block6Explorer::InitByBlock (const TopoDS_Shape& theBlock)
00480 {
00481   // 1. Find any one face of the block
00482   TopExp_Explorer faces (theBlock, TopAbs_FACE);
00483   if (!faces.More()) {
00484     Standard_ConstructionError::Raise("The block has no faces");
00485   }
00486   TopoDS_Shape aFirstFace = faces.Current();
00487 
00488   // 2. Store all elements of the block relatively aFirstFace
00489   InitByBlockAndFace(theBlock, aFirstFace);
00490 }
00491 
00492 //=======================================================================
00493 //function : InitByBlockAndFace
00494 //purpose  :
00495 //=======================================================================
00496 void GEOMImpl_Block6Explorer::InitByBlockAndFace (const TopoDS_Shape& theBlock,
00497                                                   const TopoDS_Shape& theFace)
00498 {
00499   myFaces(1) = theFace;
00500 
00501   // 2. Get wire of the first face
00502   TopExp_Explorer wires (myFaces(1), TopAbs_WIRE);
00503   if (!wires.More()) {
00504     Standard_ConstructionError::Raise("A face of the block has no wires");
00505   }
00506   TopoDS_Shape aWire = wires.Current();
00507   wires.Next();
00508   if (wires.More()) {
00509     Standard_ConstructionError::Raise("A face of the block has more than one wires");
00510   }
00511 
00512   // 3. Explore wire to init edges and vertices of the first face
00513   BRepTools_WireExplorer aWE (TopoDS::Wire(aWire), TopoDS::Face(myFaces(1)));
00514   Standard_Integer nb = 1;
00515   for (; aWE.More(); aWE.Next(), nb++) {
00516     if (nb > 4) {
00517       Standard_ConstructionError::Raise("A face of the block has more than four edges");
00518     }
00519     myEdges(edge_id(1, nb)) = aWE.Current();
00520     myVertices(vertex_id(1, nb)) = aWE.CurrentVertex();
00521   }
00522   if (nb < 5) {
00523     Standard_ConstructionError::Raise("A face of the block has less than four edges");
00524   }
00525 
00526   // 2. Store all other elements of the block
00527   InitByBlockAndVertices (theBlock,
00528                           myVertices(vertex_id(1,1)),
00529                           myVertices(vertex_id(1,2)),
00530                           myVertices(vertex_id(1,3)));
00531 }
00532 
00533 //=======================================================================
00534 //function : InitByBlockAndEdges
00535 //purpose  :
00536 //=======================================================================
00537 void GEOMImpl_Block6Explorer::InitByBlockAndEdges (const TopoDS_Shape& theBlock,
00538                                                    const TopoDS_Shape& theEdge1,
00539                                                    const TopoDS_Shape& theEdge3)
00540 {
00541   // 1. Store vertices and edges of the first face
00542 
00543   // 1.1. Store two given edges
00544   myEdges(edge_id(1, 1)) = theEdge1;
00545   myEdges(edge_id(1, 3)) = theEdge3;
00546 
00547   // 1.2. Find and store the first face
00548   TopTools_IndexedDataMapOfShapeListOfShape MEF;
00549   MapShapesAndAncestors(theBlock, TopAbs_EDGE, TopAbs_FACE, MEF);
00550   if (MEF.Extent() != NBEDGES) {
00551     Standard_TypeMismatch::Raise("Block has wrong number of edges");
00552   }
00553   const TopTools_ListOfShape& aFacesOfE1 = MEF.FindFromKey(theEdge1);
00554   const TopTools_ListOfShape& aFacesOfE3 = MEF.FindFromKey(theEdge3);
00555 
00556   Standard_Boolean isFound = Standard_False;
00557   TopTools_ListIteratorOfListOfShape anIterF1 (aFacesOfE1);
00558   for (; anIterF1.More() && !isFound; anIterF1.Next()) {
00559 
00560     TopTools_ListIteratorOfListOfShape anIterF3 (aFacesOfE3);
00561     for (; anIterF3.More() && !isFound; anIterF3.Next()) {
00562 
00563       if (anIterF1.Value().IsSame(anIterF3.Value())) {
00564         isFound = Standard_True;
00565 
00566         // Store the face, defined by two opposite edges
00567         myFaces(1) = anIterF1.Value();
00568       }
00569     }
00570   }
00571   if (!isFound) {
00572     Standard_ConstructionError::Raise
00573       ("Edges 1 and 2 do not belong to one face of the block");
00574   }
00575 
00576   // 1.3. Make vertices of the first edge the first and the
00577   //      second vertices of the first face. Order is free.
00578   TopoDS_Edge E = TopoDS::Edge(theEdge1);
00579   TopoDS_Vertex V1, V2;
00580   TopExp::Vertices(E, V1, V2, Standard_True);
00581   myVertices(vertex_id(1,1)) = V1;
00582   myVertices(vertex_id(1,2)) = V2;
00583 
00584   // Init maps vertex->list_of_edges for the face
00585   TopTools_IndexedDataMapOfShapeListOfShape M1;
00586   MapShapesAndAncestors(myFaces(1), TopAbs_VERTEX, TopAbs_EDGE, M1);
00587   if (M1.Extent() != 4) {
00588     Standard_TypeMismatch::Raise("The first face of block has wrong number of vertices");
00589   }
00590 
00591   // 1.4. Find and store others elements of the first face
00592 
00593   // edges of the first vertex
00594   TopoDS_Shape E1_f = M1.FindFromKey(V1).First();
00595   TopoDS_Shape E1_l = M1.FindFromKey(V1).Last();
00596 
00597   if (E1_f.IsSame(theEdge1)) {
00598     myEdges(edge_id(1, 4)) = E1_l;
00599   } else {
00600     myEdges(edge_id(1, 4)) = E1_f;
00601   }
00602 
00603   // fourth vertex
00604   TopoDS_Edge E4 = TopoDS::Edge(myEdges(edge_id(1, 4)));
00605   TopoDS_Vertex V41, V42;
00606   TopExp::Vertices(E4, V41, V42, Standard_True);
00607   if (V41.IsSame(V1)) {
00608     myVertices(vertex_id(1,4)) = V42;
00609   } else {
00610     myVertices(vertex_id(1,4)) = V41;
00611   }
00612 
00613   // edges of the second vertex
00614   TopoDS_Shape E2_f = M1.FindFromKey(V2).First();
00615   TopoDS_Shape E2_l = M1.FindFromKey(V2).Last();
00616 
00617   if (E2_f.IsSame(theEdge1)) {
00618     myEdges(edge_id(1, 2)) = E2_l;
00619   } else {
00620     myEdges(edge_id(1, 2)) = E2_f;
00621   }
00622 
00623   // fird vertex
00624   TopoDS_Edge E2 = TopoDS::Edge(myEdges(edge_id(1, 2)));
00625   TopoDS_Vertex V21, V22;
00626   TopExp::Vertices(E2, V21, V22, Standard_True);
00627   if (V21.IsSame(V2)) {
00628     myVertices(vertex_id(1,3)) = V22;
00629   } else {
00630     myVertices(vertex_id(1,3)) = V21;
00631   }
00632 
00633   // 2. Store all other elements of the block
00634   InitByBlockAndVertices (theBlock,
00635                           myVertices(vertex_id(1,1)),
00636                           myVertices(vertex_id(1,2)),
00637                           myVertices(vertex_id(1,3)));
00638 }
00639 
00640 //=======================================================================
00641 //function : InitByBlockAndVertices
00642 //purpose  :
00643 //=======================================================================
00644 void GEOMImpl_Block6Explorer::InitByBlockAndVertices (const TopoDS_Shape& theBlock,
00645                                                       const TopoDS_Shape& theVertex1,
00646                                                       const TopoDS_Shape& theVertex2,
00647                                                       const TopoDS_Shape& theVertex3)
00648 {
00649   // Here we suppose, that vertices are ordered, i.e. exists edge between
00650   // theVertex1 and theVertex2 and edge between theVertex2 and theVertex3
00651 
00652   // 1. Store vertices and edges of the first face.
00653   //    If the first face is initialized, it means, that this
00654   //    method is called from another initialization method, and all
00655   //    vertices and edges of the first face are also initialized
00656   if (myFaces(1).IsNull()) {
00657 
00658     // 1.1. Store first three vertices
00659     myVertices(vertex_id(1, 1)) = theVertex1;
00660     myVertices(vertex_id(1, 2)) = theVertex2;
00661     myVertices(vertex_id(1, 3)) = theVertex3;
00662 
00663     // 1.2. Find and store the first face
00664     TopTools_IndexedDataMapOfShapeListOfShape MVF;
00665     MapShapesAndAncestors(theBlock, TopAbs_VERTEX, TopAbs_FACE, MVF);
00666     if (MVF.Extent() != NBVERTS) {
00667       Standard_TypeMismatch::Raise("Block has wrong number of vertices");
00668     }
00669     const TopTools_ListOfShape& aFacesOfV1 = MVF.FindFromKey(theVertex1);
00670     const TopTools_ListOfShape& aFacesOfV3 = MVF.FindFromKey(theVertex3);
00671 
00672     Standard_Boolean isFound = Standard_False;
00673     TopTools_ListIteratorOfListOfShape anIterF1 (aFacesOfV1);
00674     for (; anIterF1.More() && !isFound; anIterF1.Next()) {
00675 
00676       TopTools_ListIteratorOfListOfShape anIterF3 (aFacesOfV3);
00677       for (; anIterF3.More() && !isFound; anIterF3.Next()) {
00678 
00679         if (anIterF1.Value().IsSame(anIterF3.Value())) {
00680           isFound = Standard_True;
00681 
00682           // Store the face, defined by two opposite vertices
00683           myFaces(1) = anIterF1.Value();
00684         }
00685       }
00686     }
00687     if (!isFound) {
00688       Standard_ConstructionError::Raise
00689         ("Vertices 1 and 3 do not belong to one face of the block");
00690     }
00691 
00692     // Init maps vertex->list_of_edges for the face
00693     TopTools_IndexedDataMapOfShapeListOfShape M1;
00694     MapShapesAndAncestors(myFaces(1), TopAbs_VERTEX, TopAbs_EDGE, M1);
00695     if (M1.Extent() != 4) {
00696       Standard_TypeMismatch::Raise("The first face of block has wrong number of vertices");
00697     }
00698 
00699     // 1.3. Find and store edges and last vertex of the first face
00700     const TopTools_ListOfShape& anEdgesOfV1 = M1.FindFromKey(theVertex1);
00701     const TopTools_ListOfShape& anEdgesOfV2 = M1.FindFromKey(theVertex2);
00702     const TopTools_ListOfShape& anEdgesOfV3 = M1.FindFromKey(theVertex3);
00703 
00704     TopTools_ListIteratorOfListOfShape anIterE2 (anEdgesOfV2);
00705     for (; anIterE2.More(); anIterE2.Next()) {
00706 
00707       TopTools_ListIteratorOfListOfShape anIterE1 (anEdgesOfV1);
00708       for (; anIterE1.More(); anIterE1.Next()) {
00709 
00710         if (anIterE1.Value().IsSame(anIterE2.Value())) {
00711           // Store the first edge, defined by two vertices
00712           myEdges(edge_id(1,1)) = anIterE1.Value();
00713 
00714         } else {
00715           // Store the last edge
00716           myEdges(edge_id(1,4)) = anIterE1.Value();
00717 
00718           // Find and store the last vertex
00719           TopoDS_Edge E = TopoDS::Edge(myEdges(4));
00720           TopoDS_Vertex V1, V2;
00721           TopExp::Vertices(E, V1, V2, Standard_True);
00722 
00723           if (V1.IsSame(theVertex1)) {
00724             myVertices(vertex_id(1,4)) = V2;
00725           } else {
00726             myVertices(vertex_id(1,4)) = V1;
00727           }
00728         }
00729       }
00730 
00731       TopTools_ListIteratorOfListOfShape anIterE3 (anEdgesOfV3);
00732       for (; anIterE3.More(); anIterE3.Next()) {
00733 
00734         if (anIterE3.Value().IsSame(anIterE2.Value())) {
00735           // Store the second edge, defined by two vertices
00736           myEdges(edge_id(1,2)) = anIterE3.Value();
00737 
00738         } else {
00739           // Store the fird edge
00740           myEdges(edge_id(1,3)) = anIterE3.Value();
00741         }
00742       }
00743     }
00744   }
00745 
00746   // Init map vertex->list_of_edges for the block
00747   TopTools_IndexedDataMapOfShapeListOfShape MB;
00748   MapShapesAndAncestors(theBlock, TopAbs_VERTEX, TopAbs_EDGE, MB);
00749   if (MB.Extent() != NBVERTS) {
00750     Standard_TypeMismatch::Raise("Block has wrong number of vertices");
00751   }
00752 
00753   // 2. Store edges, linking the first face with the second one
00754   //    and vertices of the second face
00755   TopTools_IndexedMapOfShape aFaceEdges;
00756   TopExp::MapShapes(myFaces(1), TopAbs_EDGE, aFaceEdges);
00757 
00758   Standard_Integer i = 1;
00759   for (; i <= 4; i++) {
00760     // Get i-th vertex of the face 1
00761     TopoDS_Shape Vi = myVertices(vertex_id(1, i));
00762     if (!MB.Contains(Vi)) {
00763       Standard_ConstructionError::Raise("Face does not belong to the block");
00764     }
00765 
00766     // Get list of block's edges, sharing this Vertex
00767     const TopTools_ListOfShape& anEdgesOfVi = MB.FindFromKey(Vi);
00768     TopTools_ListIteratorOfListOfShape anEdgesIter (anEdgesOfVi);
00769 
00770     // Get Edge (from the List), not belonging to the face 1
00771     Standard_Boolean isFound = Standard_False;
00772     for (; anEdgesIter.More() && !isFound; anEdgesIter.Next()) {
00773       if (!aFaceEdges.Contains(anEdgesIter.Value())) {
00774         isFound = Standard_True;
00775 
00776         // Store the linking edge
00777         TopoDS_Shape aLinkEdge = anEdgesIter.Value();
00778         myEdges(side_edge_id(i)) = aLinkEdge;
00779 
00780         // Get another vertex of the linking edge
00781         TopoDS_Edge E = TopoDS::Edge(aLinkEdge);
00782         TopoDS_Vertex V1, V2;
00783         TopExp::Vertices(E, V1, V2, Standard_True);
00784 
00785         // Store the i-th vertex of the second (opposite to the first) face
00786         if (V1.IsSame(Vi)) {
00787           myVertices(vertex_id(2, i)) = V2;
00788         } else {
00789           myVertices(vertex_id(2, i)) = V1;
00790         }
00791       }
00792     }
00793   }
00794 
00795   // 3. Store edges of the second (opposite to the first) face
00796   for (i = 1; i <= 4; i++) {
00797     // Get i-th and (i+1)-th vertices of the face 2
00798     TopoDS_Shape Vi = myVertices(vertex_id(2, i));
00799     TopoDS_Shape Vj = myVertices(vertex_id(2, mod4(i + 1)));
00800 
00801     // Get list of block's edges, sharing Vi
00802     const TopTools_ListOfShape& anEdgesOfVi = MB.FindFromKey(Vi);
00803     // Get list of block's edges, sharing Vj
00804     const TopTools_ListOfShape& anEdgesOfVj = MB.FindFromKey(Vj);
00805 
00806     // Get Edge (from the List), linking this vertex with the next one
00807     Standard_Boolean isFound = Standard_False;
00808     TopTools_ListIteratorOfListOfShape anEdgesIteri (anEdgesOfVi);
00809     for (; anEdgesIteri.More() && !isFound; anEdgesIteri.Next()) {
00810 
00811       TopTools_ListIteratorOfListOfShape anEdgesIterj (anEdgesOfVj);
00812       for (; anEdgesIterj.More() && !isFound; anEdgesIterj.Next()) {
00813 
00814         if (anEdgesIteri.Value().IsSame(anEdgesIterj.Value())) {
00815           isFound = Standard_True;
00816 
00817           // Store the linking edge
00818           myEdges(edge_id(2, i)) = anEdgesIteri.Value();
00819         }
00820       }
00821     }
00822   }
00823 
00824   // 4. Store faces of the block
00825   TopTools_IndexedDataMapOfShapeListOfShape MBE;
00826   MapShapesAndAncestors(theBlock, TopAbs_EDGE, TopAbs_FACE, MBE);
00827   if (MBE.Extent() != NBEDGES) {
00828     Standard_TypeMismatch::Raise("Block has wrong number of edges");
00829   }
00830 
00831   for (i = 2; i <= NBFACES; i++) {
00832     TopoDS_Shape Ei1 = myEdges(edge_id(i, 1));
00833     TopoDS_Shape Ei2 = myEdges(edge_id(i, 2));
00834     const TopTools_ListOfShape& aFacesOfEi1 = MBE.FindFromKey(Ei1);
00835     const TopTools_ListOfShape& aFacesOfEi2 = MBE.FindFromKey(Ei2);
00836 
00837     Standard_Boolean isFound = Standard_False;
00838     TopTools_ListIteratorOfListOfShape anIterEi1 (aFacesOfEi1);
00839     for (; anIterEi1.More() && !isFound; anIterEi1.Next()) {
00840 
00841       TopTools_ListIteratorOfListOfShape anIterEi2 (aFacesOfEi2);
00842       for (; anIterEi2.More() && !isFound; anIterEi2.Next()) {
00843 
00844         if (anIterEi1.Value().IsSame(anIterEi2.Value())) {
00845           isFound = Standard_True;
00846 
00847           // Store the face, defined by two edges
00848           myFaces(i) = anIterEi1.Value();
00849         }
00850       }
00851     }
00852   }
00853 }
00854 
00855 //=======================================================================
00856 //function : InitByTwoFaces
00857 //purpose  :
00858 //=======================================================================
00859 void GEOMImpl_Block6Explorer::InitByTwoFaces (const TopoDS_Shape& theFace1,
00860                                               const TopoDS_Shape& theFace2)
00861 {
00862   if (theFace1.IsSame(theFace2)) {
00863     Standard_ConstructionError::Raise("The faces must be different");
00864   }
00865 
00866   // Add two given faces in the structure
00867   myFaces(1) = theFace1;
00868   myFaces(2) = theFace2;
00869 
00870   // Step 1. Order vertices (and edges)
00871 
00872   // 1.1. Ordered vertices and edges of the first face we put in <myVertices>
00873 
00874   // Get wire of the first face
00875   TopExp_Explorer wires1 (myFaces(1), TopAbs_WIRE);
00876   if (!wires1.More()) {
00877     Standard_ConstructionError::Raise("A face for the block has no wires");
00878   }
00879   TopoDS_Shape aWire1 = wires1.Current();
00880   wires1.Next();
00881   if (wires1.More()) {
00882     Standard_ConstructionError::Raise("A face for the block has more than one wire");
00883   }
00884 
00885   BRepTools_WireExplorer aWE1 (TopoDS::Wire(aWire1), TopoDS::Face(myFaces(1)));
00886   Standard_Integer nb;
00887   for (nb = 1; aWE1.More(); aWE1.Next(), nb++) {
00888     if (nb > 4) {
00889       Standard_ConstructionError::Raise("A face for the block has more than four edges");
00890     }
00891     myEdges(edge_id(1, nb)) = aWE1.Current();
00892     myVertices(vertex_id(1, nb)) = aWE1.CurrentVertex();
00893   }
00894   if (nb < 5) {
00895     Standard_ConstructionError::Raise("A face for the block has less than four edges");
00896   }
00897 
00898   // 1.2. Ordered vertices and edges of the second face we temporarily store
00899   // in arrays, to find for them rigth location in <myVertices> on the Step 2.
00900 
00901   // declare arrays
00902   TopTools_Array1OfShape aVertis2(1,4); // ordered vertices of the second face
00903   TopTools_Array1OfShape anEdges2(1,4); // anEdges2(i) links aVertis2(i) and aVertis2(i+1)
00904 
00905   // Get wire of the second face
00906   TopExp_Explorer wires2 (myFaces(2), TopAbs_WIRE);
00907   if (!wires2.More()) {
00908     Standard_ConstructionError::Raise("A face for the block has no wires");
00909   }
00910   TopoDS_Shape aWire2 = wires2.Current();
00911   wires2.Next();
00912   if (wires2.More()) {
00913     Standard_ConstructionError::Raise("A face for the block has more than one wire");
00914   }
00915 
00916   BRepTools_WireExplorer aWE2 (TopoDS::Wire(aWire2), TopoDS::Face(myFaces(2)));
00917   for (nb = 1; aWE2.More(); aWE2.Next(), nb++) {
00918     if (nb > 4) {
00919       Standard_ConstructionError::Raise("A face for the block has more than four edges");
00920     }
00921     anEdges2(nb) = aWE2.Current();
00922     aVertis2(nb) = aWE2.CurrentVertex();
00923   }
00924   if (nb < 5) {
00925     Standard_ConstructionError::Raise("A face for the block has less than four edges");
00926   }
00927 
00928   // Step 2. Find right place in <myVertices> for the <aVertis2>,
00929   //         so as to minimize common length of linking edges
00930   //         between face 1 and face 2.
00931   //         Each linking edge (of four) will link vertices of the
00932   //         faces 1 and 2 with equal local numbers.
00933   // The right place is defined by:
00934   //  - vertex <aVertis2(i_min)>, which will become the first vertex
00935   //         of the second face <myVertices(vertex_id(2,1))>
00936   //  - orientation of <aVertis2> relatively their future location
00937   //         in <myVertices> (s_min = 1 if direct, s_min = -1 if reversed)
00938   Standard_Integer i_min = 0, s_min = 0;
00939 
00940   TColgp_Array1OfPnt aPnts1 (1,4); // points of the first face
00941   aPnts1(1) = BRep_Tool::Pnt(TopoDS::Vertex(myVertices(vertex_id(1, 1))));
00942   aPnts1(2) = BRep_Tool::Pnt(TopoDS::Vertex(myVertices(vertex_id(1, 2))));
00943   aPnts1(3) = BRep_Tool::Pnt(TopoDS::Vertex(myVertices(vertex_id(1, 3))));
00944   aPnts1(4) = BRep_Tool::Pnt(TopoDS::Vertex(myVertices(vertex_id(1, 4))));
00945 
00946   TColgp_Array1OfPnt aPnts2 (1,4); // points of the second face
00947   aPnts2(1) = BRep_Tool::Pnt(TopoDS::Vertex(aVertis2(1)));
00948   aPnts2(2) = BRep_Tool::Pnt(TopoDS::Vertex(aVertis2(2)));
00949   aPnts2(3) = BRep_Tool::Pnt(TopoDS::Vertex(aVertis2(3)));
00950   aPnts2(4) = BRep_Tool::Pnt(TopoDS::Vertex(aVertis2(4)));
00951 
00952   Standard_Real Dist_min = RealLast();
00953   // try all possible locations to find the best (with minimum sum distance)
00954   Standard_Integer i = 1;
00955   for (; i <= 4; i++) {
00956     // try direct orientation
00957     Standard_Real Dist_plus = aPnts1(1).Distance(aPnts2(i)) +
00958                               aPnts1(2).Distance(aPnts2(mod4(i + 1))) +
00959                               aPnts1(3).Distance(aPnts2(mod4(i + 2))) +
00960                               aPnts1(4).Distance(aPnts2(mod4(i + 3)));
00961     if (Dist_plus < Dist_min) {
00962       Dist_min = Dist_plus;
00963       i_min = i;
00964       s_min = 1;
00965     }
00966 
00967     // try reversed orientation
00968     Standard_Real Dist_minus = aPnts1(1).Distance(aPnts2(i)) +
00969                                aPnts1(2).Distance(aPnts2(mod4(i - 1))) +
00970                                aPnts1(3).Distance(aPnts2(mod4(i - 2))) +
00971                                aPnts1(4).Distance(aPnts2(mod4(i - 3)));
00972     if (Dist_minus < Dist_min) {
00973       Dist_min = Dist_minus;
00974       i_min = i;
00975       s_min = - 1;
00976     }
00977   }
00978 
00979   // 3. Put vertices and edges of the second face to they
00980   //    permanent location in <myVertices> and <myEdges>
00981   for (i = 1; i <= 4; i++) {
00982     Standard_Integer nb = mod4(i_min + s_min*(i - 1));
00983 
00984     if (aPnts1(i).Distance(aPnts2(nb)) < Precision::Confusion()) {
00985       Standard_ConstructionError::Raise("The faces are too close");
00986     }
00987 
00988     myVertices(vertex_id(2, i)) = aVertis2(nb);
00989 
00990     if (s_min == -1) nb = mod4(nb - 1);
00991     myEdges(edge_id(2, i)) = anEdges2(nb);
00992   }
00993 
00994   // check the wires closure
00995   TopoDS_Wire wire1 = TopoDS::Wire(aWire1);
00996   TopoDS_Wire wire2 = TopoDS::Wire(aWire2);
00997   TopoDS_Vertex aV1, aV2;
00998 
00999   TopExp::Vertices(wire1, aV1, aV2);
01000   if (!aV1.IsNull() && !aV2.IsNull() && aV1.IsSame(aV2))
01001     aWire1.Closed(true);
01002 
01003   TopExp::Vertices(wire2, aV1, aV2);
01004   if (!aV1.IsNull() && !aV2.IsNull() && aV1.IsSame(aV2))
01005     aWire2.Closed(true);
01006 
01007   // 4. Generate side surface
01008   if (!aWire1.Closed() || !aWire2.Closed()) {
01009     // BRepOffsetAPI_ThruSections is not applicable on not closed wires
01010     GetFace(3, Standard_True);
01011     GetFace(4, Standard_True);
01012     GetFace(5, Standard_True);
01013     GetFace(6, Standard_True);
01014   } else {
01015     // try to build faces on native surfaces of edges or planar
01016     Standard_Boolean tryThru = Standard_False;
01017     for (Standard_Integer i = 3; i <= 6 && !tryThru; i++) {
01018       Standard_Boolean doMake = Standard_True;
01019       TopoDS_Shape E1 = GetEdge(edge_id(i, 1), doMake);
01020       TopoDS_Shape E2 = GetEdge(edge_id(i, 2), doMake);
01021       TopoDS_Shape E3 = GetEdge(edge_id(i, 3), doMake);
01022       TopoDS_Shape E4 = GetEdge(edge_id(i, 4), doMake);
01023 
01024       BRepBuilderAPI_MakeWire MW (TopoDS::Edge(E1),
01025                                   TopoDS::Edge(E2),
01026                                   TopoDS::Edge(E3),
01027                                   TopoDS::Edge(E4));
01028       if (!MW.IsDone()) {
01029         Standard_ConstructionError::Raise("Wire construction failed");
01030       }
01031 
01032       BRepBuilderAPI_MakeFace MF (MW, Standard_False);
01033       if (MF.IsDone()) {
01034         myFaces(i) = MF.Shape();
01035       } else {
01036         tryThru = Standard_True;
01037       }
01038     }
01039 
01040     // Build side surface by ThruSections algorithm
01041     if (tryThru) {
01042       BRepOffsetAPI_ThruSections THS;
01043       THS.AddWire(TopoDS::Wire(aWire1));
01044       THS.AddWire(TopoDS::Wire(aWire2));
01045       THS.Build();
01046       if (!THS.IsDone()) {
01047         StdFail_NotDone::Raise("Side surface generation failed");
01048       }
01049       for (Standard_Integer i = 1; i <= 4; i++) {
01050         // fill face
01051         myFaces(i+2) = THS.GeneratedFace(myEdges(i));
01052 
01053         // fill edge
01054         Standard_Integer ee = side_edge_id(i);
01055         TopTools_IndexedDataMapOfShapeListOfShape MVE;
01056         MapShapesAndAncestors(myFaces(i+2), TopAbs_VERTEX, TopAbs_EDGE, MVE);
01057         FindEdge(myEdges(ee),
01058                  myVertices(vertex_id_edge(ee, 1)),
01059                  myVertices(vertex_id_edge(ee, 2)),
01060                  MVE);
01061       }
01062     }
01063   }
01064 }
01065 
01066 //=======================================================================
01067 //function : MapShapesAndAncestors
01068 //purpose  :
01069 //=======================================================================
01070 void GEOMImpl_Block6Explorer::MapShapesAndAncestors (const TopoDS_Shape& S,
01071                                                      const TopAbs_ShapeEnum TS,
01072                                                      const TopAbs_ShapeEnum TA,
01073                                                      TopTools_IndexedDataMapOfShapeListOfShape& M)
01074 {
01075   TopTools_ListOfShape empty;
01076   TopTools_MapOfShape mapA;
01077 
01078   // visit ancestors
01079   TopExp_Explorer exa (S,TA);
01080   for (; exa.More(); exa.Next()) {
01081     // visit shapes
01082     const TopoDS_Shape& anc = exa.Current();
01083     if (mapA.Add(anc)) {
01084       TopExp_Explorer exs (anc,TS);
01085       TopTools_MapOfShape mapS;
01086       for (; exs.More(); exs.Next()) {
01087         if (mapS.Add(exs.Current())) {
01088           Standard_Integer index = M.FindIndex(exs.Current());
01089           if (index == 0) index = M.Add(exs.Current(),empty);
01090           M(index).Append(anc);
01091         }
01092       }
01093     }
01094   }
01095 
01096   // visit shapes not under ancestors
01097   TopExp_Explorer ex (S,TS,TA);
01098   for (; ex.More(); ex.Next()) {
01099     Standard_Integer index = M.FindIndex(ex.Current());
01100     if (index == 0) index = M.Add(ex.Current(),empty);
01101   }
01102 }
01103 
01104 //=======================================================================
01105 //function : IsSimilarEdges
01106 //purpose  :
01107 //=======================================================================
01108 Standard_Boolean GEOMImpl_Block6Explorer::IsSimilarEdges (const TopoDS_Shape& E1,
01109                                                           const TopoDS_Shape& E2)
01110 {
01111   TopoDS_Edge E1e = TopoDS::Edge(E1);
01112   TopoDS_Edge E2e = TopoDS::Edge(E2);
01113   TopoDS_Vertex V11, V12, V21, V22;
01114   TopExp::Vertices(E1e, V11, V12, Standard_True);
01115   TopExp::Vertices(E2e, V21, V22, Standard_True);
01116   if (BRepTools::Compare(V11, V21) && BRepTools::Compare(V12, V22))
01117     return Standard_True;
01118   if (BRepTools::Compare(V11, V22) && BRepTools::Compare(V12, V21))
01119     return Standard_True;
01120 
01121   return Standard_False;
01122 }
01123 
01124 //=======================================================================
01125 //function : FindEdge
01126 //purpose  :
01127 //=======================================================================
01128 Standard_Integer GEOMImpl_Block6Explorer::FindEdge
01129                    (TopoDS_Shape&       theResult,
01130                     const TopoDS_Shape& V1,
01131                     const TopoDS_Shape& V2,
01132                     const TopTools_IndexedDataMapOfShapeListOfShape& MVE,
01133                     const Standard_Boolean findAll)
01134 {
01135   Standard_Integer isFound = 0;
01136 
01137   const TopTools_ListOfShape& anEdgesOfV1 = MVE.FindFromKey(V1);
01138   const TopTools_ListOfShape& anEdgesOfV2 = MVE.FindFromKey(V2);
01139 
01140   TopTools_ListIteratorOfListOfShape it1 (anEdgesOfV1);
01141   for (; it1.More(); it1.Next()) {
01142     TopTools_ListIteratorOfListOfShape it2 (anEdgesOfV2);
01143     for (; it2.More(); it2.Next()) {
01144       if (it1.Value().IsSame(it2.Value())) {
01145         isFound++;
01146         theResult = it1.Value();
01147         if (!findAll) return isFound;
01148       }
01149     }
01150   }
01151 
01152   return isFound;
01153 }
01154 
01155 //=======================================================================
01156 //function : FindFace
01157 //purpose  :
01158 //=======================================================================
01159 Standard_Integer GEOMImpl_Block6Explorer::FindFace
01160                    (TopoDS_Shape&       theResult,
01161                     const TopoDS_Shape& V1,
01162                     const TopoDS_Shape& V2,
01163                     const TopoDS_Shape& V3,
01164                     const TopoDS_Shape& V4,
01165                     const TopTools_IndexedDataMapOfShapeListOfShape& MVF,
01166                     const Standard_Boolean findAll)
01167 {
01168   Standard_Integer isFound = Standard_False;
01169 
01170   const TopTools_ListOfShape& aFacesOfV1 = MVF.FindFromKey(V1);
01171   const TopTools_ListOfShape& aFacesOfV2 = MVF.FindFromKey(V2);
01172   const TopTools_ListOfShape& aFacesOfV3 = MVF.FindFromKey(V3);
01173   const TopTools_ListOfShape& aFacesOfV4 = MVF.FindFromKey(V4);
01174 
01175   TopTools_ListIteratorOfListOfShape it1 (aFacesOfV1);
01176   for (; it1.More(); it1.Next()) {
01177     TopTools_ListIteratorOfListOfShape it2 (aFacesOfV2);
01178     for (; it2.More(); it2.Next()) {
01179       if (it1.Value().IsSame(it2.Value())) {
01180         TopTools_ListIteratorOfListOfShape it3 (aFacesOfV3);
01181         for (; it3.More(); it3.Next()) {
01182           if (it1.Value().IsSame(it3.Value())) {
01183             TopTools_ListIteratorOfListOfShape it4 (aFacesOfV4);
01184             for (; it4.More(); it4.Next()) {
01185               if (it1.Value().IsSame(it4.Value())) {
01186                 isFound++;
01187                 theResult = it1.Value();
01188                 if (!findAll) return isFound;
01189               }
01190             }
01191           }
01192         }
01193       }
01194     }
01195   }
01196 
01197   return isFound;
01198 }
01199 
01200 //=======================================================================
01201 //function : MakeFace
01202 //purpose  :
01203 //=======================================================================
01204 TCollection_AsciiString GEOMImpl_Block6Explorer::MakeFace (const TopoDS_Wire&     theWire,
01205                                                            const Standard_Boolean isPlanarWanted,
01206                                                            TopoDS_Shape&          theResult)
01207 {
01208   if (!isPlanarWanted)
01209     return MakeAnyFace(theWire, theResult);
01210 
01211   // Try to build a planar face.
01212 
01213   // If required tolerance increase will be
01214   // higher than PLANAR_FACE_MAX_TOLERANCE,
01215   // we will try to build a non-planar face.
01216 
01217   TCollection_AsciiString aWarning;
01218 
01219   // Workaround for Mantis issue 0020956
01220 
01221   // Count the number of points in the wire.
01222   // Collect the first three points.
01223   gp_Pnt p1, p2, p3;
01224   bool is3Pnts (false);
01225   bool p1set(false), p2set(false), p3set(false);
01226   BRepTools_WireExplorer wexpl (theWire);
01227   for (; wexpl.More(); wexpl.Next()) {
01228     if (!p1set) {
01229       p1set = true;
01230       p1 = BRep_Tool::Pnt(wexpl.CurrentVertex());
01231     }
01232     else if (!p2set) {
01233       p2set = true;
01234       p2 = BRep_Tool::Pnt(wexpl.CurrentVertex());
01235     }
01236     else if (!p3set) {
01237       p3set = true;
01238       is3Pnts = true;
01239       p3 = BRep_Tool::Pnt(wexpl.CurrentVertex());
01240     }
01241     else {
01242       is3Pnts = false;
01243       break;
01244     }
01245   }
01246 
01247   // Construct a plane for the case of three points in the wire.
01248   gp_Pln plane;
01249   if (is3Pnts) {
01250     gce_MakePln mkPln (p1, p2, p3);
01251     if (mkPln.IsDone()) {
01252       plane = mkPln.Value();
01253     }
01254     else {
01255       is3Pnts = false;
01256     }
01257   }
01258 
01259   // Construct a face based on the plane (in case of three points in the wire) or
01260   // allow MakeFace to build the plane itself (in case of the number of points is greater than 3).
01261   if (is3Pnts) {
01262     BRepBuilderAPI_MakeFace MK (plane, theWire, isPlanarWanted);
01263     if (MK.IsDone()) {
01264       theResult = MK.Shape();
01265       return aWarning;
01266     }
01267   }
01268   else {
01269     BRepBuilderAPI_MakeFace MK (theWire, isPlanarWanted);
01270     if (MK.IsDone()) {
01271       theResult = MK.Shape();
01272       return aWarning;
01273     }
01274   }
01275 
01276   // try to update wire tolerances to build a planar face
01277 
01278   // Find a deviation
01279   Standard_Real aToleranceReached, aTol;
01280   BRepLib_FindSurface aFS;
01281   aFS.Init(theWire, -1., isPlanarWanted);
01282   aToleranceReached = aFS.ToleranceReached();
01283   aTol = aFS.Tolerance();
01284 
01285   if (!aFS.Found()) {
01286     aFS.Init(theWire, aToleranceReached, isPlanarWanted);
01287     if (!aFS.Found()) return aWarning;
01288     aToleranceReached = aFS.ToleranceReached();
01289     aTol = aFS.Tolerance();
01290   }
01291   aTol = Max(1.2 * aToleranceReached, aTol);
01292 
01293   // Mantis issue 0021432: EDF GEOM: Faces with huge tolerance can be built in GEOM
01294   if (aTol > PLANAR_FACE_MAX_TOLERANCE) {
01295     aWarning = MakeAnyFace(theWire, theResult);
01296     if (aWarning.IsEmpty() && !theResult.IsNull())
01297       aWarning = "MAKE_FACE_TOLERANCE_TOO_BIG";
01298     return aWarning;
01299   }
01300 
01301   // Copy the wire, bacause it can be updated with very-very big tolerance here
01302   BRepBuilderAPI_Copy aMC (theWire);
01303   if (!aMC.IsDone()) return aWarning;
01304   TopoDS_Wire aWire = TopoDS::Wire(aMC.Shape());
01305   // Update tolerances to <aTol>
01306   BRep_Builder B;
01307   for (TopExp_Explorer expE (aWire, TopAbs_EDGE); expE.More(); expE.Next()) {
01308     TopoDS_Edge anE = TopoDS::Edge(expE.Current());
01309     B.UpdateEdge(anE, aTol);
01310   }
01311   for (TopExp_Explorer expV (aWire, TopAbs_VERTEX); expV.More(); expV.Next()) {
01312     TopoDS_Vertex aV = TopoDS::Vertex(expV.Current());
01313     B.UpdateVertex(aV, aTol);
01314   }
01315   //BRepLib::UpdateTolerances(aWire);
01316   // Build face
01317   BRepBuilderAPI_MakeFace MK1 (aWire, isPlanarWanted);
01318   if (MK1.IsDone()) {
01319     theResult = MK1.Shape();
01320     // Mantis issue 0021432: EDF GEOM: Faces with huge tolerance can be built in GEOM
01321     //if (aTol > PLANAR_FACE_MAX_TOLERANCE)
01322     //  aWarning = "MAKE_FACE_TOLERANCE_TOO_BIG";
01323   }
01324 
01325   return aWarning;
01326 }
01327 
01328 //=======================================================================
01329 //function : MakeAnyFace
01330 //purpose  :
01331 //=======================================================================
01332 TCollection_AsciiString GEOMImpl_Block6Explorer::MakeAnyFace (const TopoDS_Wire& theWire,
01333                                                               TopoDS_Shape&      theResult)
01334 {
01335   TCollection_AsciiString aWarning;
01336 
01337   // try to build a face on any surface under the edges of the wire
01338   BRepBuilderAPI_MakeFace MK (theWire, Standard_False);
01339   if (MK.IsDone()) {
01340     theResult = MK.Shape();
01341     return aWarning;
01342   }
01343 
01344   // try to construct filling surface
01345   BRepOffsetAPI_MakeFilling MF;
01346 
01347   Standard_Integer nbEdges = 0;
01348   BRepTools_WireExplorer aWE (theWire);
01349   for (; aWE.More(); aWE.Next(), nbEdges++) {
01350     MF.Add(TopoDS::Edge(aWE.Current()), GeomAbs_C0);
01351   }
01352 
01353   MF.Build();
01354   if (!MF.IsDone()) {
01355     aWarning = "BRepOffsetAPI_MakeFilling failed";
01356     return aWarning;
01357   }
01358 
01359   // Result of filling
01360   TopoDS_Shape aFace = MF.Shape();
01361 
01362   // 12.04.2006 for PAL12149 begin
01363   Handle(Geom_Surface) aGS = BRep_Tool::Surface(TopoDS::Face(aFace));
01364 
01365 // VSR: debug issues 0021568 and 0021550 (15/05/2012) - BEGIN
01366 // the following block, when enabled, leads to extra vertices generation by partition algorithm
01367 // in some cases, for example when fillet is made on a PipeTShape
01368 //#if OCC_VERSION_LARGE > 0x06050200
01369 #if 0
01370 // VSR: debug issues 0021568 and 0021550 (15/05/2012) - END
01371   BRep_Builder BB;
01372   TopoDS_Iterator itw(theWire);
01373   for (; itw.More(); itw.Next())
01374   {
01375     const TopoDS_Edge& anEdge = TopoDS::Edge(itw.Value());
01376     TopoDS_Edge NewEdge = TopoDS::Edge(MF.Generated(anEdge).First());
01377     Standard_Real fpar, lpar;
01378     Handle(Geom2d_Curve) NewPCurve = BRep_Tool::CurveOnSurface(NewEdge, TopoDS::Face(aFace), fpar, lpar);
01379     TopLoc_Location aLoc;
01380     Standard_Real NewTol = BRep_Tool::Tolerance(NewEdge);
01381     BB.UpdateEdge(anEdge, NewPCurve, aGS, aLoc, NewTol);
01382   }
01383 #endif
01384 
01385   BRepBuilderAPI_MakeFace MK1 (aGS, theWire);
01386   if (MK1.IsDone()) {
01387     TopoDS_Shape aFace1 = MK1.Shape();
01388 
01389     BRepCheck_Analyzer ana (aFace1, false);
01390     if (!ana.IsValid()) {
01391       TopoDS_Shape aFace2;
01392       ShHealOper_ShapeProcess aHealer;
01393       aHealer.Perform(aFace1, aFace2);
01394       if (aHealer.isDone())
01395         theResult = aFace2;
01396     }
01397   }
01398   // 12.04.2006 for PAL12149 end
01399 
01400   if (theResult.IsNull()) { // try to deal with pure result of filling
01401     // Update tolerance
01402     Standard_Real aTol = MF.G0Error();
01403 
01404     TColgp_Array1OfPnt aPnts (1,nbEdges); // points of the given wire
01405     BRepTools_WireExplorer aWE1 (theWire);
01406     Standard_Integer vi = 1;
01407     for (; aWE1.More() && vi <= nbEdges; aWE1.Next(), vi++) {
01408       aPnts(vi) = BRep_Tool::Pnt(TopoDS::Vertex(aWE1.CurrentVertex()));
01409     }
01410 
01411     // Find maximum deviation in vertices
01412     TopExp_Explorer exp (aFace, TopAbs_VERTEX);
01413     TopTools_MapOfShape mapShape;
01414     for (; exp.More(); exp.Next()) {
01415       if (mapShape.Add(exp.Current())) {
01416         TopoDS_Vertex aV = TopoDS::Vertex(exp.Current());
01417         Standard_Real aTolV = BRep_Tool::Tolerance(aV);
01418         gp_Pnt aP = BRep_Tool::Pnt(aV);
01419         Standard_Real min_dist = aP.Distance(aPnts(1));
01420         for (vi = 2; vi <= nbEdges; vi++) {
01421           min_dist = Min(min_dist, aP.Distance(aPnts(vi)));
01422         }
01423         aTol = Max(aTol, aTolV);
01424         aTol = Max(aTol, min_dist);
01425       }
01426     }
01427 
01428     if ((*((Handle(BRep_TFace)*)&aFace.TShape()))->Tolerance() < aTol) {
01429       (*((Handle(BRep_TFace)*)&aFace.TShape()))->Tolerance(aTol);
01430     }
01431     theResult = aFace;
01432   }
01433 
01434   return aWarning;
01435 }