1 #include <Standard_Stream.hxx>
3 #include <BRepOffsetAPI_MakeFilling.hxx>
5 #include <GEOMImpl_Block6Explorer.hxx>
9 #include <BRep_Tool.hxx>
10 #include <BRep_TFace.hxx>
11 #include <BRep_Builder.hxx>
12 #include <BRepLib.hxx>
13 #include <BRepLib_FindSurface.hxx>
14 #include <BRepTools.hxx>
15 #include <BRepTools_WireExplorer.hxx>
16 #include <BRepOffsetAPI_ThruSections.hxx>
17 #include <BRepBuilderAPI_Copy.hxx>
18 #include <BRepBuilderAPI_MakeEdge.hxx>
19 #include <BRepBuilderAPI_MakeWire.hxx>
20 #include <BRepBuilderAPI_MakeFace.hxx>
21 #include <BRepBuilderAPI_Transform.hxx>
25 #include <TopoDS_Shape.hxx>
26 #include <TopoDS_Edge.hxx>
27 #include <TopoDS_Wire.hxx>
28 #include <TopoDS_Solid.hxx>
30 #include <TopExp_Explorer.hxx>
31 #include <TopTools_MapOfShape.hxx>
32 #include <TopTools_ListOfShape.hxx>
33 #include <TopTools_ListIteratorOfListOfShape.hxx>
34 #include <TopTools_IndexedMapOfShape.hxx>
35 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
37 #include <Geom_Curve.hxx>
38 #include <Geom_TrimmedCurve.hxx>
39 #include <GeomFill_Generator.hxx>
41 #include <Precision.hxx>
43 #include <TColgp_Array1OfPnt.hxx>
45 #include <StdFail_NotDone.hxx>
46 #include <Standard_NullObject.hxx>
47 #include <Standard_TypeMismatch.hxx>
48 #include <Standard_ConstructionError.hxx>
49 #include <Standard_NoSuchObject.hxx>
55 static Standard_Integer mod4 (Standard_Integer nb)
57 if (nb <= 0) return nb + 4;
58 if (nb > 4) return nb - 4;
62 static Standard_Integer edge_id (const Standard_Integer theFaceID,
63 const Standard_Integer theEdgeNB)
65 static Standard_Integer edge_ids[NBFACES][4] = {
66 { 1, 2, 3, 4 }, // face 1
67 { 5, 6, 7, 8 }, // face 2
68 { 9, 5, 10, 1 }, // face 3
69 { 12, 7, 11, 3 }, // face 4
70 { 4, 12, 8, 9 }, // face 5
71 { 2, 11, 6, 10 } }; // face 6
73 return edge_ids[theFaceID - 1][theEdgeNB - 1];
76 static Standard_Integer side_edge_id (const Standard_Integer theEdgeNB)
78 static Standard_Integer side_edge_ids[4] = {9, 10, 11, 12};
80 return side_edge_ids[theEdgeNB - 1];
83 static Standard_Integer vertex_id (const Standard_Integer theFaceID,
84 const Standard_Integer theVertexNB)
86 static Standard_Integer vertex_ids[NBFACES][4] = {
87 { 1, 2, 3, 4 }, // face 1
88 { 5, 6, 7, 8 }, // face 2
89 { 1, 5, 6, 2 }, // face 3
90 { 4, 8, 7, 3 }, // face 4
91 { 1, 4, 8, 5 }, // face 5
92 { 2, 3, 7, 6 } }; // face 6
94 return vertex_ids[theFaceID - 1][theVertexNB - 1];
97 static Standard_Integer vertex_id_edge (const Standard_Integer theEdgeID, // [1,12]
98 const Standard_Integer theVertexNB) // [1,2]
100 static Standard_Integer vertex_ids_edge[NBEDGES][2] = {
114 return vertex_ids_edge[theEdgeID - 1][theVertexNB - 1];
117 static Standard_Integer face_id_edges (const Standard_Integer theEdge1ID, // [1,12]
118 const Standard_Integer theEdge2ID) // [1,12]
120 static Standard_Integer face_ids_edges[NBEDGES][NBEDGES] = {
121 // 1 2 3 4 5 6 7 8 9 10 11 12
122 { 0, 1, 1, 1, 3, 0, 0, 0, 3, 3, 0, 0 }, // edge 1
123 { 1, 0, 1, 1, 0, 6, 0, 0, 0, 6, 6, 0 }, // edge 2
124 { 1, 1, 0, 1, 0, 0, 4, 0, 0, 0, 4, 4 }, // edge 3
125 { 1, 1, 1, 0, 0, 0, 0, 5, 5, 0, 0, 5 }, // edge 4
126 { 3, 0, 0, 0, 0, 2, 2, 2, 3, 3, 0, 0 }, // edge 5
127 { 0, 6, 0, 0, 2, 0, 2, 2, 0, 6, 6, 0 }, // edge 6
128 { 0, 0, 4, 0, 2, 2, 0, 2, 0, 0, 4, 4 }, // edge 7
129 { 0, 0, 0, 5, 2, 2, 2, 0, 5, 0, 0, 5 }, // edge 8
130 { 3, 0, 0, 5, 3, 0, 0, 5, 0, 3, 0, 5 }, // edge 9
131 { 3, 6, 0, 0, 3, 6, 0, 0, 3, 0, 6, 0 }, // edge 10
132 { 0, 6, 4, 0, 0, 6, 4, 0, 0, 6, 0, 4 }, // edge 11
133 { 0, 0, 4, 5, 0, 0, 4, 5, 5, 0, 4, 0 } }; // edge 12
135 return face_ids_edges[theEdge1ID - 1][theEdge2ID - 1];
138 static Standard_Integer edge_id_vertices (const Standard_Integer theVertex1ID, // [1,8]
139 const Standard_Integer theVertex2ID) // [1,8]
141 static Standard_Integer edge_ids_vertices[NBVERTS][NBVERTS] = {
143 { 0, 1, 0, 4, 9, 0, 0, 0}, // vertex 1
144 { 1, 0, 2, 0, 0, 10, 0, 0}, // vertex 2
145 { 0, 2, 0, 3, 0, 0, 11, 0}, // vertex 3
146 { 4, 0, 3, 0, 0, 0, 0, 12}, // vertex 4
147 { 9, 0, 0, 0, 0, 5, 0, 8}, // vertex 5
148 { 0, 10, 0, 0, 5, 0, 6, 0}, // vertex 6
149 { 0, 0, 11, 0, 0, 6, 0, 7}, // vertex 7
150 { 0, 0, 0, 12, 8, 0, 7, 0} }; // vertex 8
152 return edge_ids_vertices[theVertex1ID - 1][theVertex2ID - 1];
155 static Standard_Integer edge_id_faces (const Standard_Integer theFace1ID, // [1,6]
156 const Standard_Integer theFace2ID) // [1,6]
158 static Standard_Integer edge_ids_faces[NBFACES][NBFACES] = {
160 { 0, 0, 1, 3, 4, 2 }, // face 1
161 { 0, 0, 5, 7, 8, 6 }, // face 2
162 { 1, 5, 0, 0, 9, 10 }, // face 3
163 { 3, 7, 0, 0, 12, 11 }, // face 4
164 { 4, 8, 9, 12, 0, 0 }, // face 5
165 { 2, 6, 10, 11, 0, 0 } }; // face 6
167 return edge_ids_faces[theFace1ID - 1][theFace2ID - 1];
170 //=======================================================================
171 //function : GEOMImpl_Block6Explorer
172 //purpose : Constructor
173 //=======================================================================
174 GEOMImpl_Block6Explorer::GEOMImpl_Block6Explorer ()
175 : myFaces(1,NBFACES), myEdges(1,NBEDGES), myVertices(1,NBVERTS)
179 //=======================================================================
180 //function : GetVertex
182 //=======================================================================
183 TopoDS_Shape GEOMImpl_Block6Explorer::GetVertex (const Standard_Integer theVertexID)
185 TopoDS_Shape aNullShape;
186 if (theVertexID < 1 || theVertexID > NBVERTS) return aNullShape;
187 return myVertices(theVertexID);
190 //=======================================================================
191 //function : GetVertexID
193 //=======================================================================
194 Standard_Integer GEOMImpl_Block6Explorer::GetVertexID (const TopoDS_Shape& theVertex)
196 for (Standard_Integer id = 1; id <= NBVERTS; id++) {
197 if (theVertex.IsSame(myVertices(id))) return id;
199 Standard_NoSuchObject::Raise("The Vertex does not belong to the Block");
203 //=======================================================================
204 //function : GetVertexID
206 //=======================================================================
207 Standard_Integer GEOMImpl_Block6Explorer::GetVertexID (const Standard_Integer theFaceID,
208 const Standard_Integer theVertexNB)
210 return vertex_id(theFaceID, theVertexNB);
213 //=======================================================================
214 //function : GetVertexOnEdgeID
216 //=======================================================================
217 Standard_Integer GEOMImpl_Block6Explorer::GetVertexOnEdgeID
218 (const Standard_Integer theEdgeID,
219 const Standard_Integer theVertexNB)
221 return vertex_id_edge(theEdgeID, theVertexNB);
224 //=======================================================================
227 //=======================================================================
228 TopoDS_Shape GEOMImpl_Block6Explorer::GetEdge (const Standard_Integer theEdgeID,
229 const Standard_Boolean doMake)
231 TopoDS_Shape aNullShape;
232 if (theEdgeID < 1 || theEdgeID > NBEDGES) return aNullShape;
233 if (myEdges(theEdgeID).IsNull() && doMake) {
234 // Create the required edge as a linear segment between
235 // corresponding vertices and put it in the Block's edges
236 BRepBuilderAPI_MakeEdge ME (TopoDS::Vertex(myVertices(vertex_id_edge(theEdgeID, 1))),
237 TopoDS::Vertex(myVertices(vertex_id_edge(theEdgeID, 2))));
239 Standard_ConstructionError::Raise("Edge construction failed");
241 myEdges(theEdgeID) = ME.Shape();
244 return myEdges(theEdgeID);
247 //=======================================================================
248 //function : GetEdgeID
250 //=======================================================================
251 Standard_Integer GEOMImpl_Block6Explorer::GetEdgeID (const TopoDS_Shape& theEdge)
253 for (Standard_Integer id = 1; id <= NBEDGES; id++) {
254 if (theEdge.IsSame(myEdges(id))) return id;
256 Standard_NoSuchObject::Raise("The Edge does not belong to the Block");
260 //=======================================================================
261 //function : GetEdgeID
263 //=======================================================================
264 Standard_Integer GEOMImpl_Block6Explorer::GetEdgeID (const Standard_Integer theFaceID,
265 const Standard_Integer theEdgeNB)
267 return edge_id(theFaceID, theEdgeNB);
270 //=======================================================================
271 //function : FindEdgeID
273 //=======================================================================
274 Standard_Integer GEOMImpl_Block6Explorer::FindEdgeID (const Standard_Integer theVertex1ID,
275 const Standard_Integer theVertex2ID)
277 return edge_id_vertices(theVertex1ID, theVertex2ID);
280 //=======================================================================
281 //function : FindCommonEdgeID
283 //=======================================================================
284 Standard_Integer GEOMImpl_Block6Explorer::FindCommonEdgeID
285 (const Standard_Integer theFace1ID,
286 const Standard_Integer theFace2ID)
288 return edge_id_faces(theFace1ID, theFace2ID);
291 //=======================================================================
294 //=======================================================================
295 TopoDS_Shape GEOMImpl_Block6Explorer::GetFace (const Standard_Integer theFaceID,
296 const Standard_Boolean doMake)
298 TopoDS_Shape aNullShape;
299 if (theFaceID < 1 || theFaceID > NBFACES) return aNullShape;
301 if (myFaces(theFaceID).IsNull() && doMake) {
303 // Create the required face between
304 // corresponding edges and put it in the Block's faces
306 TopoDS_Shape E1 = GetEdge(edge_id(theFaceID, 1), doMake);
307 TopoDS_Shape E2 = GetEdge(edge_id(theFaceID, 2), doMake);
308 TopoDS_Shape E3 = GetEdge(edge_id(theFaceID, 3), doMake);
309 TopoDS_Shape E4 = GetEdge(edge_id(theFaceID, 4), doMake);
311 BRepBuilderAPI_MakeWire MW (TopoDS::Edge(E1),
316 Standard_ConstructionError::Raise("Wire construction failed");
319 MakeFace(MW, Standard_False, aFace);
320 if (aFace.IsNull()) {
321 Standard_ConstructionError::Raise("Face construction failed");
323 myFaces(theFaceID) = aFace;
326 return myFaces(theFaceID);
329 //=======================================================================
330 //function : GetFaceID
332 //=======================================================================
333 Standard_Integer GEOMImpl_Block6Explorer::GetFaceID (const TopoDS_Shape& theFace)
335 for (Standard_Integer id = 1; id <= NBFACES; id++) {
336 if (theFace.IsSame(myFaces(id))) return id;
338 Standard_NoSuchObject::Raise("The Face does not belong to the Block");
342 //=======================================================================
343 //function : FindFaceID
345 //=======================================================================
346 Standard_Integer GEOMImpl_Block6Explorer::FindFaceID (const Standard_Integer theEdge1ID,
347 const Standard_Integer theEdge2ID)
349 return face_id_edges(theEdge1ID, theEdge2ID);
352 //=======================================================================
353 //function : GetOppositeFaceID
355 //=======================================================================
356 Standard_Integer GEOMImpl_Block6Explorer::GetOppositeFaceID (const Standard_Integer theFaceID)
358 Standard_Integer opp_face_id[NBFACES + 1] = {
367 return opp_face_id[theFaceID];
370 //=======================================================================
371 //function : IsSimilarFaces
373 //=======================================================================
374 Standard_Boolean GEOMImpl_Block6Explorer::IsSimilarFaces (const Standard_Integer theFace1ID,
375 const Standard_Integer theFace2ID,
376 const gp_Trsf theTransformation)
378 Standard_Integer common_edge_id = FindCommonEdgeID(theFace1ID, theFace2ID);
380 if (common_edge_id == 0) { // opposite faces
381 for (Standard_Integer id = 1; id <= 4; id++) {
382 TopoDS_Shape E1 = GetEdge(edge_id(theFace1ID, id));
383 TopoDS_Shape E2 = GetEdge(edge_id(theFace2ID, id));
385 BRepBuilderAPI_Transform aTrsf (E1, theTransformation, Standard_False);
386 if (!IsSimilarEdges(aTrsf.Shape(), E2))
387 return Standard_False;
389 } else { // the faces have common edge
390 TopTools_Array1OfShape aVerts1 (1,4);
391 TopTools_Array1OfShape aVerts2 (1,4);
393 Standard_Integer common_vertex1 = GetVertexOnEdgeID(common_edge_id, 1);
394 Standard_Integer common_vertex2 = GetVertexOnEdgeID(common_edge_id, 2);
395 aVerts1(1) = myVertices(common_vertex1);
396 aVerts1(2) = myVertices(common_vertex2);
397 aVerts2(1) = myVertices(common_vertex1);
398 aVerts2(2) = myVertices(common_vertex2);
400 Standard_Integer not_common_v11 = 0, not_common_v12 = 0;
401 Standard_Integer vnb, vid;
402 for (vnb = 1; vnb <= 4; vnb++) {
403 vid = GetVertexID(theFace1ID, vnb);
404 if (vid != common_vertex1 && FindEdgeID(vid, common_vertex1) == 0) {
405 not_common_v12 = vid;
407 if (vid != common_vertex2 && FindEdgeID(vid, common_vertex2) == 0) {
408 not_common_v11 = vid;
413 Standard_Integer not_common_v21 = 0, not_common_v22 = 0;
414 for (vnb = 1; vnb <= 4; vnb++) {
415 vid = GetVertexID(theFace2ID, vnb);
416 if (vid != common_vertex1 && FindEdgeID(vid, common_vertex1) == 0) {
417 not_common_v22 = vid;
419 if (vid != common_vertex2 && FindEdgeID(vid, common_vertex2) == 0) {
420 not_common_v21 = vid;
424 aVerts1(3) = myVertices(not_common_v11);
425 aVerts1(4) = myVertices(not_common_v12);
426 aVerts2(3) = myVertices(not_common_v21);
427 aVerts2(4) = myVertices(not_common_v22);
429 for (Standard_Integer id = 1; id <= 4; id++) {
430 BRepBuilderAPI_Transform aTrsf (aVerts1(id), theTransformation, Standard_False);
431 TopoDS_Vertex V1 = TopoDS::Vertex(aTrsf.Shape());
432 TopoDS_Vertex V2 = TopoDS::Vertex(aVerts2(id));
433 if (!BRepTools::Compare(V1, V2)) {
434 return Standard_False;
439 return Standard_True;
442 //============ Initialization methods ===================================
444 //=======================================================================
445 //function : InitByBlock
447 //=======================================================================
448 void GEOMImpl_Block6Explorer::InitByBlock (const TopoDS_Shape& theBlock)
450 // 1. Find any one face of the block
451 TopExp_Explorer faces (theBlock, TopAbs_FACE);
453 Standard_ConstructionError::Raise("The block has no faces");
455 TopoDS_Shape aFirstFace = faces.Current();
457 // 2. Store all elements of the block relatively aFirstFace
458 InitByBlockAndFace(theBlock, aFirstFace);
461 //=======================================================================
462 //function : InitByBlockAndFace
464 //=======================================================================
465 void GEOMImpl_Block6Explorer::InitByBlockAndFace (const TopoDS_Shape& theBlock,
466 const TopoDS_Shape& theFace)
468 myFaces(1) = theFace;
470 // 2. Get wire of the first face
471 TopExp_Explorer wires (myFaces(1), TopAbs_WIRE);
473 Standard_ConstructionError::Raise("A face of the block has no wires");
475 TopoDS_Shape aWire = wires.Current();
478 Standard_ConstructionError::Raise("A face of the block has more than one wires");
481 // 3. Explore wire to init edges and vertices of the first face
482 BRepTools_WireExplorer aWE (TopoDS::Wire(aWire), TopoDS::Face(myFaces(1)));
483 Standard_Integer nb = 1;
484 for (; aWE.More(); aWE.Next(), nb++) {
486 Standard_ConstructionError::Raise("A face of the block has more than four edges");
488 myEdges(edge_id(1, nb)) = aWE.Current();
489 myVertices(vertex_id(1, nb)) = aWE.CurrentVertex();
492 Standard_ConstructionError::Raise("A face of the block has less than four edges");
495 // 2. Store all other elements of the block
496 InitByBlockAndVertices (theBlock,
497 myVertices(vertex_id(1,1)),
498 myVertices(vertex_id(1,2)),
499 myVertices(vertex_id(1,3)));
502 //=======================================================================
503 //function : InitByBlockAndEdges
505 //=======================================================================
506 void GEOMImpl_Block6Explorer::InitByBlockAndEdges (const TopoDS_Shape& theBlock,
507 const TopoDS_Shape& theEdge1,
508 const TopoDS_Shape& theEdge3)
510 // 1. Store vertices and edges of the first face
512 // 1.1. Store two given edges
513 myEdges(edge_id(1, 1)) = theEdge1;
514 myEdges(edge_id(1, 3)) = theEdge3;
516 // 1.2. Find and store the first face
517 TopTools_IndexedDataMapOfShapeListOfShape MEF;
518 MapShapesAndAncestors(theBlock, TopAbs_EDGE, TopAbs_FACE, MEF);
519 if (MEF.Extent() != NBEDGES) {
520 Standard_TypeMismatch::Raise("Block has wrong number of edges");
522 const TopTools_ListOfShape& aFacesOfE1 = MEF.FindFromKey(theEdge1);
523 const TopTools_ListOfShape& aFacesOfE3 = MEF.FindFromKey(theEdge3);
525 Standard_Boolean isFound = Standard_False;
526 TopTools_ListIteratorOfListOfShape anIterF1 (aFacesOfE1);
527 for (; anIterF1.More() && !isFound; anIterF1.Next()) {
529 TopTools_ListIteratorOfListOfShape anIterF3 (aFacesOfE3);
530 for (; anIterF3.More() && !isFound; anIterF3.Next()) {
532 if (anIterF1.Value().IsSame(anIterF3.Value())) {
533 isFound = Standard_True;
535 // Store the face, defined by two opposite edges
536 myFaces(1) = anIterF1.Value();
541 Standard_ConstructionError::Raise
542 ("Edges 1 and 2 do not belong to one face of the block");
545 // 1.3. Make vertices of the first edge the first and the
546 // second vertices of the first face. Order is free.
547 TopoDS_Edge E = TopoDS::Edge(theEdge1);
548 TopoDS_Vertex V1, V2;
549 TopExp::Vertices(E, V1, V2, Standard_True);
550 myVertices(vertex_id(1,1)) = V1;
551 myVertices(vertex_id(1,2)) = V2;
553 // Init maps vertex->list_of_edges for the face
554 TopTools_IndexedDataMapOfShapeListOfShape M1;
555 MapShapesAndAncestors(myFaces(1), TopAbs_VERTEX, TopAbs_EDGE, M1);
556 if (M1.Extent() != 4) {
557 Standard_TypeMismatch::Raise("The first face of block has wrong number of vertices");
560 // 1.4. Find and store others elements of the first face
562 // edges of the first vertex
563 TopoDS_Shape E1_f = M1.FindFromKey(V1).First();
564 TopoDS_Shape E1_l = M1.FindFromKey(V1).Last();
566 if (E1_f.IsSame(theEdge1)) {
567 myEdges(edge_id(1, 4)) = E1_l;
569 myEdges(edge_id(1, 4)) = E1_f;
573 TopoDS_Edge E4 = TopoDS::Edge(myEdges(edge_id(1, 4)));
574 TopoDS_Vertex V41, V42;
575 TopExp::Vertices(E4, V41, V42, Standard_True);
576 if (V41.IsSame(V1)) {
577 myVertices(vertex_id(1,4)) = V42;
579 myVertices(vertex_id(1,4)) = V41;
582 // edges of the second vertex
583 TopoDS_Shape E2_f = M1.FindFromKey(V2).First();
584 TopoDS_Shape E2_l = M1.FindFromKey(V2).Last();
586 if (E2_f.IsSame(theEdge1)) {
587 myEdges(edge_id(1, 2)) = E2_l;
589 myEdges(edge_id(1, 2)) = E2_f;
593 TopoDS_Edge E2 = TopoDS::Edge(myEdges(edge_id(1, 2)));
594 TopoDS_Vertex V21, V22;
595 TopExp::Vertices(E2, V21, V22, Standard_True);
596 if (V21.IsSame(V2)) {
597 myVertices(vertex_id(1,3)) = V22;
599 myVertices(vertex_id(1,3)) = V21;
602 // 2. Store all other elements of the block
603 InitByBlockAndVertices (theBlock,
604 myVertices(vertex_id(1,1)),
605 myVertices(vertex_id(1,2)),
606 myVertices(vertex_id(1,3)));
609 //=======================================================================
610 //function : InitByBlockAndVertices
612 //=======================================================================
613 void GEOMImpl_Block6Explorer::InitByBlockAndVertices (const TopoDS_Shape& theBlock,
614 const TopoDS_Shape& theVertex1,
615 const TopoDS_Shape& theVertex2,
616 const TopoDS_Shape& theVertex3)
618 // Here we suppose, that vertices are ordered, i.e. exists edge between
619 // theVertex1 and theVertex2 and edge between theVertex2 and theVertex3
621 // 1. Store vertices and edges of the first face.
622 // If the first face is initialized, it means, that this
623 // method is called from another initialization method, and all
624 // vertices and edges of the first face are also initialized
625 if (myFaces(1).IsNull()) {
627 // 1.1. Store first three vertices
628 myVertices(vertex_id(1, 1)) = theVertex1;
629 myVertices(vertex_id(1, 2)) = theVertex2;
630 myVertices(vertex_id(1, 3)) = theVertex3;
632 // 1.2. Find and store the first face
633 TopTools_IndexedDataMapOfShapeListOfShape MVF;
634 MapShapesAndAncestors(theBlock, TopAbs_VERTEX, TopAbs_FACE, MVF);
635 if (MVF.Extent() != NBVERTS) {
636 Standard_TypeMismatch::Raise("Block has wrong number of vertices");
638 const TopTools_ListOfShape& aFacesOfV1 = MVF.FindFromKey(theVertex1);
639 const TopTools_ListOfShape& aFacesOfV3 = MVF.FindFromKey(theVertex3);
641 Standard_Boolean isFound = Standard_False;
642 TopTools_ListIteratorOfListOfShape anIterF1 (aFacesOfV1);
643 for (; anIterF1.More() && !isFound; anIterF1.Next()) {
645 TopTools_ListIteratorOfListOfShape anIterF3 (aFacesOfV3);
646 for (; anIterF3.More() && !isFound; anIterF3.Next()) {
648 if (anIterF1.Value().IsSame(anIterF3.Value())) {
649 isFound = Standard_True;
651 // Store the face, defined by two opposite vertices
652 myFaces(1) = anIterF1.Value();
657 Standard_ConstructionError::Raise
658 ("Vertices 1 and 3 do not belong to one face of the block");
661 // Init maps vertex->list_of_edges for the face
662 TopTools_IndexedDataMapOfShapeListOfShape M1;
663 MapShapesAndAncestors(myFaces(1), TopAbs_VERTEX, TopAbs_EDGE, M1);
664 if (M1.Extent() != 4) {
665 Standard_TypeMismatch::Raise("The first face of block has wrong number of vertices");
668 // 1.3. Find and store edges and last vertex of the first face
669 const TopTools_ListOfShape& anEdgesOfV1 = M1.FindFromKey(theVertex1);
670 const TopTools_ListOfShape& anEdgesOfV2 = M1.FindFromKey(theVertex2);
671 const TopTools_ListOfShape& anEdgesOfV3 = M1.FindFromKey(theVertex3);
673 TopTools_ListIteratorOfListOfShape anIterE2 (anEdgesOfV2);
674 for (; anIterE2.More(); anIterE2.Next()) {
676 TopTools_ListIteratorOfListOfShape anIterE1 (anEdgesOfV1);
677 for (; anIterE1.More(); anIterE1.Next()) {
679 if (anIterE1.Value().IsSame(anIterE2.Value())) {
680 // Store the first edge, defined by two vertices
681 myEdges(edge_id(1,1)) = anIterE1.Value();
684 // Store the last edge
685 myEdges(edge_id(1,4)) = anIterE1.Value();
687 // Find and store the last vertex
688 TopoDS_Edge E = TopoDS::Edge(myEdges(4));
689 TopoDS_Vertex V1, V2;
690 TopExp::Vertices(E, V1, V2, Standard_True);
692 if (V1.IsSame(theVertex1)) {
693 myVertices(vertex_id(1,4)) = V2;
695 myVertices(vertex_id(1,4)) = V1;
700 TopTools_ListIteratorOfListOfShape anIterE3 (anEdgesOfV3);
701 for (; anIterE3.More(); anIterE3.Next()) {
703 if (anIterE3.Value().IsSame(anIterE2.Value())) {
704 // Store the second edge, defined by two vertices
705 myEdges(edge_id(1,2)) = anIterE3.Value();
708 // Store the fird edge
709 myEdges(edge_id(1,3)) = anIterE3.Value();
715 // Init map vertex->list_of_edges for the block
716 TopTools_IndexedDataMapOfShapeListOfShape MB;
717 MapShapesAndAncestors(theBlock, TopAbs_VERTEX, TopAbs_EDGE, MB);
718 if (MB.Extent() != NBVERTS) {
719 Standard_TypeMismatch::Raise("Block has wrong number of vertices");
722 // 2. Store edges, linking the first face with the second one
723 // and vertices of the second face
724 TopTools_IndexedMapOfShape aFaceEdges;
725 TopExp::MapShapes(myFaces(1), TopAbs_EDGE, aFaceEdges);
727 Standard_Integer i = 1;
728 for (; i <= 4; i++) {
729 // Get i-th vertex of the face 1
730 TopoDS_Shape Vi = myVertices(vertex_id(1, i));
731 if (!MB.Contains(Vi)) {
732 Standard_ConstructionError::Raise("Face does not belong to the block");
735 // Get list of block's edges, sharing this Vertex
736 const TopTools_ListOfShape& anEdgesOfVi = MB.FindFromKey(Vi);
737 TopTools_ListIteratorOfListOfShape anEdgesIter (anEdgesOfVi);
739 // Get Edge (from the List), not belonging to the face 1
740 Standard_Boolean isFound = Standard_False;
741 for (; anEdgesIter.More() && !isFound; anEdgesIter.Next()) {
742 if (!aFaceEdges.Contains(anEdgesIter.Value())) {
743 isFound = Standard_True;
745 // Store the linking edge
746 TopoDS_Shape aLinkEdge = anEdgesIter.Value();
747 myEdges(side_edge_id(i)) = aLinkEdge;
749 // Get another vertex of the linking edge
750 TopoDS_Edge E = TopoDS::Edge(aLinkEdge);
751 TopoDS_Vertex V1, V2;
752 TopExp::Vertices(E, V1, V2, Standard_True);
754 // Store the i-th vertex of the second (opposite to the first) face
756 myVertices(vertex_id(2, i)) = V2;
758 myVertices(vertex_id(2, i)) = V1;
764 // 3. Store edges of the second (opposite to the first) face
765 for (i = 1; i <= 4; i++) {
766 // Get i-th and (i+1)-th vertices of the face 2
767 TopoDS_Shape Vi = myVertices(vertex_id(2, i));
768 TopoDS_Shape Vj = myVertices(vertex_id(2, mod4(i + 1)));
770 // Get list of block's edges, sharing Vi
771 const TopTools_ListOfShape& anEdgesOfVi = MB.FindFromKey(Vi);
772 // Get list of block's edges, sharing Vj
773 const TopTools_ListOfShape& anEdgesOfVj = MB.FindFromKey(Vj);
775 // Get Edge (from the List), linking this vertex with the next one
776 Standard_Boolean isFound = Standard_False;
777 TopTools_ListIteratorOfListOfShape anEdgesIteri (anEdgesOfVi);
778 for (; anEdgesIteri.More() && !isFound; anEdgesIteri.Next()) {
780 TopTools_ListIteratorOfListOfShape anEdgesIterj (anEdgesOfVj);
781 for (; anEdgesIterj.More() && !isFound; anEdgesIterj.Next()) {
783 if (anEdgesIteri.Value().IsSame(anEdgesIterj.Value())) {
784 isFound = Standard_True;
786 // Store the linking edge
787 myEdges(edge_id(2, i)) = anEdgesIteri.Value();
793 // 4. Store faces of the block
794 TopTools_IndexedDataMapOfShapeListOfShape MBE;
795 MapShapesAndAncestors(theBlock, TopAbs_EDGE, TopAbs_FACE, MBE);
796 if (MBE.Extent() != NBEDGES) {
797 Standard_TypeMismatch::Raise("Block has wrong number of edges");
800 for (i = 2; i <= NBFACES; i++) {
801 TopoDS_Shape Ei1 = myEdges(edge_id(i, 1));
802 TopoDS_Shape Ei2 = myEdges(edge_id(i, 2));
803 const TopTools_ListOfShape& aFacesOfEi1 = MBE.FindFromKey(Ei1);
804 const TopTools_ListOfShape& aFacesOfEi2 = MBE.FindFromKey(Ei2);
806 Standard_Boolean isFound = Standard_False;
807 TopTools_ListIteratorOfListOfShape anIterEi1 (aFacesOfEi1);
808 for (; anIterEi1.More() && !isFound; anIterEi1.Next()) {
810 TopTools_ListIteratorOfListOfShape anIterEi2 (aFacesOfEi2);
811 for (; anIterEi2.More() && !isFound; anIterEi2.Next()) {
813 if (anIterEi1.Value().IsSame(anIterEi2.Value())) {
814 isFound = Standard_True;
816 // Store the face, defined by two edges
817 myFaces(i) = anIterEi1.Value();
824 //=======================================================================
825 //function : InitByTwoFaces
827 //=======================================================================
828 void GEOMImpl_Block6Explorer::InitByTwoFaces (const TopoDS_Shape& theFace1,
829 const TopoDS_Shape& theFace2)
831 if (theFace1.IsSame(theFace2)) {
832 Standard_ConstructionError::Raise("The faces must be different");
835 // Add two given faces in the structure
836 myFaces(1) = theFace1;
837 myFaces(2) = theFace2;
839 // Step 1. Order vertices (and edges)
841 // 1.1. Ordered vertices and edges of the first face we put in <myVertices>
843 // Get wire of the first face
844 TopExp_Explorer wires1 (myFaces(1), TopAbs_WIRE);
845 if (!wires1.More()) {
846 Standard_ConstructionError::Raise("A face for the block has no wires");
848 TopoDS_Shape aWire1 = wires1.Current();
851 Standard_ConstructionError::Raise("A face for the block has more than one wire");
854 BRepTools_WireExplorer aWE1 (TopoDS::Wire(aWire1), TopoDS::Face(myFaces(1)));
856 for (nb = 1; aWE1.More(); aWE1.Next(), nb++) {
858 Standard_ConstructionError::Raise("A face for the block has more than four edges");
860 myEdges(edge_id(1, nb)) = aWE1.Current();
861 myVertices(vertex_id(1, nb)) = aWE1.CurrentVertex();
864 Standard_ConstructionError::Raise("A face for the block has less than four edges");
867 // 1.2. Ordered vertices and edges of the second face we temporarily store
868 // in arrays, to find for them rigth location in <myVertices> on the Step 2.
871 TopTools_Array1OfShape aVertis2(1,4); // ordered vertices of the second face
872 TopTools_Array1OfShape anEdges2(1,4); // anEdges2(i) links aVertis2(i) and aVertis2(i+1)
874 // Get wire of the second face
875 TopExp_Explorer wires2 (myFaces(2), TopAbs_WIRE);
876 if (!wires2.More()) {
877 Standard_ConstructionError::Raise("A face for the block has no wires");
879 TopoDS_Shape aWire2 = wires2.Current();
882 Standard_ConstructionError::Raise("A face for the block has more than one wire");
885 BRepTools_WireExplorer aWE2 (TopoDS::Wire(aWire2), TopoDS::Face(myFaces(2)));
886 for (nb = 1; aWE2.More(); aWE2.Next(), nb++) {
888 Standard_ConstructionError::Raise("A face for the block has more than four edges");
890 anEdges2(nb) = aWE2.Current();
891 aVertis2(nb) = aWE2.CurrentVertex();
894 Standard_ConstructionError::Raise("A face for the block has less than four edges");
897 // Step 2. Find right place in <myVertices> for the <aVertis2>,
898 // so as to minimize common length of linking edges
899 // between face 1 and face 2.
900 // Each linking edge (of four) will link vertices of the
901 // faces 1 and 2 with equal local numbers.
902 // The right place is defined by:
903 // - vertex <aVertis2(i_min)>, which will become the first vertex
904 // of the second face <myVertices(vertex_id(2,1))>
905 // - orientation of <aVertis2> relatively their future location
906 // in <myVertices> (s_min = 1 if direct, s_min = -1 if reversed)
907 Standard_Integer i_min = 0, s_min = 0;
909 TColgp_Array1OfPnt aPnts1 (1,4); // points of the first face
910 aPnts1(1) = BRep_Tool::Pnt(TopoDS::Vertex(myVertices(vertex_id(1, 1))));
911 aPnts1(2) = BRep_Tool::Pnt(TopoDS::Vertex(myVertices(vertex_id(1, 2))));
912 aPnts1(3) = BRep_Tool::Pnt(TopoDS::Vertex(myVertices(vertex_id(1, 3))));
913 aPnts1(4) = BRep_Tool::Pnt(TopoDS::Vertex(myVertices(vertex_id(1, 4))));
915 TColgp_Array1OfPnt aPnts2 (1,4); // points of the second face
916 aPnts2(1) = BRep_Tool::Pnt(TopoDS::Vertex(aVertis2(1)));
917 aPnts2(2) = BRep_Tool::Pnt(TopoDS::Vertex(aVertis2(2)));
918 aPnts2(3) = BRep_Tool::Pnt(TopoDS::Vertex(aVertis2(3)));
919 aPnts2(4) = BRep_Tool::Pnt(TopoDS::Vertex(aVertis2(4)));
921 Standard_Real Dist_min = RealLast();
922 // try all possible locations to find the best (with minimum sum distance)
923 Standard_Integer i = 1;
924 for (; i <= 4; i++) {
925 // try direct orientation
926 Standard_Real Dist_plus = aPnts1(1).Distance(aPnts2(i)) +
927 aPnts1(2).Distance(aPnts2(mod4(i + 1))) +
928 aPnts1(3).Distance(aPnts2(mod4(i + 2))) +
929 aPnts1(4).Distance(aPnts2(mod4(i + 3)));
930 if (Dist_plus < Dist_min) {
931 Dist_min = Dist_plus;
936 // try reversed orientation
937 Standard_Real Dist_minus = aPnts1(1).Distance(aPnts2(i)) +
938 aPnts1(2).Distance(aPnts2(mod4(i - 1))) +
939 aPnts1(3).Distance(aPnts2(mod4(i - 2))) +
940 aPnts1(4).Distance(aPnts2(mod4(i - 3)));
941 if (Dist_minus < Dist_min) {
942 Dist_min = Dist_minus;
948 // 3. Put vertices and edges of the second face to they
949 // permanent location in <myVertices> and <myEdges>
950 for (i = 1; i <= 4; i++) {
951 Standard_Integer nb = mod4(i_min + s_min*(i - 1));
953 if (aPnts1(i).Distance(aPnts2(nb)) < Precision::Confusion()) {
954 Standard_ConstructionError::Raise("The faces are too close");
957 myVertices(vertex_id(2, i)) = aVertis2(nb);
959 if (s_min == -1) nb = mod4(nb - 1);
960 myEdges(edge_id(2, i)) = anEdges2(nb);
963 // 4. Generate side surface
964 if (!aWire1.Closed() || !aWire2.Closed()) {
965 // BRepOffsetAPI_ThruSections is not applicable on not closed wires
966 GetFace(3, Standard_True);
967 GetFace(4, Standard_True);
968 GetFace(5, Standard_True);
969 GetFace(6, Standard_True);
971 // try to build faces on native surfaces of edges or planar
972 Standard_Boolean tryThru = Standard_False;
973 for (Standard_Integer i = 3; i <= 6 && !tryThru; i++) {
974 Standard_Boolean doMake = Standard_True;
975 TopoDS_Shape E1 = GetEdge(edge_id(i, 1), doMake);
976 TopoDS_Shape E2 = GetEdge(edge_id(i, 2), doMake);
977 TopoDS_Shape E3 = GetEdge(edge_id(i, 3), doMake);
978 TopoDS_Shape E4 = GetEdge(edge_id(i, 4), doMake);
980 BRepBuilderAPI_MakeWire MW (TopoDS::Edge(E1),
985 Standard_ConstructionError::Raise("Wire construction failed");
988 BRepBuilderAPI_MakeFace MF (MW, Standard_False);
990 myFaces(i) = MF.Shape();
992 tryThru = Standard_True;
996 // Build side surface by ThruSections algorithm
998 BRepOffsetAPI_ThruSections THS;
999 THS.AddWire(TopoDS::Wire(aWire1));
1000 THS.AddWire(TopoDS::Wire(aWire2));
1002 if (!THS.IsDone()) {
1003 StdFail_NotDone::Raise("Side surface generation failed");
1005 for (Standard_Integer i = 1; i <= 4; i++) {
1007 myFaces(i+2) = THS.GeneratedFace(myEdges(i));
1010 Standard_Integer ee = side_edge_id(i);
1011 TopTools_IndexedDataMapOfShapeListOfShape MVE;
1012 MapShapesAndAncestors(myFaces(i+2), TopAbs_VERTEX, TopAbs_EDGE, MVE);
1013 FindEdge(myEdges(ee),
1014 myVertices(vertex_id_edge(ee, 1)),
1015 myVertices(vertex_id_edge(ee, 2)),
1022 //=======================================================================
1023 //function : MapShapesAndAncestors
1025 //=======================================================================
1026 void GEOMImpl_Block6Explorer::MapShapesAndAncestors (const TopoDS_Shape& S,
1027 const TopAbs_ShapeEnum TS,
1028 const TopAbs_ShapeEnum TA,
1029 TopTools_IndexedDataMapOfShapeListOfShape& M)
1031 TopTools_ListOfShape empty;
1032 TopTools_MapOfShape mapA;
1035 TopExp_Explorer exa (S,TA);
1036 for (; exa.More(); exa.Next()) {
1038 const TopoDS_Shape& anc = exa.Current();
1039 if (mapA.Add(anc)) {
1040 TopExp_Explorer exs (anc,TS);
1041 TopTools_MapOfShape mapS;
1042 for (; exs.More(); exs.Next()) {
1043 if (mapS.Add(exs.Current())) {
1044 Standard_Integer index = M.FindIndex(exs.Current());
1045 if (index == 0) index = M.Add(exs.Current(),empty);
1046 M(index).Append(anc);
1052 // visit shapes not under ancestors
1053 TopExp_Explorer ex (S,TS,TA);
1054 for (; ex.More(); ex.Next()) {
1055 Standard_Integer index = M.FindIndex(ex.Current());
1056 if (index == 0) index = M.Add(ex.Current(),empty);
1060 //=======================================================================
1061 //function : IsSimilarEdges
1063 //=======================================================================
1064 Standard_Boolean GEOMImpl_Block6Explorer::IsSimilarEdges (const TopoDS_Shape& E1,
1065 const TopoDS_Shape& E2)
1067 TopoDS_Edge E1e = TopoDS::Edge(E1);
1068 TopoDS_Edge E2e = TopoDS::Edge(E2);
1069 TopoDS_Vertex V11, V12, V21, V22;
1070 TopExp::Vertices(E1e, V11, V12, Standard_True);
1071 TopExp::Vertices(E2e, V21, V22, Standard_True);
1072 if (BRepTools::Compare(V11, V21) && BRepTools::Compare(V12, V22))
1073 return Standard_True;
1074 if (BRepTools::Compare(V11, V22) && BRepTools::Compare(V12, V21))
1075 return Standard_True;
1077 return Standard_False;
1080 //=======================================================================
1081 //function : FindEdge
1083 //=======================================================================
1084 Standard_Integer GEOMImpl_Block6Explorer::FindEdge
1085 (TopoDS_Shape& theResult,
1086 const TopoDS_Shape& V1,
1087 const TopoDS_Shape& V2,
1088 const TopTools_IndexedDataMapOfShapeListOfShape& MVE,
1089 const Standard_Boolean findAll)
1091 Standard_Integer isFound = 0;
1093 const TopTools_ListOfShape& anEdgesOfV1 = MVE.FindFromKey(V1);
1094 const TopTools_ListOfShape& anEdgesOfV2 = MVE.FindFromKey(V2);
1096 TopTools_ListIteratorOfListOfShape it1 (anEdgesOfV1);
1097 for (; it1.More(); it1.Next()) {
1098 TopTools_ListIteratorOfListOfShape it2 (anEdgesOfV2);
1099 for (; it2.More(); it2.Next()) {
1100 if (it1.Value().IsSame(it2.Value())) {
1102 theResult = it1.Value();
1103 if (!findAll) return isFound;
1111 //=======================================================================
1112 //function : FindFace
1114 //=======================================================================
1115 Standard_Integer GEOMImpl_Block6Explorer::FindFace
1116 (TopoDS_Shape& theResult,
1117 const TopoDS_Shape& V1,
1118 const TopoDS_Shape& V2,
1119 const TopoDS_Shape& V3,
1120 const TopoDS_Shape& V4,
1121 const TopTools_IndexedDataMapOfShapeListOfShape& MVF,
1122 const Standard_Boolean findAll)
1124 Standard_Integer isFound = Standard_False;
1126 const TopTools_ListOfShape& aFacesOfV1 = MVF.FindFromKey(V1);
1127 const TopTools_ListOfShape& aFacesOfV2 = MVF.FindFromKey(V2);
1128 const TopTools_ListOfShape& aFacesOfV3 = MVF.FindFromKey(V3);
1129 const TopTools_ListOfShape& aFacesOfV4 = MVF.FindFromKey(V4);
1131 TopTools_ListIteratorOfListOfShape it1 (aFacesOfV1);
1132 for (; it1.More(); it1.Next()) {
1133 TopTools_ListIteratorOfListOfShape it2 (aFacesOfV2);
1134 for (; it2.More(); it2.Next()) {
1135 if (it1.Value().IsSame(it2.Value())) {
1136 TopTools_ListIteratorOfListOfShape it3 (aFacesOfV3);
1137 for (; it3.More(); it3.Next()) {
1138 if (it1.Value().IsSame(it3.Value())) {
1139 TopTools_ListIteratorOfListOfShape it4 (aFacesOfV4);
1140 for (; it4.More(); it4.Next()) {
1141 if (it1.Value().IsSame(it4.Value())) {
1143 theResult = it1.Value();
1144 if (!findAll) return isFound;
1156 //=======================================================================
1157 //function : MakeFace
1159 //=======================================================================
1160 void GEOMImpl_Block6Explorer::MakeFace (const TopoDS_Wire& theWire,
1161 const Standard_Boolean isPlanarWanted,
1162 TopoDS_Shape& theResult)
1164 // try to build face on plane or on any surface under the edges of the wire
1165 BRepBuilderAPI_MakeFace MK (theWire, isPlanarWanted);
1167 theResult = MK.Shape();
1171 if (!isPlanarWanted) {
1172 // try to construct filling surface
1173 BRepOffsetAPI_MakeFilling MF;
1175 Standard_Integer nbEdges = 0;
1176 BRepTools_WireExplorer aWE (theWire);
1177 for (; aWE.More(); aWE.Next(), nbEdges++) {
1178 MF.Add(TopoDS::Edge(aWE.Current()), GeomAbs_C0);
1183 // Result of filling
1184 TopoDS_Shape aFace = MF.Shape();
1187 Standard_Real aTol = MF.G0Error();
1189 TColgp_Array1OfPnt aPnts (1,nbEdges); // points of the given wire
1190 BRepTools_WireExplorer aWE1 (theWire);
1191 Standard_Integer vi = 1;
1192 for (; aWE1.More() && vi <= nbEdges; aWE1.Next(), vi++) {
1193 aPnts(vi) = BRep_Tool::Pnt(TopoDS::Vertex(aWE1.CurrentVertex()));
1196 // Find maximum deviation in vertices
1197 TopExp_Explorer exp (aFace, TopAbs_VERTEX);
1198 TopTools_MapOfShape mapShape;
1199 for (; exp.More(); exp.Next()) {
1200 if (mapShape.Add(exp.Current())) {
1201 TopoDS_Vertex aV = TopoDS::Vertex(exp.Current());
1202 Standard_Real aTolV = BRep_Tool::Tolerance(aV);
1203 gp_Pnt aP = BRep_Tool::Pnt(aV);
1204 Standard_Real min_dist = aP.Distance(aPnts(1));
1205 for (vi = 2; vi <= nbEdges; vi++) {
1206 min_dist = Min(min_dist, aP.Distance(aPnts(vi)));
1208 aTol = Max(aTol, aTolV);
1209 aTol = Max(aTol, min_dist);
1213 if ((*((Handle(BRep_TFace)*)&aFace.TShape()))->Tolerance() < aTol) {
1214 (*((Handle(BRep_TFace)*)&aFace.TShape()))->Tolerance(aTol);
1219 // try to update wire tolerances to build a planar face
1221 // With OCCT6.0 or lower
1224 Standard_Real aToleranceReached, aTol;
1225 BRepLib_FindSurface aFS;
1226 aFS.Init(theWire, -1., isPlanarWanted);
1227 aToleranceReached = aFS.ToleranceReached();
1228 aTol = aFS.Tolerance();
1231 aFS.Init(theWire, aToleranceReached, isPlanarWanted);
1232 if (!aFS.Found()) return;
1233 aToleranceReached = aFS.ToleranceReached();
1234 aTol = aFS.Tolerance();
1236 aTol = Max(1.2 * aToleranceReached, aTol);
1238 // Copy the wire, bacause it can be updated with very-very big tolerance here
1239 BRepBuilderAPI_Copy aMC (theWire);
1240 if (!aMC.IsDone()) return;
1241 TopoDS_Wire aWire = TopoDS::Wire(aMC.Shape());
1242 // Update tolerances to <aTol>
1244 for (TopExp_Explorer expE (aWire, TopAbs_EDGE); expE.More(); expE.Next()) {
1245 TopoDS_Edge anE = TopoDS::Edge(expE.Current());
1246 B.UpdateEdge(anE, aTol);
1248 for (TopExp_Explorer expV (aWire, TopAbs_VERTEX); expV.More(); expV.Next()) {
1249 TopoDS_Vertex aV = TopoDS::Vertex(expV.Current());
1250 B.UpdateVertex(aV, aTol);
1252 //BRepLib::UpdateTolerances(aWire);
1254 BRepBuilderAPI_MakeFace MK1 (aWire, isPlanarWanted);
1256 theResult = MK1.Shape();
1260 // After migration on OCCT version higher than 6.0
1261 //BRepLib_MakeFace aBMF;
1262 //aBMF.Init(theWire, isPlanarWanted, Standard_True);
1263 //if (aBMF.Error() == BRepLib_FaceDone) {
1264 // theResult = aBMF.Shape();