PageRenderTime 172ms CodeModel.GetById 13ms app.highlight 149ms RepoModel.GetById 1ms app.codeStats 0ms

/src/contrib/geom-5.1.2.7/src/GEOMImpl/GEOMImpl_Block6Explorer.cpp

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