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