1 // Copyright (C) 2007-2016 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, or (at your option) any later version.
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
23 #include <Standard_Stream.hxx>
25 #include <GEOMImpl_Block6Explorer.hxx>
27 #include <ShHealOper_ShapeProcess.hxx>
29 #include "utilities.h"
31 #include <Basics_OCCTVersion.hxx>
33 #include <BRep_Tool.hxx>
34 #include <BRep_TFace.hxx>
35 #include <BRep_Builder.hxx>
36 #include <BRepLib.hxx>
37 #include <BRepLib_FindSurface.hxx>
38 #include <BRepTools.hxx>
39 #include <BRepTools_WireExplorer.hxx>
40 #include <BRepOffsetAPI_ThruSections.hxx>
41 #include <BRepOffsetAPI_MakeFilling.hxx>
42 #include <BRepCheck_Analyzer.hxx>
43 #include <BRepBuilderAPI_Copy.hxx>
44 #include <BRepBuilderAPI_MakeEdge.hxx>
45 #include <BRepBuilderAPI_MakeWire.hxx>
46 #include <BRepBuilderAPI_MakeFace.hxx>
47 #include <BRepBuilderAPI_Transform.hxx>
51 #include <TopoDS_Shape.hxx>
52 #include <TopoDS_Edge.hxx>
53 #include <TopoDS_Wire.hxx>
54 #include <TopoDS_Solid.hxx>
56 #include <TopExp_Explorer.hxx>
57 #include <TopTools_MapOfShape.hxx>
58 #include <TopTools_ListOfShape.hxx>
59 #include <TopTools_ListIteratorOfListOfShape.hxx>
60 #include <TopTools_IndexedMapOfShape.hxx>
61 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
63 #include <Geom_Curve.hxx>
64 #include <Geom_TrimmedCurve.hxx>
65 #include <GeomFill_Generator.hxx>
67 #include <gce_MakePln.hxx>
69 #include <Precision.hxx>
72 #include <TColgp_Array1OfPnt.hxx>
74 #include <StdFail_NotDone.hxx>
75 #include <Standard_NullObject.hxx>
76 #include <Standard_TypeMismatch.hxx>
77 #include <Standard_ConstructionError.hxx>
78 #include <Standard_NoSuchObject.hxx>
84 #define PLANAR_FACE_MAX_TOLERANCE 1e-06
86 // The following macro, when enabled, causes pcurves upgrade after MakeFilling algorithm
87 // in MakeAnyFace function;
88 // WARNING: it may lead to extra vertices generation by partition algorithm
89 // in some cases, for example when fillet is made on a PipeTShape -
90 // see issues 0021568 and 0021550
91 // VSR (15/05/2012): macro commented out (disabled) to avoid extra vertices!
92 //#define MAKE_FACE_UPGRADE_PCURVES
94 // The following macro, when enabled, causes fixing tolerance for pcurves
95 // after BRepBuilderAPI_MakeFace + ShHealOper_ShapeProcess in MakeAnyFace function;
96 // This sometimes allows to fix problems of extra vertices generation
98 // VSR (17/11/2014): macro enabled
99 #define MAKE_FACE_PCURVES_FIX_TOLERANCE
101 #ifdef MAKE_FACE_PCURVES_FIX_TOLERANCE
102 #include <BOPTools_AlgoTools.hxx>
103 #include <NCollection_DataMap.hxx>
104 #include <ShapeFix_ShapeTolerance.hxx>
107 static Standard_Integer mod4 (Standard_Integer nb)
109 if (nb <= 0) return nb + 4;
110 if (nb > 4) return nb - 4;
114 static Standard_Integer edge_id (const Standard_Integer theFaceID,
115 const Standard_Integer theEdgeNB)
117 static Standard_Integer edge_ids[NBFACES][4] = {
118 { 1, 2, 3, 4 }, // face 1
119 { 5, 6, 7, 8 }, // face 2
120 { 9, 5, 10, 1 }, // face 3
121 { 12, 7, 11, 3 }, // face 4
122 { 4, 12, 8, 9 }, // face 5
123 { 2, 11, 6, 10 } }; // face 6
125 return edge_ids[theFaceID - 1][theEdgeNB - 1];
128 static Standard_Integer side_edge_id (const Standard_Integer theEdgeNB)
130 static Standard_Integer side_edge_ids[4] = {9, 10, 11, 12};
132 return side_edge_ids[theEdgeNB - 1];
135 static Standard_Integer vertex_id (const Standard_Integer theFaceID,
136 const Standard_Integer theVertexNB)
138 static Standard_Integer vertex_ids[NBFACES][4] = {
139 { 1, 2, 3, 4 }, // face 1
140 { 5, 6, 7, 8 }, // face 2
141 { 1, 5, 6, 2 }, // face 3
142 { 4, 8, 7, 3 }, // face 4
143 { 1, 4, 8, 5 }, // face 5
144 { 2, 3, 7, 6 } }; // face 6
146 return vertex_ids[theFaceID - 1][theVertexNB - 1];
149 static Standard_Integer vertex_id_edge (const Standard_Integer theEdgeID, // [1,12]
150 const Standard_Integer theVertexNB) // [1,2]
152 static Standard_Integer vertex_ids_edge[NBEDGES][2] = {
166 return vertex_ids_edge[theEdgeID - 1][theVertexNB - 1];
169 static Standard_Integer face_id_edges (const Standard_Integer theEdge1ID, // [1,12]
170 const Standard_Integer theEdge2ID) // [1,12]
172 static Standard_Integer face_ids_edges[NBEDGES][NBEDGES] = {
173 // 1 2 3 4 5 6 7 8 9 10 11 12
174 { 0, 1, 1, 1, 3, 0, 0, 0, 3, 3, 0, 0 }, // edge 1
175 { 1, 0, 1, 1, 0, 6, 0, 0, 0, 6, 6, 0 }, // edge 2
176 { 1, 1, 0, 1, 0, 0, 4, 0, 0, 0, 4, 4 }, // edge 3
177 { 1, 1, 1, 0, 0, 0, 0, 5, 5, 0, 0, 5 }, // edge 4
178 { 3, 0, 0, 0, 0, 2, 2, 2, 3, 3, 0, 0 }, // edge 5
179 { 0, 6, 0, 0, 2, 0, 2, 2, 0, 6, 6, 0 }, // edge 6
180 { 0, 0, 4, 0, 2, 2, 0, 2, 0, 0, 4, 4 }, // edge 7
181 { 0, 0, 0, 5, 2, 2, 2, 0, 5, 0, 0, 5 }, // edge 8
182 { 3, 0, 0, 5, 3, 0, 0, 5, 0, 3, 0, 5 }, // edge 9
183 { 3, 6, 0, 0, 3, 6, 0, 0, 3, 0, 6, 0 }, // edge 10
184 { 0, 6, 4, 0, 0, 6, 4, 0, 0, 6, 0, 4 }, // edge 11
185 { 0, 0, 4, 5, 0, 0, 4, 5, 5, 0, 4, 0 } }; // edge 12
187 return face_ids_edges[theEdge1ID - 1][theEdge2ID - 1];
190 static Standard_Integer edge_id_vertices (const Standard_Integer theVertex1ID, // [1,8]
191 const Standard_Integer theVertex2ID) // [1,8]
193 static Standard_Integer edge_ids_vertices[NBVERTS][NBVERTS] = {
195 { 0, 1, 0, 4, 9, 0, 0, 0}, // vertex 1
196 { 1, 0, 2, 0, 0, 10, 0, 0}, // vertex 2
197 { 0, 2, 0, 3, 0, 0, 11, 0}, // vertex 3
198 { 4, 0, 3, 0, 0, 0, 0, 12}, // vertex 4
199 { 9, 0, 0, 0, 0, 5, 0, 8}, // vertex 5
200 { 0, 10, 0, 0, 5, 0, 6, 0}, // vertex 6
201 { 0, 0, 11, 0, 0, 6, 0, 7}, // vertex 7
202 { 0, 0, 0, 12, 8, 0, 7, 0} }; // vertex 8
204 return edge_ids_vertices[theVertex1ID - 1][theVertex2ID - 1];
207 static Standard_Integer edge_id_faces (const Standard_Integer theFace1ID, // [1,6]
208 const Standard_Integer theFace2ID) // [1,6]
210 static Standard_Integer edge_ids_faces[NBFACES][NBFACES] = {
212 { 0, 0, 1, 3, 4, 2 }, // face 1
213 { 0, 0, 5, 7, 8, 6 }, // face 2
214 { 1, 5, 0, 0, 9, 10 }, // face 3
215 { 3, 7, 0, 0, 12, 11 }, // face 4
216 { 4, 8, 9, 12, 0, 0 }, // face 5
217 { 2, 6, 10, 11, 0, 0 } }; // face 6
219 return edge_ids_faces[theFace1ID - 1][theFace2ID - 1];
222 //=======================================================================
223 //function : GEOMImpl_Block6Explorer
224 //purpose : Constructor
225 //=======================================================================
226 GEOMImpl_Block6Explorer::GEOMImpl_Block6Explorer ()
227 : myFaces(1,NBFACES), myEdges(1,NBEDGES), myVertices(1,NBVERTS)
231 //=======================================================================
232 //function : GetVertex
234 //=======================================================================
235 TopoDS_Shape GEOMImpl_Block6Explorer::GetVertex (const Standard_Integer theVertexID)
237 TopoDS_Shape aNullShape;
238 if (theVertexID < 1 || theVertexID > NBVERTS) return aNullShape;
239 return myVertices(theVertexID);
242 //=======================================================================
243 //function : GetVertexID
245 //=======================================================================
246 Standard_Integer GEOMImpl_Block6Explorer::GetVertexID (const TopoDS_Shape& theVertex)
248 for (Standard_Integer id = 1; id <= NBVERTS; id++) {
249 if (theVertex.IsSame(myVertices(id))) return id;
251 Standard_NoSuchObject::Raise("The Vertex does not belong to the Block");
255 //=======================================================================
256 //function : GetVertexID
258 //=======================================================================
259 Standard_Integer GEOMImpl_Block6Explorer::GetVertexID (const Standard_Integer theFaceID,
260 const Standard_Integer theVertexNB)
262 return vertex_id(theFaceID, theVertexNB);
265 //=======================================================================
266 //function : GetVertexOnEdgeID
268 //=======================================================================
269 Standard_Integer GEOMImpl_Block6Explorer::GetVertexOnEdgeID
270 (const Standard_Integer theEdgeID,
271 const Standard_Integer theVertexNB)
273 return vertex_id_edge(theEdgeID, theVertexNB);
276 //=======================================================================
279 //=======================================================================
280 TopoDS_Shape GEOMImpl_Block6Explorer::GetEdge (const Standard_Integer theEdgeID,
281 const Standard_Boolean doMake)
283 TopoDS_Shape aNullShape;
284 if (theEdgeID < 1 || theEdgeID > NBEDGES) return aNullShape;
285 if (myEdges(theEdgeID).IsNull() && doMake) {
286 // Create the required edge as a linear segment between
287 // corresponding vertices and put it in the Block's edges
288 BRepBuilderAPI_MakeEdge ME (TopoDS::Vertex(myVertices(vertex_id_edge(theEdgeID, 1))),
289 TopoDS::Vertex(myVertices(vertex_id_edge(theEdgeID, 2))));
291 Standard_ConstructionError::Raise("Edge construction failed");
293 myEdges(theEdgeID) = ME.Shape();
296 return myEdges(theEdgeID);
299 //=======================================================================
300 //function : GetEdgeID
302 //=======================================================================
303 Standard_Integer GEOMImpl_Block6Explorer::GetEdgeID (const TopoDS_Shape& theEdge)
305 for (Standard_Integer id = 1; id <= NBEDGES; id++) {
306 if (theEdge.IsSame(myEdges(id))) return id;
308 Standard_NoSuchObject::Raise("The Edge does not belong to the Block");
312 //=======================================================================
313 //function : GetEdgeID
315 //=======================================================================
316 Standard_Integer GEOMImpl_Block6Explorer::GetEdgeID (const Standard_Integer theFaceID,
317 const Standard_Integer theEdgeNB)
319 return edge_id(theFaceID, theEdgeNB);
322 //=======================================================================
323 //function : FindEdgeID
325 //=======================================================================
326 Standard_Integer GEOMImpl_Block6Explorer::FindEdgeID (const Standard_Integer theVertex1ID,
327 const Standard_Integer theVertex2ID)
329 return edge_id_vertices(theVertex1ID, theVertex2ID);
332 //=======================================================================
333 //function : FindCommonEdgeID
335 //=======================================================================
336 Standard_Integer GEOMImpl_Block6Explorer::FindCommonEdgeID
337 (const Standard_Integer theFace1ID,
338 const Standard_Integer theFace2ID)
340 return edge_id_faces(theFace1ID, theFace2ID);
343 //=======================================================================
346 //=======================================================================
347 TopoDS_Shape GEOMImpl_Block6Explorer::GetFace (const Standard_Integer theFaceID,
348 const Standard_Boolean doMake)
350 TopoDS_Shape aNullShape;
351 if (theFaceID < 1 || theFaceID > NBFACES) return aNullShape;
353 if (myFaces(theFaceID).IsNull() && doMake) {
355 // Create the required face between
356 // corresponding edges and put it in the Block's faces
358 TopoDS_Shape E1 = GetEdge(edge_id(theFaceID, 1), doMake);
359 TopoDS_Shape E2 = GetEdge(edge_id(theFaceID, 2), doMake);
360 TopoDS_Shape E3 = GetEdge(edge_id(theFaceID, 3), doMake);
361 TopoDS_Shape E4 = GetEdge(edge_id(theFaceID, 4), doMake);
363 BRepBuilderAPI_MakeWire MW (TopoDS::Edge(E1),
368 Standard_ConstructionError::Raise("Wire construction failed");
371 MakeFace(MW, Standard_False, aFace);
372 if (aFace.IsNull()) {
373 Standard_ConstructionError::Raise("Face construction failed");
375 myFaces(theFaceID) = aFace;
378 return myFaces(theFaceID);
381 //=======================================================================
382 //function : GetFaceID
384 //=======================================================================
385 Standard_Integer GEOMImpl_Block6Explorer::GetFaceID (const TopoDS_Shape& theFace)
387 for (Standard_Integer id = 1; id <= NBFACES; id++) {
388 if (theFace.IsSame(myFaces(id))) return id;
390 Standard_NoSuchObject::Raise("The Face does not belong to the Block");
394 //=======================================================================
395 //function : FindFaceID
397 //=======================================================================
398 Standard_Integer GEOMImpl_Block6Explorer::FindFaceID (const Standard_Integer theEdge1ID,
399 const Standard_Integer theEdge2ID)
401 return face_id_edges(theEdge1ID, theEdge2ID);
404 //=======================================================================
405 //function : GetOppositeFaceID
407 //=======================================================================
408 Standard_Integer GEOMImpl_Block6Explorer::GetOppositeFaceID (const Standard_Integer theFaceID)
410 Standard_Integer opp_face_id[NBFACES + 1] = {
419 return opp_face_id[theFaceID];
422 //=======================================================================
423 //function : IsSimilarFaces
425 //=======================================================================
426 Standard_Boolean GEOMImpl_Block6Explorer::IsSimilarFaces (const Standard_Integer theFace1ID,
427 const Standard_Integer theFace2ID,
428 const gp_Trsf theTransformation)
430 Standard_Integer common_edge_id = FindCommonEdgeID(theFace1ID, theFace2ID);
432 if (common_edge_id == 0) { // opposite faces
433 for (Standard_Integer id = 1; id <= 4; id++) {
434 TopoDS_Shape E1 = GetEdge(edge_id(theFace1ID, id));
435 TopoDS_Shape E2 = GetEdge(edge_id(theFace2ID, id));
437 BRepBuilderAPI_Transform aTrsf (E1, theTransformation, Standard_False);
438 if (!IsSimilarEdges(aTrsf.Shape(), E2))
439 return Standard_False;
441 } else { // the faces have common edge
442 TopTools_Array1OfShape aVerts1 (1,4);
443 TopTools_Array1OfShape aVerts2 (1,4);
445 Standard_Integer common_vertex1 = GetVertexOnEdgeID(common_edge_id, 1);
446 Standard_Integer common_vertex2 = GetVertexOnEdgeID(common_edge_id, 2);
447 aVerts1(1) = myVertices(common_vertex1);
448 aVerts1(2) = myVertices(common_vertex2);
449 aVerts2(1) = myVertices(common_vertex1);
450 aVerts2(2) = myVertices(common_vertex2);
452 Standard_Integer not_common_v11 = 0, not_common_v12 = 0;
453 Standard_Integer vnb, vid;
454 for (vnb = 1; vnb <= 4; vnb++) {
455 vid = GetVertexID(theFace1ID, vnb);
456 if (vid != common_vertex1 && FindEdgeID(vid, common_vertex1) == 0) {
457 not_common_v12 = vid;
459 if (vid != common_vertex2 && FindEdgeID(vid, common_vertex2) == 0) {
460 not_common_v11 = vid;
465 Standard_Integer not_common_v21 = 0, not_common_v22 = 0;
466 for (vnb = 1; vnb <= 4; vnb++) {
467 vid = GetVertexID(theFace2ID, vnb);
468 if (vid != common_vertex1 && FindEdgeID(vid, common_vertex1) == 0) {
469 not_common_v22 = vid;
471 if (vid != common_vertex2 && FindEdgeID(vid, common_vertex2) == 0) {
472 not_common_v21 = vid;
476 aVerts1(3) = myVertices(not_common_v11);
477 aVerts1(4) = myVertices(not_common_v12);
478 aVerts2(3) = myVertices(not_common_v21);
479 aVerts2(4) = myVertices(not_common_v22);
481 for (Standard_Integer id = 1; id <= 4; id++) {
482 BRepBuilderAPI_Transform aTrsf (aVerts1(id), theTransformation, Standard_False);
483 TopoDS_Vertex V1 = TopoDS::Vertex(aTrsf.Shape());
484 TopoDS_Vertex V2 = TopoDS::Vertex(aVerts2(id));
485 if (!BRepTools::Compare(V1, V2)) {
486 return Standard_False;
491 return Standard_True;
494 //============ Initialization methods ===================================
496 //=======================================================================
497 //function : InitByBlock
499 //=======================================================================
500 void GEOMImpl_Block6Explorer::InitByBlock (const TopoDS_Shape& theBlock)
502 // 1. Find any one face of the block
503 TopExp_Explorer faces (theBlock, TopAbs_FACE);
505 Standard_ConstructionError::Raise("The block has no faces");
507 TopoDS_Shape aFirstFace = faces.Current();
509 // 2. Store all elements of the block relatively aFirstFace
510 InitByBlockAndFace(theBlock, aFirstFace);
513 //=======================================================================
514 //function : InitByBlockAndFace
516 //=======================================================================
517 void GEOMImpl_Block6Explorer::InitByBlockAndFace (const TopoDS_Shape& theBlock,
518 const TopoDS_Shape& theFace)
520 myFaces(1) = theFace;
522 // 2. Get wire of the first face
523 TopExp_Explorer wires (myFaces(1), TopAbs_WIRE);
525 Standard_ConstructionError::Raise("A face of the block has no wires");
527 TopoDS_Shape aWire = wires.Current();
530 Standard_ConstructionError::Raise("A face of the block has more than one wires");
533 // 3. Explore wire to init edges and vertices of the first face
534 BRepTools_WireExplorer aWE (TopoDS::Wire(aWire), TopoDS::Face(myFaces(1)));
535 Standard_Integer nb = 1;
536 for (; aWE.More(); aWE.Next(), nb++) {
538 Standard_ConstructionError::Raise("A face of the block has more than four edges");
540 myEdges(edge_id(1, nb)) = aWE.Current();
541 myVertices(vertex_id(1, nb)) = aWE.CurrentVertex();
544 Standard_ConstructionError::Raise("A face of the block has less than four edges");
547 // 2. Store all other elements of the block
548 InitByBlockAndVertices (theBlock,
549 myVertices(vertex_id(1,1)),
550 myVertices(vertex_id(1,2)),
551 myVertices(vertex_id(1,3)));
554 //=======================================================================
555 //function : InitByBlockAndEdges
557 //=======================================================================
558 void GEOMImpl_Block6Explorer::InitByBlockAndEdges (const TopoDS_Shape& theBlock,
559 const TopoDS_Shape& theEdge1,
560 const TopoDS_Shape& theEdge3)
562 // 1. Store vertices and edges of the first face
564 // 1.1. Store two given edges
565 myEdges(edge_id(1, 1)) = theEdge1;
566 myEdges(edge_id(1, 3)) = theEdge3;
568 // 1.2. Find and store the first face
569 TopTools_IndexedDataMapOfShapeListOfShape MEF;
570 MapShapesAndAncestors(theBlock, TopAbs_EDGE, TopAbs_FACE, MEF);
571 if (MEF.Extent() != NBEDGES) {
572 Standard_TypeMismatch::Raise("Block has wrong number of edges");
574 const TopTools_ListOfShape& aFacesOfE1 = MEF.FindFromKey(theEdge1);
575 const TopTools_ListOfShape& aFacesOfE3 = MEF.FindFromKey(theEdge3);
577 Standard_Boolean isFound = Standard_False;
578 TopTools_ListIteratorOfListOfShape anIterF1 (aFacesOfE1);
579 for (; anIterF1.More() && !isFound; anIterF1.Next()) {
581 TopTools_ListIteratorOfListOfShape anIterF3 (aFacesOfE3);
582 for (; anIterF3.More() && !isFound; anIterF3.Next()) {
584 if (anIterF1.Value().IsSame(anIterF3.Value())) {
585 isFound = Standard_True;
587 // Store the face, defined by two opposite edges
588 myFaces(1) = anIterF1.Value();
593 Standard_ConstructionError::Raise
594 ("Edges 1 and 2 do not belong to one face of the block");
597 // 1.3. Make vertices of the first edge the first and the
598 // second vertices of the first face. Order is free.
599 TopoDS_Edge E = TopoDS::Edge(theEdge1);
600 TopoDS_Vertex V1, V2;
601 TopExp::Vertices(E, V1, V2, Standard_True);
602 myVertices(vertex_id(1,1)) = V1;
603 myVertices(vertex_id(1,2)) = V2;
605 // Init maps vertex->list_of_edges for the face
606 TopTools_IndexedDataMapOfShapeListOfShape M1;
607 MapShapesAndAncestors(myFaces(1), TopAbs_VERTEX, TopAbs_EDGE, M1);
608 if (M1.Extent() != 4) {
609 Standard_TypeMismatch::Raise("The first face of block has wrong number of vertices");
612 // 1.4. Find and store others elements of the first face
614 // edges of the first vertex
615 TopoDS_Shape E1_f = M1.FindFromKey(V1).First();
616 TopoDS_Shape E1_l = M1.FindFromKey(V1).Last();
618 if (E1_f.IsSame(theEdge1)) {
619 myEdges(edge_id(1, 4)) = E1_l;
621 myEdges(edge_id(1, 4)) = E1_f;
625 TopoDS_Edge E4 = TopoDS::Edge(myEdges(edge_id(1, 4)));
626 TopoDS_Vertex V41, V42;
627 TopExp::Vertices(E4, V41, V42, Standard_True);
628 if (V41.IsSame(V1)) {
629 myVertices(vertex_id(1,4)) = V42;
631 myVertices(vertex_id(1,4)) = V41;
634 // edges of the second vertex
635 TopoDS_Shape E2_f = M1.FindFromKey(V2).First();
636 TopoDS_Shape E2_l = M1.FindFromKey(V2).Last();
638 if (E2_f.IsSame(theEdge1)) {
639 myEdges(edge_id(1, 2)) = E2_l;
641 myEdges(edge_id(1, 2)) = E2_f;
645 TopoDS_Edge E2 = TopoDS::Edge(myEdges(edge_id(1, 2)));
646 TopoDS_Vertex V21, V22;
647 TopExp::Vertices(E2, V21, V22, Standard_True);
648 if (V21.IsSame(V2)) {
649 myVertices(vertex_id(1,3)) = V22;
651 myVertices(vertex_id(1,3)) = V21;
654 // 2. Store all other elements of the block
655 InitByBlockAndVertices (theBlock,
656 myVertices(vertex_id(1,1)),
657 myVertices(vertex_id(1,2)),
658 myVertices(vertex_id(1,3)));
661 //=======================================================================
662 //function : InitByBlockAndVertices
664 //=======================================================================
665 void GEOMImpl_Block6Explorer::InitByBlockAndVertices (const TopoDS_Shape& theBlock,
666 const TopoDS_Shape& theVertex1,
667 const TopoDS_Shape& theVertex2,
668 const TopoDS_Shape& theVertex3)
670 // Here we suppose, that vertices are ordered, i.e. exists edge between
671 // theVertex1 and theVertex2 and edge between theVertex2 and theVertex3
673 // 1. Store vertices and edges of the first face.
674 // If the first face is initialized, it means, that this
675 // method is called from another initialization method, and all
676 // vertices and edges of the first face are also initialized
677 if (myFaces(1).IsNull()) {
679 // 1.1. Store first three vertices
680 myVertices(vertex_id(1, 1)) = theVertex1;
681 myVertices(vertex_id(1, 2)) = theVertex2;
682 myVertices(vertex_id(1, 3)) = theVertex3;
684 // 1.2. Find and store the first face
685 TopTools_IndexedDataMapOfShapeListOfShape MVF;
686 MapShapesAndAncestors(theBlock, TopAbs_VERTEX, TopAbs_FACE, MVF);
687 if (MVF.Extent() != NBVERTS) {
688 Standard_TypeMismatch::Raise("Block has wrong number of vertices");
690 const TopTools_ListOfShape& aFacesOfV1 = MVF.FindFromKey(theVertex1);
691 const TopTools_ListOfShape& aFacesOfV3 = MVF.FindFromKey(theVertex3);
693 Standard_Boolean isFound = Standard_False;
694 TopTools_ListIteratorOfListOfShape anIterF1 (aFacesOfV1);
695 for (; anIterF1.More() && !isFound; anIterF1.Next()) {
697 TopTools_ListIteratorOfListOfShape anIterF3 (aFacesOfV3);
698 for (; anIterF3.More() && !isFound; anIterF3.Next()) {
700 if (anIterF1.Value().IsSame(anIterF3.Value())) {
701 isFound = Standard_True;
703 // Store the face, defined by two opposite vertices
704 myFaces(1) = anIterF1.Value();
709 Standard_ConstructionError::Raise
710 ("Vertices 1 and 3 do not belong to one face of the block");
713 // Init maps vertex->list_of_edges for the face
714 TopTools_IndexedDataMapOfShapeListOfShape M1;
715 MapShapesAndAncestors(myFaces(1), TopAbs_VERTEX, TopAbs_EDGE, M1);
716 if (M1.Extent() != 4) {
717 Standard_TypeMismatch::Raise("The first face of block has wrong number of vertices");
720 // 1.3. Find and store edges and last vertex of the first face
721 const TopTools_ListOfShape& anEdgesOfV1 = M1.FindFromKey(theVertex1);
722 const TopTools_ListOfShape& anEdgesOfV2 = M1.FindFromKey(theVertex2);
723 const TopTools_ListOfShape& anEdgesOfV3 = M1.FindFromKey(theVertex3);
725 TopTools_ListIteratorOfListOfShape anIterE2 (anEdgesOfV2);
726 for (; anIterE2.More(); anIterE2.Next()) {
728 TopTools_ListIteratorOfListOfShape anIterE1 (anEdgesOfV1);
729 for (; anIterE1.More(); anIterE1.Next()) {
731 if (anIterE1.Value().IsSame(anIterE2.Value())) {
732 // Store the first edge, defined by two vertices
733 myEdges(edge_id(1,1)) = anIterE1.Value();
736 // Store the last edge
737 myEdges(edge_id(1,4)) = anIterE1.Value();
739 // Find and store the last vertex
740 TopoDS_Edge E = TopoDS::Edge(myEdges(4));
741 TopoDS_Vertex V1, V2;
742 TopExp::Vertices(E, V1, V2, Standard_True);
744 if (V1.IsSame(theVertex1)) {
745 myVertices(vertex_id(1,4)) = V2;
747 myVertices(vertex_id(1,4)) = V1;
752 TopTools_ListIteratorOfListOfShape anIterE3 (anEdgesOfV3);
753 for (; anIterE3.More(); anIterE3.Next()) {
755 if (anIterE3.Value().IsSame(anIterE2.Value())) {
756 // Store the second edge, defined by two vertices
757 myEdges(edge_id(1,2)) = anIterE3.Value();
760 // Store the fird edge
761 myEdges(edge_id(1,3)) = anIterE3.Value();
767 // Init map vertex->list_of_edges for the block
768 TopTools_IndexedDataMapOfShapeListOfShape MB;
769 MapShapesAndAncestors(theBlock, TopAbs_VERTEX, TopAbs_EDGE, MB);
770 if (MB.Extent() != NBVERTS) {
771 Standard_TypeMismatch::Raise("Block has wrong number of vertices");
774 // 2. Store edges, linking the first face with the second one
775 // and vertices of the second face
776 TopTools_IndexedMapOfShape aFaceEdges;
777 TopExp::MapShapes(myFaces(1), TopAbs_EDGE, aFaceEdges);
779 Standard_Integer i = 1;
780 for (; i <= 4; i++) {
781 // Get i-th vertex of the face 1
782 TopoDS_Shape Vi = myVertices(vertex_id(1, i));
783 if (!MB.Contains(Vi)) {
784 Standard_ConstructionError::Raise("Face does not belong to the block");
787 // Get list of block's edges, sharing this Vertex
788 const TopTools_ListOfShape& anEdgesOfVi = MB.FindFromKey(Vi);
789 TopTools_ListIteratorOfListOfShape anEdgesIter (anEdgesOfVi);
791 // Get Edge (from the List), not belonging to the face 1
792 Standard_Boolean isFound = Standard_False;
793 for (; anEdgesIter.More() && !isFound; anEdgesIter.Next()) {
794 if (!aFaceEdges.Contains(anEdgesIter.Value())) {
795 isFound = Standard_True;
797 // Store the linking edge
798 TopoDS_Shape aLinkEdge = anEdgesIter.Value();
799 myEdges(side_edge_id(i)) = aLinkEdge;
801 // Get another vertex of the linking edge
802 TopoDS_Edge E = TopoDS::Edge(aLinkEdge);
803 TopoDS_Vertex V1, V2;
804 TopExp::Vertices(E, V1, V2, Standard_True);
806 // Store the i-th vertex of the second (opposite to the first) face
808 myVertices(vertex_id(2, i)) = V2;
810 myVertices(vertex_id(2, i)) = V1;
816 // 3. Store edges of the second (opposite to the first) face
817 for (i = 1; i <= 4; i++) {
818 // Get i-th and (i+1)-th vertices of the face 2
819 TopoDS_Shape Vi = myVertices(vertex_id(2, i));
820 TopoDS_Shape Vj = myVertices(vertex_id(2, mod4(i + 1)));
822 // Get list of block's edges, sharing Vi
823 const TopTools_ListOfShape& anEdgesOfVi = MB.FindFromKey(Vi);
824 // Get list of block's edges, sharing Vj
825 const TopTools_ListOfShape& anEdgesOfVj = MB.FindFromKey(Vj);
827 // Get Edge (from the List), linking this vertex with the next one
828 Standard_Boolean isFound = Standard_False;
829 TopTools_ListIteratorOfListOfShape anEdgesIteri (anEdgesOfVi);
830 for (; anEdgesIteri.More() && !isFound; anEdgesIteri.Next()) {
832 TopTools_ListIteratorOfListOfShape anEdgesIterj (anEdgesOfVj);
833 for (; anEdgesIterj.More() && !isFound; anEdgesIterj.Next()) {
835 if (anEdgesIteri.Value().IsSame(anEdgesIterj.Value())) {
836 isFound = Standard_True;
838 // Store the linking edge
839 myEdges(edge_id(2, i)) = anEdgesIteri.Value();
845 // 4. Store faces of the block
846 TopTools_IndexedDataMapOfShapeListOfShape MBE;
847 MapShapesAndAncestors(theBlock, TopAbs_EDGE, TopAbs_FACE, MBE);
848 if (MBE.Extent() != NBEDGES) {
849 Standard_TypeMismatch::Raise("Block has wrong number of edges");
852 for (i = 2; i <= NBFACES; i++) {
853 TopoDS_Shape Ei1 = myEdges(edge_id(i, 1));
854 TopoDS_Shape Ei2 = myEdges(edge_id(i, 2));
855 const TopTools_ListOfShape& aFacesOfEi1 = MBE.FindFromKey(Ei1);
856 const TopTools_ListOfShape& aFacesOfEi2 = MBE.FindFromKey(Ei2);
858 Standard_Boolean isFound = Standard_False;
859 TopTools_ListIteratorOfListOfShape anIterEi1 (aFacesOfEi1);
860 for (; anIterEi1.More() && !isFound; anIterEi1.Next()) {
862 TopTools_ListIteratorOfListOfShape anIterEi2 (aFacesOfEi2);
863 for (; anIterEi2.More() && !isFound; anIterEi2.Next()) {
865 if (anIterEi1.Value().IsSame(anIterEi2.Value())) {
866 isFound = Standard_True;
868 // Store the face, defined by two edges
869 myFaces(i) = anIterEi1.Value();
876 //=======================================================================
877 //function : InitByTwoFaces
879 //=======================================================================
880 void GEOMImpl_Block6Explorer::InitByTwoFaces (const TopoDS_Shape& theFace1,
881 const TopoDS_Shape& theFace2)
883 if (theFace1.IsSame(theFace2)) {
884 Standard_ConstructionError::Raise("The faces must be different");
887 // Add two given faces in the structure
888 myFaces(1) = theFace1;
889 myFaces(2) = theFace2;
891 // Step 1. Order vertices (and edges)
893 // 1.1. Ordered vertices and edges of the first face we put in <myVertices>
895 // Get wire of the first face
896 TopExp_Explorer wires1 (myFaces(1), TopAbs_WIRE);
897 if (!wires1.More()) {
898 Standard_ConstructionError::Raise("A face for the block has no wires");
900 TopoDS_Shape aWire1 = wires1.Current();
903 Standard_ConstructionError::Raise("A face for the block has more than one wire");
906 BRepTools_WireExplorer aWE1 (TopoDS::Wire(aWire1), TopoDS::Face(myFaces(1)));
908 for (nb = 1; aWE1.More(); aWE1.Next(), nb++) {
910 Standard_ConstructionError::Raise("A face for the block has more than four edges");
912 myEdges(edge_id(1, nb)) = aWE1.Current();
913 myVertices(vertex_id(1, nb)) = aWE1.CurrentVertex();
916 Standard_ConstructionError::Raise("A face for the block has less than four edges");
919 // 1.2. Ordered vertices and edges of the second face we temporarily store
920 // in arrays, to find for them rigth location in <myVertices> on the Step 2.
923 TopTools_Array1OfShape aVertis2(1,4); // ordered vertices of the second face
924 TopTools_Array1OfShape anEdges2(1,4); // anEdges2(i) links aVertis2(i) and aVertis2(i+1)
926 // Get wire of the second face
927 TopExp_Explorer wires2 (myFaces(2), TopAbs_WIRE);
928 if (!wires2.More()) {
929 Standard_ConstructionError::Raise("A face for the block has no wires");
931 TopoDS_Shape aWire2 = wires2.Current();
934 Standard_ConstructionError::Raise("A face for the block has more than one wire");
937 BRepTools_WireExplorer aWE2 (TopoDS::Wire(aWire2), TopoDS::Face(myFaces(2)));
938 for (nb = 1; aWE2.More(); aWE2.Next(), nb++) {
940 Standard_ConstructionError::Raise("A face for the block has more than four edges");
942 anEdges2(nb) = aWE2.Current();
943 aVertis2(nb) = aWE2.CurrentVertex();
946 Standard_ConstructionError::Raise("A face for the block has less than four edges");
949 // Step 2. Find right place in <myVertices> for the <aVertis2>,
950 // so as to minimize common length of linking edges
951 // between face 1 and face 2.
952 // Each linking edge (of four) will link vertices of the
953 // faces 1 and 2 with equal local numbers.
954 // The right place is defined by:
955 // - vertex <aVertis2(i_min)>, which will become the first vertex
956 // of the second face <myVertices(vertex_id(2,1))>
957 // - orientation of <aVertis2> relatively their future location
958 // in <myVertices> (s_min = 1 if direct, s_min = -1 if reversed)
959 Standard_Integer i_min = 0, s_min = 0;
961 TColgp_Array1OfPnt aPnts1 (1,4); // points of the first face
962 aPnts1(1) = BRep_Tool::Pnt(TopoDS::Vertex(myVertices(vertex_id(1, 1))));
963 aPnts1(2) = BRep_Tool::Pnt(TopoDS::Vertex(myVertices(vertex_id(1, 2))));
964 aPnts1(3) = BRep_Tool::Pnt(TopoDS::Vertex(myVertices(vertex_id(1, 3))));
965 aPnts1(4) = BRep_Tool::Pnt(TopoDS::Vertex(myVertices(vertex_id(1, 4))));
967 TColgp_Array1OfPnt aPnts2 (1,4); // points of the second face
968 aPnts2(1) = BRep_Tool::Pnt(TopoDS::Vertex(aVertis2(1)));
969 aPnts2(2) = BRep_Tool::Pnt(TopoDS::Vertex(aVertis2(2)));
970 aPnts2(3) = BRep_Tool::Pnt(TopoDS::Vertex(aVertis2(3)));
971 aPnts2(4) = BRep_Tool::Pnt(TopoDS::Vertex(aVertis2(4)));
973 Standard_Real Dist_min = RealLast();
974 // try all possible locations to find the best (with minimum sum distance)
975 Standard_Integer i = 1;
976 for (; i <= 4; i++) {
977 // try direct orientation
978 Standard_Real Dist_plus = aPnts1(1).Distance(aPnts2(i)) +
979 aPnts1(2).Distance(aPnts2(mod4(i + 1))) +
980 aPnts1(3).Distance(aPnts2(mod4(i + 2))) +
981 aPnts1(4).Distance(aPnts2(mod4(i + 3)));
982 if (Dist_plus < Dist_min) {
983 Dist_min = Dist_plus;
988 // try reversed orientation
989 Standard_Real Dist_minus = aPnts1(1).Distance(aPnts2(i)) +
990 aPnts1(2).Distance(aPnts2(mod4(i - 1))) +
991 aPnts1(3).Distance(aPnts2(mod4(i - 2))) +
992 aPnts1(4).Distance(aPnts2(mod4(i - 3)));
993 if (Dist_minus < Dist_min) {
994 Dist_min = Dist_minus;
1000 // 3. Put vertices and edges of the second face to they
1001 // permanent location in <myVertices> and <myEdges>
1002 for (i = 1; i <= 4; i++) {
1003 Standard_Integer nb = mod4(i_min + s_min*(i - 1));
1005 if (aPnts1(i).Distance(aPnts2(nb)) < Precision::Confusion()) {
1006 Standard_ConstructionError::Raise("The faces are too close");
1009 myVertices(vertex_id(2, i)) = aVertis2(nb);
1011 if (s_min == -1) nb = mod4(nb - 1);
1012 myEdges(edge_id(2, i)) = anEdges2(nb);
1015 // check the wires closure
1016 TopoDS_Wire wire1 = TopoDS::Wire(aWire1);
1017 TopoDS_Wire wire2 = TopoDS::Wire(aWire2);
1018 TopoDS_Vertex aV1, aV2;
1020 TopExp::Vertices(wire1, aV1, aV2);
1021 if (!aV1.IsNull() && !aV2.IsNull() && aV1.IsSame(aV2))
1022 aWire1.Closed(true);
1024 TopExp::Vertices(wire2, aV1, aV2);
1025 if (!aV1.IsNull() && !aV2.IsNull() && aV1.IsSame(aV2))
1026 aWire2.Closed(true);
1028 // 4. Generate side surface
1029 if (!aWire1.Closed() || !aWire2.Closed()) {
1030 // BRepOffsetAPI_ThruSections is not applicable on not closed wires
1031 GetFace(3, Standard_True);
1032 GetFace(4, Standard_True);
1033 GetFace(5, Standard_True);
1034 GetFace(6, Standard_True);
1036 // try to build faces on native surfaces of edges or planar
1037 Standard_Boolean tryThru = Standard_False;
1038 for (Standard_Integer i = 3; i <= 6 && !tryThru; i++) {
1039 Standard_Boolean doMake = Standard_True;
1040 TopoDS_Shape E1 = GetEdge(edge_id(i, 1), doMake);
1041 TopoDS_Shape E2 = GetEdge(edge_id(i, 2), doMake);
1042 TopoDS_Shape E3 = GetEdge(edge_id(i, 3), doMake);
1043 TopoDS_Shape E4 = GetEdge(edge_id(i, 4), doMake);
1045 BRepBuilderAPI_MakeWire MW (TopoDS::Edge(E1),
1050 Standard_ConstructionError::Raise("Wire construction failed");
1053 BRepBuilderAPI_MakeFace MF (MW, Standard_False);
1055 myFaces(i) = MF.Shape();
1057 tryThru = Standard_True;
1061 // Build side surface by ThruSections algorithm
1063 BRepOffsetAPI_ThruSections THS;
1064 THS.AddWire(TopoDS::Wire(aWire1));
1065 THS.AddWire(TopoDS::Wire(aWire2));
1067 if (!THS.IsDone()) {
1068 StdFail_NotDone::Raise("Side surface generation failed");
1070 for (Standard_Integer i = 1; i <= 4; i++) {
1072 myFaces(i+2) = THS.GeneratedFace(myEdges(i));
1075 Standard_Integer ee = side_edge_id(i);
1076 TopTools_IndexedDataMapOfShapeListOfShape MVE;
1077 MapShapesAndAncestors(myFaces(i+2), TopAbs_VERTEX, TopAbs_EDGE, MVE);
1078 FindEdge(myEdges(ee),
1079 myVertices(vertex_id_edge(ee, 1)),
1080 myVertices(vertex_id_edge(ee, 2)),
1087 //=======================================================================
1088 //function : MapShapesAndAncestors
1090 //=======================================================================
1091 void GEOMImpl_Block6Explorer::MapShapesAndAncestors (const TopoDS_Shape& S,
1092 const TopAbs_ShapeEnum TS,
1093 const TopAbs_ShapeEnum TA,
1094 TopTools_IndexedDataMapOfShapeListOfShape& M)
1096 TopTools_ListOfShape empty;
1097 TopTools_MapOfShape mapA;
1100 TopExp_Explorer exa (S,TA);
1101 for (; exa.More(); exa.Next()) {
1103 const TopoDS_Shape& anc = exa.Current();
1104 if (mapA.Add(anc)) {
1105 TopExp_Explorer exs (anc,TS);
1106 TopTools_MapOfShape mapS;
1107 for (; exs.More(); exs.Next()) {
1108 if (mapS.Add(exs.Current())) {
1109 Standard_Integer index = M.FindIndex(exs.Current());
1110 if (index == 0) index = M.Add(exs.Current(),empty);
1111 M(index).Append(anc);
1117 // visit shapes not under ancestors
1118 TopExp_Explorer ex (S,TS,TA);
1119 for (; ex.More(); ex.Next()) {
1120 Standard_Integer index = M.FindIndex(ex.Current());
1121 if (index == 0) index = M.Add(ex.Current(),empty);
1125 //=======================================================================
1126 //function : IsSimilarEdges
1128 //=======================================================================
1129 Standard_Boolean GEOMImpl_Block6Explorer::IsSimilarEdges (const TopoDS_Shape& E1,
1130 const TopoDS_Shape& E2)
1132 TopoDS_Edge E1e = TopoDS::Edge(E1);
1133 TopoDS_Edge E2e = TopoDS::Edge(E2);
1134 TopoDS_Vertex V11, V12, V21, V22;
1135 TopExp::Vertices(E1e, V11, V12, Standard_True);
1136 TopExp::Vertices(E2e, V21, V22, Standard_True);
1137 if (BRepTools::Compare(V11, V21) && BRepTools::Compare(V12, V22))
1138 return Standard_True;
1139 if (BRepTools::Compare(V11, V22) && BRepTools::Compare(V12, V21))
1140 return Standard_True;
1142 return Standard_False;
1145 //=======================================================================
1146 //function : FindEdge
1148 //=======================================================================
1149 Standard_Integer GEOMImpl_Block6Explorer::FindEdge
1150 (TopoDS_Shape& theResult,
1151 const TopoDS_Shape& V1,
1152 const TopoDS_Shape& V2,
1153 const TopTools_IndexedDataMapOfShapeListOfShape& MVE,
1154 const Standard_Boolean findAll)
1156 Standard_Integer isFound = 0;
1158 const TopTools_ListOfShape& anEdgesOfV1 = MVE.FindFromKey(V1);
1159 const TopTools_ListOfShape& anEdgesOfV2 = MVE.FindFromKey(V2);
1161 TopTools_ListIteratorOfListOfShape it1 (anEdgesOfV1);
1162 for (; it1.More(); it1.Next()) {
1163 TopTools_ListIteratorOfListOfShape it2 (anEdgesOfV2);
1164 for (; it2.More(); it2.Next()) {
1165 if (it1.Value().IsSame(it2.Value())) {
1167 theResult = it1.Value();
1168 if (!findAll) return isFound;
1176 //=======================================================================
1177 //function : FindFace
1179 //=======================================================================
1180 Standard_Integer GEOMImpl_Block6Explorer::FindFace
1181 (TopoDS_Shape& theResult,
1182 const TopoDS_Shape& V1,
1183 const TopoDS_Shape& V2,
1184 const TopoDS_Shape& V3,
1185 const TopoDS_Shape& V4,
1186 const TopTools_IndexedDataMapOfShapeListOfShape& MVF,
1187 const Standard_Boolean findAll)
1189 Standard_Integer isFound = Standard_False;
1191 const TopTools_ListOfShape& aFacesOfV1 = MVF.FindFromKey(V1);
1192 const TopTools_ListOfShape& aFacesOfV2 = MVF.FindFromKey(V2);
1193 const TopTools_ListOfShape& aFacesOfV3 = MVF.FindFromKey(V3);
1194 const TopTools_ListOfShape& aFacesOfV4 = MVF.FindFromKey(V4);
1196 TopTools_ListIteratorOfListOfShape it1 (aFacesOfV1);
1197 for (; it1.More(); it1.Next()) {
1198 TopTools_ListIteratorOfListOfShape it2 (aFacesOfV2);
1199 for (; it2.More(); it2.Next()) {
1200 if (it1.Value().IsSame(it2.Value())) {
1201 TopTools_ListIteratorOfListOfShape it3 (aFacesOfV3);
1202 for (; it3.More(); it3.Next()) {
1203 if (it1.Value().IsSame(it3.Value())) {
1204 TopTools_ListIteratorOfListOfShape it4 (aFacesOfV4);
1205 for (; it4.More(); it4.Next()) {
1206 if (it1.Value().IsSame(it4.Value())) {
1208 theResult = it1.Value();
1209 if (!findAll) return isFound;
1221 //=======================================================================
1222 //function : MakeFace
1224 //=======================================================================
1225 TCollection_AsciiString GEOMImpl_Block6Explorer::MakeFace (const TopoDS_Wire& theWire,
1226 const Standard_Boolean isPlanarWanted,
1227 TopoDS_Shape& theResult)
1229 if (!isPlanarWanted)
1230 return MakeAnyFace(theWire, theResult);
1232 // Try to build a planar face.
1234 // If required tolerance increase will be
1235 // higher than PLANAR_FACE_MAX_TOLERANCE,
1236 // we will try to build a non-planar face.
1238 TCollection_AsciiString aWarning;
1239 BRepBuilderAPI_MakeFace MK (theWire, isPlanarWanted);
1241 theResult = MK.Shape();
1245 // try to update wire tolerances to build a planar face
1248 Standard_Real aToleranceReached, aTol;
1249 BRepLib_FindSurface aFS;
1250 aFS.Init(theWire, -1., isPlanarWanted);
1251 aToleranceReached = aFS.ToleranceReached();
1252 aTol = aFS.Tolerance();
1255 aFS.Init(theWire, aToleranceReached, isPlanarWanted);
1256 if (!aFS.Found()) return aWarning;
1257 aToleranceReached = aFS.ToleranceReached();
1258 aTol = aFS.Tolerance();
1260 aTol = Max(1.2 * aToleranceReached, aTol);
1262 // Mantis issue 0021432: EDF GEOM: Faces with huge tolerance can be built in GEOM
1263 if (aTol > PLANAR_FACE_MAX_TOLERANCE) {
1264 aWarning = MakeAnyFace(theWire, theResult);
1265 if (aWarning.IsEmpty() && !theResult.IsNull())
1266 aWarning = "MAKE_FACE_TOLERANCE_TOO_BIG";
1270 // Copy the wire, bacause it can be updated with very-very big tolerance here
1271 BRepBuilderAPI_Copy aMC (theWire);
1272 if (!aMC.IsDone()) return aWarning;
1273 TopoDS_Wire aWire = TopoDS::Wire(aMC.Shape());
1274 // Update tolerances to <aTol>
1276 for (TopExp_Explorer expE (aWire, TopAbs_EDGE); expE.More(); expE.Next()) {
1277 TopoDS_Edge anE = TopoDS::Edge(expE.Current());
1278 B.UpdateEdge(anE, aTol);
1280 for (TopExp_Explorer expV (aWire, TopAbs_VERTEX); expV.More(); expV.Next()) {
1281 TopoDS_Vertex aV = TopoDS::Vertex(expV.Current());
1282 B.UpdateVertex(aV, aTol);
1284 //BRepLib::UpdateTolerances(aWire);
1286 BRepBuilderAPI_MakeFace MK1 (aWire, isPlanarWanted);
1288 theResult = MK1.Shape();
1289 // Mantis issue 0021432: EDF GEOM: Faces with huge tolerance can be built in GEOM
1290 //if (aTol > PLANAR_FACE_MAX_TOLERANCE)
1291 // aWarning = "MAKE_FACE_TOLERANCE_TOO_BIG";
1297 //=======================================================================
1298 //function : MakeAnyFace
1300 //=======================================================================
1301 TCollection_AsciiString GEOMImpl_Block6Explorer::MakeAnyFace (const TopoDS_Wire& theWire,
1302 TopoDS_Shape& theResult)
1304 TCollection_AsciiString aWarning;
1306 // try to build a face on any surface under the edges of the wire
1307 BRepBuilderAPI_MakeFace MK (theWire, Standard_False);
1309 theResult = MK.Shape();
1313 // try to construct filling surface
1314 BRepOffsetAPI_MakeFilling MF;
1316 Standard_Integer nbEdges = 0;
1317 BRepTools_WireExplorer aWE (theWire);
1318 for (; aWE.More(); aWE.Next(), nbEdges++) {
1319 MF.Add(TopoDS::Edge(aWE.Current()), GeomAbs_C0);
1324 aWarning = "BRepOffsetAPI_MakeFilling failed";
1328 // Result of filling
1329 TopoDS_Shape aFace = MF.Shape();
1331 // 12.04.2006 for PAL12149 begin
1332 Handle(Geom_Surface) aGS = BRep_Tool::Surface(TopoDS::Face(aFace));
1334 #ifdef MAKE_FACE_UPGRADE_PCURVES
1336 TopoDS_Iterator itw(theWire);
1337 for (; itw.More(); itw.Next())
1339 const TopoDS_Edge& anEdge = TopoDS::Edge(itw.Value());
1340 TopoDS_Edge NewEdge = TopoDS::Edge(MF.Generated(anEdge).First());
1341 Standard_Real fpar, lpar;
1342 Handle(Geom2d_Curve) NewPCurve = BRep_Tool::CurveOnSurface(NewEdge, TopoDS::Face(aFace), fpar, lpar);
1343 TopLoc_Location aLoc;
1344 Standard_Real NewTol = BRep_Tool::Tolerance(NewEdge);
1345 BB.UpdateEdge(anEdge, NewPCurve, aGS, aLoc, NewTol);
1349 BRepBuilderAPI_MakeFace MK1 (aGS, theWire);
1351 TopoDS_Shape aFace1 = MK1.Shape();
1353 BRepCheck_Analyzer ana (aFace1, false);
1354 if (!ana.IsValid()) {
1355 TopoDS_Shape aFace2;
1356 ShHealOper_ShapeProcess aHealer;
1357 aHealer.Perform(aFace1, aFace2);
1358 if (aHealer.isDone())
1362 // 12.04.2006 for PAL12149 end
1364 if (!theResult.IsNull()) {
1365 // try to deal with result of BRepBuilderAPI_MakeFace + ShHealOper_ShapeProcess
1366 #if OCC_VERSION_LARGE >= 0x06080000
1367 #ifdef MAKE_FACE_PCURVES_FIX_TOLERANCE
1368 // check and fix pcurves, if necessary
1369 Standard_Real aT, aTolE, aD, aDMax;
1370 TopExp_Explorer aExpF, aExpE;
1371 NCollection_DataMap<TopoDS_Shape, Standard_Real, TopTools_ShapeMapHasher> aDMETol;
1372 aExpF.Init(theResult, TopAbs_FACE);
1373 for (; aExpF.More(); aExpF.Next()) {
1374 const TopoDS_Face& aF = *(TopoDS_Face*)&aExpF.Current();
1375 aExpE.Init(aF, TopAbs_EDGE);
1376 for (; aExpE.More(); aExpE.Next()) {
1377 const TopoDS_Edge& aE = *(TopoDS_Edge*)&aExpE.Current();
1378 if (!BOPTools_AlgoTools::ComputeTolerance(aF, aE, aDMax, aT)) continue;
1379 aTolE = BRep_Tool::Tolerance(aE);
1380 if (aDMax < aTolE) continue;
1381 if (aDMETol.IsBound(aE)) {
1382 aD = aDMETol.Find(aE);
1385 aDMETol.Bind(aE, aDMax);
1389 aDMETol.Bind(aE, aDMax);
1393 NCollection_DataMap<TopoDS_Shape, Standard_Real, TopTools_ShapeMapHasher>::Iterator aDMETolIt(aDMETol);
1394 ShapeFix_ShapeTolerance sat;
1395 for (; aDMETolIt.More(); aDMETolIt.Next()) {
1396 sat.LimitTolerance(aDMETolIt.Key(), aDMETolIt.Value());
1402 // try to deal with pure result of BRepOffsetAPI_MakeFilling
1405 Standard_Real aTol = MF.G0Error();
1407 TColgp_Array1OfPnt aPnts (1,nbEdges); // points of the given wire
1408 BRepTools_WireExplorer aWE1 (theWire);
1409 Standard_Integer vi = 1;
1410 for (; aWE1.More() && vi <= nbEdges; aWE1.Next(), vi++) {
1411 aPnts(vi) = BRep_Tool::Pnt(TopoDS::Vertex(aWE1.CurrentVertex()));
1414 // Find maximum deviation in vertices
1415 TopExp_Explorer exp (aFace, TopAbs_VERTEX);
1416 TopTools_MapOfShape mapShape;
1417 for (; exp.More(); exp.Next()) {
1418 if (mapShape.Add(exp.Current())) {
1419 TopoDS_Vertex aV = TopoDS::Vertex(exp.Current());
1420 Standard_Real aTolV = BRep_Tool::Tolerance(aV);
1421 gp_Pnt aP = BRep_Tool::Pnt(aV);
1422 Standard_Real min_dist = aP.Distance(aPnts(1));
1423 for (vi = 2; vi <= nbEdges; vi++) {
1424 min_dist = Min(min_dist, aP.Distance(aPnts(vi)));
1426 aTol = Max(aTol, aTolV);
1427 aTol = Max(aTol, min_dist);
1431 if ((*((Handle(BRep_TFace)*)&aFace.TShape()))->Tolerance() < aTol) {
1432 (*((Handle(BRep_TFace)*)&aFace.TShape()))->Tolerance(aTol);