]> SALOME platform Git repositories - modules/geom.git/blob - src/GEOMImpl/GEOMImpl_BlockDriver.cxx
Salome HOME
92dbc1be252d438fb9db8f1399017d5b8de9bc01
[modules/geom.git] / src / GEOMImpl / GEOMImpl_BlockDriver.cxx
1 // Copyright (C) 2007-2021  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 #include <Standard_Stream.hxx>
24
25 #include <BRepOffsetAPI_MakeFilling.hxx>
26
27 #include <GEOMImpl_BlockDriver.hxx>
28 #include <GEOMImpl_IBlocks.hxx>
29 #include <GEOMImpl_IBlockTrsf.hxx>
30 #include <GEOMImpl_GlueDriver.hxx>
31 #include <GEOMImpl_Types.hxx>
32 #include <GEOMImpl_ILocalOperations.hxx>
33 #include <GEOMImpl_Block6Explorer.hxx>
34 #include <GEOMImpl_IBlocksOperations.hxx>
35
36 #include <GEOM_Function.hxx>
37
38 #include <ShHealOper_Sewing.hxx>
39 #include <ShHealOper_ShapeProcess.hxx>
40 //#include <GEOMAlgo_Gluer.hxx>
41 #include <BlockFix_BlockFixAPI.hxx>
42 #include <BlockFix_UnionFaces.hxx>
43
44 #include "utilities.h"
45
46 #include <TNaming_CopyShape.hxx>
47
48 #include <BRepAdaptor_Curve.hxx>
49 #include <BRepLib.hxx>
50 #include <BRep_Tool.hxx>
51 #include <BRepTools.hxx>
52 #include <BRepGProp.hxx>
53 #include <BRep_Builder.hxx>
54 #include <BRepTools_Quilt.hxx>
55 #include <BRepTools_WireExplorer.hxx>
56 #include <BRepBuilderAPI_MakeEdge.hxx>
57 #include <BRepBuilderAPI_MakeWire.hxx>
58 #include <BRepBuilderAPI_MakePolygon.hxx>
59 #include <BRepBuilderAPI_Transform.hxx>
60 #include <BRepCheck_Analyzer.hxx>
61 #include <BRepClass_FaceClassifier.hxx>
62 #include <BRepClass3d_SolidClassifier.hxx>
63 #include <BRepExtrema_ExtPF.hxx>
64 #include <BRepExtrema_DistShapeShape.hxx>
65
66 #include <ShapeUpgrade_UnifySameDomain.hxx>
67
68 #include <TopAbs.hxx>
69 #include <TopoDS.hxx>
70 #include <TopoDS_Shape.hxx>
71 #include <TopoDS_Edge.hxx>
72 #include <TopoDS_Wire.hxx>
73 #include <TopoDS_Shell.hxx>
74 #include <TopoDS_Solid.hxx>
75 #include <TopoDS_Compound.hxx>
76 #include <TopoDS_Iterator.hxx>
77 #include <TopExp.hxx>
78 #include <TopExp_Explorer.hxx>
79 #include <TopTools_MapOfShape.hxx>
80 #include <TopTools_MapIteratorOfMapOfShape.hxx>
81 #include <TopTools_Array1OfShape.hxx>
82 #include <TopTools_SequenceOfShape.hxx>
83 #include <TopTools_ListOfShape.hxx>
84 #include <TopTools_ListIteratorOfListOfShape.hxx>
85 #include <TopTools_IndexedMapOfShape.hxx>
86 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
87
88 #include <GProp_GProps.hxx>
89
90 #include <Geom_Line.hxx>
91 #include <GC_MakeLine.hxx>
92
93 #include <gp.hxx>
94 #include <gp_Pnt.hxx>
95 #include <gp_Ax3.hxx>
96 #include <Precision.hxx>
97 #include <TColgp_Array1OfPnt.hxx>
98 #include <TColStd_Array1OfInteger.hxx>
99 #include <TColStd_IndexedDataMapOfTransientTransient.hxx>
100 #include <StdFail_NotDone.hxx>
101 #include <Standard_NullObject.hxx>
102 #include <Standard_TypeMismatch.hxx>
103 #include <Standard_ConstructionError.hxx>
104
105 //=======================================================================
106 //function : GetID
107 //purpose  :
108 //=======================================================================
109 const Standard_GUID& GEOMImpl_BlockDriver::GetID()
110 {
111   static Standard_GUID aBlockDriver("FF1BBB67-5D14-4df2-980B-3A668264EA16");
112   return aBlockDriver;
113 }
114
115
116 //=======================================================================
117 //function : GEOMImpl_BlockDriver
118 //purpose  :
119 //=======================================================================
120 GEOMImpl_BlockDriver::GEOMImpl_BlockDriver()
121 {
122 }
123
124 //=======================================================================
125 //function : Execute
126 //purpose  :
127 //=======================================================================
128 Standard_Integer GEOMImpl_BlockDriver::Execute(Handle(TFunction_Logbook)& log) const
129 {
130   if (Label().IsNull()) return 0;
131   Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
132
133   Standard_Integer aType = aFunction->GetType();
134
135   TopoDS_Shape aShape;
136   BRep_Builder B;
137
138   Standard_Real prec = Precision::Confusion();
139
140   Standard_Integer aNbSub = 0;
141   if (aType == BLOCK_COMPOUND_GLUE) {
142
143     aNbSub = 1;
144
145   } else if (aType == BLOCK_FACE_TWO_EDGES ||
146              aType == BLOCK_TWO_FACES) {
147
148     aNbSub = 2;
149
150   } else if (aType == BLOCK_FACE_FOUR_PNT ||
151              aType == BLOCK_FACE_FOUR_EDGES) {
152
153     aNbSub = 4;
154
155   } else if (aType == BLOCK_SIX_FACES) {
156
157     aNbSub = 6;
158
159   } else {
160   }
161
162   if (aNbSub > 0) {
163     GEOMImpl_IBlocks aCI (aFunction);
164     Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes();
165     Standard_Integer nbshapes = aShapes->Length();
166
167     if (nbshapes != aNbSub) {
168       Standard_TypeMismatch::Raise
169         ("Number of elements for object construction does not correspond to the used constructor");
170     }
171
172     TopTools_Array1OfShape anArgs (1, aNbSub);
173     Standard_Integer argi;
174     for (argi = 1; argi <= aNbSub; argi++) {
175       Handle(GEOM_Function) aRef = Handle(GEOM_Function)::DownCast(aShapes->Value(argi));
176       TopoDS_Shape anArg = aRef->GetValue();
177       if (anArg.IsNull()) {
178         Standard_NullObject::Raise("Null shape is given as argument");
179       }
180       anArgs(argi) = anArg;
181     }
182
183     if (aType == BLOCK_FACE_FOUR_EDGES) {
184
185       // Make face from four edges
186       if (anArgs(1).ShapeType() != TopAbs_EDGE || anArgs(2).ShapeType() != TopAbs_EDGE ||
187           anArgs(3).ShapeType() != TopAbs_EDGE || anArgs(4).ShapeType() != TopAbs_EDGE) {
188         Standard_TypeMismatch::Raise("Shape for face construction is not an edge");
189       }
190
191       // count corner vertices
192       TopTools_MapOfShape aVertMap;
193       for (Standard_Integer ii = 1; ii <= 4; ii++) {
194         TopoDS_Edge anEdge = TopoDS::Edge(anArgs(ii));
195         TopoDS_Vertex V1, V2;
196         TopExp::Vertices(anEdge, V1, V2, Standard_True);
197         if (V1.IsNull() || V2.IsNull()) {
198           Standard_NullObject::Raise("Bad edge for face construction: vertex is not defined");
199         }
200         if (BRepTools::Compare(V1,V2)) {
201           Standard_ConstructionError::Raise("Edge ends are too close");
202         }
203         Standard_Boolean isCoin1 = Standard_False, isCoin2 = Standard_False;
204         TopTools_MapIteratorOfMapOfShape anIter (aVertMap);
205         for (; anIter.More(); anIter.Next()) {
206           TopoDS_Vertex V = TopoDS::Vertex(anIter.Key());
207           if (BRepTools::Compare(V,V1)) isCoin1 = Standard_True;
208           if (BRepTools::Compare(V,V2)) isCoin2 = Standard_True;
209         }
210         if (!isCoin1) aVertMap.Add(V1);
211         if (!isCoin2) aVertMap.Add(V2);
212       }
213       if (aVertMap.Extent() != 4) {
214         Standard_ConstructionError::Raise("The edges must form a closed wire");
215       }
216
217       TopoDS_Edge anEdge1 = TopoDS::Edge(anArgs(1));
218       TopoDS_Edge anEdge2 = TopoDS::Edge(anArgs(2));
219       TopoDS_Edge anEdge3 = TopoDS::Edge(anArgs(3));
220       TopoDS_Edge anEdge4 = TopoDS::Edge(anArgs(4));
221
222       // check, if anEdge1 has common/coincident vertex with anEdge2,
223       Standard_Boolean isConnected12 = Standard_False;
224       TopoDS_Vertex V11, V12, V21, V22;
225       TopExp::Vertices(anEdge1, V11, V12, Standard_True);
226       TopExp::Vertices(anEdge2, V21, V22, Standard_True);
227       if (BRepTools::Compare(V11,V21) || BRepTools::Compare(V11,V22) ||
228           BRepTools::Compare(V12,V21) || BRepTools::Compare(V12,V22)) {
229         // the edges have common vertex
230         isConnected12 = Standard_True;
231       }
232
233       // build wire in right order, corresponding to edges connexity
234       BRepBuilderAPI_MakeWire* MW;
235       if (isConnected12)
236         MW = new BRepBuilderAPI_MakeWire(anEdge1, anEdge2, anEdge3, anEdge4);
237       else
238         MW = new BRepBuilderAPI_MakeWire(anEdge1, anEdge3, anEdge2, anEdge4);
239
240       if (!MW->IsDone()) {
241         Standard_ConstructionError::Raise
242           ("Impossible to build a connected wire from the given edges");
243       }
244       TopoDS_Wire aWire = *MW;
245       delete MW;
246
247       // check the wire closure
248       TopoDS_Vertex aV1, aV2;
249       TopExp::Vertices(aWire, aV1, aV2);
250       if ( !aV1.IsNull() && !aV2.IsNull() && aV1.IsSame(aV2) )
251         aWire.Closed( true );
252
253       if (!aWire.Closed()) {
254         Standard_ConstructionError::Raise
255           ("Impossible to build a closed wire from the given edges");
256       }
257
258       // try to build face on the wire
259       GEOMImpl_Block6Explorer::MakeFace(aWire, Standard_False, aShape);
260       if (aShape.IsNull()) {
261         Standard_ConstructionError::Raise("Face construction failed");
262       }
263
264     } else if (aType == BLOCK_FACE_TWO_EDGES) {
265
266       // Make face from two opposite edges
267       if (anArgs(1).ShapeType() != TopAbs_EDGE ||
268           anArgs(2).ShapeType() != TopAbs_EDGE) {
269         Standard_TypeMismatch::Raise("Shape for face construction is not an edge");
270       }
271
272       TopoDS_Edge anEdge1 = TopoDS::Edge(anArgs(1));
273       TopoDS_Edge anEdge2 = TopoDS::Edge(anArgs(2));
274
275       if (anEdge1.IsSame(anEdge2)) {
276         Standard_ConstructionError::Raise("The edges must be different");
277       }
278
279       // create two edges, linking ends of the given edges
280       TopoDS_Vertex V11, V12, V21, V22;
281       TopExp::Vertices(anEdge1, V11, V12, Standard_False);
282       TopExp::Vertices(anEdge2, V21, V22, Standard_False);
283       if (V11.IsNull() || V12.IsNull() ||
284           V21.IsNull() || V22.IsNull()) {
285         Standard_NullObject::Raise("Bad edge for face construction: vertex is not defined");
286       }
287
288       BRepAdaptor_Curve C1 (anEdge1);
289       BRepAdaptor_Curve C2 (anEdge2);
290       gp_Pnt P11, P12, P21, P22;
291
292       // Mantis issue 0020599: Creation of a quadrangle face from 2 edges: SIGSEGV
293       P11 = C1.Value(C1.FirstParameter());
294       P12 = C1.Value(C1.LastParameter());
295       P21 = C2.Value(C2.FirstParameter());
296       P22 = C2.Value(C2.LastParameter());
297       //gp_Pnt P11 = BRep_Tool::Pnt(V11);
298       //gp_Pnt P12 = BRep_Tool::Pnt(V12);
299       //gp_Pnt P21 = BRep_Tool::Pnt(V21);
300       //gp_Pnt P22 = BRep_Tool::Pnt(V22);
301
302       if (P11.Distance(P21) < prec || P12.Distance(P22) < prec ||
303           P11.Distance(P22) < prec || P12.Distance(P21) < prec) {
304         Standard_ConstructionError::Raise("Given edges have too close ends");
305       }
306
307       Standard_Real per11 = P11.Distance(P21) + P12.Distance(P22);
308       Standard_Real per12 = P11.Distance(P22) + P12.Distance(P21);
309
310       BRep_Builder BB;
311
312       TopoDS_Edge anEdge3;
313       TopoDS_Edge anEdge4;
314
315       // Mantis issue 0020599: Creation of a quadrangle face from 2 edges: SIGSEGV
316       if (per11 < per12) {
317         Handle(Geom_Line) Line1 = GC_MakeLine(P11, P21).Value();
318         Handle(Geom_Line) Line2 = GC_MakeLine(P12, P22).Value();
319
320         BB.MakeEdge(anEdge3, Line1, Precision::Confusion());
321         BB.Range(anEdge3, 0., P11.Distance(P21));
322         BB.Add(anEdge3, V11.Oriented(TopAbs_FORWARD));
323         BB.Add(anEdge3, V21.Oriented(TopAbs_REVERSED));
324
325         BB.MakeEdge(anEdge4, Line2, Precision::Confusion());
326         BB.Range(anEdge4, 0., P12.Distance(P22));
327         BB.Add(anEdge4, V12.Oriented(TopAbs_FORWARD));
328         BB.Add(anEdge4, V22.Oriented(TopAbs_REVERSED));
329       }
330       else {
331         Handle(Geom_Line) Line1 = GC_MakeLine(P11, P22).Value();
332         Handle(Geom_Line) Line2 = GC_MakeLine(P12, P21).Value();
333
334         BB.MakeEdge(anEdge3, Line1, Precision::Confusion());
335         BB.Range(anEdge3, 0., P11.Distance(P22));
336         BB.Add(anEdge3, V11.Oriented(TopAbs_FORWARD));
337         BB.Add(anEdge3, V22.Oriented(TopAbs_REVERSED));
338
339         BB.MakeEdge(anEdge4, Line2, Precision::Confusion());
340         BB.Range(anEdge4, 0., P12.Distance(P21));
341         BB.Add(anEdge4, V12.Oriented(TopAbs_FORWARD));
342         BB.Add(anEdge4, V21.Oriented(TopAbs_REVERSED));
343       }
344       //if (per11 < per12) {
345       //  anEdge3 = BRepBuilderAPI_MakeEdge(V11, V21);
346       //  anEdge4 = BRepBuilderAPI_MakeEdge(V12, V22);
347       //} else {
348       //  anEdge3 = BRepBuilderAPI_MakeEdge(V11, V22);
349       //  anEdge4 = BRepBuilderAPI_MakeEdge(V12, V21);
350       //}
351
352       // build a wire
353       BRepBuilderAPI_MakeWire* MW;
354       MW = new BRepBuilderAPI_MakeWire(anEdge1, anEdge3, anEdge2, anEdge4);
355       if (!MW->IsDone()) {
356         Standard_ConstructionError::Raise("Wire construction failed");
357       }
358
359       TopoDS_Wire aWire = *MW;
360       delete MW;
361
362       TopoDS_Vertex aV1, aV2;
363       TopExp::Vertices(aWire, aV1, aV2);
364       if ( !aV1.IsNull() && !aV2.IsNull() && aV1.IsSame(aV2) )
365         aWire.Closed( true );
366
367       if (!aWire.Closed()) {
368         Standard_ConstructionError::Raise
369           ("Impossible to build a closed wire from the given edges");
370       }
371
372       // try to build face on the wire
373       GEOMImpl_Block6Explorer::MakeFace(aWire, Standard_False, aShape);
374       if (aShape.IsNull()) {
375         Standard_ConstructionError::Raise("Face construction failed");
376       }
377
378     } else if (aType == BLOCK_FACE_FOUR_PNT) {
379
380       // Make face from four corner vertices
381       if (anArgs(1).ShapeType() != TopAbs_VERTEX ||
382           anArgs(2).ShapeType() != TopAbs_VERTEX ||
383           anArgs(3).ShapeType() != TopAbs_VERTEX ||
384           anArgs(4).ShapeType() != TopAbs_VERTEX) {
385         Standard_TypeMismatch::Raise("Shape for face construction is not a vertex");
386       }
387
388       TopoDS_Vertex V1 = TopoDS::Vertex(anArgs(1));
389       TopoDS_Vertex V2 = TopoDS::Vertex(anArgs(2));
390       TopoDS_Vertex V3 = TopoDS::Vertex(anArgs(3));
391       TopoDS_Vertex V4 = TopoDS::Vertex(anArgs(4));
392
393       gp_Pnt P1 = BRep_Tool::Pnt(V1);
394       gp_Pnt P2 = BRep_Tool::Pnt(V2);
395       gp_Pnt P3 = BRep_Tool::Pnt(V3);
396       gp_Pnt P4 = BRep_Tool::Pnt(V4);
397
398       if (P1.Distance(P2) < prec || P1.Distance(P3) < prec ||
399           P1.Distance(P4) < prec || P2.Distance(P3) < prec ||
400           P2.Distance(P4) < prec || P3.Distance(P4) < prec) {
401         Standard_ConstructionError::Raise("Four not coincident points must be given");
402       }
403
404       // calculate perimeters
405       Standard_Real per1234 = P1.Distance(P2) + P2.Distance(P3) +
406                               P3.Distance(P4) + P4.Distance(P1);
407       Standard_Real per1243 = P1.Distance(P2) + P2.Distance(P4) +
408                               P4.Distance(P3) + P3.Distance(P1);
409       Standard_Real per1324 = P1.Distance(P3) + P3.Distance(P2) +
410                               P2.Distance(P4) + P4.Distance(P1);
411
412       // order vertices
413       if (per1243 < per1234 && per1243 < per1324) {
414         TopoDS_Vertex Vtmp = V3;
415         V3 = V4;
416         V4 = Vtmp;
417       } else if (per1324 < per1234 && per1324 < per1243) {
418         TopoDS_Vertex Vtmp = V3;
419         V3 = V2;
420         V2 = Vtmp;
421       } else {
422       }
423
424       // build wire
425       BRepBuilderAPI_MakePolygon aMkPoly (V1, V2, V3, V4, Standard_True);
426       if (!aMkPoly.IsDone()) {
427         Standard_ConstructionError::Raise("Polygon construction failed");
428       }
429
430       // try to build face on the wire
431       aMkPoly.Close();
432       GEOMImpl_Block6Explorer::MakeFace(aMkPoly, Standard_False, aShape);
433       if (aShape.IsNull()) {
434         Standard_ConstructionError::Raise("Face construction failed");
435       }
436
437     } else if (aType == BLOCK_SIX_FACES || aType == BLOCK_TWO_FACES) {
438
439       BRepTools_Quilt Glue;
440
441       if (aType == BLOCK_SIX_FACES) {
442         // Make block (hexahedral solid) from six faces
443         for (Standard_Integer ind = 1; ind <= nbshapes; ind++) {
444           if (anArgs(ind).ShapeType() != TopAbs_FACE) {
445             Standard_TypeMismatch::Raise("Shape for block construction is not a face");
446           }
447           Glue.Add(anArgs(ind));
448         }
449
450       }
451       else {
452         // Make block (hexahedral solid) from two opposite faces
453         if (anArgs(1).ShapeType() != TopAbs_FACE ||
454             anArgs(2).ShapeType() != TopAbs_FACE) {
455           Standard_TypeMismatch::Raise("Shape for block construction is not a face");
456         }
457
458         // Get wires of the given faces
459         TopExp_Explorer wires1 (anArgs(1), TopAbs_WIRE);
460         TopExp_Explorer wires2 (anArgs(2), TopAbs_WIRE);
461         if (!wires1.More() || !wires2.More()) {
462           Standard_ConstructionError::Raise("A face for the block has no wires");
463         }
464         TopoDS_Shape aWire1 = wires1.Current();
465         TopoDS_Shape aWire2 = wires2.Current();
466         wires1.Next();
467         wires2.Next();
468         if (wires1.More() || wires2.More()) {
469           Standard_ConstructionError::Raise("A face for the block has more than one wire");
470         }
471
472         GEOMImpl_Block6Explorer aBlockTool;
473         aBlockTool.InitByTwoFaces(anArgs(1), anArgs(2));
474
475         // Construct the linking faces and add them in the gluing tool
476         Glue.Add(anArgs(1));
477         Glue.Add(aBlockTool.GetFace(3, Standard_True));
478         Glue.Add(aBlockTool.GetFace(4, Standard_True));
479         Glue.Add(aBlockTool.GetFace(5, Standard_True));
480         Glue.Add(aBlockTool.GetFace(6, Standard_True));
481         Glue.Add(anArgs(2));
482       }
483
484       TopExp_Explorer exp (Glue.Shells(), TopAbs_SHELL);
485       Standard_Integer ish = 0;
486       TopTools_MapOfShape mapShape;
487       for (; exp.More(); exp.Next()) {
488         if (mapShape.Add(exp.Current())) {
489           aShape = exp.Current();
490           ish++;
491         }
492       }
493
494       if (ish > 1) {
495         aShape = Glue.Shells();
496         Standard_Real aTol = prec; // Precision::Confusion()
497         TopExp_Explorer expF (aShape, TopAbs_FACE);
498         TopTools_MapOfShape mapF;
499         TopoDS_Shell Shell;
500         B.MakeShell(Shell);
501         for (; expF.More(); expF.Next()) {
502           if (mapF.Add(expF.Current())) {
503             B.Add(Shell, expF.Current());
504             Standard_Real aToler = BRep_Tool::Tolerance(TopoDS::Face(expF.Current()));
505             if (aToler > aTol)
506               aTol = aToler;
507           }
508         }
509         ShHealOper_Sewing aHealer (Shell, aTol);
510         if (aHealer.Perform())
511           aShape = aHealer.GetResultShape();
512         else
513           Standard_ConstructionError::Raise
514             ("Impossible to build a connected shell on the given faces");
515       }
516
517       if (aType == BLOCK_SIX_FACES) {
518         if (!aShape.Closed()) {
519           Standard_ConstructionError::Raise
520             ("Impossible to build a closed shell on the given faces");
521         }
522       }
523
524       TopoDS_Solid Sol;
525       B.MakeSolid(Sol);
526       B.Add(Sol, aShape);
527       BRepClass3d_SolidClassifier SC (Sol);
528       SC.PerformInfinitePoint(prec);
529       if (SC.State() == TopAbs_IN) {
530         B.MakeSolid(Sol);
531         B.Add(Sol, aShape.Reversed());
532       }
533       aShape = Sol;
534       BRepLib::SameParameter(aShape, 1.E-5, Standard_True);
535     }
536     else if (aType == BLOCK_COMPOUND_GLUE) {
537       // Make blocks compound from a compound
538       if (anArgs(1).ShapeType() != TopAbs_COMPOUND &&
539           anArgs(2).ShapeType() != TopAbs_COMPSOLID) {
540         Standard_TypeMismatch::Raise("Not a compound given");
541       }
542
543       TopoDS_Shape aCompound = anArgs(1);
544
545       // Glue coincident faces and edges
546       aShape = GEOMImpl_GlueDriver::GlueFaces(aCompound, Precision::Confusion(), Standard_True);
547       //GEOMAlgo_Gluer aGluer;
548       //aGluer.SetShape(aCompound);
549       //aGluer.SetCheckGeometry(Standard_True);
550       //aGluer.Perform();
551       //aShape = aGluer.Result();
552     }
553     else {
554     }
555
556   } else { // Multi-transformations and compound improving
557
558     if (aType == BLOCK_REMOVE_EXTRA ||
559         aType == BLOCK_COMPOUND_IMPROVE) {
560
561       GEOMImpl_IBlockTrsf aCI (aFunction);
562       Handle(GEOM_Function) aRefShape = aCI.GetOriginal();
563       TopoDS_Shape aBlockOrComp = aRefShape->GetValue();
564       if (aBlockOrComp.IsNull()) {
565         Standard_NullObject::Raise("Null Shape given");
566       }
567
568       // Copy shape to avoid problems (Mantis issue 0021683)
569       TopoDS_Shape aShapeCopy;
570       TColStd_IndexedDataMapOfTransientTransient aMapTShapes;
571       TNaming_CopyShape::CopyTool(aBlockOrComp, aMapTShapes, aShapeCopy);
572       aBlockOrComp = aShapeCopy;
573
574       // 1. Improve solids with seam and/or degenerated edges
575       BlockFix_BlockFixAPI aTool;
576       //aTool.Tolerance() = toler;
577       aTool.OptimumNbFaces() = aCI.GetOptimumNbFaces();
578       aTool.SetShape(aBlockOrComp);
579       aTool.Perform();
580
581       TopoDS_Shape aFixedExtra = aTool.Shape();
582
583       // Repair result
584       BRepCheck_Analyzer ana (aFixedExtra, false);
585       if (!ana.IsValid()) {
586         TopoDS_Shape aFixed;
587         ShHealOper_ShapeProcess aHealer;
588         aHealer.Perform(aFixedExtra, aFixed);
589         if (aHealer.isDone())
590           aFixedExtra = aFixed;
591       }
592
593       if (aType == BLOCK_REMOVE_EXTRA)
594       {
595         aShape = aFixedExtra;
596
597         if (aShape == aBlockOrComp) {
598           MESSAGE("No modifications have been done");
599         }
600       }
601       else // aType == BLOCK_COMPOUND_IMPROVE
602       {
603         // 2. Separate non-blocks
604         TopTools_ListOfShape BLO; // All blocks from the given compound
605         TopTools_ListOfShape NOT; // Not blocks
606         TopTools_ListOfShape EXT; // Hexahedral solids, having degenerated and/or seam edges
607         TopTools_ListOfShape NOQ; // All non-quadrangular faces
608         GEOMImpl_IBlocksOperations::AddBlocksFrom(aFixedExtra, BLO, NOT, EXT, NOQ);
609
610         if (NOT.Extent() > 0) {
611           MESSAGE("Some non-blocks have been removed");
612         }
613
614         // 3. Warn about staying extra-edges
615         if (EXT.Extent() > 0) {
616           MESSAGE("Warning: Not all seam or degenerated edges was removed");
617         }
618
619         // ??? Throw away standalone blocks ???
620
621         // 4. Create compound of all blocks
622         TopoDS_Compound aComp;
623         BRep_Builder BB;
624         BB.MakeCompound(aComp);
625         TopTools_ListIteratorOfListOfShape BLOit (BLO);
626         for (; BLOit.More(); BLOit.Next()) {
627           BB.Add(aComp, BLOit.Value());
628         }
629
630         // 5. Glue Faces
631         aShape = GEOMImpl_GlueDriver::GlueFaces(aComp, Precision::Confusion(), Standard_False);
632       }
633
634     } else if (aType == BLOCK_MULTI_TRANSFORM_1D ||
635                aType == BLOCK_MULTI_TRANSFORM_2D) {
636
637       TopoDS_Shape aMulti;
638       GEOMImpl_IBlockTrsf aCI (aFunction);
639       Handle(GEOM_Function) aRefShape = aCI.GetOriginal();
640       TopoDS_Shape aBlockIni = aRefShape->GetValue();
641       if (aBlockIni.IsNull()) {
642         Standard_NullObject::Raise("Null Block");
643       }
644
645       // Copy block to avoid problems (PAL6706)
646       TColStd_IndexedDataMapOfTransientTransient aMap;
647       TopoDS_Shape aBlock;
648       TNaming_CopyShape::CopyTool(aBlockIni, aMap, aBlock);
649
650       // Block tolerance in vertices
651       Standard_Real aTol = prec;
652       TopExp_Explorer expV (aBlock, TopAbs_VERTEX);
653       TopTools_MapOfShape mapShape;
654       for (; expV.More(); expV.Next()) {
655         if (mapShape.Add(expV.Current())) {
656           TopoDS_Vertex aV = TopoDS::Vertex(expV.Current());
657           aTol = Max(BRep_Tool::Tolerance(aV), aTol);
658         }
659       }
660
661       if (aType == BLOCK_MULTI_TRANSFORM_1D) {
662         // Retrieve a faces by Ids
663         Standard_Integer aFace1Id = aCI.GetFace1U();
664         Standard_Integer aFace2Id = aCI.GetFace2U();
665         TopoDS_Shape aFace1, aFace2;
666         if (!GEOMImpl_ILocalOperations::GetSubShape(aBlock, aFace1Id, aFace1)) {
667           Standard_NullObject::Raise("Can not retrieve a sub-shape with given Id");
668         }
669         if (aFace1.ShapeType() != TopAbs_FACE) {
670           Standard_TypeMismatch::Raise("Sub-shape with given Id is not a face");
671         }
672
673         if (aFace2Id > 0) {
674           if (!GEOMImpl_ILocalOperations::GetSubShape(aBlock, aFace2Id, aFace2)) {
675             Standard_NullObject::Raise("Can not retrieve a sub-shape with given Id");
676           }
677           if (aFace2.ShapeType() != TopAbs_FACE) {
678             Standard_TypeMismatch::Raise("Sub-shape with given Id is not a face");
679           }
680         }
681
682         Standard_Integer aNbIter = aCI.GetNbIterU();
683
684         MultiTransformate1D(aBlock, aFace1, aFace2, aNbIter, aMulti);
685
686       } else { // aType == BLOCK_MULTI_TRANSFORM_2D
687         // Retrieve a faces by Ids
688         Standard_Integer aFace1UId = aCI.GetFace1U();
689         Standard_Integer aFace2UId = aCI.GetFace2U();
690         Standard_Integer aFace1VId = aCI.GetFace1V();
691         Standard_Integer aFace2VId = aCI.GetFace2V();
692
693         TopoDS_Shape aFace1U, aFace2U, aFace1V, aFace2V;
694         if (!GEOMImpl_ILocalOperations::GetSubShape(aBlock, aFace1UId, aFace1U) ||
695             !GEOMImpl_ILocalOperations::GetSubShape(aBlock, aFace1VId, aFace1V)) {
696           Standard_NullObject::Raise("Can not retrieve a sub-shape with given Id");
697         }
698
699         if (aFace1U.ShapeType() != TopAbs_FACE ||
700             aFace1V.ShapeType() != TopAbs_FACE) {
701           Standard_TypeMismatch::Raise("Sub-shape with given Id is not a face");
702         }
703
704         if (aFace2UId > 0) {
705           if (!GEOMImpl_ILocalOperations::GetSubShape(aBlock, aFace2UId, aFace2U)) {
706             Standard_NullObject::Raise("Can not retrieve a sub-shape with given Id");
707           }
708
709           if (aFace2U.ShapeType() != TopAbs_FACE) {
710             Standard_TypeMismatch::Raise("Sub-shape with given Id is not a face");
711           }
712         }
713
714         if (aFace2VId > 0) {
715           if (!GEOMImpl_ILocalOperations::GetSubShape(aBlock, aFace2VId, aFace2V)) {
716             Standard_NullObject::Raise("Can not retrieve a sub-shape with given Id");
717           }
718
719           if (aFace2V.ShapeType() != TopAbs_FACE) {
720             Standard_TypeMismatch::Raise("Sub-shape with given Id is not a face");
721           }
722         }
723
724         Standard_Integer aNbIterU = aCI.GetNbIterU();
725         Standard_Integer aNbIterV = aCI.GetNbIterV();
726
727         MultiTransformate2D(aBlock,
728                             aFace1U, aFace2U, aNbIterU,
729                             aFace1V, aFace2V, aNbIterV, aMulti);
730       }
731
732       if (aMulti.IsNull()) {
733         StdFail_NotDone::Raise("Multi-transformation failed");
734       }
735
736       // Glue faces of the multi-block
737       aShape = GEOMImpl_GlueDriver::GlueFaces(aMulti, aTol, Standard_False);
738
739     } else if (aType == BLOCK_UNION_FACES) {
740       GEOMImpl_IBlockTrsf aCI (aFunction);
741       Handle(GEOM_Function) aRefShape = aCI.GetOriginal();
742       TopoDS_Shape aBlockOrComp = aRefShape->GetValue();
743       if (aBlockOrComp.IsNull()) {
744         Standard_NullObject::Raise("Null Shape given");
745       }
746
747       //BlockFix_UnionFaces aFaceUnifier;
748       //aFaceUnifier.GetOptimumNbFaces() = 0; // To force union faces.
749       //aShape = aFaceUnifier.Perform(aBlockOrComp);
750       // Use OCCT algo ShapeUpgrade_UnifySameDomain instead of BlockFix_UnionFaces:
751       Standard_Boolean isUnifyEdges = Standard_False;
752       Standard_Boolean isUnifyFaces = Standard_True;
753       Standard_Boolean isConcatBSplines = Standard_True;
754       ShapeUpgrade_UnifySameDomain aUnifier (aBlockOrComp,
755                                              isUnifyEdges, isUnifyFaces, isConcatBSplines);
756       aUnifier.SetLinearTolerance(Precision::Confusion());
757       aUnifier.SetAngularTolerance(Precision::Confusion());
758       aUnifier.Build();
759       aShape = aUnifier.Shape();
760     } else { // unknown function type
761       return 0;
762     }
763   }
764
765   if (aShape.IsNull()) return 0;
766
767   aFunction->SetValue(aShape);
768
769   log->SetTouched(Label());
770
771   return 1;
772 }
773
774 //=======================================================================
775 //function :  MultiTransformate1D
776 //purpose  :
777 //=======================================================================
778 void GEOMImpl_BlockDriver::MultiTransformate1D (const TopoDS_Shape&    theBlock,
779                                                 const TopoDS_Shape&    theFace1,
780                                                 const TopoDS_Shape&    theFace2,
781                                                 const Standard_Integer theNbIter,
782                                                 TopoDS_Shape&          theResult) const
783 {
784   // Construct Tool, where <theFace1> will be the first face,
785   // and a face, opposite to <theFace1>, will be the second face
786   GEOMImpl_Block6Explorer aBlockTool;
787   aBlockTool.InitByBlockAndFace(theBlock, theFace1);
788
789   // Find IDs of the faces
790   Standard_Integer dir_face1 = 1, dir_face2 = 2;
791   if (!theFace2.IsNull()) {
792     dir_face2 = aBlockTool.GetFaceID(theFace2);
793   }
794
795   // Find three pairs of points
796   Standard_Integer v11_id = 0, v12_id = 0, v13_id = 0; // vertices of the first face
797   Standard_Integer v21_id = 0, v22_id = 0, v23_id = 0; // vertices of the second face
798
799   if (dir_face2 == 2) { // <theFace2> is opposite to <theFace1>
800
801     // We will take vertices with equal local numbers on the faces,
802     // as the Block6Explorer gives equal local numbers
803     // to the linked vertices on the opposite faces,
804     // i.e. v1* is linked with the v2* by an edge:
805
806     //          _________
807     //        /|v23     /|
808     //       / |       / |    dir_face1 - bottom
809     //      /  |      /  |
810     //     /________ /   |    dir_face2 - top
811     //    |v21 |    |v22 |
812     //    |    |____|____|
813     //    |   / v13 |   /
814     //    |  /      |  /
815     //    | /       | /
816     //    |/________|/
817     //     v11       v12
818
819     v11_id = aBlockTool.GetVertexID(dir_face1, 1);
820     v12_id = aBlockTool.GetVertexID(dir_face1, 2);
821     v13_id = aBlockTool.GetVertexID(dir_face1, 4);
822
823     v21_id = aBlockTool.GetVertexID(dir_face2, 1);
824     v22_id = aBlockTool.GetVertexID(dir_face2, 2);
825     v23_id = aBlockTool.GetVertexID(dir_face2, 4);
826
827   } else {
828
829     //          _________
830     //        /|        /|
831     //       / |       / |    dir_face1 - bottom
832     //      /  |      /  |
833     //     /________ /   |    dir_face2 - right (for example)
834     //    |    |    |v23 |
835     //    |    |____|____|
836     //    |   /     |   /v12 = v22 (common_vertex2)
837     //    |  /      |  /
838     //    | /       | /
839     //    |/________|/
840     //     v13       v11 = v21 (common_vertex1)
841
842     Standard_Integer common_edge_id = aBlockTool.FindCommonEdgeID(dir_face1, dir_face2);
843     Standard_Integer common_vertex1 = aBlockTool.GetVertexOnEdgeID(common_edge_id, 1);
844     Standard_Integer common_vertex2 = aBlockTool.GetVertexOnEdgeID(common_edge_id, 2);
845
846     Standard_Integer not_common_v1 = 0;
847     Standard_Integer vid = 1;
848     Standard_Boolean isFound = Standard_False;
849     while (!isFound && vid <= 4) {
850       not_common_v1 = aBlockTool.GetVertexID(dir_face1, vid);
851       isFound = (not_common_v1 != common_vertex2 &&
852                  aBlockTool.FindEdgeID(not_common_v1, common_vertex1) != 0);
853       vid++;
854     }
855
856     Standard_Integer not_common_v2 = 0;
857     vid = 1;
858     isFound = Standard_False;
859     while (!isFound && vid <= 4) {
860       not_common_v2 = aBlockTool.GetVertexID(dir_face2, vid);
861       isFound = (not_common_v2 != common_vertex2 &&
862                  aBlockTool.FindEdgeID(not_common_v2, common_vertex1) != 0);
863       vid++;
864     }
865
866     v11_id = common_vertex1;
867     v12_id = common_vertex2;
868     v13_id = not_common_v1;
869
870     v21_id = common_vertex1;
871     v22_id = common_vertex2;
872     v23_id = not_common_v2;
873   }
874
875   // Construct a transformation operator
876   TopoDS_Vertex V11 = TopoDS::Vertex(aBlockTool.GetVertex(v11_id));
877   TopoDS_Vertex V12 = TopoDS::Vertex(aBlockTool.GetVertex(v12_id));
878   TopoDS_Vertex V13 = TopoDS::Vertex(aBlockTool.GetVertex(v13_id));
879
880   TopoDS_Vertex V21 = TopoDS::Vertex(aBlockTool.GetVertex(v21_id));
881   TopoDS_Vertex V22 = TopoDS::Vertex(aBlockTool.GetVertex(v22_id));
882   TopoDS_Vertex V23 = TopoDS::Vertex(aBlockTool.GetVertex(v23_id));
883
884   // Axes of the first direction face
885   gp_Pnt P1 = BRep_Tool::Pnt(V11);
886   gp_Vec VecN1 (P1, BRep_Tool::Pnt(V12));
887   gp_Vec VecX1 (P1, BRep_Tool::Pnt(V13));
888   gp_Ax3 Ax1 (P1, VecN1, VecX1);
889
890   // Axes of the second direction face
891   gp_Pnt P2 = BRep_Tool::Pnt(V21);
892   gp_Vec VecN2 (P2, BRep_Tool::Pnt(V22));
893   gp_Vec VecX2 (P2, BRep_Tool::Pnt(V23));
894   gp_Ax3 Ax2 (P2, VecN2, VecX2);
895
896   gp_Trsf aTrsf;
897   aTrsf.SetDisplacement(Ax1, Ax2);
898
899   // Check, that <theFace2> is similar to <theFace1>.
900   // Actually, we need only to check right position of one
901   // vertex, not involved into the transformation construction.
902   if (!aBlockTool.IsSimilarFaces(dir_face1, dir_face2, aTrsf)) {
903     Standard_ConstructionError::Raise("The direction faces are not similar");
904   }
905
906   // Perform multi-transformation
907   TopoDS_Compound aCompound;
908   BRep_Builder B;
909   B.MakeCompound(aCompound);
910
911   TopoDS_Shape aPrevShape = theBlock;
912   for (Standard_Integer i = 0; i < theNbIter; i++) {
913     B.Add(aCompound, aPrevShape);
914     BRepBuilderAPI_Transform aTransformation (aPrevShape, aTrsf, Standard_False);
915     aPrevShape = aTransformation.Shape();
916   }
917   theResult = aCompound;
918 }
919
920 //=======================================================================
921 //function :  MultiTransformate2D
922 //purpose  :
923 //=======================================================================
924 void GEOMImpl_BlockDriver::MultiTransformate2D (const TopoDS_Shape&    theBlock,
925                                                 const TopoDS_Shape&    theFace1U,
926                                                 const TopoDS_Shape&    theFace2U,
927                                                 const Standard_Integer theNbIterU,
928                                                 const TopoDS_Shape&    theFace1V,
929                                                 const TopoDS_Shape&    theFace2V,
930                                                 const Standard_Integer theNbIterV,
931                                                 TopoDS_Shape&          theResult) const
932 {
933   // Construct Tool, where <theFace1U> will be the first face,
934   // and a face, opposite to <theFace1U>, will be the second face
935   GEOMImpl_Block6Explorer aBlockTool;
936   aBlockTool.InitByBlockAndFace(theBlock, theFace1U);
937
938   gp_Trsf aTrsfU, aTrsfV;
939   gp_Ax3 Ax1V, Ax2V;
940   for (Standard_Integer uv = 1; uv <= 2; uv++) {
941     // U transformation
942     TopoDS_Shape theFace1 = theFace1U;
943     TopoDS_Shape theFace2 = theFace2U;
944     if (uv == 2) {
945       // V transformation
946       theFace1 = theFace1V;
947       theFace2 = theFace2V;
948     }
949
950     // Find IDs of the faces
951     Standard_Integer dir_face1 = aBlockTool.GetFaceID(theFace1);
952     Standard_Integer dir_face2 = 0;
953     Standard_Integer opp_face1 = aBlockTool.GetOppositeFaceID(dir_face1);
954     if (theFace2.IsNull()) {
955       dir_face2 = opp_face1;
956     } else {
957       dir_face2 = aBlockTool.GetFaceID(theFace2);
958     }
959
960     // Find three pairs of points
961     Standard_Integer v11_id = 0, v12_id = 0, v13_id = 0; // vertices of the first face
962     Standard_Integer v21_id = 0, v22_id = 0, v23_id = 0; // vertices of the second face
963
964     if (dir_face2 == opp_face1) { // <theFace2> is opposite to <theFace1>
965
966       // We will take vertices with equal local numbers on the faces,
967       // as the Block6Explorer gives equal local numbers
968       // to the linked vertices on the opposite faces,
969       // i.e. v1* is linked with the v2* by an edge:
970
971       v11_id = aBlockTool.GetVertexID(dir_face1, 1);
972       v12_id = aBlockTool.GetVertexID(dir_face1, 2);
973       v13_id = aBlockTool.GetVertexID(dir_face1, 4);
974
975       v21_id = aBlockTool.GetVertexID(dir_face2, 1);
976       v22_id = aBlockTool.GetVertexID(dir_face2, 2);
977       v23_id = aBlockTool.GetVertexID(dir_face2, 4);
978
979     } else {
980
981       Standard_Integer common_edge_id = aBlockTool.FindCommonEdgeID(dir_face1, dir_face2);
982       Standard_Integer common_vertex1 = aBlockTool.GetVertexOnEdgeID(common_edge_id, 1);
983       Standard_Integer common_vertex2 = aBlockTool.GetVertexOnEdgeID(common_edge_id, 2);
984
985       Standard_Integer not_common_v1 = 0;
986       Standard_Integer vid = 1;
987       Standard_Boolean isFound = Standard_False;
988       while (!isFound && vid <= 4) {
989         not_common_v1 = aBlockTool.GetVertexID(dir_face1, vid);
990         isFound = (not_common_v1 != common_vertex2 &&
991                    aBlockTool.FindEdgeID(not_common_v1, common_vertex1) != 0);
992         vid++;
993       }
994
995       Standard_Integer not_common_v2 = 0;
996       vid = 1;
997       isFound = Standard_False;
998       while (!isFound && vid <= 4) {
999         not_common_v2 = aBlockTool.GetVertexID(dir_face2, vid);
1000         isFound = (not_common_v2 != common_vertex2 &&
1001                    aBlockTool.FindEdgeID(not_common_v2, common_vertex1) != 0);
1002         vid++;
1003       }
1004
1005       v11_id = common_vertex1;
1006       v12_id = common_vertex2;
1007       v13_id = not_common_v1;
1008
1009       v21_id = common_vertex1;
1010       v22_id = common_vertex2;
1011       v23_id = not_common_v2;
1012     }
1013
1014     // Construct a transformation operator
1015     TopoDS_Vertex V11 = TopoDS::Vertex(aBlockTool.GetVertex(v11_id));
1016     TopoDS_Vertex V12 = TopoDS::Vertex(aBlockTool.GetVertex(v12_id));
1017     TopoDS_Vertex V13 = TopoDS::Vertex(aBlockTool.GetVertex(v13_id));
1018
1019     TopoDS_Vertex V21 = TopoDS::Vertex(aBlockTool.GetVertex(v21_id));
1020     TopoDS_Vertex V22 = TopoDS::Vertex(aBlockTool.GetVertex(v22_id));
1021     TopoDS_Vertex V23 = TopoDS::Vertex(aBlockTool.GetVertex(v23_id));
1022
1023     // Axes of the first direction face
1024     gp_Pnt P1 = BRep_Tool::Pnt(V11);
1025     gp_Vec VecN1 (P1, BRep_Tool::Pnt(V12));
1026     gp_Vec VecX1 (P1, BRep_Tool::Pnt(V13));
1027     gp_Ax3 Ax1 (P1, VecN1, VecX1);
1028
1029     // Axes of the second direction face
1030     gp_Pnt P2 = BRep_Tool::Pnt(V21);
1031     gp_Vec VecN2 (P2, BRep_Tool::Pnt(V22));
1032     gp_Vec VecX2 (P2, BRep_Tool::Pnt(V23));
1033     gp_Ax3 Ax2 (P2, VecN2, VecX2);
1034
1035     gp_Trsf aTrsf;
1036     aTrsf.SetDisplacement(Ax1, Ax2);
1037     if (uv == 1) {
1038       aTrsfU = aTrsf;
1039     } else {
1040       aTrsfV = aTrsf;
1041       Ax1V = Ax1;
1042       Ax2V = Ax2;
1043     }
1044
1045     // Check, that <theFace2> is similar to <theFace1>.
1046     // Actually, we need only to check right position of one
1047     // vertex, not involved into the transformation construction.
1048     if (!aBlockTool.IsSimilarFaces(dir_face1, dir_face2, aTrsf)) {
1049       Standard_ConstructionError::Raise("The direction faces are not similar");
1050     }
1051   }
1052
1053   // Perform multi-transformation
1054   TopoDS_Compound aCompound;
1055   BRep_Builder B;
1056   B.MakeCompound(aCompound);
1057
1058   TopoDS_Shape aPrevShapeU = theBlock;
1059   for (int i = 0; i < theNbIterU; i++) {
1060     TopoDS_Shape aPrevShapeV = aPrevShapeU;
1061     for (int j = 0; j < theNbIterV; j++) {
1062       B.Add(aCompound, aPrevShapeV);
1063       BRepBuilderAPI_Transform aTransformationV (aPrevShapeV, aTrsfV, Standard_False);
1064       aPrevShapeV = aTransformationV.Shape();
1065     }
1066     BRepBuilderAPI_Transform aTransformationU (aPrevShapeU, aTrsfU, Standard_False);
1067     aPrevShapeU = aTransformationU.Shape();
1068     // Correction of the second transformation according to the first transformation
1069     Ax1V.Transform(aTrsfU);
1070     Ax2V.Transform(aTrsfU);
1071     aTrsfV.SetDisplacement(Ax1V, Ax2V);
1072     // Correction done
1073   }
1074   theResult = aCompound;
1075 }
1076
1077 //================================================================================
1078 /*!
1079  * \brief Returns a name of creation operation and names and values of creation parameters
1080  */
1081 //================================================================================
1082
1083 bool GEOMImpl_BlockDriver::
1084 GetCreationInformation(std::string&             theOperationName,
1085                        std::vector<GEOM_Param>& theParams)
1086 {
1087   if (Label().IsNull()) return 0;
1088   Handle(GEOM_Function) function = GEOM_Function::GetFunction(Label());
1089
1090   Standard_Integer aType = function->GetType();
1091   GEOMImpl_IBlocks    aCI1 (function);
1092   GEOMImpl_IBlockTrsf aCI2 (function);
1093   Handle(TColStd_HSequenceOfTransient) aShapes = aCI1.GetShapes();
1094
1095   switch ( aType ) {
1096   case BLOCK_FACE_FOUR_EDGES:
1097     theOperationName = "Q_FACE";
1098     AddParam( theParams, "Edge 1", aShapes->Value(1) );
1099     AddParam( theParams, "Edge 2", aShapes->Value(2) );
1100     AddParam( theParams, "Edge 3", aShapes->Value(3) );
1101     AddParam( theParams, "Edge 4", aShapes->Value(4) );
1102     break;
1103   case BLOCK_FACE_TWO_EDGES:
1104     theOperationName = "Q_FACE";
1105     AddParam( theParams, "Edge 1", aShapes->Value(1) );
1106     AddParam( theParams, "Edge 2", aShapes->Value(2) );
1107     break;
1108   case BLOCK_FACE_FOUR_PNT:
1109     theOperationName = "Q_FACE";
1110     AddParam( theParams, "Point 1", aShapes->Value(1) );
1111     AddParam( theParams, "Point 2", aShapes->Value(2) );
1112     AddParam( theParams, "Point 3", aShapes->Value(3) );
1113     AddParam( theParams, "Point 4", aShapes->Value(4) );
1114     break;
1115   case BLOCK_SIX_FACES:
1116     theOperationName = "HEX_SOLID";
1117     AddParam( theParams, "Face 1", aShapes->Value(1) );
1118     AddParam( theParams, "Face 2", aShapes->Value(2) );
1119     AddParam( theParams, "Face 3", aShapes->Value(3) );
1120     AddParam( theParams, "Face 4", aShapes->Value(4) );
1121     AddParam( theParams, "Face 5", aShapes->Value(5) );
1122     AddParam( theParams, "Face 6", aShapes->Value(6) );
1123     break;
1124   case BLOCK_TWO_FACES:
1125     theOperationName = "HEX_SOLID";
1126     AddParam( theParams, "Face 1", aShapes->Value(1) );
1127     AddParam( theParams, "Face 2", aShapes->Value(2) );
1128     break;
1129   case BLOCK_COMPOUND_GLUE:
1130     theOperationName = "MakeBlockCompound";
1131     AddParam( theParams, "Compound", aShapes->Value(1) );
1132     break;
1133   case BLOCK_REMOVE_EXTRA:
1134     theOperationName = "REMOVE_EXTRA_EDGES";
1135     AddParam( theParams, "Selected shape", aCI2.GetOriginal() );
1136     AddParam( theParams, "Union faces", aCI2.GetOptimumNbFaces() == 0);
1137     break;
1138   case BLOCK_COMPOUND_IMPROVE:
1139     theOperationName = "CHECK_COMPOUND";
1140     AddParam( theParams, "Selected shape", aCI2.GetOriginal() );
1141     break;
1142   case BLOCK_MULTI_TRANSFORM_1D:
1143     theOperationName = "MUL_TRANSFORM";
1144     AddParam( theParams, "Main Object", aCI2.GetOriginal() );
1145     AddParam( theParams, "Face 1", aCI2.GetFace1U() );
1146     AddParam( theParams, "Face 2", aCI2.GetFace2U() );
1147     AddParam( theParams, "Nb. Times", aCI2.GetNbIterU() );
1148     break;
1149   case BLOCK_MULTI_TRANSFORM_2D:
1150     theOperationName = "MUL_TRANSFORM";
1151     AddParam( theParams, "Main Object", aCI2.GetOriginal() );
1152     AddParam( theParams, "Face 1 U", aCI2.GetFace1U() );
1153     AddParam( theParams, "Face 2 U", aCI2.GetFace2U() );
1154     AddParam( theParams, "Nb. Times V", aCI2.GetNbIterV() );
1155     AddParam( theParams, "Face 1 V", aCI2.GetFace1V() );
1156     AddParam( theParams, "Face 2 V", aCI2.GetFace2V() );
1157     AddParam( theParams, "Nb. Times V", aCI2.GetNbIterV() );
1158     break;
1159   case BLOCK_UNION_FACES:
1160     theOperationName = "UNION_FACES";
1161     AddParam( theParams, "Selected shape", aCI2.GetOriginal() );
1162     break;
1163   default:
1164     return false;
1165   }
1166
1167   return true;
1168 }
1169
1170 IMPLEMENT_STANDARD_RTTIEXT (GEOMImpl_BlockDriver,GEOM_BaseDriver)