1 // Copyright (C) 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 #include <Standard_Stream.hxx>
24 #include <GEOMImpl_Block6Explorer.hxx>
26 #include <ShHealOper_ShapeProcess.hxx>
28 #include "utilities.h"
30 #include <Basics_OCCTVersion.hxx>
32 #include <BRep_Tool.hxx>
33 #include <BRep_TFace.hxx>
34 #include <BRep_Builder.hxx>
35 #include <BRepLib.hxx>
36 #include <BRepLib_FindSurface.hxx>
37 #include <BRepTools.hxx>
38 #include <BRepTools_WireExplorer.hxx>
39 #include <BRepOffsetAPI_ThruSections.hxx>
40 #include <BRepOffsetAPI_MakeFilling.hxx>
41 #include <BRepCheck_Analyzer.hxx>
42 #include <BRepBuilderAPI_Copy.hxx>
43 #include <BRepBuilderAPI_MakeEdge.hxx>
44 #include <BRepBuilderAPI_MakeWire.hxx>
45 #include <BRepBuilderAPI_MakeFace.hxx>
46 #include <BRepBuilderAPI_Transform.hxx>
50 #include <TopoDS_Shape.hxx>
51 #include <TopoDS_Edge.hxx>
52 #include <TopoDS_Wire.hxx>
53 #include <TopoDS_Solid.hxx>
55 #include <TopExp_Explorer.hxx>
56 #include <TopTools_MapOfShape.hxx>
57 #include <TopTools_ListOfShape.hxx>
58 #include <TopTools_ListIteratorOfListOfShape.hxx>
59 #include <TopTools_IndexedMapOfShape.hxx>
60 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
62 #include <Geom_Curve.hxx>
63 #include <Geom_TrimmedCurve.hxx>
64 #include <GeomFill_Generator.hxx>
66 #include <gce_MakePln.hxx>
68 #include <Precision.hxx>
71 #include <TColgp_Array1OfPnt.hxx>
73 #include <StdFail_NotDone.hxx>
74 #include <Standard_NullObject.hxx>
75 #include <Standard_TypeMismatch.hxx>
76 #include <Standard_ConstructionError.hxx>
77 #include <Standard_NoSuchObject.hxx>
83 #define PLANAR_FACE_MAX_TOLERANCE 1e-06
85 static Standard_Integer mod4 (Standard_Integer nb)
87 if (nb <= 0) return nb + 4;
88 if (nb > 4) return nb - 4;
92 static Standard_Integer edge_id (const Standard_Integer theFaceID,
93 const Standard_Integer theEdgeNB)
95 static Standard_Integer edge_ids[NBFACES][4] = {
96 { 1, 2, 3, 4 }, // face 1
97 { 5, 6, 7, 8 }, // face 2
98 { 9, 5, 10, 1 }, // face 3
99 { 12, 7, 11, 3 }, // face 4
100 { 4, 12, 8, 9 }, // face 5
101 { 2, 11, 6, 10 } }; // face 6
103 return edge_ids[theFaceID - 1][theEdgeNB - 1];
106 static Standard_Integer side_edge_id (const Standard_Integer theEdgeNB)
108 static Standard_Integer side_edge_ids[4] = {9, 10, 11, 12};
110 return side_edge_ids[theEdgeNB - 1];
113 static Standard_Integer vertex_id (const Standard_Integer theFaceID,
114 const Standard_Integer theVertexNB)
116 static Standard_Integer vertex_ids[NBFACES][4] = {
117 { 1, 2, 3, 4 }, // face 1
118 { 5, 6, 7, 8 }, // face 2
119 { 1, 5, 6, 2 }, // face 3
120 { 4, 8, 7, 3 }, // face 4
121 { 1, 4, 8, 5 }, // face 5
122 { 2, 3, 7, 6 } }; // face 6
124 return vertex_ids[theFaceID - 1][theVertexNB - 1];
127 static Standard_Integer vertex_id_edge (const Standard_Integer theEdgeID, // [1,12]
128 const Standard_Integer theVertexNB) // [1,2]
130 static Standard_Integer vertex_ids_edge[NBEDGES][2] = {
144 return vertex_ids_edge[theEdgeID - 1][theVertexNB - 1];
147 static Standard_Integer face_id_edges (const Standard_Integer theEdge1ID, // [1,12]
148 const Standard_Integer theEdge2ID) // [1,12]
150 static Standard_Integer face_ids_edges[NBEDGES][NBEDGES] = {
151 // 1 2 3 4 5 6 7 8 9 10 11 12
152 { 0, 1, 1, 1, 3, 0, 0, 0, 3, 3, 0, 0 }, // edge 1
153 { 1, 0, 1, 1, 0, 6, 0, 0, 0, 6, 6, 0 }, // edge 2
154 { 1, 1, 0, 1, 0, 0, 4, 0, 0, 0, 4, 4 }, // edge 3
155 { 1, 1, 1, 0, 0, 0, 0, 5, 5, 0, 0, 5 }, // edge 4
156 { 3, 0, 0, 0, 0, 2, 2, 2, 3, 3, 0, 0 }, // edge 5
157 { 0, 6, 0, 0, 2, 0, 2, 2, 0, 6, 6, 0 }, // edge 6
158 { 0, 0, 4, 0, 2, 2, 0, 2, 0, 0, 4, 4 }, // edge 7
159 { 0, 0, 0, 5, 2, 2, 2, 0, 5, 0, 0, 5 }, // edge 8
160 { 3, 0, 0, 5, 3, 0, 0, 5, 0, 3, 0, 5 }, // edge 9
161 { 3, 6, 0, 0, 3, 6, 0, 0, 3, 0, 6, 0 }, // edge 10
162 { 0, 6, 4, 0, 0, 6, 4, 0, 0, 6, 0, 4 }, // edge 11
163 { 0, 0, 4, 5, 0, 0, 4, 5, 5, 0, 4, 0 } }; // edge 12
165 return face_ids_edges[theEdge1ID - 1][theEdge2ID - 1];
168 static Standard_Integer edge_id_vertices (const Standard_Integer theVertex1ID, // [1,8]
169 const Standard_Integer theVertex2ID) // [1,8]
171 static Standard_Integer edge_ids_vertices[NBVERTS][NBVERTS] = {
173 { 0, 1, 0, 4, 9, 0, 0, 0}, // vertex 1
174 { 1, 0, 2, 0, 0, 10, 0, 0}, // vertex 2
175 { 0, 2, 0, 3, 0, 0, 11, 0}, // vertex 3
176 { 4, 0, 3, 0, 0, 0, 0, 12}, // vertex 4
177 { 9, 0, 0, 0, 0, 5, 0, 8}, // vertex 5
178 { 0, 10, 0, 0, 5, 0, 6, 0}, // vertex 6
179 { 0, 0, 11, 0, 0, 6, 0, 7}, // vertex 7
180 { 0, 0, 0, 12, 8, 0, 7, 0} }; // vertex 8
182 return edge_ids_vertices[theVertex1ID - 1][theVertex2ID - 1];
185 static Standard_Integer edge_id_faces (const Standard_Integer theFace1ID, // [1,6]
186 const Standard_Integer theFace2ID) // [1,6]
188 static Standard_Integer edge_ids_faces[NBFACES][NBFACES] = {
190 { 0, 0, 1, 3, 4, 2 }, // face 1
191 { 0, 0, 5, 7, 8, 6 }, // face 2
192 { 1, 5, 0, 0, 9, 10 }, // face 3
193 { 3, 7, 0, 0, 12, 11 }, // face 4
194 { 4, 8, 9, 12, 0, 0 }, // face 5
195 { 2, 6, 10, 11, 0, 0 } }; // face 6
197 return edge_ids_faces[theFace1ID - 1][theFace2ID - 1];
200 //=======================================================================
201 //function : GEOMImpl_Block6Explorer
202 //purpose : Constructor
203 //=======================================================================
204 GEOMImpl_Block6Explorer::GEOMImpl_Block6Explorer ()
205 : myFaces(1,NBFACES), myEdges(1,NBEDGES), myVertices(1,NBVERTS)
209 //=======================================================================
210 //function : GetVertex
212 //=======================================================================
213 TopoDS_Shape GEOMImpl_Block6Explorer::GetVertex (const Standard_Integer theVertexID)
215 TopoDS_Shape aNullShape;
216 if (theVertexID < 1 || theVertexID > NBVERTS) return aNullShape;
217 return myVertices(theVertexID);
220 //=======================================================================
221 //function : GetVertexID
223 //=======================================================================
224 Standard_Integer GEOMImpl_Block6Explorer::GetVertexID (const TopoDS_Shape& theVertex)
226 for (Standard_Integer id = 1; id <= NBVERTS; id++) {
227 if (theVertex.IsSame(myVertices(id))) return id;
229 Standard_NoSuchObject::Raise("The Vertex does not belong to the Block");
233 //=======================================================================
234 //function : GetVertexID
236 //=======================================================================
237 Standard_Integer GEOMImpl_Block6Explorer::GetVertexID (const Standard_Integer theFaceID,
238 const Standard_Integer theVertexNB)
240 return vertex_id(theFaceID, theVertexNB);
243 //=======================================================================
244 //function : GetVertexOnEdgeID
246 //=======================================================================
247 Standard_Integer GEOMImpl_Block6Explorer::GetVertexOnEdgeID
248 (const Standard_Integer theEdgeID,
249 const Standard_Integer theVertexNB)
251 return vertex_id_edge(theEdgeID, theVertexNB);
254 //=======================================================================
257 //=======================================================================
258 TopoDS_Shape GEOMImpl_Block6Explorer::GetEdge (const Standard_Integer theEdgeID,
259 const Standard_Boolean doMake)
261 TopoDS_Shape aNullShape;
262 if (theEdgeID < 1 || theEdgeID > NBEDGES) return aNullShape;
263 if (myEdges(theEdgeID).IsNull() && doMake) {
264 // Create the required edge as a linear segment between
265 // corresponding vertices and put it in the Block's edges
266 BRepBuilderAPI_MakeEdge ME (TopoDS::Vertex(myVertices(vertex_id_edge(theEdgeID, 1))),
267 TopoDS::Vertex(myVertices(vertex_id_edge(theEdgeID, 2))));
269 Standard_ConstructionError::Raise("Edge construction failed");
271 myEdges(theEdgeID) = ME.Shape();
274 return myEdges(theEdgeID);
277 //=======================================================================
278 //function : GetEdgeID
280 //=======================================================================
281 Standard_Integer GEOMImpl_Block6Explorer::GetEdgeID (const TopoDS_Shape& theEdge)
283 for (Standard_Integer id = 1; id <= NBEDGES; id++) {
284 if (theEdge.IsSame(myEdges(id))) return id;
286 Standard_NoSuchObject::Raise("The Edge does not belong to the Block");
290 //=======================================================================
291 //function : GetEdgeID
293 //=======================================================================
294 Standard_Integer GEOMImpl_Block6Explorer::GetEdgeID (const Standard_Integer theFaceID,
295 const Standard_Integer theEdgeNB)
297 return edge_id(theFaceID, theEdgeNB);
300 //=======================================================================
301 //function : FindEdgeID
303 //=======================================================================
304 Standard_Integer GEOMImpl_Block6Explorer::FindEdgeID (const Standard_Integer theVertex1ID,
305 const Standard_Integer theVertex2ID)
307 return edge_id_vertices(theVertex1ID, theVertex2ID);
310 //=======================================================================
311 //function : FindCommonEdgeID
313 //=======================================================================
314 Standard_Integer GEOMImpl_Block6Explorer::FindCommonEdgeID
315 (const Standard_Integer theFace1ID,
316 const Standard_Integer theFace2ID)
318 return edge_id_faces(theFace1ID, theFace2ID);
321 //=======================================================================
324 //=======================================================================
325 TopoDS_Shape GEOMImpl_Block6Explorer::GetFace (const Standard_Integer theFaceID,
326 const Standard_Boolean doMake)
328 TopoDS_Shape aNullShape;
329 if (theFaceID < 1 || theFaceID > NBFACES) return aNullShape;
331 if (myFaces(theFaceID).IsNull() && doMake) {
333 // Create the required face between
334 // corresponding edges and put it in the Block's faces
336 TopoDS_Shape E1 = GetEdge(edge_id(theFaceID, 1), doMake);
337 TopoDS_Shape E2 = GetEdge(edge_id(theFaceID, 2), doMake);
338 TopoDS_Shape E3 = GetEdge(edge_id(theFaceID, 3), doMake);
339 TopoDS_Shape E4 = GetEdge(edge_id(theFaceID, 4), doMake);
341 BRepBuilderAPI_MakeWire MW (TopoDS::Edge(E1),
346 Standard_ConstructionError::Raise("Wire construction failed");
349 MakeFace(MW, Standard_False, aFace);
350 if (aFace.IsNull()) {
351 Standard_ConstructionError::Raise("Face construction failed");
353 myFaces(theFaceID) = aFace;
356 return myFaces(theFaceID);
359 //=======================================================================
360 //function : GetFaceID
362 //=======================================================================
363 Standard_Integer GEOMImpl_Block6Explorer::GetFaceID (const TopoDS_Shape& theFace)
365 for (Standard_Integer id = 1; id <= NBFACES; id++) {
366 if (theFace.IsSame(myFaces(id))) return id;
368 Standard_NoSuchObject::Raise("The Face does not belong to the Block");
372 //=======================================================================
373 //function : FindFaceID
375 //=======================================================================
376 Standard_Integer GEOMImpl_Block6Explorer::FindFaceID (const Standard_Integer theEdge1ID,
377 const Standard_Integer theEdge2ID)
379 return face_id_edges(theEdge1ID, theEdge2ID);
382 //=======================================================================
383 //function : GetOppositeFaceID
385 //=======================================================================
386 Standard_Integer GEOMImpl_Block6Explorer::GetOppositeFaceID (const Standard_Integer theFaceID)
388 Standard_Integer opp_face_id[NBFACES + 1] = {
397 return opp_face_id[theFaceID];
400 //=======================================================================
401 //function : IsSimilarFaces
403 //=======================================================================
404 Standard_Boolean GEOMImpl_Block6Explorer::IsSimilarFaces (const Standard_Integer theFace1ID,
405 const Standard_Integer theFace2ID,
406 const gp_Trsf theTransformation)
408 Standard_Integer common_edge_id = FindCommonEdgeID(theFace1ID, theFace2ID);
410 if (common_edge_id == 0) { // opposite faces
411 for (Standard_Integer id = 1; id <= 4; id++) {
412 TopoDS_Shape E1 = GetEdge(edge_id(theFace1ID, id));
413 TopoDS_Shape E2 = GetEdge(edge_id(theFace2ID, id));
415 BRepBuilderAPI_Transform aTrsf (E1, theTransformation, Standard_False);
416 if (!IsSimilarEdges(aTrsf.Shape(), E2))
417 return Standard_False;
419 } else { // the faces have common edge
420 TopTools_Array1OfShape aVerts1 (1,4);
421 TopTools_Array1OfShape aVerts2 (1,4);
423 Standard_Integer common_vertex1 = GetVertexOnEdgeID(common_edge_id, 1);
424 Standard_Integer common_vertex2 = GetVertexOnEdgeID(common_edge_id, 2);
425 aVerts1(1) = myVertices(common_vertex1);
426 aVerts1(2) = myVertices(common_vertex2);
427 aVerts2(1) = myVertices(common_vertex1);
428 aVerts2(2) = myVertices(common_vertex2);
430 Standard_Integer not_common_v11 = 0, not_common_v12 = 0;
431 Standard_Integer vnb, vid;
432 for (vnb = 1; vnb <= 4; vnb++) {
433 vid = GetVertexID(theFace1ID, vnb);
434 if (vid != common_vertex1 && FindEdgeID(vid, common_vertex1) == 0) {
435 not_common_v12 = vid;
437 if (vid != common_vertex2 && FindEdgeID(vid, common_vertex2) == 0) {
438 not_common_v11 = vid;
443 Standard_Integer not_common_v21 = 0, not_common_v22 = 0;
444 for (vnb = 1; vnb <= 4; vnb++) {
445 vid = GetVertexID(theFace2ID, vnb);
446 if (vid != common_vertex1 && FindEdgeID(vid, common_vertex1) == 0) {
447 not_common_v22 = vid;
449 if (vid != common_vertex2 && FindEdgeID(vid, common_vertex2) == 0) {
450 not_common_v21 = vid;
454 aVerts1(3) = myVertices(not_common_v11);
455 aVerts1(4) = myVertices(not_common_v12);
456 aVerts2(3) = myVertices(not_common_v21);
457 aVerts2(4) = myVertices(not_common_v22);
459 for (Standard_Integer id = 1; id <= 4; id++) {
460 BRepBuilderAPI_Transform aTrsf (aVerts1(id), theTransformation, Standard_False);
461 TopoDS_Vertex V1 = TopoDS::Vertex(aTrsf.Shape());
462 TopoDS_Vertex V2 = TopoDS::Vertex(aVerts2(id));
463 if (!BRepTools::Compare(V1, V2)) {
464 return Standard_False;
469 return Standard_True;
472 //============ Initialization methods ===================================
474 //=======================================================================
475 //function : InitByBlock
477 //=======================================================================
478 void GEOMImpl_Block6Explorer::InitByBlock (const TopoDS_Shape& theBlock)
480 // 1. Find any one face of the block
481 TopExp_Explorer faces (theBlock, TopAbs_FACE);
483 Standard_ConstructionError::Raise("The block has no faces");
485 TopoDS_Shape aFirstFace = faces.Current();
487 // 2. Store all elements of the block relatively aFirstFace
488 InitByBlockAndFace(theBlock, aFirstFace);
491 //=======================================================================
492 //function : InitByBlockAndFace
494 //=======================================================================
495 void GEOMImpl_Block6Explorer::InitByBlockAndFace (const TopoDS_Shape& theBlock,
496 const TopoDS_Shape& theFace)
498 myFaces(1) = theFace;
500 // 2. Get wire of the first face
501 TopExp_Explorer wires (myFaces(1), TopAbs_WIRE);
503 Standard_ConstructionError::Raise("A face of the block has no wires");
505 TopoDS_Shape aWire = wires.Current();
508 Standard_ConstructionError::Raise("A face of the block has more than one wires");
511 // 3. Explore wire to init edges and vertices of the first face
512 BRepTools_WireExplorer aWE (TopoDS::Wire(aWire), TopoDS::Face(myFaces(1)));
513 Standard_Integer nb = 1;
514 for (; aWE.More(); aWE.Next(), nb++) {
516 Standard_ConstructionError::Raise("A face of the block has more than four edges");
518 myEdges(edge_id(1, nb)) = aWE.Current();
519 myVertices(vertex_id(1, nb)) = aWE.CurrentVertex();
522 Standard_ConstructionError::Raise("A face of the block has less than four edges");
525 // 2. Store all other elements of the block
526 InitByBlockAndVertices (theBlock,
527 myVertices(vertex_id(1,1)),
528 myVertices(vertex_id(1,2)),
529 myVertices(vertex_id(1,3)));
532 //=======================================================================
533 //function : InitByBlockAndEdges
535 //=======================================================================
536 void GEOMImpl_Block6Explorer::InitByBlockAndEdges (const TopoDS_Shape& theBlock,
537 const TopoDS_Shape& theEdge1,
538 const TopoDS_Shape& theEdge3)
540 // 1. Store vertices and edges of the first face
542 // 1.1. Store two given edges
543 myEdges(edge_id(1, 1)) = theEdge1;
544 myEdges(edge_id(1, 3)) = theEdge3;
546 // 1.2. Find and store the first face
547 TopTools_IndexedDataMapOfShapeListOfShape MEF;
548 MapShapesAndAncestors(theBlock, TopAbs_EDGE, TopAbs_FACE, MEF);
549 if (MEF.Extent() != NBEDGES) {
550 Standard_TypeMismatch::Raise("Block has wrong number of edges");
552 const TopTools_ListOfShape& aFacesOfE1 = MEF.FindFromKey(theEdge1);
553 const TopTools_ListOfShape& aFacesOfE3 = MEF.FindFromKey(theEdge3);
555 Standard_Boolean isFound = Standard_False;
556 TopTools_ListIteratorOfListOfShape anIterF1 (aFacesOfE1);
557 for (; anIterF1.More() && !isFound; anIterF1.Next()) {
559 TopTools_ListIteratorOfListOfShape anIterF3 (aFacesOfE3);
560 for (; anIterF3.More() && !isFound; anIterF3.Next()) {
562 if (anIterF1.Value().IsSame(anIterF3.Value())) {
563 isFound = Standard_True;
565 // Store the face, defined by two opposite edges
566 myFaces(1) = anIterF1.Value();
571 Standard_ConstructionError::Raise
572 ("Edges 1 and 2 do not belong to one face of the block");
575 // 1.3. Make vertices of the first edge the first and the
576 // second vertices of the first face. Order is free.
577 TopoDS_Edge E = TopoDS::Edge(theEdge1);
578 TopoDS_Vertex V1, V2;
579 TopExp::Vertices(E, V1, V2, Standard_True);
580 myVertices(vertex_id(1,1)) = V1;
581 myVertices(vertex_id(1,2)) = V2;
583 // Init maps vertex->list_of_edges for the face
584 TopTools_IndexedDataMapOfShapeListOfShape M1;
585 MapShapesAndAncestors(myFaces(1), TopAbs_VERTEX, TopAbs_EDGE, M1);
586 if (M1.Extent() != 4) {
587 Standard_TypeMismatch::Raise("The first face of block has wrong number of vertices");
590 // 1.4. Find and store others elements of the first face
592 // edges of the first vertex
593 TopoDS_Shape E1_f = M1.FindFromKey(V1).First();
594 TopoDS_Shape E1_l = M1.FindFromKey(V1).Last();
596 if (E1_f.IsSame(theEdge1)) {
597 myEdges(edge_id(1, 4)) = E1_l;
599 myEdges(edge_id(1, 4)) = E1_f;
603 TopoDS_Edge E4 = TopoDS::Edge(myEdges(edge_id(1, 4)));
604 TopoDS_Vertex V41, V42;
605 TopExp::Vertices(E4, V41, V42, Standard_True);
606 if (V41.IsSame(V1)) {
607 myVertices(vertex_id(1,4)) = V42;
609 myVertices(vertex_id(1,4)) = V41;
612 // edges of the second vertex
613 TopoDS_Shape E2_f = M1.FindFromKey(V2).First();
614 TopoDS_Shape E2_l = M1.FindFromKey(V2).Last();
616 if (E2_f.IsSame(theEdge1)) {
617 myEdges(edge_id(1, 2)) = E2_l;
619 myEdges(edge_id(1, 2)) = E2_f;
623 TopoDS_Edge E2 = TopoDS::Edge(myEdges(edge_id(1, 2)));
624 TopoDS_Vertex V21, V22;
625 TopExp::Vertices(E2, V21, V22, Standard_True);
626 if (V21.IsSame(V2)) {
627 myVertices(vertex_id(1,3)) = V22;
629 myVertices(vertex_id(1,3)) = V21;
632 // 2. Store all other elements of the block
633 InitByBlockAndVertices (theBlock,
634 myVertices(vertex_id(1,1)),
635 myVertices(vertex_id(1,2)),
636 myVertices(vertex_id(1,3)));
639 //=======================================================================
640 //function : InitByBlockAndVertices
642 //=======================================================================
643 void GEOMImpl_Block6Explorer::InitByBlockAndVertices (const TopoDS_Shape& theBlock,
644 const TopoDS_Shape& theVertex1,
645 const TopoDS_Shape& theVertex2,
646 const TopoDS_Shape& theVertex3)
648 // Here we suppose, that vertices are ordered, i.e. exists edge between
649 // theVertex1 and theVertex2 and edge between theVertex2 and theVertex3
651 // 1. Store vertices and edges of the first face.
652 // If the first face is initialized, it means, that this
653 // method is called from another initialization method, and all
654 // vertices and edges of the first face are also initialized
655 if (myFaces(1).IsNull()) {
657 // 1.1. Store first three vertices
658 myVertices(vertex_id(1, 1)) = theVertex1;
659 myVertices(vertex_id(1, 2)) = theVertex2;
660 myVertices(vertex_id(1, 3)) = theVertex3;
662 // 1.2. Find and store the first face
663 TopTools_IndexedDataMapOfShapeListOfShape MVF;
664 MapShapesAndAncestors(theBlock, TopAbs_VERTEX, TopAbs_FACE, MVF);
665 if (MVF.Extent() != NBVERTS) {
666 Standard_TypeMismatch::Raise("Block has wrong number of vertices");
668 const TopTools_ListOfShape& aFacesOfV1 = MVF.FindFromKey(theVertex1);
669 const TopTools_ListOfShape& aFacesOfV3 = MVF.FindFromKey(theVertex3);
671 Standard_Boolean isFound = Standard_False;
672 TopTools_ListIteratorOfListOfShape anIterF1 (aFacesOfV1);
673 for (; anIterF1.More() && !isFound; anIterF1.Next()) {
675 TopTools_ListIteratorOfListOfShape anIterF3 (aFacesOfV3);
676 for (; anIterF3.More() && !isFound; anIterF3.Next()) {
678 if (anIterF1.Value().IsSame(anIterF3.Value())) {
679 isFound = Standard_True;
681 // Store the face, defined by two opposite vertices
682 myFaces(1) = anIterF1.Value();
687 Standard_ConstructionError::Raise
688 ("Vertices 1 and 3 do not belong to one face of the block");
691 // Init maps vertex->list_of_edges for the face
692 TopTools_IndexedDataMapOfShapeListOfShape M1;
693 MapShapesAndAncestors(myFaces(1), TopAbs_VERTEX, TopAbs_EDGE, M1);
694 if (M1.Extent() != 4) {
695 Standard_TypeMismatch::Raise("The first face of block has wrong number of vertices");
698 // 1.3. Find and store edges and last vertex of the first face
699 const TopTools_ListOfShape& anEdgesOfV1 = M1.FindFromKey(theVertex1);
700 const TopTools_ListOfShape& anEdgesOfV2 = M1.FindFromKey(theVertex2);
701 const TopTools_ListOfShape& anEdgesOfV3 = M1.FindFromKey(theVertex3);
703 TopTools_ListIteratorOfListOfShape anIterE2 (anEdgesOfV2);
704 for (; anIterE2.More(); anIterE2.Next()) {
706 TopTools_ListIteratorOfListOfShape anIterE1 (anEdgesOfV1);
707 for (; anIterE1.More(); anIterE1.Next()) {
709 if (anIterE1.Value().IsSame(anIterE2.Value())) {
710 // Store the first edge, defined by two vertices
711 myEdges(edge_id(1,1)) = anIterE1.Value();
714 // Store the last edge
715 myEdges(edge_id(1,4)) = anIterE1.Value();
717 // Find and store the last vertex
718 TopoDS_Edge E = TopoDS::Edge(myEdges(4));
719 TopoDS_Vertex V1, V2;
720 TopExp::Vertices(E, V1, V2, Standard_True);
722 if (V1.IsSame(theVertex1)) {
723 myVertices(vertex_id(1,4)) = V2;
725 myVertices(vertex_id(1,4)) = V1;
730 TopTools_ListIteratorOfListOfShape anIterE3 (anEdgesOfV3);
731 for (; anIterE3.More(); anIterE3.Next()) {
733 if (anIterE3.Value().IsSame(anIterE2.Value())) {
734 // Store the second edge, defined by two vertices
735 myEdges(edge_id(1,2)) = anIterE3.Value();
738 // Store the fird edge
739 myEdges(edge_id(1,3)) = anIterE3.Value();
745 // Init map vertex->list_of_edges for the block
746 TopTools_IndexedDataMapOfShapeListOfShape MB;
747 MapShapesAndAncestors(theBlock, TopAbs_VERTEX, TopAbs_EDGE, MB);
748 if (MB.Extent() != NBVERTS) {
749 Standard_TypeMismatch::Raise("Block has wrong number of vertices");
752 // 2. Store edges, linking the first face with the second one
753 // and vertices of the second face
754 TopTools_IndexedMapOfShape aFaceEdges;
755 TopExp::MapShapes(myFaces(1), TopAbs_EDGE, aFaceEdges);
757 Standard_Integer i = 1;
758 for (; i <= 4; i++) {
759 // Get i-th vertex of the face 1
760 TopoDS_Shape Vi = myVertices(vertex_id(1, i));
761 if (!MB.Contains(Vi)) {
762 Standard_ConstructionError::Raise("Face does not belong to the block");
765 // Get list of block's edges, sharing this Vertex
766 const TopTools_ListOfShape& anEdgesOfVi = MB.FindFromKey(Vi);
767 TopTools_ListIteratorOfListOfShape anEdgesIter (anEdgesOfVi);
769 // Get Edge (from the List), not belonging to the face 1
770 Standard_Boolean isFound = Standard_False;
771 for (; anEdgesIter.More() && !isFound; anEdgesIter.Next()) {
772 if (!aFaceEdges.Contains(anEdgesIter.Value())) {
773 isFound = Standard_True;
775 // Store the linking edge
776 TopoDS_Shape aLinkEdge = anEdgesIter.Value();
777 myEdges(side_edge_id(i)) = aLinkEdge;
779 // Get another vertex of the linking edge
780 TopoDS_Edge E = TopoDS::Edge(aLinkEdge);
781 TopoDS_Vertex V1, V2;
782 TopExp::Vertices(E, V1, V2, Standard_True);
784 // Store the i-th vertex of the second (opposite to the first) face
786 myVertices(vertex_id(2, i)) = V2;
788 myVertices(vertex_id(2, i)) = V1;
794 // 3. Store edges of the second (opposite to the first) face
795 for (i = 1; i <= 4; i++) {
796 // Get i-th and (i+1)-th vertices of the face 2
797 TopoDS_Shape Vi = myVertices(vertex_id(2, i));
798 TopoDS_Shape Vj = myVertices(vertex_id(2, mod4(i + 1)));
800 // Get list of block's edges, sharing Vi
801 const TopTools_ListOfShape& anEdgesOfVi = MB.FindFromKey(Vi);
802 // Get list of block's edges, sharing Vj
803 const TopTools_ListOfShape& anEdgesOfVj = MB.FindFromKey(Vj);
805 // Get Edge (from the List), linking this vertex with the next one
806 Standard_Boolean isFound = Standard_False;
807 TopTools_ListIteratorOfListOfShape anEdgesIteri (anEdgesOfVi);
808 for (; anEdgesIteri.More() && !isFound; anEdgesIteri.Next()) {
810 TopTools_ListIteratorOfListOfShape anEdgesIterj (anEdgesOfVj);
811 for (; anEdgesIterj.More() && !isFound; anEdgesIterj.Next()) {
813 if (anEdgesIteri.Value().IsSame(anEdgesIterj.Value())) {
814 isFound = Standard_True;
816 // Store the linking edge
817 myEdges(edge_id(2, i)) = anEdgesIteri.Value();
823 // 4. Store faces of the block
824 TopTools_IndexedDataMapOfShapeListOfShape MBE;
825 MapShapesAndAncestors(theBlock, TopAbs_EDGE, TopAbs_FACE, MBE);
826 if (MBE.Extent() != NBEDGES) {
827 Standard_TypeMismatch::Raise("Block has wrong number of edges");
830 for (i = 2; i <= NBFACES; i++) {
831 TopoDS_Shape Ei1 = myEdges(edge_id(i, 1));
832 TopoDS_Shape Ei2 = myEdges(edge_id(i, 2));
833 const TopTools_ListOfShape& aFacesOfEi1 = MBE.FindFromKey(Ei1);
834 const TopTools_ListOfShape& aFacesOfEi2 = MBE.FindFromKey(Ei2);
836 Standard_Boolean isFound = Standard_False;
837 TopTools_ListIteratorOfListOfShape anIterEi1 (aFacesOfEi1);
838 for (; anIterEi1.More() && !isFound; anIterEi1.Next()) {
840 TopTools_ListIteratorOfListOfShape anIterEi2 (aFacesOfEi2);
841 for (; anIterEi2.More() && !isFound; anIterEi2.Next()) {
843 if (anIterEi1.Value().IsSame(anIterEi2.Value())) {
844 isFound = Standard_True;
846 // Store the face, defined by two edges
847 myFaces(i) = anIterEi1.Value();
854 //=======================================================================
855 //function : InitByTwoFaces
857 //=======================================================================
858 void GEOMImpl_Block6Explorer::InitByTwoFaces (const TopoDS_Shape& theFace1,
859 const TopoDS_Shape& theFace2)
861 if (theFace1.IsSame(theFace2)) {
862 Standard_ConstructionError::Raise("The faces must be different");
865 // Add two given faces in the structure
866 myFaces(1) = theFace1;
867 myFaces(2) = theFace2;
869 // Step 1. Order vertices (and edges)
871 // 1.1. Ordered vertices and edges of the first face we put in <myVertices>
873 // Get wire of the first face
874 TopExp_Explorer wires1 (myFaces(1), TopAbs_WIRE);
875 if (!wires1.More()) {
876 Standard_ConstructionError::Raise("A face for the block has no wires");
878 TopoDS_Shape aWire1 = wires1.Current();
881 Standard_ConstructionError::Raise("A face for the block has more than one wire");
884 BRepTools_WireExplorer aWE1 (TopoDS::Wire(aWire1), TopoDS::Face(myFaces(1)));
886 for (nb = 1; aWE1.More(); aWE1.Next(), nb++) {
888 Standard_ConstructionError::Raise("A face for the block has more than four edges");
890 myEdges(edge_id(1, nb)) = aWE1.Current();
891 myVertices(vertex_id(1, nb)) = aWE1.CurrentVertex();
894 Standard_ConstructionError::Raise("A face for the block has less than four edges");
897 // 1.2. Ordered vertices and edges of the second face we temporarily store
898 // in arrays, to find for them rigth location in <myVertices> on the Step 2.
901 TopTools_Array1OfShape aVertis2(1,4); // ordered vertices of the second face
902 TopTools_Array1OfShape anEdges2(1,4); // anEdges2(i) links aVertis2(i) and aVertis2(i+1)
904 // Get wire of the second face
905 TopExp_Explorer wires2 (myFaces(2), TopAbs_WIRE);
906 if (!wires2.More()) {
907 Standard_ConstructionError::Raise("A face for the block has no wires");
909 TopoDS_Shape aWire2 = wires2.Current();
912 Standard_ConstructionError::Raise("A face for the block has more than one wire");
915 BRepTools_WireExplorer aWE2 (TopoDS::Wire(aWire2), TopoDS::Face(myFaces(2)));
916 for (nb = 1; aWE2.More(); aWE2.Next(), nb++) {
918 Standard_ConstructionError::Raise("A face for the block has more than four edges");
920 anEdges2(nb) = aWE2.Current();
921 aVertis2(nb) = aWE2.CurrentVertex();
924 Standard_ConstructionError::Raise("A face for the block has less than four edges");
927 // Step 2. Find right place in <myVertices> for the <aVertis2>,
928 // so as to minimize common length of linking edges
929 // between face 1 and face 2.
930 // Each linking edge (of four) will link vertices of the
931 // faces 1 and 2 with equal local numbers.
932 // The right place is defined by:
933 // - vertex <aVertis2(i_min)>, which will become the first vertex
934 // of the second face <myVertices(vertex_id(2,1))>
935 // - orientation of <aVertis2> relatively their future location
936 // in <myVertices> (s_min = 1 if direct, s_min = -1 if reversed)
937 Standard_Integer i_min = 0, s_min = 0;
939 TColgp_Array1OfPnt aPnts1 (1,4); // points of the first face
940 aPnts1(1) = BRep_Tool::Pnt(TopoDS::Vertex(myVertices(vertex_id(1, 1))));
941 aPnts1(2) = BRep_Tool::Pnt(TopoDS::Vertex(myVertices(vertex_id(1, 2))));
942 aPnts1(3) = BRep_Tool::Pnt(TopoDS::Vertex(myVertices(vertex_id(1, 3))));
943 aPnts1(4) = BRep_Tool::Pnt(TopoDS::Vertex(myVertices(vertex_id(1, 4))));
945 TColgp_Array1OfPnt aPnts2 (1,4); // points of the second face
946 aPnts2(1) = BRep_Tool::Pnt(TopoDS::Vertex(aVertis2(1)));
947 aPnts2(2) = BRep_Tool::Pnt(TopoDS::Vertex(aVertis2(2)));
948 aPnts2(3) = BRep_Tool::Pnt(TopoDS::Vertex(aVertis2(3)));
949 aPnts2(4) = BRep_Tool::Pnt(TopoDS::Vertex(aVertis2(4)));
951 Standard_Real Dist_min = RealLast();
952 // try all possible locations to find the best (with minimum sum distance)
953 Standard_Integer i = 1;
954 for (; i <= 4; i++) {
955 // try direct orientation
956 Standard_Real Dist_plus = aPnts1(1).Distance(aPnts2(i)) +
957 aPnts1(2).Distance(aPnts2(mod4(i + 1))) +
958 aPnts1(3).Distance(aPnts2(mod4(i + 2))) +
959 aPnts1(4).Distance(aPnts2(mod4(i + 3)));
960 if (Dist_plus < Dist_min) {
961 Dist_min = Dist_plus;
966 // try reversed orientation
967 Standard_Real Dist_minus = aPnts1(1).Distance(aPnts2(i)) +
968 aPnts1(2).Distance(aPnts2(mod4(i - 1))) +
969 aPnts1(3).Distance(aPnts2(mod4(i - 2))) +
970 aPnts1(4).Distance(aPnts2(mod4(i - 3)));
971 if (Dist_minus < Dist_min) {
972 Dist_min = Dist_minus;
978 // 3. Put vertices and edges of the second face to they
979 // permanent location in <myVertices> and <myEdges>
980 for (i = 1; i <= 4; i++) {
981 Standard_Integer nb = mod4(i_min + s_min*(i - 1));
983 if (aPnts1(i).Distance(aPnts2(nb)) < Precision::Confusion()) {
984 Standard_ConstructionError::Raise("The faces are too close");
987 myVertices(vertex_id(2, i)) = aVertis2(nb);
989 if (s_min == -1) nb = mod4(nb - 1);
990 myEdges(edge_id(2, i)) = anEdges2(nb);
993 // check the wires closure
994 TopoDS_Wire wire1 = TopoDS::Wire(aWire1);
995 TopoDS_Wire wire2 = TopoDS::Wire(aWire2);
996 TopoDS_Vertex aV1, aV2;
998 TopExp::Vertices(wire1, aV1, aV2);
999 if (!aV1.IsNull() && !aV2.IsNull() && aV1.IsSame(aV2))
1000 aWire1.Closed(true);
1002 TopExp::Vertices(wire2, aV1, aV2);
1003 if (!aV1.IsNull() && !aV2.IsNull() && aV1.IsSame(aV2))
1004 aWire2.Closed(true);
1006 // 4. Generate side surface
1007 if (!aWire1.Closed() || !aWire2.Closed()) {
1008 // BRepOffsetAPI_ThruSections is not applicable on not closed wires
1009 GetFace(3, Standard_True);
1010 GetFace(4, Standard_True);
1011 GetFace(5, Standard_True);
1012 GetFace(6, Standard_True);
1014 // try to build faces on native surfaces of edges or planar
1015 Standard_Boolean tryThru = Standard_False;
1016 for (Standard_Integer i = 3; i <= 6 && !tryThru; i++) {
1017 Standard_Boolean doMake = Standard_True;
1018 TopoDS_Shape E1 = GetEdge(edge_id(i, 1), doMake);
1019 TopoDS_Shape E2 = GetEdge(edge_id(i, 2), doMake);
1020 TopoDS_Shape E3 = GetEdge(edge_id(i, 3), doMake);
1021 TopoDS_Shape E4 = GetEdge(edge_id(i, 4), doMake);
1023 BRepBuilderAPI_MakeWire MW (TopoDS::Edge(E1),
1028 Standard_ConstructionError::Raise("Wire construction failed");
1031 BRepBuilderAPI_MakeFace MF (MW, Standard_False);
1033 myFaces(i) = MF.Shape();
1035 tryThru = Standard_True;
1039 // Build side surface by ThruSections algorithm
1041 BRepOffsetAPI_ThruSections THS;
1042 THS.AddWire(TopoDS::Wire(aWire1));
1043 THS.AddWire(TopoDS::Wire(aWire2));
1045 if (!THS.IsDone()) {
1046 StdFail_NotDone::Raise("Side surface generation failed");
1048 for (Standard_Integer i = 1; i <= 4; i++) {
1050 myFaces(i+2) = THS.GeneratedFace(myEdges(i));
1053 Standard_Integer ee = side_edge_id(i);
1054 TopTools_IndexedDataMapOfShapeListOfShape MVE;
1055 MapShapesAndAncestors(myFaces(i+2), TopAbs_VERTEX, TopAbs_EDGE, MVE);
1056 FindEdge(myEdges(ee),
1057 myVertices(vertex_id_edge(ee, 1)),
1058 myVertices(vertex_id_edge(ee, 2)),
1065 //=======================================================================
1066 //function : MapShapesAndAncestors
1068 //=======================================================================
1069 void GEOMImpl_Block6Explorer::MapShapesAndAncestors (const TopoDS_Shape& S,
1070 const TopAbs_ShapeEnum TS,
1071 const TopAbs_ShapeEnum TA,
1072 TopTools_IndexedDataMapOfShapeListOfShape& M)
1074 TopTools_ListOfShape empty;
1075 TopTools_MapOfShape mapA;
1078 TopExp_Explorer exa (S,TA);
1079 for (; exa.More(); exa.Next()) {
1081 const TopoDS_Shape& anc = exa.Current();
1082 if (mapA.Add(anc)) {
1083 TopExp_Explorer exs (anc,TS);
1084 TopTools_MapOfShape mapS;
1085 for (; exs.More(); exs.Next()) {
1086 if (mapS.Add(exs.Current())) {
1087 Standard_Integer index = M.FindIndex(exs.Current());
1088 if (index == 0) index = M.Add(exs.Current(),empty);
1089 M(index).Append(anc);
1095 // visit shapes not under ancestors
1096 TopExp_Explorer ex (S,TS,TA);
1097 for (; ex.More(); ex.Next()) {
1098 Standard_Integer index = M.FindIndex(ex.Current());
1099 if (index == 0) index = M.Add(ex.Current(),empty);
1103 //=======================================================================
1104 //function : IsSimilarEdges
1106 //=======================================================================
1107 Standard_Boolean GEOMImpl_Block6Explorer::IsSimilarEdges (const TopoDS_Shape& E1,
1108 const TopoDS_Shape& E2)
1110 TopoDS_Edge E1e = TopoDS::Edge(E1);
1111 TopoDS_Edge E2e = TopoDS::Edge(E2);
1112 TopoDS_Vertex V11, V12, V21, V22;
1113 TopExp::Vertices(E1e, V11, V12, Standard_True);
1114 TopExp::Vertices(E2e, V21, V22, Standard_True);
1115 if (BRepTools::Compare(V11, V21) && BRepTools::Compare(V12, V22))
1116 return Standard_True;
1117 if (BRepTools::Compare(V11, V22) && BRepTools::Compare(V12, V21))
1118 return Standard_True;
1120 return Standard_False;
1123 //=======================================================================
1124 //function : FindEdge
1126 //=======================================================================
1127 Standard_Integer GEOMImpl_Block6Explorer::FindEdge
1128 (TopoDS_Shape& theResult,
1129 const TopoDS_Shape& V1,
1130 const TopoDS_Shape& V2,
1131 const TopTools_IndexedDataMapOfShapeListOfShape& MVE,
1132 const Standard_Boolean findAll)
1134 Standard_Integer isFound = 0;
1136 const TopTools_ListOfShape& anEdgesOfV1 = MVE.FindFromKey(V1);
1137 const TopTools_ListOfShape& anEdgesOfV2 = MVE.FindFromKey(V2);
1139 TopTools_ListIteratorOfListOfShape it1 (anEdgesOfV1);
1140 for (; it1.More(); it1.Next()) {
1141 TopTools_ListIteratorOfListOfShape it2 (anEdgesOfV2);
1142 for (; it2.More(); it2.Next()) {
1143 if (it1.Value().IsSame(it2.Value())) {
1145 theResult = it1.Value();
1146 if (!findAll) return isFound;
1154 //=======================================================================
1155 //function : FindFace
1157 //=======================================================================
1158 Standard_Integer GEOMImpl_Block6Explorer::FindFace
1159 (TopoDS_Shape& theResult,
1160 const TopoDS_Shape& V1,
1161 const TopoDS_Shape& V2,
1162 const TopoDS_Shape& V3,
1163 const TopoDS_Shape& V4,
1164 const TopTools_IndexedDataMapOfShapeListOfShape& MVF,
1165 const Standard_Boolean findAll)
1167 Standard_Integer isFound = Standard_False;
1169 const TopTools_ListOfShape& aFacesOfV1 = MVF.FindFromKey(V1);
1170 const TopTools_ListOfShape& aFacesOfV2 = MVF.FindFromKey(V2);
1171 const TopTools_ListOfShape& aFacesOfV3 = MVF.FindFromKey(V3);
1172 const TopTools_ListOfShape& aFacesOfV4 = MVF.FindFromKey(V4);
1174 TopTools_ListIteratorOfListOfShape it1 (aFacesOfV1);
1175 for (; it1.More(); it1.Next()) {
1176 TopTools_ListIteratorOfListOfShape it2 (aFacesOfV2);
1177 for (; it2.More(); it2.Next()) {
1178 if (it1.Value().IsSame(it2.Value())) {
1179 TopTools_ListIteratorOfListOfShape it3 (aFacesOfV3);
1180 for (; it3.More(); it3.Next()) {
1181 if (it1.Value().IsSame(it3.Value())) {
1182 TopTools_ListIteratorOfListOfShape it4 (aFacesOfV4);
1183 for (; it4.More(); it4.Next()) {
1184 if (it1.Value().IsSame(it4.Value())) {
1186 theResult = it1.Value();
1187 if (!findAll) return isFound;
1199 //=======================================================================
1200 //function : MakeFace
1202 //=======================================================================
1203 TCollection_AsciiString GEOMImpl_Block6Explorer::MakeFace (const TopoDS_Wire& theWire,
1204 const Standard_Boolean isPlanarWanted,
1205 TopoDS_Shape& theResult)
1207 if (!isPlanarWanted)
1208 return MakeAnyFace(theWire, theResult);
1210 // Try to build a planar face.
1212 // If required tolerance increase will be
1213 // higher than PLANAR_FACE_MAX_TOLERANCE,
1214 // we will try to build a non-planar face.
1216 TCollection_AsciiString aWarning;
1218 // Workaround for Mantis issue 0020956
1220 // Count the number of points in the wire.
1221 // Collect the first three points.
1223 bool is3Pnts (false);
1224 bool p1set(false), p2set(false), p3set(false);
1225 BRepTools_WireExplorer wexpl (theWire);
1226 for (; wexpl.More(); wexpl.Next()) {
1229 p1 = BRep_Tool::Pnt(wexpl.CurrentVertex());
1233 p2 = BRep_Tool::Pnt(wexpl.CurrentVertex());
1238 p3 = BRep_Tool::Pnt(wexpl.CurrentVertex());
1246 // Construct a plane for the case of three points in the wire.
1249 gce_MakePln mkPln (p1, p2, p3);
1250 if (mkPln.IsDone()) {
1251 plane = mkPln.Value();
1258 // Construct a face based on the plane (in case of three points in the wire) or
1259 // allow MakeFace to build the plane itself (in case of the number of points is greater than 3).
1261 BRepBuilderAPI_MakeFace MK (plane, theWire, isPlanarWanted);
1263 theResult = MK.Shape();
1268 BRepBuilderAPI_MakeFace MK (theWire, isPlanarWanted);
1270 theResult = MK.Shape();
1275 // try to update wire tolerances to build a planar face
1278 Standard_Real aToleranceReached, aTol;
1279 BRepLib_FindSurface aFS;
1280 aFS.Init(theWire, -1., isPlanarWanted);
1281 aToleranceReached = aFS.ToleranceReached();
1282 aTol = aFS.Tolerance();
1285 aFS.Init(theWire, aToleranceReached, isPlanarWanted);
1286 if (!aFS.Found()) return aWarning;
1287 aToleranceReached = aFS.ToleranceReached();
1288 aTol = aFS.Tolerance();
1290 aTol = Max(1.2 * aToleranceReached, aTol);
1292 // Mantis issue 0021432: EDF GEOM: Faces with huge tolerance can be built in GEOM
1293 if (aTol > PLANAR_FACE_MAX_TOLERANCE) {
1294 aWarning = MakeAnyFace(theWire, theResult);
1295 if (aWarning.IsEmpty() && !theResult.IsNull())
1296 aWarning = "MAKE_FACE_TOLERANCE_TOO_BIG";
1300 // Copy the wire, bacause it can be updated with very-very big tolerance here
1301 BRepBuilderAPI_Copy aMC (theWire);
1302 if (!aMC.IsDone()) return aWarning;
1303 TopoDS_Wire aWire = TopoDS::Wire(aMC.Shape());
1304 // Update tolerances to <aTol>
1306 for (TopExp_Explorer expE (aWire, TopAbs_EDGE); expE.More(); expE.Next()) {
1307 TopoDS_Edge anE = TopoDS::Edge(expE.Current());
1308 B.UpdateEdge(anE, aTol);
1310 for (TopExp_Explorer expV (aWire, TopAbs_VERTEX); expV.More(); expV.Next()) {
1311 TopoDS_Vertex aV = TopoDS::Vertex(expV.Current());
1312 B.UpdateVertex(aV, aTol);
1314 //BRepLib::UpdateTolerances(aWire);
1316 BRepBuilderAPI_MakeFace MK1 (aWire, isPlanarWanted);
1318 theResult = MK1.Shape();
1319 // Mantis issue 0021432: EDF GEOM: Faces with huge tolerance can be built in GEOM
1320 //if (aTol > PLANAR_FACE_MAX_TOLERANCE)
1321 // aWarning = "MAKE_FACE_TOLERANCE_TOO_BIG";
1327 //=======================================================================
1328 //function : MakeAnyFace
1330 //=======================================================================
1331 TCollection_AsciiString GEOMImpl_Block6Explorer::MakeAnyFace (const TopoDS_Wire& theWire,
1332 TopoDS_Shape& theResult)
1334 TCollection_AsciiString aWarning;
1336 // try to build a face on any surface under the edges of the wire
1337 BRepBuilderAPI_MakeFace MK (theWire, Standard_False);
1339 theResult = MK.Shape();
1343 // try to construct filling surface
1344 BRepOffsetAPI_MakeFilling MF;
1346 Standard_Integer nbEdges = 0;
1347 BRepTools_WireExplorer aWE (theWire);
1348 for (; aWE.More(); aWE.Next(), nbEdges++) {
1349 MF.Add(TopoDS::Edge(aWE.Current()), GeomAbs_C0);
1354 aWarning = "BRepOffsetAPI_MakeFilling failed";
1358 // Result of filling
1359 TopoDS_Shape aFace = MF.Shape();
1361 // 12.04.2006 for PAL12149 begin
1362 Handle(Geom_Surface) aGS = BRep_Tool::Surface(TopoDS::Face(aFace));
1363 #if OCC_VERSION_LARGE > 0x06050200
1365 TopoDS_Iterator itw(theWire);
1366 for (; itw.More(); itw.Next())
1368 const TopoDS_Edge& anEdge = TopoDS::Edge(itw.Value());
1369 TopoDS_Edge NewEdge = TopoDS::Edge(MF.Generated(anEdge).First());
1370 Standard_Real fpar, lpar;
1371 Handle(Geom2d_Curve) NewPCurve = BRep_Tool::CurveOnSurface(NewEdge, TopoDS::Face(aFace), fpar, lpar);
1372 TopLoc_Location aLoc;
1373 Standard_Real NewTol = BRep_Tool::Tolerance(NewEdge);
1374 BB.UpdateEdge(anEdge, NewPCurve, aGS, aLoc, NewTol);
1377 BRepBuilderAPI_MakeFace MK1 (aGS, theWire);
1379 TopoDS_Shape aFace1 = MK1.Shape();
1381 BRepCheck_Analyzer ana (aFace1, false);
1382 if (!ana.IsValid()) {
1383 TopoDS_Shape aFace2;
1384 ShHealOper_ShapeProcess aHealer;
1385 aHealer.Perform(aFace1, aFace2);
1386 if (aHealer.isDone())
1390 // 12.04.2006 for PAL12149 end
1392 if (theResult.IsNull()) { // try to deal with pure result of filling
1394 Standard_Real aTol = MF.G0Error();
1396 TColgp_Array1OfPnt aPnts (1,nbEdges); // points of the given wire
1397 BRepTools_WireExplorer aWE1 (theWire);
1398 Standard_Integer vi = 1;
1399 for (; aWE1.More() && vi <= nbEdges; aWE1.Next(), vi++) {
1400 aPnts(vi) = BRep_Tool::Pnt(TopoDS::Vertex(aWE1.CurrentVertex()));
1403 // Find maximum deviation in vertices
1404 TopExp_Explorer exp (aFace, TopAbs_VERTEX);
1405 TopTools_MapOfShape mapShape;
1406 for (; exp.More(); exp.Next()) {
1407 if (mapShape.Add(exp.Current())) {
1408 TopoDS_Vertex aV = TopoDS::Vertex(exp.Current());
1409 Standard_Real aTolV = BRep_Tool::Tolerance(aV);
1410 gp_Pnt aP = BRep_Tool::Pnt(aV);
1411 Standard_Real min_dist = aP.Distance(aPnts(1));
1412 for (vi = 2; vi <= nbEdges; vi++) {
1413 min_dist = Min(min_dist, aP.Distance(aPnts(vi)));
1415 aTol = Max(aTol, aTolV);
1416 aTol = Max(aTol, min_dist);
1420 if ((*((Handle(BRep_TFace)*)&aFace.TShape()))->Tolerance() < aTol) {
1421 (*((Handle(BRep_TFace)*)&aFace.TShape()))->Tolerance(aTol);