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