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 <BRepTools.hxx>
12 #include <BRepTools_WireExplorer.hxx>
13 #include <BRepOffsetAPI_ThruSections.hxx>
14 #include <BRepBuilderAPI_MakeEdge.hxx>
15 #include <BRepBuilderAPI_MakeWire.hxx>
16 #include <BRepBuilderAPI_MakeFace.hxx>
17 #include <BRepBuilderAPI_Transform.hxx>
21 #include <TopoDS_Shape.hxx>
22 #include <TopoDS_Edge.hxx>
23 #include <TopoDS_Wire.hxx>
24 #include <TopoDS_Solid.hxx>
26 #include <TopExp_Explorer.hxx>
27 #include <TopTools_MapOfShape.hxx>
28 #include <TopTools_ListOfShape.hxx>
29 #include <TopTools_ListIteratorOfListOfShape.hxx>
30 #include <TopTools_IndexedMapOfShape.hxx>
31 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
33 #include <Geom_Curve.hxx>
34 #include <Geom_TrimmedCurve.hxx>
35 #include <GeomFill_Generator.hxx>
37 #include <Precision.hxx>
39 #include <TColgp_Array1OfPnt.hxx>
41 #include <StdFail_NotDone.hxx>
42 #include <Standard_NullObject.hxx>
43 #include <Standard_TypeMismatch.hxx>
44 #include <Standard_ConstructionError.hxx>
45 #include <Standard_NoSuchObject.hxx>
51 static Standard_Integer mod4 (Standard_Integer nb)
53 if (nb <= 0) return nb + 4;
54 if (nb > 4) return nb - 4;
58 static Standard_Integer edge_id (const Standard_Integer theFaceID,
59 const Standard_Integer theEdgeNB)
61 static Standard_Integer edge_ids[NBFACES][4] = {
62 { 1, 2, 3, 4 }, // face 1
63 { 5, 6, 7, 8 }, // face 2
64 { 9, 5, 10, 1 }, // face 3
65 { 12, 7, 11, 3 }, // face 4
66 { 4, 12, 8, 9 }, // face 5
67 { 2, 11, 6, 10 } }; // face 6
69 return edge_ids[theFaceID - 1][theEdgeNB - 1];
72 static Standard_Integer side_edge_id (const Standard_Integer theEdgeNB)
74 static Standard_Integer side_edge_ids[4] = {9, 10, 11, 12};
76 return side_edge_ids[theEdgeNB - 1];
79 static Standard_Integer vertex_id (const Standard_Integer theFaceID,
80 const Standard_Integer theVertexNB)
82 static Standard_Integer vertex_ids[NBFACES][4] = {
83 { 1, 2, 3, 4 }, // face 1
84 { 5, 6, 7, 8 }, // face 2
85 { 1, 5, 6, 2 }, // face 3
86 { 4, 8, 7, 3 }, // face 4
87 { 1, 4, 8, 5 }, // face 5
88 { 2, 3, 7, 6 } }; // face 6
90 return vertex_ids[theFaceID - 1][theVertexNB - 1];
93 static Standard_Integer vertex_id_edge (const Standard_Integer theEdgeID, // [1,12]
94 const Standard_Integer theVertexNB) // [1,2]
96 static Standard_Integer vertex_ids_edge[NBEDGES][2] = {
110 return vertex_ids_edge[theEdgeID - 1][theVertexNB - 1];
113 static Standard_Integer face_id_edges (const Standard_Integer theEdge1ID, // [1,12]
114 const Standard_Integer theEdge2ID) // [1,12]
116 static Standard_Integer face_ids_edges[NBEDGES][NBEDGES] = {
117 // 1 2 3 4 5 6 7 8 9 10 11 12
118 { 0, 1, 1, 1, 3, 0, 0, 0, 3, 3, 0, 0 }, // edge 1
119 { 1, 0, 1, 1, 0, 6, 0, 0, 0, 6, 6, 0 }, // edge 2
120 { 1, 1, 0, 1, 0, 0, 4, 0, 0, 0, 4, 4 }, // edge 3
121 { 1, 1, 1, 0, 0, 0, 0, 5, 5, 0, 0, 5 }, // edge 4
122 { 3, 0, 0, 0, 0, 2, 2, 2, 3, 3, 0, 0 }, // edge 5
123 { 0, 6, 0, 0, 2, 0, 2, 2, 0, 6, 6, 0 }, // edge 6
124 { 0, 0, 4, 0, 2, 2, 0, 2, 0, 0, 4, 4 }, // edge 7
125 { 0, 0, 0, 5, 2, 2, 2, 0, 5, 0, 0, 5 }, // edge 8
126 { 3, 0, 0, 5, 3, 0, 0, 5, 0, 3, 0, 5 }, // edge 9
127 { 3, 6, 0, 0, 3, 6, 0, 0, 3, 0, 6, 0 }, // edge 10
128 { 0, 6, 4, 0, 0, 6, 4, 0, 0, 6, 0, 4 }, // edge 11
129 { 0, 0, 4, 5, 0, 0, 4, 5, 5, 0, 4, 0 } }; // edge 12
131 return face_ids_edges[theEdge1ID - 1][theEdge2ID - 1];
134 static Standard_Integer edge_id_vertices (const Standard_Integer theVertex1ID, // [1,8]
135 const Standard_Integer theVertex2ID) // [1,8]
137 static Standard_Integer edge_ids_vertices[NBVERTS][NBVERTS] = {
139 { 0, 1, 0, 4, 9, 0, 0, 0}, // vertex 1
140 { 1, 0, 2, 0, 0, 10, 0, 0}, // vertex 2
141 { 0, 2, 0, 3, 0, 0, 11, 0}, // vertex 3
142 { 4, 0, 3, 0, 0, 0, 0, 12}, // vertex 4
143 { 9, 0, 0, 0, 0, 5, 0, 8}, // vertex 5
144 { 0, 10, 0, 0, 5, 0, 6, 0}, // vertex 6
145 { 0, 0, 11, 0, 0, 6, 0, 7}, // vertex 7
146 { 0, 0, 0, 12, 8, 0, 7, 0} }; // vertex 8
148 return edge_ids_vertices[theVertex1ID - 1][theVertex2ID - 1];
151 static Standard_Integer edge_id_faces (const Standard_Integer theFace1ID, // [1,6]
152 const Standard_Integer theFace2ID) // [1,6]
154 static Standard_Integer edge_ids_faces[NBFACES][NBFACES] = {
156 { 0, 0, 1, 3, 4, 2 }, // face 1
157 { 0, 0, 5, 7, 8, 6 }, // face 2
158 { 1, 5, 0, 0, 9, 10 }, // face 3
159 { 3, 7, 0, 0, 12, 11 }, // face 4
160 { 4, 8, 9, 12, 0, 0 }, // face 5
161 { 2, 6, 10, 11, 0, 0 } }; // face 6
163 return edge_ids_faces[theFace1ID - 1][theFace2ID - 1];
166 //=======================================================================
167 //function : GEOMImpl_Block6Explorer
168 //purpose : Constructor
169 //=======================================================================
170 GEOMImpl_Block6Explorer::GEOMImpl_Block6Explorer ()
171 : myFaces(1,NBFACES), myEdges(1,NBEDGES), myVertices(1,NBVERTS)
175 //=======================================================================
176 //function : GetVertex
178 //=======================================================================
179 TopoDS_Shape GEOMImpl_Block6Explorer::GetVertex (const Standard_Integer theVertexID)
181 TopoDS_Shape aNullShape;
182 if (theVertexID < 1 || theVertexID > NBVERTS) return aNullShape;
183 return myVertices(theVertexID);
186 //=======================================================================
187 //function : GetVertexID
189 //=======================================================================
190 Standard_Integer GEOMImpl_Block6Explorer::GetVertexID (const TopoDS_Shape& theVertex)
192 for (Standard_Integer id = 1; id <= NBVERTS; id++) {
193 if (theVertex.IsSame(myVertices(id))) return id;
195 Standard_NoSuchObject::Raise("The Vertex does not belong to the Block");
199 //=======================================================================
200 //function : GetVertexID
202 //=======================================================================
203 Standard_Integer GEOMImpl_Block6Explorer::GetVertexID (const Standard_Integer theFaceID,
204 const Standard_Integer theVertexNB)
206 return vertex_id(theFaceID, theVertexNB);
209 //=======================================================================
210 //function : GetVertexOnEdgeID
212 //=======================================================================
213 Standard_Integer GEOMImpl_Block6Explorer::GetVertexOnEdgeID
214 (const Standard_Integer theEdgeID,
215 const Standard_Integer theVertexNB)
217 return vertex_id_edge(theEdgeID, theVertexNB);
220 //=======================================================================
223 //=======================================================================
224 TopoDS_Shape GEOMImpl_Block6Explorer::GetEdge (const Standard_Integer theEdgeID,
225 const Standard_Boolean doMake)
227 TopoDS_Shape aNullShape;
228 if (theEdgeID < 1 || theEdgeID > NBEDGES) return aNullShape;
229 if (myEdges(theEdgeID).IsNull() && doMake) {
230 // Create the required edge as a linear segment between
231 // corresponding vertices and put it in the Block's edges
232 BRepBuilderAPI_MakeEdge ME (TopoDS::Vertex(myVertices(vertex_id_edge(theEdgeID, 1))),
233 TopoDS::Vertex(myVertices(vertex_id_edge(theEdgeID, 2))));
235 Standard_ConstructionError::Raise("Edge construction failed");
237 myEdges(theEdgeID) = ME.Shape();
240 return myEdges(theEdgeID);
243 //=======================================================================
244 //function : GetEdgeID
246 //=======================================================================
247 Standard_Integer GEOMImpl_Block6Explorer::GetEdgeID (const TopoDS_Shape& theEdge)
249 for (Standard_Integer id = 1; id <= NBEDGES; id++) {
250 if (theEdge.IsSame(myEdges(id))) return id;
252 Standard_NoSuchObject::Raise("The Edge does not belong to the Block");
256 //=======================================================================
257 //function : GetEdgeID
259 //=======================================================================
260 Standard_Integer GEOMImpl_Block6Explorer::GetEdgeID (const Standard_Integer theFaceID,
261 const Standard_Integer theEdgeNB)
263 return edge_id(theFaceID, theEdgeNB);
266 //=======================================================================
267 //function : FindEdgeID
269 //=======================================================================
270 Standard_Integer GEOMImpl_Block6Explorer::FindEdgeID (const Standard_Integer theVertex1ID,
271 const Standard_Integer theVertex2ID)
273 return edge_id_vertices(theVertex1ID, theVertex2ID);
276 //=======================================================================
277 //function : FindCommonEdgeID
279 //=======================================================================
280 Standard_Integer GEOMImpl_Block6Explorer::FindCommonEdgeID
281 (const Standard_Integer theFace1ID,
282 const Standard_Integer theFace2ID)
284 return edge_id_faces(theFace1ID, theFace2ID);
287 //=======================================================================
290 //=======================================================================
291 TopoDS_Shape GEOMImpl_Block6Explorer::GetFace (const Standard_Integer theFaceID,
292 const Standard_Boolean doMake)
294 TopoDS_Shape aNullShape;
295 if (theFaceID < 1 || theFaceID > NBFACES) return aNullShape;
297 if (myFaces(theFaceID).IsNull() && doMake) {
299 // Create the required face between
300 // corresponding edges and put it in the Block's faces
302 TopoDS_Shape E1 = GetEdge(edge_id(theFaceID, 1), doMake);
303 TopoDS_Shape E2 = GetEdge(edge_id(theFaceID, 2), doMake);
304 TopoDS_Shape E3 = GetEdge(edge_id(theFaceID, 3), doMake);
305 TopoDS_Shape E4 = GetEdge(edge_id(theFaceID, 4), doMake);
307 BRepBuilderAPI_MakeWire MW (TopoDS::Edge(E1),
312 Standard_ConstructionError::Raise("Wire construction failed");
315 MakeFace(MW, Standard_False, aFace);
316 if (aFace.IsNull()) {
317 Standard_ConstructionError::Raise("Face construction failed");
319 myFaces(theFaceID) = aFace;
322 return myFaces(theFaceID);
325 //=======================================================================
326 //function : GetFaceID
328 //=======================================================================
329 Standard_Integer GEOMImpl_Block6Explorer::GetFaceID (const TopoDS_Shape& theFace)
331 for (Standard_Integer id = 1; id <= NBFACES; id++) {
332 if (theFace.IsSame(myFaces(id))) return id;
334 Standard_NoSuchObject::Raise("The Face does not belong to the Block");
338 //=======================================================================
339 //function : FindFaceID
341 //=======================================================================
342 Standard_Integer GEOMImpl_Block6Explorer::FindFaceID (const Standard_Integer theEdge1ID,
343 const Standard_Integer theEdge2ID)
345 return face_id_edges(theEdge1ID, theEdge2ID);
348 //=======================================================================
349 //function : GetOppositeFaceID
351 //=======================================================================
352 Standard_Integer GEOMImpl_Block6Explorer::GetOppositeFaceID (const Standard_Integer theFaceID)
354 Standard_Integer opp_face_id[NBFACES + 1] = {
363 return opp_face_id[theFaceID];
366 //=======================================================================
367 //function : IsSimilarFaces
369 //=======================================================================
370 Standard_Boolean GEOMImpl_Block6Explorer::IsSimilarFaces (const Standard_Integer theFace1ID,
371 const Standard_Integer theFace2ID,
372 const gp_Trsf theTransformation)
374 Standard_Integer common_edge_id = FindCommonEdgeID(theFace1ID, theFace2ID);
376 if (common_edge_id == 0) { // opposite faces
377 for (Standard_Integer id = 1; id <= 4; id++) {
378 TopoDS_Shape E1 = GetEdge(edge_id(theFace1ID, id));
379 TopoDS_Shape E2 = GetEdge(edge_id(theFace2ID, id));
381 BRepBuilderAPI_Transform aTrsf (E1, theTransformation, Standard_False);
382 if (!IsSimilarEdges(aTrsf.Shape(), E2))
383 return Standard_False;
385 } else { // the faces have common edge
386 TopTools_Array1OfShape aVerts1 (1,4);
387 TopTools_Array1OfShape aVerts2 (1,4);
389 Standard_Integer common_vertex1 = GetVertexOnEdgeID(common_edge_id, 1);
390 Standard_Integer common_vertex2 = GetVertexOnEdgeID(common_edge_id, 2);
391 aVerts1(1) = myVertices(common_vertex1);
392 aVerts1(2) = myVertices(common_vertex2);
393 aVerts2(1) = myVertices(common_vertex1);
394 aVerts2(2) = myVertices(common_vertex2);
396 Standard_Integer not_common_v11 = 0, not_common_v12 = 0;
397 Standard_Integer vnb, vid;
398 for (vnb = 1; vnb <= 4; vnb++) {
399 vid = GetVertexID(theFace1ID, vnb);
400 if (vid != common_vertex1 && FindEdgeID(vid, common_vertex1) == 0) {
401 not_common_v12 = vid;
403 if (vid != common_vertex2 && FindEdgeID(vid, common_vertex2) == 0) {
404 not_common_v11 = vid;
409 Standard_Integer not_common_v21 = 0, not_common_v22 = 0;
410 for (vnb = 1; vnb <= 4; vnb++) {
411 vid = GetVertexID(theFace2ID, vnb);
412 if (vid != common_vertex1 && FindEdgeID(vid, common_vertex1) == 0) {
413 not_common_v22 = vid;
415 if (vid != common_vertex2 && FindEdgeID(vid, common_vertex2) == 0) {
416 not_common_v21 = vid;
420 aVerts1(3) = myVertices(not_common_v11);
421 aVerts1(4) = myVertices(not_common_v12);
422 aVerts2(3) = myVertices(not_common_v21);
423 aVerts2(4) = myVertices(not_common_v22);
425 for (Standard_Integer id = 1; id <= 4; id++) {
426 BRepBuilderAPI_Transform aTrsf (aVerts1(id), theTransformation, Standard_False);
427 TopoDS_Vertex V1 = TopoDS::Vertex(aTrsf.Shape());
428 TopoDS_Vertex V2 = TopoDS::Vertex(aVerts2(id));
429 if (!BRepTools::Compare(V1, V2)) {
430 return Standard_False;
435 return Standard_True;
438 //============ Initialization methods ===================================
440 //=======================================================================
441 //function : InitByBlock
443 //=======================================================================
444 void GEOMImpl_Block6Explorer::InitByBlock (const TopoDS_Shape& theBlock)
446 // 1. Find any one face of the block
447 TopExp_Explorer faces (theBlock, TopAbs_FACE);
449 Standard_ConstructionError::Raise("The block has no faces");
451 TopoDS_Shape aFirstFace = faces.Current();
453 // 2. Store all elements of the block relatively aFirstFace
454 InitByBlockAndFace(theBlock, aFirstFace);
457 //=======================================================================
458 //function : InitByBlockAndFace
460 //=======================================================================
461 void GEOMImpl_Block6Explorer::InitByBlockAndFace (const TopoDS_Shape& theBlock,
462 const TopoDS_Shape& theFace)
464 myFaces(1) = theFace;
466 // 2. Get wire of the first face
467 TopExp_Explorer wires (myFaces(1), TopAbs_WIRE);
469 Standard_ConstructionError::Raise("A face of the block has no wires");
471 TopoDS_Shape aWire = wires.Current();
474 Standard_ConstructionError::Raise("A face of the block has more than one wires");
477 // 3. Explore wire to init edges and vertices of the first face
478 BRepTools_WireExplorer aWE (TopoDS::Wire(aWire), TopoDS::Face(myFaces(1)));
479 Standard_Integer nb = 1;
480 for (; aWE.More(); aWE.Next(), nb++) {
482 Standard_ConstructionError::Raise("A face of the block has more than four edges");
484 myEdges(edge_id(1, nb)) = aWE.Current();
485 myVertices(vertex_id(1, nb)) = aWE.CurrentVertex();
488 Standard_ConstructionError::Raise("A face of the block has less than four edges");
491 // 2. Store all other elements of the block
492 InitByBlockAndVertices (theBlock,
493 myVertices(vertex_id(1,1)),
494 myVertices(vertex_id(1,2)),
495 myVertices(vertex_id(1,3)));
498 //=======================================================================
499 //function : InitByBlockAndEdges
501 //=======================================================================
502 void GEOMImpl_Block6Explorer::InitByBlockAndEdges (const TopoDS_Shape& theBlock,
503 const TopoDS_Shape& theEdge1,
504 const TopoDS_Shape& theEdge3)
506 // 1. Store vertices and edges of the first face
508 // 1.1. Store two given edges
509 myEdges(edge_id(1, 1)) = theEdge1;
510 myEdges(edge_id(1, 3)) = theEdge3;
512 // 1.2. Find and store the first face
513 TopTools_IndexedDataMapOfShapeListOfShape MEF;
514 MapShapesAndAncestors(theBlock, TopAbs_EDGE, TopAbs_FACE, MEF);
515 if (MEF.Extent() != NBEDGES) {
516 Standard_TypeMismatch::Raise("Block has wrong number of edges");
518 const TopTools_ListOfShape& aFacesOfE1 = MEF.FindFromKey(theEdge1);
519 const TopTools_ListOfShape& aFacesOfE3 = MEF.FindFromKey(theEdge3);
521 Standard_Boolean isFound = Standard_False;
522 TopTools_ListIteratorOfListOfShape anIterF1 (aFacesOfE1);
523 for (; anIterF1.More() && !isFound; anIterF1.Next()) {
525 TopTools_ListIteratorOfListOfShape anIterF3 (aFacesOfE3);
526 for (; anIterF3.More() && !isFound; anIterF3.Next()) {
528 if (anIterF1.Value().IsSame(anIterF3.Value())) {
529 isFound = Standard_True;
531 // Store the face, defined by two opposite edges
532 myFaces(1) = anIterF1.Value();
537 Standard_ConstructionError::Raise
538 ("Edges 1 and 2 do not belong to one face of the block");
541 // 1.3. Make vertices of the first edge the first and the
542 // second vertices of the first face. Order is free.
543 TopoDS_Edge E = TopoDS::Edge(theEdge1);
544 TopoDS_Vertex V1, V2;
545 TopExp::Vertices(E, V1, V2, Standard_True);
546 myVertices(vertex_id(1,1)) = V1;
547 myVertices(vertex_id(1,2)) = V2;
549 // Init maps vertex->list_of_edges for the face
550 TopTools_IndexedDataMapOfShapeListOfShape M1;
551 MapShapesAndAncestors(myFaces(1), TopAbs_VERTEX, TopAbs_EDGE, M1);
552 if (M1.Extent() != 4) {
553 Standard_TypeMismatch::Raise("The first face of block has wrong number of vertices");
556 // 1.4. Find and store others elements of the first face
558 // edges of the first vertex
559 TopoDS_Shape E1_f = M1.FindFromKey(V1).First();
560 TopoDS_Shape E1_l = M1.FindFromKey(V1).Last();
562 if (E1_f.IsSame(theEdge1)) {
563 myEdges(edge_id(1, 4)) = E1_l;
565 myEdges(edge_id(1, 4)) = E1_f;
569 TopoDS_Edge E4 = TopoDS::Edge(myEdges(edge_id(1, 4)));
570 TopoDS_Vertex V41, V42;
571 TopExp::Vertices(E4, V41, V42, Standard_True);
572 if (V41.IsSame(V1)) {
573 myVertices(vertex_id(1,4)) = V42;
575 myVertices(vertex_id(1,4)) = V41;
578 // edges of the second vertex
579 TopoDS_Shape E2_f = M1.FindFromKey(V2).First();
580 TopoDS_Shape E2_l = M1.FindFromKey(V2).Last();
582 if (E2_f.IsSame(theEdge1)) {
583 myEdges(edge_id(1, 2)) = E2_l;
585 myEdges(edge_id(1, 2)) = E2_f;
589 TopoDS_Edge E2 = TopoDS::Edge(myEdges(edge_id(1, 2)));
590 TopoDS_Vertex V21, V22;
591 TopExp::Vertices(E2, V21, V22, Standard_True);
592 if (V21.IsSame(V2)) {
593 myVertices(vertex_id(1,3)) = V22;
595 myVertices(vertex_id(1,3)) = V21;
598 // 2. Store all other elements of the block
599 InitByBlockAndVertices (theBlock,
600 myVertices(vertex_id(1,1)),
601 myVertices(vertex_id(1,2)),
602 myVertices(vertex_id(1,3)));
605 //=======================================================================
606 //function : InitByBlockAndVertices
608 //=======================================================================
609 void GEOMImpl_Block6Explorer::InitByBlockAndVertices (const TopoDS_Shape& theBlock,
610 const TopoDS_Shape& theVertex1,
611 const TopoDS_Shape& theVertex2,
612 const TopoDS_Shape& theVertex3)
614 // Here we suppose, that vertices are ordered, i.e. exists edge between
615 // theVertex1 and theVertex2 and edge between theVertex2 and theVertex3
617 // 1. Store vertices and edges of the first face.
618 // If the first face is initialized, it means, that this
619 // method is called from another initialization method, and all
620 // vertices and edges of the first face are also initialized
621 if (myFaces(1).IsNull()) {
623 // 1.1. Store first three vertices
624 myVertices(vertex_id(1, 1)) = theVertex1;
625 myVertices(vertex_id(1, 2)) = theVertex2;
626 myVertices(vertex_id(1, 3)) = theVertex3;
628 // 1.2. Find and store the first face
629 TopTools_IndexedDataMapOfShapeListOfShape MVF;
630 MapShapesAndAncestors(theBlock, TopAbs_VERTEX, TopAbs_FACE, MVF);
631 if (MVF.Extent() != NBVERTS) {
632 Standard_TypeMismatch::Raise("Block has wrong number of vertices");
634 const TopTools_ListOfShape& aFacesOfV1 = MVF.FindFromKey(theVertex1);
635 const TopTools_ListOfShape& aFacesOfV3 = MVF.FindFromKey(theVertex3);
637 Standard_Boolean isFound = Standard_False;
638 TopTools_ListIteratorOfListOfShape anIterF1 (aFacesOfV1);
639 for (; anIterF1.More() && !isFound; anIterF1.Next()) {
641 TopTools_ListIteratorOfListOfShape anIterF3 (aFacesOfV3);
642 for (; anIterF3.More() && !isFound; anIterF3.Next()) {
644 if (anIterF1.Value().IsSame(anIterF3.Value())) {
645 isFound = Standard_True;
647 // Store the face, defined by two opposite vertices
648 myFaces(1) = anIterF1.Value();
653 Standard_ConstructionError::Raise
654 ("Vertices 1 and 3 do not belong to one face of the block");
657 // Init maps vertex->list_of_edges for the face
658 TopTools_IndexedDataMapOfShapeListOfShape M1;
659 MapShapesAndAncestors(myFaces(1), TopAbs_VERTEX, TopAbs_EDGE, M1);
660 if (M1.Extent() != 4) {
661 Standard_TypeMismatch::Raise("The first face of block has wrong number of vertices");
664 // 1.3. Find and store edges and last vertex of the first face
665 const TopTools_ListOfShape& anEdgesOfV1 = M1.FindFromKey(theVertex1);
666 const TopTools_ListOfShape& anEdgesOfV2 = M1.FindFromKey(theVertex2);
667 const TopTools_ListOfShape& anEdgesOfV3 = M1.FindFromKey(theVertex3);
669 TopTools_ListIteratorOfListOfShape anIterE2 (anEdgesOfV2);
670 for (; anIterE2.More(); anIterE2.Next()) {
672 TopTools_ListIteratorOfListOfShape anIterE1 (anEdgesOfV1);
673 for (; anIterE1.More(); anIterE1.Next()) {
675 if (anIterE1.Value().IsSame(anIterE2.Value())) {
676 // Store the first edge, defined by two vertices
677 myEdges(edge_id(1,1)) = anIterE1.Value();
680 // Store the last edge
681 myEdges(edge_id(1,4)) = anIterE1.Value();
683 // Find and store the last vertex
684 TopoDS_Edge E = TopoDS::Edge(myEdges(4));
685 TopoDS_Vertex V1, V2;
686 TopExp::Vertices(E, V1, V2, Standard_True);
688 if (V1.IsSame(theVertex1)) {
689 myVertices(vertex_id(1,4)) = V2;
691 myVertices(vertex_id(1,4)) = V1;
696 TopTools_ListIteratorOfListOfShape anIterE3 (anEdgesOfV3);
697 for (; anIterE3.More(); anIterE3.Next()) {
699 if (anIterE3.Value().IsSame(anIterE2.Value())) {
700 // Store the second edge, defined by two vertices
701 myEdges(edge_id(1,2)) = anIterE3.Value();
704 // Store the fird edge
705 myEdges(edge_id(1,3)) = anIterE3.Value();
711 // Init map vertex->list_of_edges for the block
712 TopTools_IndexedDataMapOfShapeListOfShape MB;
713 MapShapesAndAncestors(theBlock, TopAbs_VERTEX, TopAbs_EDGE, MB);
714 if (MB.Extent() != NBVERTS) {
715 Standard_TypeMismatch::Raise("Block has wrong number of vertices");
718 // 2. Store edges, linking the first face with the second one
719 // and vertices of the second face
720 TopTools_IndexedMapOfShape aFaceEdges;
721 TopExp::MapShapes(myFaces(1), TopAbs_EDGE, aFaceEdges);
723 Standard_Integer i = 1;
724 for (; i <= 4; i++) {
725 // Get i-th vertex of the face 1
726 TopoDS_Shape Vi = myVertices(vertex_id(1, i));
727 if (!MB.Contains(Vi)) {
728 Standard_ConstructionError::Raise("Face does not belong to the block");
731 // Get list of block's edges, sharing this Vertex
732 const TopTools_ListOfShape& anEdgesOfVi = MB.FindFromKey(Vi);
733 TopTools_ListIteratorOfListOfShape anEdgesIter (anEdgesOfVi);
735 // Get Edge (from the List), not belonging to the face 1
736 Standard_Boolean isFound = Standard_False;
737 for (; anEdgesIter.More() && !isFound; anEdgesIter.Next()) {
738 if (!aFaceEdges.Contains(anEdgesIter.Value())) {
739 isFound = Standard_True;
741 // Store the linking edge
742 TopoDS_Shape aLinkEdge = anEdgesIter.Value();
743 myEdges(side_edge_id(i)) = aLinkEdge;
745 // Get another vertex of the linking edge
746 TopoDS_Edge E = TopoDS::Edge(aLinkEdge);
747 TopoDS_Vertex V1, V2;
748 TopExp::Vertices(E, V1, V2, Standard_True);
750 // Store the i-th vertex of the second (opposite to the first) face
752 myVertices(vertex_id(2, i)) = V2;
754 myVertices(vertex_id(2, i)) = V1;
760 // 3. Store edges of the second (opposite to the first) face
761 for (i = 1; i <= 4; i++) {
762 // Get i-th and (i+1)-th vertices of the face 2
763 TopoDS_Shape Vi = myVertices(vertex_id(2, i));
764 TopoDS_Shape Vj = myVertices(vertex_id(2, mod4(i + 1)));
766 // Get list of block's edges, sharing Vi
767 const TopTools_ListOfShape& anEdgesOfVi = MB.FindFromKey(Vi);
768 // Get list of block's edges, sharing Vj
769 const TopTools_ListOfShape& anEdgesOfVj = MB.FindFromKey(Vj);
771 // Get Edge (from the List), linking this vertex with the next one
772 Standard_Boolean isFound = Standard_False;
773 TopTools_ListIteratorOfListOfShape anEdgesIteri (anEdgesOfVi);
774 for (; anEdgesIteri.More() && !isFound; anEdgesIteri.Next()) {
776 TopTools_ListIteratorOfListOfShape anEdgesIterj (anEdgesOfVj);
777 for (; anEdgesIterj.More() && !isFound; anEdgesIterj.Next()) {
779 if (anEdgesIteri.Value().IsSame(anEdgesIterj.Value())) {
780 isFound = Standard_True;
782 // Store the linking edge
783 myEdges(edge_id(2, i)) = anEdgesIteri.Value();
789 // 4. Store faces of the block
790 TopTools_IndexedDataMapOfShapeListOfShape MBE;
791 MapShapesAndAncestors(theBlock, TopAbs_EDGE, TopAbs_FACE, MBE);
792 if (MBE.Extent() != NBEDGES) {
793 Standard_TypeMismatch::Raise("Block has wrong number of edges");
796 for (i = 2; i <= NBFACES; i++) {
797 TopoDS_Shape Ei1 = myEdges(edge_id(i, 1));
798 TopoDS_Shape Ei2 = myEdges(edge_id(i, 2));
799 const TopTools_ListOfShape& aFacesOfEi1 = MBE.FindFromKey(Ei1);
800 const TopTools_ListOfShape& aFacesOfEi2 = MBE.FindFromKey(Ei2);
802 Standard_Boolean isFound = Standard_False;
803 TopTools_ListIteratorOfListOfShape anIterEi1 (aFacesOfEi1);
804 for (; anIterEi1.More() && !isFound; anIterEi1.Next()) {
806 TopTools_ListIteratorOfListOfShape anIterEi2 (aFacesOfEi2);
807 for (; anIterEi2.More() && !isFound; anIterEi2.Next()) {
809 if (anIterEi1.Value().IsSame(anIterEi2.Value())) {
810 isFound = Standard_True;
812 // Store the face, defined by two edges
813 myFaces(i) = anIterEi1.Value();
820 //=======================================================================
821 //function : InitByTwoFaces
823 //=======================================================================
824 void GEOMImpl_Block6Explorer::InitByTwoFaces (const TopoDS_Shape& theFace1,
825 const TopoDS_Shape& theFace2)
827 if (theFace1.IsSame(theFace2)) {
828 Standard_ConstructionError::Raise("The faces must be different");
831 // Add two given faces in the structure
832 myFaces(1) = theFace1;
833 myFaces(2) = theFace2;
835 // Step 1. Order vertices (and edges)
837 // 1.1. Ordered vertices and edges of the first face we put in <myVertices>
839 // Get wire of the first face
840 TopExp_Explorer wires1 (myFaces(1), TopAbs_WIRE);
841 if (!wires1.More()) {
842 Standard_ConstructionError::Raise("A face for the block has no wires");
844 TopoDS_Shape aWire1 = wires1.Current();
847 Standard_ConstructionError::Raise("A face for the block has more than one wire");
850 BRepTools_WireExplorer aWE1 (TopoDS::Wire(aWire1), TopoDS::Face(myFaces(1)));
852 for (nb = 1; aWE1.More(); aWE1.Next(), nb++) {
854 Standard_ConstructionError::Raise("A face for the block has more than four edges");
856 myEdges(edge_id(1, nb)) = aWE1.Current();
857 myVertices(vertex_id(1, nb)) = aWE1.CurrentVertex();
860 Standard_ConstructionError::Raise("A face for the block has less than four edges");
863 // 1.2. Ordered vertices and edges of the second face we temporarily store
864 // in arrays, to find for them rigth location in <myVertices> on the Step 2.
867 TopTools_Array1OfShape aVertis2(1,4); // ordered vertices of the second face
868 TopTools_Array1OfShape anEdges2(1,4); // anEdges2(i) links aVertis2(i) and aVertis2(i+1)
870 // Get wire of the second face
871 TopExp_Explorer wires2 (myFaces(2), TopAbs_WIRE);
872 if (!wires2.More()) {
873 Standard_ConstructionError::Raise("A face for the block has no wires");
875 TopoDS_Shape aWire2 = wires2.Current();
878 Standard_ConstructionError::Raise("A face for the block has more than one wire");
881 BRepTools_WireExplorer aWE2 (TopoDS::Wire(aWire2), TopoDS::Face(myFaces(2)));
882 for (nb = 1; aWE2.More(); aWE2.Next(), nb++) {
884 Standard_ConstructionError::Raise("A face for the block has more than four edges");
886 anEdges2(nb) = aWE2.Current();
887 aVertis2(nb) = aWE2.CurrentVertex();
890 Standard_ConstructionError::Raise("A face for the block has less than four edges");
893 // Step 2. Find right place in <myVertices> for the <aVertis2>,
894 // so as to minimize common length of linking edges
895 // between face 1 and face 2.
896 // Each linking edge (of four) will link vertices of the
897 // faces 1 and 2 with equal local numbers.
898 // The right place is defined by:
899 // - vertex <aVertis2(i_min)>, which will become the first vertex
900 // of the second face <myVertices(vertex_id(2,1))>
901 // - orientation of <aVertis2> relatively their future location
902 // in <myVertices> (s_min = 1 if direct, s_min = -1 if reversed)
903 Standard_Integer i_min = 0, s_min = 0;
905 TColgp_Array1OfPnt aPnts1 (1,4); // points of the first face
906 aPnts1(1) = BRep_Tool::Pnt(TopoDS::Vertex(myVertices(vertex_id(1, 1))));
907 aPnts1(2) = BRep_Tool::Pnt(TopoDS::Vertex(myVertices(vertex_id(1, 2))));
908 aPnts1(3) = BRep_Tool::Pnt(TopoDS::Vertex(myVertices(vertex_id(1, 3))));
909 aPnts1(4) = BRep_Tool::Pnt(TopoDS::Vertex(myVertices(vertex_id(1, 4))));
911 TColgp_Array1OfPnt aPnts2 (1,4); // points of the second face
912 aPnts2(1) = BRep_Tool::Pnt(TopoDS::Vertex(aVertis2(1)));
913 aPnts2(2) = BRep_Tool::Pnt(TopoDS::Vertex(aVertis2(2)));
914 aPnts2(3) = BRep_Tool::Pnt(TopoDS::Vertex(aVertis2(3)));
915 aPnts2(4) = BRep_Tool::Pnt(TopoDS::Vertex(aVertis2(4)));
917 Standard_Real Dist_min = RealLast();
918 // try all possible locations to find the best (with minimum sum distance)
919 Standard_Integer i = 1;
920 for (; i <= 4; i++) {
921 // try direct orientation
922 Standard_Real Dist_plus = aPnts1(1).Distance(aPnts2(i)) +
923 aPnts1(2).Distance(aPnts2(mod4(i + 1))) +
924 aPnts1(3).Distance(aPnts2(mod4(i + 2))) +
925 aPnts1(4).Distance(aPnts2(mod4(i + 3)));
926 if (Dist_plus < Dist_min) {
927 Dist_min = Dist_plus;
932 // try reversed orientation
933 Standard_Real Dist_minus = aPnts1(1).Distance(aPnts2(i)) +
934 aPnts1(2).Distance(aPnts2(mod4(i - 1))) +
935 aPnts1(3).Distance(aPnts2(mod4(i - 2))) +
936 aPnts1(4).Distance(aPnts2(mod4(i - 3)));
937 if (Dist_minus < Dist_min) {
938 Dist_min = Dist_minus;
944 // 3. Put vertices and edges of the second face to they
945 // permanent location in <myVertices> and <myEdges>
946 for (i = 1; i <= 4; i++) {
947 Standard_Integer nb = mod4(i_min + s_min*(i - 1));
949 if (aPnts1(i).Distance(aPnts2(nb)) < Precision::Confusion()) {
950 Standard_ConstructionError::Raise("The faces are too close");
953 myVertices(vertex_id(2, i)) = aVertis2(nb);
955 if (s_min == -1) nb = mod4(nb - 1);
956 myEdges(edge_id(2, i)) = anEdges2(nb);
959 // 4. Generate side surface
960 if (!aWire1.Closed() || !aWire2.Closed()) {
961 // BRepOffsetAPI_ThruSections is not applicable on not closed wires
962 GetFace(3, Standard_True);
963 GetFace(4, Standard_True);
964 GetFace(5, Standard_True);
965 GetFace(6, Standard_True);
967 // try to build faces on native surfaces of edges or planar
968 Standard_Boolean tryThru = Standard_False;
969 for (Standard_Integer i = 3; i <= 6 && !tryThru; i++) {
970 Standard_Boolean doMake = Standard_True;
971 TopoDS_Shape E1 = GetEdge(edge_id(i, 1), doMake);
972 TopoDS_Shape E2 = GetEdge(edge_id(i, 2), doMake);
973 TopoDS_Shape E3 = GetEdge(edge_id(i, 3), doMake);
974 TopoDS_Shape E4 = GetEdge(edge_id(i, 4), doMake);
976 BRepBuilderAPI_MakeWire MW (TopoDS::Edge(E1),
981 Standard_ConstructionError::Raise("Wire construction failed");
984 BRepBuilderAPI_MakeFace MF (MW, Standard_False);
986 myFaces(i) = MF.Shape();
988 tryThru = Standard_True;
992 // Build side surface by ThruSections algorithm
994 BRepOffsetAPI_ThruSections THS;
995 THS.AddWire(TopoDS::Wire(aWire1));
996 THS.AddWire(TopoDS::Wire(aWire2));
999 StdFail_NotDone::Raise("Side surface generation failed");
1001 for (Standard_Integer i = 1; i <= 4; i++) {
1003 myFaces(i+2) = THS.GeneratedFace(myEdges(i));
1006 Standard_Integer ee = side_edge_id(i);
1007 TopTools_IndexedDataMapOfShapeListOfShape MVE;
1008 MapShapesAndAncestors(myFaces(i+2), TopAbs_VERTEX, TopAbs_EDGE, MVE);
1009 FindEdge(myEdges(ee),
1010 myVertices(vertex_id_edge(ee, 1)),
1011 myVertices(vertex_id_edge(ee, 2)),
1018 //=======================================================================
1019 //function : MapShapesAndAncestors
1021 //=======================================================================
1022 void GEOMImpl_Block6Explorer::MapShapesAndAncestors (const TopoDS_Shape& S,
1023 const TopAbs_ShapeEnum TS,
1024 const TopAbs_ShapeEnum TA,
1025 TopTools_IndexedDataMapOfShapeListOfShape& M)
1027 TopTools_ListOfShape empty;
1028 TopTools_MapOfShape mapA;
1031 TopExp_Explorer exa (S,TA);
1032 for (; exa.More(); exa.Next()) {
1034 const TopoDS_Shape& anc = exa.Current();
1035 if (mapA.Add(anc)) {
1036 TopExp_Explorer exs (anc,TS);
1037 TopTools_MapOfShape mapS;
1038 for (; exs.More(); exs.Next()) {
1039 if (mapS.Add(exs.Current())) {
1040 Standard_Integer index = M.FindIndex(exs.Current());
1041 if (index == 0) index = M.Add(exs.Current(),empty);
1042 M(index).Append(anc);
1048 // visit shapes not under ancestors
1049 TopExp_Explorer ex (S,TS,TA);
1050 for (; ex.More(); ex.Next()) {
1051 Standard_Integer index = M.FindIndex(ex.Current());
1052 if (index == 0) index = M.Add(ex.Current(),empty);
1056 //=======================================================================
1057 //function : IsSimilarEdges
1059 //=======================================================================
1060 Standard_Boolean GEOMImpl_Block6Explorer::IsSimilarEdges (const TopoDS_Shape& E1,
1061 const TopoDS_Shape& E2)
1063 TopoDS_Edge E1e = TopoDS::Edge(E1);
1064 TopoDS_Edge E2e = TopoDS::Edge(E2);
1065 TopoDS_Vertex V11, V12, V21, V22;
1066 TopExp::Vertices(E1e, V11, V12, Standard_True);
1067 TopExp::Vertices(E2e, V21, V22, Standard_True);
1068 if (BRepTools::Compare(V11, V21) && BRepTools::Compare(V12, V22))
1069 return Standard_True;
1070 if (BRepTools::Compare(V11, V22) && BRepTools::Compare(V12, V21))
1071 return Standard_True;
1073 return Standard_False;
1076 //=======================================================================
1077 //function : FindEdge
1079 //=======================================================================
1080 Standard_Integer GEOMImpl_Block6Explorer::FindEdge
1081 (TopoDS_Shape& theResult,
1082 const TopoDS_Shape& V1,
1083 const TopoDS_Shape& V2,
1084 const TopTools_IndexedDataMapOfShapeListOfShape& MVE,
1085 const Standard_Boolean findAll)
1087 Standard_Integer isFound = 0;
1089 const TopTools_ListOfShape& anEdgesOfV1 = MVE.FindFromKey(V1);
1090 const TopTools_ListOfShape& anEdgesOfV2 = MVE.FindFromKey(V2);
1092 TopTools_ListIteratorOfListOfShape it1 (anEdgesOfV1);
1093 for (; it1.More(); it1.Next()) {
1094 TopTools_ListIteratorOfListOfShape it2 (anEdgesOfV2);
1095 for (; it2.More(); it2.Next()) {
1096 if (it1.Value().IsSame(it2.Value())) {
1098 theResult = it1.Value();
1099 if (!findAll) return isFound;
1107 //=======================================================================
1108 //function : FindFace
1110 //=======================================================================
1111 Standard_Integer GEOMImpl_Block6Explorer::FindFace
1112 (TopoDS_Shape& theResult,
1113 const TopoDS_Shape& V1,
1114 const TopoDS_Shape& V2,
1115 const TopoDS_Shape& V3,
1116 const TopoDS_Shape& V4,
1117 const TopTools_IndexedDataMapOfShapeListOfShape& MVF,
1118 const Standard_Boolean findAll)
1120 Standard_Integer isFound = Standard_False;
1122 const TopTools_ListOfShape& aFacesOfV1 = MVF.FindFromKey(V1);
1123 const TopTools_ListOfShape& aFacesOfV2 = MVF.FindFromKey(V2);
1124 const TopTools_ListOfShape& aFacesOfV3 = MVF.FindFromKey(V3);
1125 const TopTools_ListOfShape& aFacesOfV4 = MVF.FindFromKey(V4);
1127 TopTools_ListIteratorOfListOfShape it1 (aFacesOfV1);
1128 for (; it1.More(); it1.Next()) {
1129 TopTools_ListIteratorOfListOfShape it2 (aFacesOfV2);
1130 for (; it2.More(); it2.Next()) {
1131 if (it1.Value().IsSame(it2.Value())) {
1132 TopTools_ListIteratorOfListOfShape it3 (aFacesOfV3);
1133 for (; it3.More(); it3.Next()) {
1134 if (it1.Value().IsSame(it3.Value())) {
1135 TopTools_ListIteratorOfListOfShape it4 (aFacesOfV4);
1136 for (; it4.More(); it4.Next()) {
1137 if (it1.Value().IsSame(it4.Value())) {
1139 theResult = it1.Value();
1140 if (!findAll) return isFound;
1152 //=======================================================================
1153 //function : MakeFace
1155 //=======================================================================
1156 void GEOMImpl_Block6Explorer::MakeFace (const TopoDS_Wire& theWire,
1157 const Standard_Boolean isPlanarWanted,
1158 TopoDS_Shape& theResult)
1160 // try to build face on plane or on any surface under the edges of the wire
1161 BRepBuilderAPI_MakeFace MK (theWire, isPlanarWanted);
1163 theResult = MK.Shape();
1167 // try to construct filling surface
1168 if (!isPlanarWanted) {
1169 BRepOffsetAPI_MakeFilling MF;
1171 Standard_Integer nbEdges = 0;
1172 BRepTools_WireExplorer aWE (theWire);
1173 for (; aWE.More(); aWE.Next(), nbEdges++) {
1174 MF.Add(TopoDS::Edge(aWE.Current()), GeomAbs_C0);
1179 // Result of filling
1180 TopoDS_Shape aFace = MF.Shape();
1183 Standard_Real aTol = MF.G0Error();
1185 TColgp_Array1OfPnt aPnts (1,nbEdges); // points of the given wire
1186 BRepTools_WireExplorer aWE1 (theWire);
1187 Standard_Integer vi = 1;
1188 for (; aWE1.More() && vi <= nbEdges; aWE1.Next(), vi++) {
1189 aPnts(vi) = BRep_Tool::Pnt(TopoDS::Vertex(aWE1.CurrentVertex()));
1192 // Find maximum deviation in vertices
1193 TopExp_Explorer exp (aFace, TopAbs_VERTEX);
1194 TopTools_MapOfShape mapShape;
1195 for (; exp.More(); exp.Next()) {
1196 if (mapShape.Add(exp.Current())) {
1197 TopoDS_Vertex aV = TopoDS::Vertex(exp.Current());
1198 Standard_Real aTolV = BRep_Tool::Tolerance(aV);
1199 gp_Pnt aP = BRep_Tool::Pnt(aV);
1200 Standard_Real min_dist = aP.Distance(aPnts(1));
1201 for (vi = 2; vi <= nbEdges; vi++) {
1202 min_dist = Min(min_dist, aP.Distance(aPnts(vi)));
1204 aTol = Max(aTol, aTolV);
1205 aTol = Max(aTol, min_dist);
1209 if ((*((Handle(BRep_TFace)*)&aFace.TShape()))->Tolerance() < aTol) {
1210 (*((Handle(BRep_TFace)*)&aFace.TShape()))->Tolerance(aTol);