4 #include <BRepOffsetAPI_MakeFilling.hxx>
6 #include "GEOMImpl_BlockDriver.hxx"
7 #include "GEOMImpl_IBlocks.hxx"
8 #include "GEOMImpl_IBlockTrsf.hxx"
9 #include "GEOMImpl_GlueDriver.hxx"
10 #include "GEOMImpl_Types.hxx"
11 #include "GEOMImpl_ILocalOperations.hxx"
12 #include "GEOMImpl_Block6Explorer.hxx"
13 #include "GEOM_Function.hxx"
15 #include "ShHealOper_Sewing.hxx"
16 #include "NMTAlgo_Splitter1.hxx"
18 #include <TNaming_CopyShape.hxx>
20 #include <BRepLib.hxx>
21 #include <BRep_Tool.hxx>
22 #include <BRepTools.hxx>
23 #include <BRepGProp.hxx>
24 #include <BRep_Builder.hxx>
25 #include <BRepTools_Quilt.hxx>
26 #include <BRepTools_WireExplorer.hxx>
27 #include <BRepBuilderAPI_MakeEdge.hxx>
28 #include <BRepBuilderAPI_MakeWire.hxx>
29 #include <BRepBuilderAPI_MakePolygon.hxx>
30 #include <BRepBuilderAPI_Transform.hxx>
31 #include <BRepClass_FaceClassifier.hxx>
32 #include <BRepClass3d_SolidClassifier.hxx>
33 #include <BRepExtrema_ExtPF.hxx>
34 #include <BRepExtrema_DistShapeShape.hxx>
38 #include <TopoDS_Shape.hxx>
39 #include <TopoDS_Edge.hxx>
40 #include <TopoDS_Wire.hxx>
41 #include <TopoDS_Shell.hxx>
42 #include <TopoDS_Solid.hxx>
43 #include <TopoDS_Compound.hxx>
44 #include <TopoDS_Iterator.hxx>
46 #include <TopExp_Explorer.hxx>
47 #include <TopTools_MapOfShape.hxx>
48 #include <TopTools_MapIteratorOfMapOfShape.hxx>
49 #include <TopTools_Array1OfShape.hxx>
50 #include <TopTools_SequenceOfShape.hxx>
51 #include <TopTools_ListOfShape.hxx>
52 #include <TopTools_ListIteratorOfListOfShape.hxx>
53 #include <TopTools_IndexedMapOfShape.hxx>
54 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
56 #include <GProp_GProps.hxx>
61 #include <Precision.hxx>
62 #include <TColgp_Array1OfPnt.hxx>
63 #include <TColStd_Array1OfInteger.hxx>
64 #include <TColStd_IndexedDataMapOfTransientTransient.hxx>
65 #include <StdFail_NotDone.hxx>
66 #include <Standard_NullObject.hxx>
67 #include <Standard_TypeMismatch.hxx>
68 #include <Standard_ConstructionError.hxx>
70 //=======================================================================
73 //=======================================================================
74 const Standard_GUID& GEOMImpl_BlockDriver::GetID()
76 static Standard_GUID aBlockDriver("FF1BBB67-5D14-4df2-980B-3A668264EA16");
81 //=======================================================================
82 //function : GEOMImpl_BlockDriver
84 //=======================================================================
85 GEOMImpl_BlockDriver::GEOMImpl_BlockDriver()
89 //=======================================================================
92 //=======================================================================
93 Standard_Integer GEOMImpl_BlockDriver::Execute(TFunction_Logbook& log) const
95 if (Label().IsNull()) return 0;
96 Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
98 Standard_Integer aType = aFunction->GetType();
103 Standard_Real prec = Precision::Confusion();
105 Standard_Integer aNbSub = 0;
106 if (aType == BLOCK_COMPOUND_GLUE) {
110 } else if (aType == BLOCK_FACE_TWO_EDGES ||
111 aType == BLOCK_TWO_FACES) {
115 } else if (aType == BLOCK_FACE_FOUR_PNT ||
116 aType == BLOCK_FACE_FOUR_EDGES) {
120 } else if (aType == BLOCK_SIX_FACES) {
128 GEOMImpl_IBlocks aCI (aFunction);
129 Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes();
130 Standard_Integer nbshapes = aShapes->Length();
132 if (nbshapes != aNbSub) {
133 Standard_TypeMismatch::Raise
134 ("Number of elements for object construction does not correspond to the used constructor");
137 TopTools_Array1OfShape anArgs (1, aNbSub);
138 Standard_Integer argi;
139 for (argi = 1; argi <= aNbSub; argi++) {
140 Handle(GEOM_Function) aRef = Handle(GEOM_Function)::DownCast(aShapes->Value(argi));
141 TopoDS_Shape anArg = aRef->GetValue();
142 if (anArg.IsNull()) {
143 Standard_NullObject::Raise("Null shape is given as argument");
145 anArgs(argi) = anArg;
148 if (aType == BLOCK_FACE_FOUR_EDGES) {
150 // Make face from four edges
151 if (anArgs(1).ShapeType() != TopAbs_EDGE || anArgs(2).ShapeType() != TopAbs_EDGE ||
152 anArgs(3).ShapeType() != TopAbs_EDGE || anArgs(4).ShapeType() != TopAbs_EDGE) {
153 Standard_TypeMismatch::Raise("Shape for face construction is not an edge");
156 // count corner vertices
157 TopTools_MapOfShape aVertMap;
158 for (Standard_Integer ii = 1; ii <= 4; ii++) {
159 TopoDS_Edge anEdge = TopoDS::Edge(anArgs(ii));
160 TopoDS_Vertex V1, V2;
161 TopExp::Vertices(anEdge, V1, V2, Standard_True);
162 if (V1.IsNull() || V2.IsNull()) {
163 Standard_NullObject::Raise("Bad edge for face construction: vertex is not defined");
165 if (BRepTools::Compare(V1,V2)) {
166 Standard_ConstructionError::Raise("Edge ends are too close");
168 Standard_Boolean isCoin1 = Standard_False, isCoin2 = Standard_False;
169 TopTools_MapIteratorOfMapOfShape anIter (aVertMap);
170 for (; anIter.More(); anIter.Next()) {
171 TopoDS_Vertex V = TopoDS::Vertex(anIter.Key());
172 if (BRepTools::Compare(V,V1)) isCoin1 = Standard_True;
173 if (BRepTools::Compare(V,V2)) isCoin2 = Standard_True;
175 if (!isCoin1) aVertMap.Add(V1);
176 if (!isCoin2) aVertMap.Add(V2);
178 if (aVertMap.Extent() != 4) {
179 Standard_ConstructionError::Raise("The edges must form a closed wire");
182 TopoDS_Edge anEdge1 = TopoDS::Edge(anArgs(1));
183 TopoDS_Edge anEdge2 = TopoDS::Edge(anArgs(2));
184 TopoDS_Edge anEdge3 = TopoDS::Edge(anArgs(3));
185 TopoDS_Edge anEdge4 = TopoDS::Edge(anArgs(4));
187 // check, if anEdge1 has common/coincident vertex with anEdge2,
188 Standard_Boolean isConnected12 = Standard_False;
189 TopoDS_Vertex V11, V12, V21, V22;
190 TopExp::Vertices(anEdge1, V11, V12, Standard_True);
191 TopExp::Vertices(anEdge2, V21, V22, Standard_True);
192 if (BRepTools::Compare(V11,V21) || BRepTools::Compare(V11,V22) ||
193 BRepTools::Compare(V12,V21) || BRepTools::Compare(V12,V22)) {
194 // the edges have common vertex
195 isConnected12 = Standard_True;
198 // build wire in right order, corresponding to edges connexity
199 BRepBuilderAPI_MakeWire MW;
201 MW = BRepBuilderAPI_MakeWire(anEdge1, anEdge2, anEdge3, anEdge4);
203 MW = BRepBuilderAPI_MakeWire(anEdge1, anEdge3, anEdge2, anEdge4);
206 Standard_ConstructionError::Raise
207 ("Impossible to build a connected wire from the given edges");
209 TopoDS_Wire aWire = MW;
210 if (!aWire.Closed()) {
211 Standard_ConstructionError::Raise
212 ("Impossible to build a closed wire from the given edges");
215 // try to build face on the wire
216 GEOMImpl_Block6Explorer::MakeFace(aWire, Standard_False, aShape);
217 if (aShape.IsNull()) {
218 Standard_ConstructionError::Raise("Face construction failed");
221 } else if (aType == BLOCK_FACE_TWO_EDGES) {
223 // Make face from two opposite edges
224 if (anArgs(1).ShapeType() != TopAbs_EDGE ||
225 anArgs(2).ShapeType() != TopAbs_EDGE) {
226 Standard_TypeMismatch::Raise("Shape for face construction is not an edge");
229 TopoDS_Edge anEdge1 = TopoDS::Edge(anArgs(1));
230 TopoDS_Edge anEdge2 = TopoDS::Edge(anArgs(2));
232 if (anEdge1.IsSame(anEdge2)) {
233 Standard_ConstructionError::Raise("The edges must be different");
236 // create two edges, linking ends of the given edges
237 TopoDS_Vertex V11, V12, V21, V22;
238 TopExp::Vertices(anEdge1, V11, V12, Standard_True);
239 TopExp::Vertices(anEdge2, V21, V22, Standard_True);
240 if (V11.IsNull() || V12.IsNull() ||
241 V21.IsNull() || V22.IsNull()) {
242 Standard_NullObject::Raise("Bad edge for face construction: vertex is not defined");
244 gp_Pnt P11 = BRep_Tool::Pnt(V11);
245 gp_Pnt P12 = BRep_Tool::Pnt(V12);
246 gp_Pnt P21 = BRep_Tool::Pnt(V21);
247 gp_Pnt P22 = BRep_Tool::Pnt(V22);
249 if (P11.Distance(P21) < prec || P12.Distance(P22) < prec ||
250 P11.Distance(P22) < prec || P12.Distance(P21) < prec) {
251 Standard_ConstructionError::Raise("Given edges have too close ends");
254 Standard_Real per11 = P11.Distance(P21) + P12.Distance(P22);
255 Standard_Real per12 = P11.Distance(P22) + P12.Distance(P21);
260 anEdge3 = BRepBuilderAPI_MakeEdge(V11, V21);
261 anEdge4 = BRepBuilderAPI_MakeEdge(V12, V22);
263 anEdge3 = BRepBuilderAPI_MakeEdge(V11, V22);
264 anEdge4 = BRepBuilderAPI_MakeEdge(V12, V21);
268 BRepBuilderAPI_MakeWire MW (anEdge1, anEdge3, anEdge2, anEdge4);
270 Standard_ConstructionError::Raise("Wire construction failed");
273 // try to build face on the wire
274 GEOMImpl_Block6Explorer::MakeFace(MW, Standard_False, aShape);
275 if (aShape.IsNull()) {
276 Standard_ConstructionError::Raise("Face construction failed");
279 } else if (aType == BLOCK_FACE_FOUR_PNT) {
281 // Make face from four corner vertices
282 if (anArgs(1).ShapeType() != TopAbs_VERTEX ||
283 anArgs(2).ShapeType() != TopAbs_VERTEX ||
284 anArgs(3).ShapeType() != TopAbs_VERTEX ||
285 anArgs(4).ShapeType() != TopAbs_VERTEX) {
286 Standard_TypeMismatch::Raise("Shape for face construction is not a vertex");
289 TopoDS_Vertex V1 = TopoDS::Vertex(anArgs(1));
290 TopoDS_Vertex V2 = TopoDS::Vertex(anArgs(2));
291 TopoDS_Vertex V3 = TopoDS::Vertex(anArgs(3));
292 TopoDS_Vertex V4 = TopoDS::Vertex(anArgs(4));
294 gp_Pnt P1 = BRep_Tool::Pnt(V1);
295 gp_Pnt P2 = BRep_Tool::Pnt(V2);
296 gp_Pnt P3 = BRep_Tool::Pnt(V3);
297 gp_Pnt P4 = BRep_Tool::Pnt(V4);
299 if (P1.Distance(P2) < prec || P1.Distance(P3) < prec ||
300 P1.Distance(P4) < prec || P2.Distance(P3) < prec ||
301 P2.Distance(P4) < prec || P3.Distance(P4) < prec) {
302 Standard_ConstructionError::Raise("Four not coincident points must be given");
305 // calculate perimeters
306 Standard_Real per1234 = P1.Distance(P2) + P2.Distance(P3) +
307 P3.Distance(P4) + P4.Distance(P1);
308 Standard_Real per1243 = P1.Distance(P2) + P2.Distance(P4) +
309 P4.Distance(P3) + P3.Distance(P1);
310 Standard_Real per1324 = P1.Distance(P3) + P3.Distance(P2) +
311 P2.Distance(P4) + P4.Distance(P1);
314 if (per1243 < per1234 && per1243 < per1324) {
315 TopoDS_Vertex Vtmp = V3;
318 } else if (per1324 < per1234 && per1324 < per1243) {
319 TopoDS_Vertex Vtmp = V3;
326 BRepBuilderAPI_MakePolygon aMkPoly (V1, V2, V3, V4, Standard_True);
327 if (!aMkPoly.IsDone()) {
328 Standard_ConstructionError::Raise("Polygon construction failed");
331 // try to build face on the wire
332 GEOMImpl_Block6Explorer::MakeFace(aMkPoly, Standard_False, aShape);
333 if (aShape.IsNull()) {
334 Standard_ConstructionError::Raise("Face construction failed");
337 } else if (aType == BLOCK_SIX_FACES || aType == BLOCK_TWO_FACES) {
339 BRepTools_Quilt Glue;
341 if (aType == BLOCK_SIX_FACES) {
343 // Make block (hexahedral solid) from six faces
344 for (Standard_Integer ind = 1; ind <= nbshapes; ind++) {
345 if (anArgs(ind).ShapeType() != TopAbs_FACE) {
346 Standard_TypeMismatch::Raise("Shape for block construction is not a face");
348 Glue.Add(anArgs(ind));
353 // Make block (hexahedral solid) from two opposite faces
354 if (anArgs(1).ShapeType() != TopAbs_FACE ||
355 anArgs(2).ShapeType() != TopAbs_FACE) {
356 Standard_TypeMismatch::Raise("Shape for block construction is not a face");
359 // Get wires of the given faces
360 TopExp_Explorer wires1 (anArgs(1), TopAbs_WIRE);
361 TopExp_Explorer wires2 (anArgs(2), TopAbs_WIRE);
362 if (!wires1.More() || !wires2.More()) {
363 Standard_ConstructionError::Raise("A face for the block has no wires");
365 TopoDS_Shape aWire1 = wires1.Current();
366 TopoDS_Shape aWire2 = wires2.Current();
369 if (wires1.More() || wires2.More()) {
370 Standard_ConstructionError::Raise("A face for the block has more than one wire");
373 GEOMImpl_Block6Explorer aBlockTool;
374 aBlockTool.InitByTwoFaces(anArgs(1), anArgs(2));
376 // Construct the linking faces and add them in the gluing tool
378 Glue.Add(aBlockTool.GetFace(3, Standard_True));
379 Glue.Add(aBlockTool.GetFace(4, Standard_True));
380 Glue.Add(aBlockTool.GetFace(5, Standard_True));
381 Glue.Add(aBlockTool.GetFace(6, Standard_True));
385 TopExp_Explorer exp (Glue.Shells(), TopAbs_SHELL);
386 Standard_Integer ish = 0;
387 TopTools_MapOfShape mapShape;
388 for (; exp.More(); exp.Next()) {
389 if (mapShape.Add(exp.Current())) {
390 aShape = exp.Current();
396 aShape = Glue.Shells();
397 Standard_Real aTol = prec; // Precision::Confusion()
398 TopExp_Explorer expF (aShape, TopAbs_FACE);
399 TopTools_MapOfShape mapF;
402 for (; expF.More(); expF.Next()) {
403 if (mapF.Add(expF.Current())) {
404 B.Add(Shell, expF.Current());
405 Standard_Real aToler = BRep_Tool::Tolerance(TopoDS::Face(expF.Current()));
410 ShHealOper_Sewing aHealer (Shell, aTol);
411 if (aHealer.Perform())
412 aShape = aHealer.GetResultShape();
414 Standard_ConstructionError::Raise
415 ("Impossible to build a connected shell on the given faces");
418 if (aType == BLOCK_SIX_FACES) {
419 if (!aShape.Closed()) {
420 Standard_ConstructionError::Raise
421 ("Impossible to build a closed shell on the given faces");
428 BRepClass3d_SolidClassifier SC (Sol);
429 SC.PerformInfinitePoint(prec);
430 if (SC.State() == TopAbs_IN) {
432 B.Add(Sol, aShape.Reversed());
435 BRepLib::SameParameter(aShape, 1.E-5, Standard_True);
437 } else if (aType == BLOCK_COMPOUND_GLUE) {
439 // Make blocks compound from a compound
440 if (anArgs(1).ShapeType() != TopAbs_COMPOUND &&
441 anArgs(2).ShapeType() != TopAbs_COMPSOLID) {
442 Standard_TypeMismatch::Raise("Not a compound given");
445 TopoDS_Shape aCompound = anArgs(1);
447 // Glue coincident faces and edges (with Partition algorithm).
448 NMTAlgo_Splitter1 PS;
449 PS.AddShape(aCompound);
451 PS.SetRemoveWebs(Standard_False);
452 // PS.Build(aCompound.ShapeType());
453 PS.Build(TopAbs_SOLID);
459 } else { // Multi-transformations
462 GEOMImpl_IBlockTrsf aCI (aFunction);
463 Handle(GEOM_Function) aRefShape = aCI.GetOriginal();
464 TopoDS_Shape aBlockIni = aRefShape->GetValue();
465 if (aBlockIni.IsNull()) {
466 Standard_NullObject::Raise("Null Block");
469 // Copy block to avoid problems (PAL6706)
470 TColStd_IndexedDataMapOfTransientTransient aMap;
472 TNaming_CopyShape::CopyTool(aBlockIni, aMap, aBlock);
474 // Block tolerance in vertices
475 Standard_Real aTol = prec;
476 TopExp_Explorer expV (aBlock, TopAbs_VERTEX);
477 TopTools_MapOfShape mapShape;
478 for (; expV.More(); expV.Next()) {
479 if (mapShape.Add(expV.Current())) {
480 TopoDS_Vertex aV = TopoDS::Vertex(expV.Current());
481 aTol = Max(BRep_Tool::Tolerance(aV), aTol);
485 if (aType == BLOCK_MULTI_TRANSFORM_1D) {
486 // Retrieve a faces by Ids
487 Standard_Integer aFace1Id = aCI.GetFace1U();
488 Standard_Integer aFace2Id = aCI.GetFace2U();
489 TopoDS_Shape aFace1, aFace2;
490 if (!GEOMImpl_ILocalOperations::GetSubShape(aBlock, aFace1Id, aFace1)) {
491 Standard_NullObject::Raise("Can not retrieve a sub-shape with given Id");
493 if (aFace1.ShapeType() != TopAbs_FACE) {
494 Standard_TypeMismatch::Raise("Sub-shape with given Id is not a face");
498 if (!GEOMImpl_ILocalOperations::GetSubShape(aBlock, aFace2Id, aFace2)) {
499 Standard_NullObject::Raise("Can not retrieve a sub-shape with given Id");
501 if (aFace2.ShapeType() != TopAbs_FACE) {
502 Standard_TypeMismatch::Raise("Sub-shape with given Id is not a face");
506 Standard_Integer aNbIter = aCI.GetNbIterU();
508 MultiTransformate1D(aBlock, aFace1, aFace2, aNbIter, aMulti);
510 } else if (aType == BLOCK_MULTI_TRANSFORM_2D) {
511 // Retrieve a faces by Ids
512 Standard_Integer aFace1UId = aCI.GetFace1U();
513 Standard_Integer aFace2UId = aCI.GetFace2U();
514 Standard_Integer aFace1VId = aCI.GetFace1V();
515 Standard_Integer aFace2VId = aCI.GetFace2V();
517 TopoDS_Shape aFace1U, aFace2U, aFace1V, aFace2V;
518 if (!GEOMImpl_ILocalOperations::GetSubShape(aBlock, aFace1UId, aFace1U) ||
519 !GEOMImpl_ILocalOperations::GetSubShape(aBlock, aFace1VId, aFace1V)) {
520 Standard_NullObject::Raise("Can not retrieve a sub-shape with given Id");
523 if (aFace1U.ShapeType() != TopAbs_FACE ||
524 aFace1V.ShapeType() != TopAbs_FACE) {
525 Standard_TypeMismatch::Raise("Sub-shape with given Id is not a face");
529 if (!GEOMImpl_ILocalOperations::GetSubShape(aBlock, aFace2UId, aFace2U)) {
530 Standard_NullObject::Raise("Can not retrieve a sub-shape with given Id");
533 if (aFace2U.ShapeType() != TopAbs_FACE) {
534 Standard_TypeMismatch::Raise("Sub-shape with given Id is not a face");
539 if (!GEOMImpl_ILocalOperations::GetSubShape(aBlock, aFace2VId, aFace2V)) {
540 Standard_NullObject::Raise("Can not retrieve a sub-shape with given Id");
543 if (aFace2V.ShapeType() != TopAbs_FACE) {
544 Standard_TypeMismatch::Raise("Sub-shape with given Id is not a face");
548 Standard_Integer aNbIterU = aCI.GetNbIterU();
549 Standard_Integer aNbIterV = aCI.GetNbIterV();
551 MultiTransformate2D(aBlock,
552 aFace1U, aFace2U, aNbIterU,
553 aFace1V, aFace2V, aNbIterV, aMulti);
559 if (aMulti.IsNull()) {
560 StdFail_NotDone::Raise("Multi-transformation failed");
564 // Glue faces of the multi-block
565 aShape = GEOMImpl_GlueDriver::GlueFaces(aMulti, aTol);
568 if (aShape.IsNull()) return 0;
570 aFunction->SetValue(aShape);
572 log.SetTouched(Label());
577 //=======================================================================
578 //function : MultiTransformate1D
580 //=======================================================================
581 void GEOMImpl_BlockDriver::MultiTransformate1D (const TopoDS_Shape& theBlock,
582 const TopoDS_Shape& theFace1,
583 const TopoDS_Shape& theFace2,
584 const Standard_Integer theNbIter,
585 TopoDS_Shape& theResult) const
587 // Construct Tool, where <theFace1> will be the first face,
588 // and a face, opposite to <theFace1>, will be the second face
589 GEOMImpl_Block6Explorer aBlockTool;
590 aBlockTool.InitByBlockAndFace(theBlock, theFace1);
592 // Find IDs of the faces
593 Standard_Integer dir_face1 = 1, dir_face2 = 2;
594 if (!theFace2.IsNull()) {
595 dir_face2 = aBlockTool.GetFaceID(theFace2);
598 // Find three pairs of points
599 Standard_Integer v11_id = 0, v12_id = 0, v13_id = 0; // vertices of the first face
600 Standard_Integer v21_id = 0, v22_id = 0, v23_id = 0; // vertices of the second face
602 if (dir_face2 == 2) { // <theFace2> is opposite to <theFace1>
604 // We will take vertices with equal local numbers on the faces,
605 // as the Block6Explorer gives equal local numbers
606 // to the linked vertices on the opposite faces,
607 // i.e. v1* is linked with the v2* by an edge:
611 // / | / | dir_face1 - bottom
613 // /________ / | dir_face2 - top
622 v11_id = aBlockTool.GetVertexID(dir_face1, 1);
623 v12_id = aBlockTool.GetVertexID(dir_face1, 2);
624 v13_id = aBlockTool.GetVertexID(dir_face1, 4);
626 v21_id = aBlockTool.GetVertexID(dir_face2, 1);
627 v22_id = aBlockTool.GetVertexID(dir_face2, 2);
628 v23_id = aBlockTool.GetVertexID(dir_face2, 4);
634 // / | / | dir_face1 - bottom
636 // /________ / | dir_face2 - right (for example)
639 // | / | /v12 = v22 (common_vertex2)
643 // v13 v11 = v21 (common_vertex1)
645 Standard_Integer common_edge_id = aBlockTool.FindCommonEdgeID(dir_face1, dir_face2);
646 Standard_Integer common_vertex1 = aBlockTool.GetVertexOnEdgeID(common_edge_id, 1);
647 Standard_Integer common_vertex2 = aBlockTool.GetVertexOnEdgeID(common_edge_id, 2);
649 Standard_Integer not_common_v1 = 0;
650 Standard_Integer vid = 1;
651 Standard_Boolean isFound = Standard_False;
652 while (!isFound && vid <= 4) {
653 not_common_v1 = aBlockTool.GetVertexID(dir_face1, vid);
654 isFound = (not_common_v1 != common_vertex2 &&
655 aBlockTool.FindEdgeID(not_common_v1, common_vertex1) != 0);
659 Standard_Integer not_common_v2 = 0;
661 isFound = Standard_False;
662 while (!isFound && vid <= 4) {
663 not_common_v2 = aBlockTool.GetVertexID(dir_face2, vid);
664 isFound = (not_common_v2 != common_vertex2 &&
665 aBlockTool.FindEdgeID(not_common_v2, common_vertex1) != 0);
669 v11_id = common_vertex1;
670 v12_id = common_vertex2;
671 v13_id = not_common_v1;
673 v21_id = common_vertex1;
674 v22_id = common_vertex2;
675 v23_id = not_common_v2;
678 // Construct a transformation operator
679 TopoDS_Vertex V11 = TopoDS::Vertex(aBlockTool.GetVertex(v11_id));
680 TopoDS_Vertex V12 = TopoDS::Vertex(aBlockTool.GetVertex(v12_id));
681 TopoDS_Vertex V13 = TopoDS::Vertex(aBlockTool.GetVertex(v13_id));
683 TopoDS_Vertex V21 = TopoDS::Vertex(aBlockTool.GetVertex(v21_id));
684 TopoDS_Vertex V22 = TopoDS::Vertex(aBlockTool.GetVertex(v22_id));
685 TopoDS_Vertex V23 = TopoDS::Vertex(aBlockTool.GetVertex(v23_id));
687 // Axes of the first direction face
688 gp_Pnt P1 = BRep_Tool::Pnt(V11);
689 gp_Vec VecN1 (P1, BRep_Tool::Pnt(V12));
690 gp_Vec VecX1 (P1, BRep_Tool::Pnt(V13));
691 gp_Ax3 Ax1 (P1, VecN1, VecX1);
693 // Axes of the second direction face
694 gp_Pnt P2 = BRep_Tool::Pnt(V21);
695 gp_Vec VecN2 (P2, BRep_Tool::Pnt(V22));
696 gp_Vec VecX2 (P2, BRep_Tool::Pnt(V23));
697 gp_Ax3 Ax2 (P2, VecN2, VecX2);
700 aTrsf.SetDisplacement(Ax1, Ax2);
702 // Check, that <theFace2> is similar to <theFace1>.
703 // Actually, we need only to check right position of one
704 // vertex, not involved into the transformation construction.
705 if (!aBlockTool.IsSimilarFaces(dir_face1, dir_face2, aTrsf)) {
706 Standard_ConstructionError::Raise("The direction faces are not similar");
709 // Perform multi-transformation
710 TopoDS_Compound aCompound;
712 B.MakeCompound(aCompound);
714 TopoDS_Shape aPrevShape = theBlock;
715 for (Standard_Integer i = 0; i < theNbIter; i++) {
716 B.Add(aCompound, aPrevShape);
717 BRepBuilderAPI_Transform aTransformation (aPrevShape, aTrsf, Standard_False);
718 aPrevShape = aTransformation.Shape();
720 theResult = aCompound;
723 //=======================================================================
724 //function : MultiTransformate2D
726 //=======================================================================
727 void GEOMImpl_BlockDriver::MultiTransformate2D (const TopoDS_Shape& theBlock,
728 const TopoDS_Shape& theFace1U,
729 const TopoDS_Shape& theFace2U,
730 const Standard_Integer theNbIterU,
731 const TopoDS_Shape& theFace1V,
732 const TopoDS_Shape& theFace2V,
733 const Standard_Integer theNbIterV,
734 TopoDS_Shape& theResult) const
736 // Construct Tool, where <theFace1U> will be the first face,
737 // and a face, opposite to <theFace1U>, will be the second face
738 GEOMImpl_Block6Explorer aBlockTool;
739 aBlockTool.InitByBlockAndFace(theBlock, theFace1U);
741 gp_Trsf aTrsfU, aTrsfV;
743 for (Standard_Integer uv = 1; uv <= 2; uv++) {
745 TopoDS_Shape theFace1 = theFace1U;
746 TopoDS_Shape theFace2 = theFace2U;
749 theFace1 = theFace1V;
750 theFace2 = theFace2V;
753 // Find IDs of the faces
754 Standard_Integer dir_face1 = aBlockTool.GetFaceID(theFace1);
755 Standard_Integer dir_face2 = 0;
756 Standard_Integer opp_face1 = aBlockTool.GetOppositeFaceID(dir_face1);
757 if (theFace2.IsNull()) {
758 dir_face2 = opp_face1;
760 dir_face2 = aBlockTool.GetFaceID(theFace2);
763 // Find three pairs of points
764 Standard_Integer v11_id = 0, v12_id = 0, v13_id = 0; // vertices of the first face
765 Standard_Integer v21_id = 0, v22_id = 0, v23_id = 0; // vertices of the second face
767 if (dir_face2 == opp_face1) { // <theFace2> is opposite to <theFace1>
769 // We will take vertices with equal local numbers on the faces,
770 // as the Block6Explorer gives equal local numbers
771 // to the linked vertices on the opposite faces,
772 // i.e. v1* is linked with the v2* by an edge:
774 v11_id = aBlockTool.GetVertexID(dir_face1, 1);
775 v12_id = aBlockTool.GetVertexID(dir_face1, 2);
776 v13_id = aBlockTool.GetVertexID(dir_face1, 4);
778 v21_id = aBlockTool.GetVertexID(dir_face2, 1);
779 v22_id = aBlockTool.GetVertexID(dir_face2, 2);
780 v23_id = aBlockTool.GetVertexID(dir_face2, 4);
784 Standard_Integer common_edge_id = aBlockTool.FindCommonEdgeID(dir_face1, dir_face2);
785 Standard_Integer common_vertex1 = aBlockTool.GetVertexOnEdgeID(common_edge_id, 1);
786 Standard_Integer common_vertex2 = aBlockTool.GetVertexOnEdgeID(common_edge_id, 2);
788 Standard_Integer not_common_v1 = 0;
789 Standard_Integer vid = 1;
790 Standard_Boolean isFound = Standard_False;
791 while (!isFound && vid <= 4) {
792 not_common_v1 = aBlockTool.GetVertexID(dir_face1, vid);
793 isFound = (not_common_v1 != common_vertex2 &&
794 aBlockTool.FindEdgeID(not_common_v1, common_vertex1) != 0);
798 Standard_Integer not_common_v2 = 0;
800 isFound = Standard_False;
801 while (!isFound && vid <= 4) {
802 not_common_v2 = aBlockTool.GetVertexID(dir_face2, vid);
803 isFound = (not_common_v2 != common_vertex2 &&
804 aBlockTool.FindEdgeID(not_common_v2, common_vertex1) != 0);
808 v11_id = common_vertex1;
809 v12_id = common_vertex2;
810 v13_id = not_common_v1;
812 v21_id = common_vertex1;
813 v22_id = common_vertex2;
814 v23_id = not_common_v2;
817 // Construct a transformation operator
818 TopoDS_Vertex V11 = TopoDS::Vertex(aBlockTool.GetVertex(v11_id));
819 TopoDS_Vertex V12 = TopoDS::Vertex(aBlockTool.GetVertex(v12_id));
820 TopoDS_Vertex V13 = TopoDS::Vertex(aBlockTool.GetVertex(v13_id));
822 TopoDS_Vertex V21 = TopoDS::Vertex(aBlockTool.GetVertex(v21_id));
823 TopoDS_Vertex V22 = TopoDS::Vertex(aBlockTool.GetVertex(v22_id));
824 TopoDS_Vertex V23 = TopoDS::Vertex(aBlockTool.GetVertex(v23_id));
826 // Axes of the first direction face
827 gp_Pnt P1 = BRep_Tool::Pnt(V11);
828 gp_Vec VecN1 (P1, BRep_Tool::Pnt(V12));
829 gp_Vec VecX1 (P1, BRep_Tool::Pnt(V13));
830 gp_Ax3 Ax1 (P1, VecN1, VecX1);
832 // Axes of the second direction face
833 gp_Pnt P2 = BRep_Tool::Pnt(V21);
834 gp_Vec VecN2 (P2, BRep_Tool::Pnt(V22));
835 gp_Vec VecX2 (P2, BRep_Tool::Pnt(V23));
836 gp_Ax3 Ax2 (P2, VecN2, VecX2);
839 aTrsf.SetDisplacement(Ax1, Ax2);
848 // Check, that <theFace2> is similar to <theFace1>.
849 // Actually, we need only to check right position of one
850 // vertex, not involved into the transformation construction.
851 if (!aBlockTool.IsSimilarFaces(dir_face1, dir_face2, aTrsf)) {
852 Standard_ConstructionError::Raise("The direction faces are not similar");
856 // Perform multi-transformation
857 TopoDS_Compound aCompound;
859 B.MakeCompound(aCompound);
861 TopoDS_Shape aPrevShapeU = theBlock;
862 for (int i = 0; i < theNbIterU; i++) {
863 TopoDS_Shape aPrevShapeV = aPrevShapeU;
864 for (int j = 0; j < theNbIterV; j++) {
865 B.Add(aCompound, aPrevShapeV);
866 BRepBuilderAPI_Transform aTransformationV (aPrevShapeV, aTrsfV, Standard_False);
867 aPrevShapeV = aTransformationV.Shape();
869 BRepBuilderAPI_Transform aTransformationU (aPrevShapeU, aTrsfU, Standard_False);
870 aPrevShapeU = aTransformationU.Shape();
871 // Correction of the second transformation according to the first transformation
872 Ax1V.Transform(aTrsfU);
873 Ax2V.Transform(aTrsfU);
874 aTrsfV.SetDisplacement(Ax1V, Ax2V);
877 theResult = aCompound;
880 //=======================================================================
881 //function : GEOMImpl_BlockDriver_Type_
883 //=======================================================================
884 Standard_EXPORT Handle_Standard_Type& GEOMImpl_BlockDriver_Type_()
887 static Handle_Standard_Type aType1 = STANDARD_TYPE(TFunction_Driver);
888 if ( aType1.IsNull()) aType1 = STANDARD_TYPE(TFunction_Driver);
889 static Handle_Standard_Type aType2 = STANDARD_TYPE(MMgt_TShared);
890 if ( aType2.IsNull()) aType2 = STANDARD_TYPE(MMgt_TShared);
891 static Handle_Standard_Type aType3 = STANDARD_TYPE(Standard_Transient);
892 if ( aType3.IsNull()) aType3 = STANDARD_TYPE(Standard_Transient);
895 static Handle_Standard_Transient _Ancestors[]= {aType1,aType2,aType3,NULL};
896 static Handle_Standard_Type _aType = new Standard_Type("GEOMImpl_BlockDriver",
897 sizeof(GEOMImpl_BlockDriver),
899 (Standard_Address)_Ancestors,
900 (Standard_Address)NULL);
905 //=======================================================================
906 //function : DownCast
908 //=======================================================================
909 const Handle(GEOMImpl_BlockDriver) Handle(GEOMImpl_BlockDriver)::DownCast(const Handle(Standard_Transient)& AnObject)
911 Handle(GEOMImpl_BlockDriver) _anOtherObject;
913 if (!AnObject.IsNull()) {
914 if (AnObject->IsKind(STANDARD_TYPE(GEOMImpl_BlockDriver))) {
915 _anOtherObject = Handle(GEOMImpl_BlockDriver)((Handle(GEOMImpl_BlockDriver)&)AnObject);
919 return _anOtherObject ;