]> SALOME platform Git repositories - modules/geom.git/blob - src/GEOMImpl/GEOMImpl_BlockDriver.cxx
Salome HOME
27073e43919bcdc6ba5e59d1556022bbefb329a9
[modules/geom.git] / src / GEOMImpl / GEOMImpl_BlockDriver.cxx
1
2 using namespace std;
3
4 #include <BRepOffsetAPI_MakeFilling.hxx>
5
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"
14
15 #include "ShHealOper_Sewing.hxx"
16 #include "NMTAlgo_Splitter1.hxx"
17
18 #include <TNaming_CopyShape.hxx>
19
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>
35
36 #include <TopAbs.hxx>
37 #include <TopoDS.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>
45 #include <TopExp.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>
55
56 #include <GProp_GProps.hxx>
57
58 #include <gp.hxx>
59 #include <gp_Pnt.hxx>
60 #include <gp_Ax3.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>
69
70 //=======================================================================
71 //function : GetID
72 //purpose  :
73 //=======================================================================
74 const Standard_GUID& GEOMImpl_BlockDriver::GetID()
75 {
76   static Standard_GUID aBlockDriver("FF1BBB67-5D14-4df2-980B-3A668264EA16");
77   return aBlockDriver;
78 }
79
80
81 //=======================================================================
82 //function : GEOMImpl_BlockDriver
83 //purpose  :
84 //=======================================================================
85 GEOMImpl_BlockDriver::GEOMImpl_BlockDriver()
86 {
87 }
88
89 //=======================================================================
90 //function : Execute
91 //purpose  :
92 //=======================================================================
93 Standard_Integer GEOMImpl_BlockDriver::Execute(TFunction_Logbook& log) const
94 {
95   if (Label().IsNull()) return 0;
96   Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
97
98   Standard_Integer aType = aFunction->GetType();
99
100   TopoDS_Shape aShape;
101   BRep_Builder B;
102
103   Standard_Real prec = Precision::Confusion();
104
105   Standard_Integer aNbSub = 0;
106   if (aType == BLOCK_COMPOUND_GLUE) {
107
108     aNbSub = 1;
109
110   } else if (aType == BLOCK_FACE_TWO_EDGES ||
111              aType == BLOCK_TWO_FACES) {
112
113     aNbSub = 2;
114
115   } else if (aType == BLOCK_FACE_FOUR_PNT ||
116              aType == BLOCK_FACE_FOUR_EDGES) {
117
118     aNbSub = 4;
119
120   } else if (aType == BLOCK_SIX_FACES) {
121
122     aNbSub = 6;
123
124   } else {
125   }
126
127   if (aNbSub > 0) {
128     GEOMImpl_IBlocks aCI (aFunction);
129     Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes();
130     Standard_Integer nbshapes = aShapes->Length();
131
132     if (nbshapes != aNbSub) {
133       Standard_TypeMismatch::Raise
134         ("Number of elements for object construction does not correspond to the used constructor");
135     }
136
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");
144       }
145       anArgs(argi) = anArg;
146     }
147
148     if (aType == BLOCK_FACE_FOUR_EDGES) {
149
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");
154       }
155
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");
164         }
165         if (BRepTools::Compare(V1,V2)) {
166           Standard_ConstructionError::Raise("Edge ends are too close");
167         }
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;
174         }
175         if (!isCoin1) aVertMap.Add(V1);
176         if (!isCoin2) aVertMap.Add(V2);
177       }
178       if (aVertMap.Extent() != 4) {
179         Standard_ConstructionError::Raise("The edges must form a closed wire");
180       }
181
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));
186
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;
196       }
197
198       // build wire in right order, corresponding to edges connexity
199       BRepBuilderAPI_MakeWire MW;
200       if (isConnected12)
201         MW = BRepBuilderAPI_MakeWire(anEdge1, anEdge2, anEdge3, anEdge4);
202       else
203         MW = BRepBuilderAPI_MakeWire(anEdge1, anEdge3, anEdge2, anEdge4);
204
205       if (!MW.IsDone()) {
206         Standard_ConstructionError::Raise
207           ("Impossible to build a connected wire from the given edges");
208       }
209       TopoDS_Wire aWire = MW;
210       if (!aWire.Closed()) {
211         Standard_ConstructionError::Raise
212           ("Impossible to build a closed wire from the given edges");
213       }
214
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");
219       }
220
221     } else if (aType == BLOCK_FACE_TWO_EDGES) {
222
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");
227       }
228
229       TopoDS_Edge anEdge1 = TopoDS::Edge(anArgs(1));
230       TopoDS_Edge anEdge2 = TopoDS::Edge(anArgs(2));
231
232       if (anEdge1.IsSame(anEdge2)) {
233         Standard_ConstructionError::Raise("The edges must be different");
234       }
235
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");
243       }
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);
248
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");
252       }
253
254       Standard_Real per11 = P11.Distance(P21) + P12.Distance(P22);
255       Standard_Real per12 = P11.Distance(P22) + P12.Distance(P21);
256
257       TopoDS_Edge anEdge3;
258       TopoDS_Edge anEdge4;
259       if (per11 < per12) {
260         anEdge3 = BRepBuilderAPI_MakeEdge(V11, V21);
261         anEdge4 = BRepBuilderAPI_MakeEdge(V12, V22);
262       } else {
263         anEdge3 = BRepBuilderAPI_MakeEdge(V11, V22);
264         anEdge4 = BRepBuilderAPI_MakeEdge(V12, V21);
265       }
266
267       // build a wire
268       BRepBuilderAPI_MakeWire MW (anEdge1, anEdge3, anEdge2, anEdge4);
269       if (!MW.IsDone()) {
270         Standard_ConstructionError::Raise("Wire construction failed");
271       }
272
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");
277       }
278
279     } else if (aType == BLOCK_FACE_FOUR_PNT) {
280
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");
287       }
288
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));
293
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);
298
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");
303       }
304
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);
312
313       // order vertices
314       if (per1243 < per1234 && per1243 < per1324) {
315         TopoDS_Vertex Vtmp = V3;
316         V3 = V4;
317         V4 = Vtmp;
318       } else if (per1324 < per1234 && per1324 < per1243) {
319         TopoDS_Vertex Vtmp = V3;
320         V3 = V2;
321         V2 = Vtmp;
322       } else {
323       }
324
325       // build wire
326       BRepBuilderAPI_MakePolygon aMkPoly (V1, V2, V3, V4, Standard_True);
327       if (!aMkPoly.IsDone()) {
328         Standard_ConstructionError::Raise("Polygon construction failed");
329       }
330
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");
335       }
336
337     } else if (aType == BLOCK_SIX_FACES || aType == BLOCK_TWO_FACES) {
338
339       BRepTools_Quilt Glue;
340
341       if (aType == BLOCK_SIX_FACES) {
342
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");
347           }
348           Glue.Add(anArgs(ind));
349         }
350
351       } else {
352
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");
357         }
358
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");
364         }
365         TopoDS_Shape aWire1 = wires1.Current();
366         TopoDS_Shape aWire2 = wires2.Current();
367         wires1.Next();
368         wires2.Next();
369         if (wires1.More() || wires2.More()) {
370           Standard_ConstructionError::Raise("A face for the block has more than one wire");
371         }
372
373         GEOMImpl_Block6Explorer aBlockTool;
374         aBlockTool.InitByTwoFaces(anArgs(1), anArgs(2));
375
376         // Construct the linking faces and add them in the gluing tool
377         Glue.Add(anArgs(1));
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));
382         Glue.Add(anArgs(2));
383       }
384
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();
391           ish++;
392         }
393       }
394
395       if (ish > 1) {
396         aShape = Glue.Shells();
397         Standard_Real aTol = prec; // Precision::Confusion()
398         TopExp_Explorer expF (aShape, TopAbs_FACE);
399         TopTools_MapOfShape mapF;
400         TopoDS_Shell Shell;
401         B.MakeShell(Shell);
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()));
406             if (aToler > aTol)
407               aTol = aToler;
408           }
409         }
410         ShHealOper_Sewing aHealer (Shell, aTol);
411         if (aHealer.Perform())
412           aShape = aHealer.GetResultShape();
413         else
414           Standard_ConstructionError::Raise
415             ("Impossible to build a connected shell on the given faces");
416       }
417
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");
422         }
423       }
424
425       TopoDS_Solid Sol;
426       B.MakeSolid(Sol);
427       B.Add(Sol, aShape);
428       BRepClass3d_SolidClassifier SC (Sol);
429       SC.PerformInfinitePoint(prec);
430       if (SC.State() == TopAbs_IN) {
431         B.MakeSolid(Sol);
432         B.Add(Sol, aShape.Reversed());
433       }
434       aShape = Sol;
435       BRepLib::SameParameter(aShape, 1.E-5, Standard_True);
436
437     } else if (aType == BLOCK_COMPOUND_GLUE) {
438
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");
443       }
444
445       TopoDS_Shape aCompound = anArgs(1);
446
447       // Glue coincident faces and edges (with Partition algorithm).
448       NMTAlgo_Splitter1 PS;
449       PS.AddShape(aCompound);
450       PS.Compute();
451       PS.SetRemoveWebs(Standard_False);
452 //      PS.Build(aCompound.ShapeType());
453       PS.Build(TopAbs_SOLID);
454
455       aShape = PS.Shape();
456     } else {
457     }
458
459   } else { // Multi-transformations
460
461     TopoDS_Shape aMulti;
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");
467     }
468
469     // Copy block to avoid problems (PAL6706)
470     TColStd_IndexedDataMapOfTransientTransient aMap;
471     TopoDS_Shape aBlock;
472     TNaming_CopyShape::CopyTool(aBlockIni, aMap, aBlock);
473
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);
482       }
483     }
484
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");
492       }
493       if (aFace1.ShapeType() != TopAbs_FACE) {
494         Standard_TypeMismatch::Raise("Sub-shape with given Id is not a face");
495       }
496
497       if (aFace2Id > 0) {
498         if (!GEOMImpl_ILocalOperations::GetSubShape(aBlock, aFace2Id, aFace2)) {
499           Standard_NullObject::Raise("Can not retrieve a sub-shape with given Id");
500         }
501         if (aFace2.ShapeType() != TopAbs_FACE) {
502           Standard_TypeMismatch::Raise("Sub-shape with given Id is not a face");
503         }
504       }
505
506       Standard_Integer aNbIter = aCI.GetNbIterU();
507
508       MultiTransformate1D(aBlock, aFace1, aFace2, aNbIter, aMulti);
509
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();
516
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");
521       }
522
523       if (aFace1U.ShapeType() != TopAbs_FACE ||
524           aFace1V.ShapeType() != TopAbs_FACE) {
525         Standard_TypeMismatch::Raise("Sub-shape with given Id is not a face");
526       }
527
528       if (aFace2UId > 0) {
529         if (!GEOMImpl_ILocalOperations::GetSubShape(aBlock, aFace2UId, aFace2U)) {
530           Standard_NullObject::Raise("Can not retrieve a sub-shape with given Id");
531         }
532
533         if (aFace2U.ShapeType() != TopAbs_FACE) {
534           Standard_TypeMismatch::Raise("Sub-shape with given Id is not a face");
535         }
536       }
537
538       if (aFace2VId > 0) {
539         if (!GEOMImpl_ILocalOperations::GetSubShape(aBlock, aFace2VId, aFace2V)) {
540           Standard_NullObject::Raise("Can not retrieve a sub-shape with given Id");
541         }
542
543         if (aFace2V.ShapeType() != TopAbs_FACE) {
544           Standard_TypeMismatch::Raise("Sub-shape with given Id is not a face");
545         }
546       }
547
548       Standard_Integer aNbIterU = aCI.GetNbIterU();
549       Standard_Integer aNbIterV = aCI.GetNbIterV();
550
551       MultiTransformate2D(aBlock,
552                           aFace1U, aFace2U, aNbIterU,
553                           aFace1V, aFace2V, aNbIterV, aMulti);
554
555     } else {
556       return 0;
557     }
558
559     if (aMulti.IsNull()) {
560       StdFail_NotDone::Raise("Multi-transformation failed");
561       return 0;
562     }
563
564     // Glue faces of the multi-block
565     aShape = GEOMImpl_GlueDriver::GlueFaces(aMulti, aTol);
566   }
567
568   if (aShape.IsNull()) return 0;
569
570   aFunction->SetValue(aShape);
571
572   log.SetTouched(Label());
573
574   return 1;
575 }
576
577 //=======================================================================
578 //function :  MultiTransformate1D
579 //purpose  :
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
586 {
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);
591
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);
596   }
597
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
601
602   if (dir_face2 == 2) { // <theFace2> is opposite to <theFace1>
603
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:
608
609     //          _________
610     //        /|v23     /|
611     //       / |       / |    dir_face1 - bottom
612     //      /  |      /  |
613     //     /________ /   |    dir_face2 - top
614     //    |v21 |    |v22 |
615     //    |    |____|____|
616     //    |   / v13 |   /
617     //    |  /      |  /
618     //    | /       | /
619     //    |/________|/
620     //     v11       v12
621
622     v11_id = aBlockTool.GetVertexID(dir_face1, 1);
623     v12_id = aBlockTool.GetVertexID(dir_face1, 2);
624     v13_id = aBlockTool.GetVertexID(dir_face1, 4);
625
626     v21_id = aBlockTool.GetVertexID(dir_face2, 1);
627     v22_id = aBlockTool.GetVertexID(dir_face2, 2);
628     v23_id = aBlockTool.GetVertexID(dir_face2, 4);
629
630   } else {
631
632     //          _________
633     //        /|        /|
634     //       / |       / |    dir_face1 - bottom
635     //      /  |      /  |
636     //     /________ /   |    dir_face2 - right (for example)
637     //    |    |    |v23 |
638     //    |    |____|____|
639     //    |   /     |   /v12 = v22 (common_vertex2)
640     //    |  /      |  /
641     //    | /       | /
642     //    |/________|/
643     //     v13       v11 = v21 (common_vertex1)
644
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);
648
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);
656       vid++;
657     }
658
659     Standard_Integer not_common_v2 = 0;
660     vid = 1;
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);
666       vid++;
667     }
668
669     v11_id = common_vertex1;
670     v12_id = common_vertex2;
671     v13_id = not_common_v1;
672
673     v21_id = common_vertex1;
674     v22_id = common_vertex2;
675     v23_id = not_common_v2;
676   }
677
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));
682
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));
686
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);
692
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);
698
699   gp_Trsf aTrsf;
700   aTrsf.SetDisplacement(Ax1, Ax2);
701
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");
707   }
708
709   // Perform multi-transformation
710   TopoDS_Compound aCompound;
711   BRep_Builder B;
712   B.MakeCompound(aCompound);
713
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();
719   }
720   theResult = aCompound;
721 }
722
723 //=======================================================================
724 //function :  MultiTransformate2D
725 //purpose  :
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
735 {
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);
740
741   gp_Trsf aTrsfU, aTrsfV;
742   gp_Ax3 Ax1V, Ax2V;
743   for (Standard_Integer uv = 1; uv <= 2; uv++) {
744     // U transformation
745     TopoDS_Shape theFace1 = theFace1U;
746     TopoDS_Shape theFace2 = theFace2U;
747     if (uv == 2) {
748       // V transformation
749       theFace1 = theFace1V;
750       theFace2 = theFace2V;
751     }
752
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;
759     } else {
760       dir_face2 = aBlockTool.GetFaceID(theFace2);
761     }
762
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
766
767     if (dir_face2 == opp_face1) { // <theFace2> is opposite to <theFace1>
768
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:
773
774       v11_id = aBlockTool.GetVertexID(dir_face1, 1);
775       v12_id = aBlockTool.GetVertexID(dir_face1, 2);
776       v13_id = aBlockTool.GetVertexID(dir_face1, 4);
777
778       v21_id = aBlockTool.GetVertexID(dir_face2, 1);
779       v22_id = aBlockTool.GetVertexID(dir_face2, 2);
780       v23_id = aBlockTool.GetVertexID(dir_face2, 4);
781
782     } else {
783
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);
787
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);
795         vid++;
796       }
797
798       Standard_Integer not_common_v2 = 0;
799       vid = 1;
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);
805         vid++;
806       }
807
808       v11_id = common_vertex1;
809       v12_id = common_vertex2;
810       v13_id = not_common_v1;
811
812       v21_id = common_vertex1;
813       v22_id = common_vertex2;
814       v23_id = not_common_v2;
815     }
816
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));
821
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));
825
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);
831
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);
837
838     gp_Trsf aTrsf;
839     aTrsf.SetDisplacement(Ax1, Ax2);
840     if (uv == 1) {
841       aTrsfU = aTrsf;
842     } else {
843       aTrsfV = aTrsf;
844       Ax1V = Ax1;
845       Ax2V = Ax2;
846     }
847
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");
853     }
854   }
855
856   // Perform multi-transformation
857   TopoDS_Compound aCompound;
858   BRep_Builder B;
859   B.MakeCompound(aCompound);
860
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();
868     }
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);
875     // Correction done
876   }
877   theResult = aCompound;
878 }
879
880 //=======================================================================
881 //function :  GEOMImpl_BlockDriver_Type_
882 //purpose  :
883 //=======================================================================
884 Standard_EXPORT Handle_Standard_Type& GEOMImpl_BlockDriver_Type_()
885 {
886
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);
893
894
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),
898                                                          1,
899                                                          (Standard_Address)_Ancestors,
900                                                          (Standard_Address)NULL);
901
902   return _aType;
903 }
904
905 //=======================================================================
906 //function : DownCast
907 //purpose  :
908 //=======================================================================
909 const Handle(GEOMImpl_BlockDriver) Handle(GEOMImpl_BlockDriver)::DownCast(const Handle(Standard_Transient)& AnObject)
910 {
911   Handle(GEOMImpl_BlockDriver) _anOtherObject;
912
913   if (!AnObject.IsNull()) {
914      if (AnObject->IsKind(STANDARD_TYPE(GEOMImpl_BlockDriver))) {
915        _anOtherObject = Handle(GEOMImpl_BlockDriver)((Handle(GEOMImpl_BlockDriver)&)AnObject);
916      }
917   }
918
919   return _anOtherObject ;
920 }