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