Salome HOME
Merge V8_4_BR branch.
[modules/geom.git] / src / AdvancedEngine / AdvancedEngine_IOperations.cxx
1 // Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 //  File   : AdvancedEngine_IOperations.cxx
20 //  Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
21
22 #include "AdvancedEngine_IOperations.hxx"
23 #include "AdvancedEngine_PipeTShapeDriver.hxx"
24 #include "AdvancedEngine_IPipeTShape.hxx"
25 #include "AdvancedEngine_DividedDiskDriver.hxx"
26 #include "AdvancedEngine_IDividedDisk.hxx"
27 #include "AdvancedEngine_SmoothingSurfaceDriver.hxx"
28 #include "AdvancedEngine_ISmoothingSurface.hxx"
29
30 #include <utilities.h>
31 #include <OpUtil.hxx>
32 #include <Utils_ExceptHandlers.hxx>
33
34 #include <GEOM_Function.hxx>
35 #include <GEOM_PythonDump.hxx>
36 #include <GEOMUtils.hxx>
37 #include <GEOMAlgo_ClsfSurf.hxx>
38 #include <GEOMAlgo_FinderShapeOn2.hxx>
39 #include <GEOMAlgo_Splitter.hxx>
40
41 #include <GEOMImpl_Gen.hxx>
42 #include <GEOMImpl_Types.hxx>
43
44 #include <GEOMImpl_IBasicOperations.hxx>
45 #include <GEOMImpl_IBooleanOperations.hxx>
46 #include <GEOMImpl_IShapesOperations.hxx>
47 #include <GEOMImpl_ITransformOperations.hxx>
48 #include <GEOMImpl_IBlocksOperations.hxx>
49 #include <GEOMImpl_I3DPrimOperations.hxx>
50 #include <GEOMImpl_ILocalOperations.hxx>
51 #include <GEOMImpl_IHealingOperations.hxx>
52 #include <GEOMImpl_IGroupOperations.hxx>
53 #include <GEOMImpl_GlueDriver.hxx>
54
55 #include <TDF_Tool.hxx>
56 #include <TFunction_DriverTable.hxx>
57 #include <TFunction_Driver.hxx>
58 #include <TNaming_CopyShape.hxx>
59
60 #include <TopExp.hxx>
61 #include <TopExp_Explorer.hxx>
62 #include <TopoDS.hxx>
63 #include <TopoDS_Vertex.hxx>
64 #include <TopTools_IndexedMapOfShape.hxx>
65 #include <TopTools_ListIteratorOfListOfShape.hxx>
66 #include <TColStd_IndexedDataMapOfTransientTransient.hxx>
67
68 #include <BRep_Builder.hxx>
69 #include <BRep_Tool.hxx>
70
71 #include <BRepAdaptor_Surface.hxx>
72 #include <BRepAlgoAPI_Cut.hxx>
73 #include <BRepAlgoAPI_Fuse.hxx>
74 #include <BRepBuilderAPI_MakeFace.hxx>
75 #include <BRepBuilderAPI_MakeVertex.hxx>
76 #include <BRepBuilderAPI_Transform.hxx>
77 #include <BRepPrimAPI_MakeCone.hxx>
78 #include <BRepPrimAPI_MakeCylinder.hxx>
79
80 #include <gp_Ax3.hxx>
81 #include <gp_Pln.hxx>
82 #include <gp_Pnt.hxx>
83 #include <gp_Vec.hxx>
84 #include <GC_MakeConicalSurface.hxx>
85 #include <Geom_CylindricalSurface.hxx>
86
87 #include <ShapeAnalysis_Edge.hxx>
88
89 #include <cmath>
90
91 #include "AdvancedEngine_Types.hxx"
92
93 #include <Standard_Stream.hxx>
94 #include <Standard_Failure.hxx>
95 #include <StdFail_NotDone.hxx>
96 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
97
98 #define HALF_LENGTH_MAIN_PIPE     "Main pipe half length" //"Tuyau principal - demi longueur"
99 #define HALF_LENGTH_INCIDENT_PIPE "Incident pipe half length" //"Tuyau incident - demi longueur"
100 #define CIRCULAR_QUARTER_PIPE     "Circular quarter of pipe" //"Circulaire - quart de tuyau"
101 #define THICKNESS                 "Thickness" //"Epaisseur"
102 #define FLANGE                    "Flange" // "Collerette"
103 #define CHAMFER_OR_FILLET         "Chamfer or fillet" //"Chanfrein ou Raccord"
104 #define JUNCTION_FACE_1           "Junction 1" //"Face de jonction 1"
105 #define JUNCTION_FACE_2           "Junction 2" //"Face de jonction 2"
106 #define JUNCTION_FACE_3           "Junction 3" //"Face de jonction 3"
107
108 #define FIND_GROUPS_BY_POINTS 1
109
110 // Undefine below macro to enable workaround about fillet problem in MakePipeTShapeFillet
111 // VSR 30/12/2014: macro enabled
112 #define FILLET_FIX_TOLERANCE
113
114 //=============================================================================
115 /*!
116  *  Constructor
117  */
118 //=============================================================================
119 AdvancedEngine_IOperations::AdvancedEngine_IOperations(GEOM_Engine* theEngine, int theDocID) :
120   GEOM_IOperations(theEngine, theDocID)
121 {
122   MESSAGE("AdvancedEngine_IOperations::AdvancedEngine_IOperations");
123   myBasicOperations     = new GEOMImpl_IBasicOperations(GetEngine(), GetDocID());
124   myBooleanOperations   = new GEOMImpl_IBooleanOperations(GetEngine(), GetDocID());
125   myShapesOperations    = new GEOMImpl_IShapesOperations(GetEngine(), GetDocID());
126   myTransformOperations = new GEOMImpl_ITransformOperations(GetEngine(), GetDocID());
127   myBlocksOperations    = new GEOMImpl_IBlocksOperations(GetEngine(), GetDocID());
128   my3DPrimOperations    = new GEOMImpl_I3DPrimOperations(GetEngine(), GetDocID());
129   myLocalOperations     = new GEOMImpl_ILocalOperations(GetEngine(), GetDocID());
130   myHealingOperations   = new GEOMImpl_IHealingOperations(GetEngine(), GetDocID());
131   myGroupOperations     = new GEOMImpl_IGroupOperations(GetEngine(), GetDocID());
132 }
133
134 //=============================================================================
135 /*!
136  *  Destructor
137  */
138 //=============================================================================
139 AdvancedEngine_IOperations::~AdvancedEngine_IOperations()
140 {
141   MESSAGE("AdvancedEngine_IOperations::~AdvancedEngine_IOperations");
142   delete myBasicOperations;
143   delete myBooleanOperations;
144   delete myShapesOperations;
145   delete myTransformOperations;
146   delete myBlocksOperations;
147   delete my3DPrimOperations;
148   delete myLocalOperations;
149   delete myHealingOperations;
150   delete myGroupOperations;
151 }
152
153 //=============================================================================
154 /*!
155  *  SetPosition
156  */
157 //=============================================================================
158 gp_Trsf AdvancedEngine_IOperations::GetPositionTrsf(double theL1, double theL2,
159                                                     Handle(GEOM_Object) theP1,
160                                                     Handle(GEOM_Object) theP2,
161                                                     Handle(GEOM_Object) theP3)
162 {
163   // Old Local Coordinates System oldLCS
164   gp_Pnt P0(0, 0, 0);
165   gp_Pnt P1(-theL1, 0, 0);
166   gp_Pnt P2(theL1, 0, 0);
167   gp_Pnt P3(0, 0, theL2);
168
169   gp_Dir oldX(gp_Vec(P1, P2));
170   gp_Dir oldZ(gp_Vec(P0, P3));
171   gp_Ax3 oldLCS(P0, oldZ, oldX);
172
173   // New Local Coordinates System newLCS
174   double LocX, LocY, LocZ;
175   gp_Pnt newP1 = BRep_Tool::Pnt(TopoDS::Vertex(theP1->GetValue()));
176   gp_Pnt newP2 = BRep_Tool::Pnt(TopoDS::Vertex(theP2->GetValue()));
177   gp_Pnt newP3 = BRep_Tool::Pnt(TopoDS::Vertex(theP3->GetValue()));
178   LocX = (newP1.X() + newP2.X()) / 2.;
179   LocY = (newP1.Y() + newP2.Y()) / 2.;
180   LocZ = (newP1.Z() + newP2.Z()) / 2.;
181   gp_Pnt newO(LocX, LocY, LocZ);
182
183   gp_Dir newX(gp_Vec(newP1, newP2)); // P1P2 Vector
184   gp_Dir newZ(gp_Vec(newO, newP3)); // OP3 Vector
185   gp_Ax3 newLCS = gp_Ax3(newO, newZ, newX);
186
187   gp_Trsf aTrsf;
188   aTrsf.SetDisplacement(oldLCS, newLCS);
189
190   return aTrsf;
191 }
192
193 //=============================================================================
194 /*!
195  *  CheckCompatiblePosition
196  *
197  */
198 //=============================================================================
199 bool AdvancedEngine_IOperations::CheckCompatiblePosition(double& theL1, double& theL2,
200                                                          Handle(GEOM_Object) theP1,
201                                                          Handle(GEOM_Object) theP2,
202                                                          Handle(GEOM_Object) theP3,
203                                                          double theTolerance)
204 {
205   SetErrorCode(KO);
206   gp_Pnt P1 = BRep_Tool::Pnt(TopoDS::Vertex(theP1->GetValue()));
207   gp_Pnt P2 = BRep_Tool::Pnt(TopoDS::Vertex(theP2->GetValue()));
208   gp_Pnt P3 = BRep_Tool::Pnt(TopoDS::Vertex(theP3->GetValue()));
209
210   double d12 = P1.Distance(P2);
211   double d13 = P1.Distance(P3);
212   double d23 = P2.Distance(P3);
213   //    double d2 = newO.Distance(P3);
214
215   if (Abs(d12) <= Precision::Confusion()) {
216     SetErrorCode("Junctions points P1 and P2 are identical");
217     return false;
218   }
219   if (Abs(d13) <= Precision::Confusion()) {
220     SetErrorCode("Junctions points P1 and P3 are identical");
221     return false;
222   }
223   if (Abs(d23) <= Precision::Confusion()) {
224     SetErrorCode("Junctions points P2 and P3 are identical");
225     return false;
226   }
227
228
229   double newL1 = 0.5 * d12;
230   double newL2 = sqrt(pow(d13,2)-pow(newL1,2));
231   //
232   // theL1*(1-theTolerance) <= newL1 <= theL1*(1+theTolerance)
233   //
234   if (fabs(newL1 - theL1) > Precision::Approximation()) {
235     if ( (newL1 * (1 - theTolerance) -theL1 <= Precision::Approximation()) &&
236          (newL1 * (1 + theTolerance) -theL1 >= Precision::Approximation()) ) {
237       //            std::cerr << "theL1 = newL1" << std::endl;
238       theL1 = newL1;
239     } else {
240       theL1 = -1;
241       SetErrorCode("Dimension for main pipe (L1) is incompatible with new position");
242       return false;
243     }
244   }
245
246   //
247   // theL2*(1-theTolerance) <= newL2  <= theL2*(1+theTolerance)
248   //
249   if (fabs(newL2 - theL2) > Precision::Approximation()) {
250     if ( (newL2 * (1 - theTolerance) -theL2 <= Precision::Approximation()) &&
251          (newL2 * (1 + theTolerance) -theL2 >= Precision::Approximation()) ) {
252       theL2 = newL2;
253     } else {
254       theL2 = -1;
255       SetErrorCode("Dimension for incident pipe (L2) is incompatible with new position");
256       return false;
257     }
258   }
259
260   SetErrorCode(OK);
261   return true;
262
263 }
264
265 //=============================================================================
266 /*!
267  *  Generate the propagation groups of a Pipe T-Shape used for hexa mesh
268  */
269 //=============================================================================
270 bool AdvancedEngine_IOperations::MakeGroups(Handle(GEOM_Object) theShape, int shapeType,
271                                             double theR1, double theW1, double theL1,
272                                             double theR2, double theW2, double theL2,
273                                             double theH, double theW, double theRF,
274                                             Handle(TColStd_HSequenceOfTransient) theSeq,
275                                             gp_Trsf aTrsf)
276 {
277   SetErrorCode(KO);
278
279   if (theShape.IsNull()) return false;
280
281   TopoDS_Shape aShape = theShape->GetValue();
282   if (aShape.IsNull()) {
283     SetErrorCode("Shape is not defined");
284     return false;
285   }
286
287   gp_Trsf aTrsfInv = aTrsf.Inverted();
288
289 //   int expectedGroups = 0;
290 //   if (shapeType == TSHAPE_BASIC)
291 //     if (Abs(theR2+theW2-theR1-theW1) <= Precision::Approximation())
292 //       expectedGroups = 10;
293 //     else
294 //       expectedGroups = 11;
295 //   else if (shapeType == TSHAPE_CHAMFER || shapeType == TSHAPE_FILLET)
296 //     expectedGroups = 12;
297
298   double aR1Ext = theR1 + theW1;
299   double aR2Ext = theR2 + theW2;
300
301   /////////////////////////
302   //// Groups of Faces ////
303   /////////////////////////
304
305   //
306   // Comment the following lines when GetInPlace bug is solved
307   // == BEGIN
308   // Workaround of GetInPlace bug
309   // Create a bounding box that fits the shape
310   Handle(GEOM_Object) aBox = my3DPrimOperations->MakeBoxDXDYDZ(2*theL1, 2*aR1Ext, aR1Ext+theL2);
311   aBox->GetLastFunction()->SetDescription("");
312   myTransformOperations->TranslateDXDYDZ(aBox, -theL1, -aR1Ext, -aR1Ext);
313   aBox->GetLastFunction()->SetDescription("");
314   // Apply transformation to box
315   BRepBuilderAPI_Transform aTransformationBox(aBox->GetValue(), aTrsf, Standard_False);
316   TopoDS_Shape aBoxShapeTrsf = aTransformationBox.Shape();
317   aBox->GetLastFunction()->SetValue(aBoxShapeTrsf);
318
319   // Get the shell of the box
320   Handle(GEOM_Object) aShell = Handle(GEOM_Object)::DownCast
321     (myShapesOperations->MakeExplode(aBox, TopAbs_SHELL, true)->Value(1));
322   aBox->GetLastFunction()->SetDescription("");
323   aShell->GetLastFunction()->SetDescription("");
324   // Get the common shapes between shell and shape
325   Handle(GEOM_Object) aCommonCompound = myBooleanOperations->MakeBoolean
326                             (theShape, aShell, 1, Standard_False); // MakeCommon
327   if (aCommonCompound.IsNull()) {
328     SetErrorCode(myBooleanOperations->GetErrorCode());
329     return false;
330   }
331   aCommonCompound->GetLastFunction()->SetDescription("");
332   // Explode the faces of common shapes => 3 faces
333   Handle(TColStd_HSequenceOfTransient) aCommonFaces =
334     myShapesOperations->MakeExplode(aCommonCompound, TopAbs_FACE, true);
335   aCommonCompound->GetLastFunction()->SetDescription("");
336   std::list<Handle(GEOM_Object)> aCompoundOfFacesList;
337
338   for (int i=0 ; i<= aCommonFaces->Length()-4 ; i+=4) {
339     std::list<Handle(GEOM_Object)> aFacesList;
340     for (int j = 1 ; j <= 4 ; j++) {
341       Handle(GEOM_Object) aFace = Handle(GEOM_Object)::DownCast(aCommonFaces->Value(i+j)); // Junction faces
342       if (!aFace.IsNull()) {
343         aFace->GetLastFunction()->SetDescription("");
344         aFacesList.push_back(aFace);
345       }
346     }
347     Handle(GEOM_Object) aCompoundOfFaces = myShapesOperations->MakeCompound(aFacesList);
348     if (!aCompoundOfFaces.IsNull()) {
349       aCompoundOfFaces->GetLastFunction()->SetDescription("");
350       aCompoundOfFacesList.push_back(aCompoundOfFaces);
351     }
352   }
353
354   if (aCompoundOfFacesList.size() == 3) {
355     Handle(GEOM_Object) aPln1 = aCompoundOfFacesList.front();
356     aCompoundOfFacesList.pop_front();
357     Handle(GEOM_Object) aPln2 = aCompoundOfFacesList.front();
358     aCompoundOfFacesList.pop_front();
359     Handle(GEOM_Object) aPln3 = aCompoundOfFacesList.front();
360     aCompoundOfFacesList.pop_front();
361     // == END
362     //
363
364
365     //     Uncomment the following lines when GetInPlace bug is solved
366     //     == BEGIN
367 //     Handle(GEOM_Object) aP1 = myBasicOperations->MakePointXYZ(-theL1, 0, 0);
368 //     Handle(GEOM_Object) aP2 = myBasicOperations->MakePointXYZ(-0, 0, theL2);
369 //     Handle(GEOM_Object) aP3 = myBasicOperations->MakePointXYZ(theL1, 0, 0);
370 //     aP1->GetLastFunction()->SetDescription("");
371 //     aP2->GetLastFunction()->SetDescription("");
372 //     aP3->GetLastFunction()->SetDescription("");
373 //     Handle(GEOM_Object) aV1 = myBasicOperations->MakeVectorDXDYDZ(-1, 0, 0);
374 //     Handle(GEOM_Object) aV2 = myBasicOperations->MakeVectorDXDYDZ(0, 0, 1);
375 //     Handle(GEOM_Object) aV3 = myBasicOperations->MakeVectorDXDYDZ(1, 0, 0);
376 //     aV1->GetLastFunction()->SetDescription("");
377 //     aV2->GetLastFunction()->SetDescription("");
378 //     aV3->GetLastFunction()->SetDescription("");
379 //     Handle(GEOM_Object) aPln1 = myBasicOperations->MakePlanePntVec(aP1, aV1, 2*(aR1Ext+theL2));
380 //     Handle(GEOM_Object) aPln2 = myBasicOperations->MakePlanePntVec(aP2, aV2, 2*(aR2Ext));
381 //     Handle(GEOM_Object) aPln3 = myBasicOperations->MakePlanePntVec(aP3, aV3, 2*(aR1Ext+theL2));
382 //     aPln1->GetLastFunction()->SetDescription("");
383 //     aPln2->GetLastFunction()->SetDescription("");
384 //     aPln3->GetLastFunction()->SetDescription("");
385 //
386 //     BRepBuilderAPI_Transform aTransformation1(aPln1->GetValue(), aTrsf, Standard_False);
387 //     TopoDS_Shape aTrsf_Shape1 = aTransformation1.Shape();
388 //     aPln1->GetLastFunction()->SetValue(aTrsf_Shape1);
389 //     BRepBuilderAPI_Transform aTransformation2(aPln2->GetValue(), aTrsf, Standard_False);
390 //     TopoDS_Shape aTrsf_Shape2 = aTransformation2.Shape();
391 //     aPln2->GetLastFunction()->SetValue(aTrsf_Shape2);
392 //     BRepBuilderAPI_Transform aTransformation3(aPln3->GetValue(), aTrsf, Standard_False);
393 //     TopoDS_Shape aTrsf_Shape3 = aTransformation3.Shape();
394 //     aPln3->GetLastFunction()->SetValue(aTrsf_Shape3);
395     //     == END
396     //
397
398     Handle(GEOM_Object) junctionFaces1 = myShapesOperations->GetInPlace(theShape, aPln1);
399     if (junctionFaces1.IsNull())
400       junctionFaces1 = myShapesOperations->GetShapesOnShapeAsCompound
401         (aPln1, theShape, TopAbs_FACE,  GEOMAlgo_ST_ONIN);
402     if (!junctionFaces1.IsNull()) {
403       junctionFaces1->GetLastFunction()->SetDescription("");
404       junctionFaces1->SetName("JUNCTION_FACE_1");
405       theSeq->Append(junctionFaces1);
406     }
407     else {
408       SetErrorCode("Junction face 1 not found");
409       //        theSeq->Append(aPln1);
410       //        return false;
411     }
412     Handle(GEOM_Object) junctionFaces2 = myShapesOperations->GetInPlace(theShape, aPln2);
413     if (junctionFaces2.IsNull())
414       junctionFaces2 = myShapesOperations->GetShapesOnShapeAsCompound
415         (aPln2, theShape, TopAbs_FACE,  GEOMAlgo_ST_ONIN);
416     if (!junctionFaces2.IsNull()) {
417       junctionFaces2->GetLastFunction()->SetDescription("");
418       junctionFaces2->SetName("JUNCTION_FACE_2");
419       theSeq->Append(junctionFaces2);
420     }
421     else {
422       SetErrorCode("Junction face 2 not found");
423       //        theSeq->Append(aPln2);
424       //        return false;
425     }
426     Handle(GEOM_Object) junctionFaces3 = myShapesOperations->GetInPlace(theShape, aPln3);
427     if (junctionFaces3.IsNull())
428       junctionFaces3 = myShapesOperations->GetShapesOnShapeAsCompound
429         (aPln3, theShape, TopAbs_FACE,  GEOMAlgo_ST_ONIN);
430     if (!junctionFaces3.IsNull()) {
431       junctionFaces3->GetLastFunction()->SetDescription("");
432       junctionFaces3->SetName("JUNCTION_FACE_3");
433       theSeq->Append(junctionFaces3);
434     }
435     else {
436       SetErrorCode("Junction face 3 not found");
437       //        theSeq->Append(aPln3);
438       //        return false;
439     }
440   // Comment the following lines when GetInPlace bug is solved
441   // == BEGIN
442   }
443   //     == END
444
445   /////////////////////////
446   //// Groups of Edges ////
447   /////////////////////////
448   // Result of propagate
449
450   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
451
452   TCollection_AsciiString theDesc = aFunction->GetDescription();
453   Handle(TColStd_HSequenceOfTransient) aSeqPropagate = myBlocksOperations->Propagate(theShape);
454   if (aSeqPropagate.IsNull() || aSeqPropagate->Length() == 0) {
455     SetErrorCode("Propagation groups not found");
456     return false;
457   }
458   Standard_Integer aNbGroups = aSeqPropagate->Length();
459   // Recover previous description to get rid of Propagate dump
460   aFunction->SetDescription(theDesc);
461
462 #ifdef FIND_GROUPS_BY_POINTS
463   // BEGIN: new groups search
464
465   //              W2  R2
466   //            .----.-----.----.
467   //           e|    |  |  |    |
468   //            |    |  |  |    |
469   //            .    |  |  |    .
470   //         g / ''..|  |  |..'' \
471   //       f  /      '''''''      \
472   //  .---.--'..     |  |  |     ..'--.---.
473   //  |a    \   '''...........'''   /     |
474   //  |-------\------'  |  '------/-------.
475   //  |         \       |       /         |
476   // c|           \     |     /           |
477   //  |    R1       \   |   /             |
478   //  |               \ | /               |
479   //  ._________________|_________________.
480   //  |       L1        |                 |
481   //  |                 |                 |
482   //  |                 |                 |
483   // b|                 |                 |
484   //  |                 |                 |
485   //  |-----------------|-----------------|
486   //  |    W1           |                 |
487   //  '-----------------'-----------------'
488   //          d
489
490   // "Thickness" group (a)
491   gp_Pnt aPntA (-theL1, 0, theR1 + theW1/2.);
492   aPntA.Transform(aTrsf);
493   BRepBuilderAPI_MakeVertex mkVertexA (aPntA);
494   TopoDS_Vertex aVertA = TopoDS::Vertex(mkVertexA.Shape());
495   TopoDS_Shape anEdgeA = GEOMUtils::GetEdgeNearPoint(aShape, aVertA);
496
497   // "Circular quarter of pipe" group (b)
498   gp_Pnt aPntB (-theL1, -aR1Ext * sin(M_PI/4.), -aR1Ext * sin(M_PI/4.));
499   aPntB.Transform(aTrsf);
500   BRepBuilderAPI_MakeVertex mkVertexB (aPntB);
501   TopoDS_Vertex aVertB = TopoDS::Vertex(mkVertexB.Shape());
502   TopoDS_Shape anEdgeB = GEOMUtils::GetEdgeNearPoint(aShape, aVertB);
503
504   // "Circular quarter of pipe" group (c)
505   gp_Pnt aPntC (-theL1, -aR1Ext * sin(M_PI/4.), aR1Ext * sin(M_PI/4.));
506   aPntC.Transform(aTrsf);
507   BRepBuilderAPI_MakeVertex mkVertexC (aPntC);
508   TopoDS_Vertex aVertC = TopoDS::Vertex(mkVertexC.Shape());
509   TopoDS_Shape anEdgeC = GEOMUtils::GetEdgeNearPoint(aShape, aVertC);
510
511   // "Main pipe half length" group (d)
512   gp_Pnt aPntD (-theL1/2., 0, -aR1Ext);
513   aPntD.Transform(aTrsf);
514   BRepBuilderAPI_MakeVertex mkVertexD (aPntD);
515   TopoDS_Vertex aVertD = TopoDS::Vertex(mkVertexD.Shape());
516   TopoDS_Shape anEdgeD = GEOMUtils::GetEdgeNearPoint(aShape, aVertD);
517
518   // "Incident pipe half length" group (e)
519   double aTol10 = Precision::Confusion() * 10.;
520   gp_Pnt aPntE (-aR2Ext, 0, theL2 - aTol10);
521   aPntE.Transform(aTrsf);
522   BRepBuilderAPI_MakeVertex mkVertexE (aPntE);
523   TopoDS_Vertex aVertE = TopoDS::Vertex(mkVertexE.Shape());
524   TopoDS_Shape anEdgeE = GEOMUtils::GetEdgeNearPoint(aShape, aVertE);
525
526   // "Flange" group (f)
527   double aFx = - aR2Ext - aTol10;
528   if (shapeType == TSHAPE_CHAMFER)
529     aFx -= theW;
530   else if (shapeType == TSHAPE_FILLET)
531     aFx -= theRF;
532   gp_Pnt aPntF (aFx, 0, aR1Ext);
533   aPntF.Transform(aTrsf);
534   BRepBuilderAPI_MakeVertex mkVertexF (aPntF);
535   TopoDS_Vertex aVertF = TopoDS::Vertex(mkVertexF.Shape());
536   TopoDS_Shape anEdgeF = GEOMUtils::GetEdgeNearPoint(aShape, aVertF);
537
538   // "Chamfer or Fillet" group (g)
539   TopoDS_Shape anEdgeG;
540   if (shapeType == TSHAPE_CHAMFER) {
541     gp_Pnt aPntG (-aR2Ext - theW/2., 0, aR1Ext + theH/2.);
542     aPntG.Transform(aTrsf);
543     BRepBuilderAPI_MakeVertex mkVertexG (aPntG);
544     TopoDS_Vertex aVertG = TopoDS::Vertex(mkVertexG.Shape());
545     anEdgeG = GEOMUtils::GetEdgeNearPoint(aShape, aVertG);
546   }
547   else if (shapeType == TSHAPE_FILLET) {
548     gp_Pnt aPntG (-aR2Ext - theRF/2., 0, aR1Ext + theRF/2.);
549     aPntG.Transform(aTrsf);
550     BRepBuilderAPI_MakeVertex mkVertexG (aPntG);
551     TopoDS_Vertex aVertG = TopoDS::Vertex(mkVertexG.Shape());
552     anEdgeG = GEOMUtils::GetEdgeNearPoint(aShape, aVertG);
553   }
554
555   for (int i = 1 ; i <= aNbGroups; i++) {
556     Handle(GEOM_Object) aGroup = Handle(GEOM_Object)::DownCast(aSeqPropagate->Value(i));
557     if (aGroup.IsNull())
558       continue;
559
560     TopoDS_Shape aGroupShape = aGroup->GetValue();
561     TopTools_IndexedMapOfShape anEdgesMap;
562     TopExp::MapShapes(aGroupShape, TopAbs_EDGE, anEdgesMap);
563
564     if (anEdgesMap.Contains(anEdgeA)) { // a
565       aGroup->SetName("THICKNESS");
566       theSeq->Append(aGroup);
567     }
568     else if (anEdgesMap.Contains(anEdgeB)) { // b
569       aGroup->SetName("CIRCULAR_QUARTER_PIPE");
570       theSeq->Append(aGroup);
571     }
572     else if (anEdgesMap.Contains(anEdgeC)) { // c
573       aGroup->SetName("CIRCULAR_QUARTER_PIPE");
574       theSeq->Append(aGroup);
575     }
576     else if (anEdgesMap.Contains(anEdgeD)) { // d
577       aGroup->SetName("HALF_LENGTH_MAIN_PIPE");
578       theSeq->Append(aGroup);
579     }
580     else if (anEdgesMap.Contains(anEdgeE)) { // e
581       aGroup->SetName("HALF_LENGTH_INCIDENT_PIPE");
582       theSeq->Append(aGroup);
583     }
584     else if (anEdgesMap.Contains(anEdgeF)) { // f
585       aGroup->SetName("FLANGE");
586       theSeq->Append(aGroup);
587     }
588     else if (shapeType == TSHAPE_CHAMFER) { // g
589       if (anEdgesMap.Contains(anEdgeG)) {
590         aGroup->SetName("CHAMFER");
591         theSeq->Append(aGroup);
592       }
593     }
594     else if (shapeType == TSHAPE_FILLET) { // g
595       if (anEdgesMap.Contains(anEdgeG)) {
596         aGroup->SetName("FILLET");
597         theSeq->Append(aGroup);
598       }
599     }
600     else {
601     }
602   }
603   // END: new groups search
604 #else
605   bool addGroup;
606   bool circularFoundAndAdded = false;
607   bool circularFound10 = false;
608   bool incidentPipeFound = false;
609   bool mainPipeFound = false;
610   bool mainPipeFoundAndAdded = false;
611   bool radialFound =false;
612   bool flangeFound = false;
613   bool flangeFoundAndAdded = false;
614   bool chamferOrFilletFound = false;
615
616   for (int i = 1 ; i <= aNbGroups; i++) {
617     addGroup = false;
618
619     Handle(GEOM_Object) aGroup = Handle(GEOM_Object)::DownCast(aSeqPropagate->Value(i));
620     if (aGroup.IsNull())
621       continue;
622
623     TopoDS_Shape aGroupShape = aGroup->GetValue();
624     BRepBuilderAPI_Transform aTransformationShapeInv (aGroupShape, aTrsfInv, Standard_False);
625     TopoDS_Shape aGroupShapeTrsfInv = aTransformationShapeInv.Shape();
626
627     TopTools_IndexedMapOfShape anEdgesMap;
628     TopExp::MapShapes(aGroupShapeTrsfInv,TopAbs_EDGE, anEdgesMap);
629     Standard_Integer nbEdges = anEdgesMap.Extent();
630
631     if (shapeType == TSHAPE_BASIC) {
632       if ((nbEdges >= 21) || /*R1Ext = R2Ext*/(nbEdges == 17)) { // 17, 17+8*{1,2,3}, 21, 21+8*{1,2,3}
633         addGroup = true;
634         aGroup->SetName("THICKNESS");
635       }
636       else if (nbEdges == 6) {
637         if (!circularFoundAndAdded) {
638           circularFoundAndAdded = true;
639           addGroup = true;
640           aGroup->SetName("CIRCULAR_QUARTER_PIPE");
641         }
642       }
643       else if (nbEdges == 8) {
644         incidentPipeFound = true;
645         mainPipeFound = false;
646         radialFound = false;
647         flangeFound = false;
648
649         TopExp_Explorer Ex(aGroupShapeTrsfInv,TopAbs_VERTEX);
650         while (Ex.More()) {
651           gp_Pnt aP =  BRep_Tool::Pnt(TopoDS::Vertex(Ex.Current()));
652           double x=aP.X(), y=aP.Y(), z=aP.Z();
653
654
655           if ((Abs(x) > aR2Ext + Precision::Confusion()) ||
656               (Abs(y) > aR2Ext + Precision::Confusion())) {
657             incidentPipeFound = false;
658           }
659
660           if ( z < -Precision::Confusion()) {
661             // length of main pipe
662             mainPipeFound = true;
663             if (!mainPipeFoundAndAdded) {
664               mainPipeFoundAndAdded = true;
665               addGroup = true;
666               aGroup->SetName("HALF_LENGTH_MAIN_PIPE");
667             }
668           }
669
670           else if (Abs(x) > (theL1-Precision::Confusion())) {
671             // discretisation circulaire
672             radialFound = true;
673             if (!circularFoundAndAdded) {
674               circularFoundAndAdded = true;
675               addGroup = true;
676               aGroup->SetName("CIRCULAR_QUARTER_PIPE");
677             }
678           }
679           Ex.Next();
680         }
681         if (incidentPipeFound) {
682           addGroup = true;
683           aGroup->SetName("HALF_LENGTH_INCIDENT_PIPE");
684         }
685         if (!addGroup && (!incidentPipeFound &&
686                           !radialFound &&
687                           !mainPipeFound &&
688                           !flangeFound)) {
689           // Flange (collerette)
690           flangeFound = true;
691           addGroup = true;
692           aGroup->SetName("FLANGE");
693         }
694       }
695       else
696         continue;
697     }
698     else if (shapeType == TSHAPE_CHAMFER || shapeType == TSHAPE_FILLET) {
699       if (nbEdges >= 25) { // 25, 25+8, 25+16, 25+24
700         addGroup = true;
701         aGroup->SetName("THICKNESS");
702       }
703       else if ((nbEdges == 10) || (nbEdges == 6)) {
704         if (!circularFoundAndAdded) {
705           addGroup = true;
706           circularFoundAndAdded = true;
707           aGroup->SetName("CIRCULAR_QUARTER_PIPE");
708           if (nbEdges == 10) {
709             circularFound10 = true;
710           }
711         }
712         else if (!circularFound10 && nbEdges == 10) {
713           circularFound10 = true;
714           addGroup = true;
715           aGroup->SetName("CIRCULAR_QUARTER_PIPE");
716         }
717       }
718       else if (nbEdges == 8) {
719         incidentPipeFound = true;
720         mainPipeFound = true;
721         flangeFound = false;
722
723         bool isNearZ0 = false;
724         bool isBelowZ0 = false;
725
726         TopExp_Explorer Ex (aGroupShapeTrsfInv,TopAbs_VERTEX);
727         while (Ex.More()) {
728           gp_Pnt aP = BRep_Tool::Pnt(TopoDS::Vertex(Ex.Current()));
729           double x=aP.X(), y=aP.Y(), z=aP.Z();
730
731           // tuy_princ_long_avant & tuy_princ_long_apres
732           //bool isMain = (((z < Precision::Confusion()) || (x < Precision::Confusion())) &&
733           //               ((y <= aR1Ext + Precision::Confusion()) ||
734           //                (y <= -(aR1Ext + Precision::Confusion())) ||
735           //                (y <= theR1 + Precision::Confusion()) ||
736           //                (y == -(theR1 + Precision::Confusion()))));
737           bool isMain = ((z < Precision::Confusion() || x < Precision::Confusion()) &&
738                          (fabs(y) > theR1 - Precision::Confusion() ||
739                           fabs(y) < Precision::Confusion()));
740
741           if (!isMain) {
742             mainPipeFound = false;
743           }
744
745           // collerette
746           //if (z < Precision::Confusion() && !isMain) {
747           //  flangeFound = true;
748           //  if (!flangeFoundAndAdded) {
749           //    flangeFoundAndAdded = true;
750           //    addGroup = true;
751           //    aGroup->SetName("FLANGE");
752           //  }
753           //}
754           if (fabs(z) < Precision::Confusion()) isNearZ0 = true;
755           if (z < - Precision::Confusion()) isBelowZ0 = true;
756
757           // tuyau incident
758           if ((Abs(x) > aR2Ext + Precision::Confusion()) ||
759               (Abs(y) > aR2Ext + Precision::Confusion())) {
760             incidentPipeFound = false;
761           }
762           Ex.Next();
763         }
764         if (mainPipeFound) {
765           addGroup = true;
766           aGroup->SetName("HALF_LENGTH_MAIN_PIPE");
767         }
768         if (incidentPipeFound) {
769           addGroup = true;
770           aGroup->SetName("HALF_LENGTH_INCIDENT_PIPE");
771         }
772         if (isNearZ0 && !isBelowZ0) {
773           flangeFound = true;
774           if (!flangeFoundAndAdded) {
775             flangeFoundAndAdded = true;
776             addGroup = true;
777             aGroup->SetName("FLANGE");
778           }
779         }
780         if (!addGroup && (!incidentPipeFound &&
781                           !mainPipeFound &&
782                           !flangeFound &&
783                           !chamferOrFilletFound)) {
784           addGroup = true;
785           chamferOrFilletFound = true;
786           if (shapeType == TSHAPE_CHAMFER)
787             aGroup->SetName("CHAMFER");
788           else
789             aGroup->SetName("FILLET");
790         }
791       }
792       else
793         continue;
794     }
795     // Add group to the list
796     if (addGroup)
797       theSeq->Append(aGroup);
798   }
799 #endif
800
801   SetErrorCode(OK);
802   return true;
803 }
804
805 //=============================================================================
806 /*!
807  *  Return faces that are laying on surface.
808  */
809 //=============================================================================
810 bool AdvancedEngine_IOperations::GetFacesOnSurf
811                      (const TopoDS_Shape &theShape,
812                       const Handle(Geom_Surface)& theSurface,
813                       const Standard_Real theTolerance,
814                       TopTools_ListOfShape &theFaces)
815 {
816   GEOMAlgo_FinderShapeOn2   aFinder;
817   Handle(GEOMAlgo_ClsfSurf) aClsfSurf = new GEOMAlgo_ClsfSurf;
818
819   aClsfSurf->SetSurface(theSurface);
820   aFinder.SetShape(theShape);
821   aFinder.SetTolerance(theTolerance);
822   aFinder.SetClsf(aClsfSurf);
823   aFinder.SetShapeType(TopAbs_FACE);
824   aFinder.SetState(GEOMAlgo_ST_ON);
825
826   // Sets the minimal number of inner points for the faces that do not have own
827   // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
828   // Default value=3
829   aFinder.SetNbPntsMin(3);
830   // Sets the maximal number of inner points for edges or faces.
831   // It is useful for the cases when this number is very big (e.g =2000) to improve
832   // the performance. If this value =0, all inner points will be taken into account.
833   // Default value=0
834   aFinder.SetNbPntsMax(100);
835   aFinder.Perform();
836
837   // Interprete results
838   Standard_Integer iErr = aFinder.ErrorStatus();
839   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn2.cxx
840   if (iErr) {
841     MESSAGE(" iErr : " << iErr);
842     TCollection_AsciiString aMsg (" iErr : ");
843     aMsg += TCollection_AsciiString(iErr);
844     SetErrorCode(aMsg);
845     return false;
846   }
847   Standard_Integer iWrn = aFinder.WarningStatus();
848   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn2.cxx
849   if (iWrn) {
850     MESSAGE(" *** iWrn : " << iWrn);
851   }
852
853   const TopTools_ListOfShape &aListRes = aFinder.Shapes(); // the result
854   TopTools_ListIteratorOfListOfShape anIter (aListRes);
855
856   for (; anIter.More(); anIter.Next()) {
857     theFaces.Append(anIter.Value());
858   }
859
860   return true;
861 }
862
863 //=============================================================================
864 /*!
865  *  Creates and returns conical face.
866  */
867 //=============================================================================
868 TopoDS_Shape AdvancedEngine_IOperations::MakeConicalFace
869                                   (const gp_Ax2 &theAxis,
870                                    const double theRadius,
871                                    const double theRadiusThin,
872                                    const double theHeight,
873                                    const gp_Trsf &theTrsf)
874 {
875   BRepPrimAPI_MakeCone aMkCone (theAxis, theRadius, theRadiusThin, theHeight);
876   TopoDS_Shape aResult;
877   
878   aMkCone.Build();
879   if (aMkCone.IsDone()) {
880     TopExp_Explorer anExp(aMkCone.Shape(), TopAbs_FACE);
881
882     for (; anExp.More(); anExp.Next()) {
883       TopoDS_Face aFace = TopoDS::Face(anExp.Current());
884
885       if (aFace.IsNull() == Standard_False) {
886         BRepAdaptor_Surface anAdaptor(aFace, Standard_False);
887
888         if (anAdaptor.GetType() == GeomAbs_Cone) {
889           // This is a conical face. Transform and return it.
890           BRepBuilderAPI_Transform aTransf(aFace, theTrsf, Standard_False);
891           
892           aResult = aTransf.Shape();
893           break;
894         }
895       }
896     }
897   }
898
899   return aResult;
900 }
901
902 //=============================================================================
903 /*!
904  *  Generate the internal group of a Pipe T-Shape
905  */
906 //=============================================================================
907 bool AdvancedEngine_IOperations::MakeInternalGroup
908                       (const Handle(GEOM_Object) &theShape,
909                        const double theR1, const double theLen1,
910                        const double theR2, const double theLen2,
911                        const double theRL, double theTransLenL,
912                        const double theRR, double theTransLenR,
913                        const double theRI, double theTransLenI,
914                        const Handle(TColStd_HSequenceOfTransient) &theSeq,
915                        const gp_Trsf &theTrsf)
916 {
917   SetErrorCode(KO);
918
919   if (theShape.IsNull()) {
920     return false;
921   }
922
923   TopoDS_Shape aShape = theShape->GetValue();
924
925   if (aShape.IsNull()) {
926     SetErrorCode("Shape is not defined");
927     return false;
928   }
929
930   // Compute tolerance
931   Standard_Real aMaxTol = -RealLast();
932   TopExp_Explorer anExp(aShape, TopAbs_VERTEX);
933
934   for (; anExp.More(); anExp.Next()) {
935     TopoDS_Vertex aVertex = TopoDS::Vertex(anExp.Current());
936
937     if (aVertex.IsNull() == Standard_False) {
938       const Standard_Real aTol = BRep_Tool::Tolerance(aVertex);
939
940       if (aTol > aMaxTol) {
941         aMaxTol = aTol;
942       }
943     }
944   }
945
946   // Construct internal surfaces.
947   Standard_Integer i = 0;
948   const Standard_Integer aMaxNbSurf = 5;
949   Handle(Geom_Surface) aSurface[aMaxNbSurf];
950   TopTools_ListOfShape aConicalFaces;
951   Standard_Real aTolConf = Precision::Confusion();
952
953   // 1. Construct the internal surface of main pipe.
954   gp_Ax2 anAxis1 (gp::Origin(), gp::DX(), gp::DZ());
955   gp_Ax2 anAxis2 (gp::Origin(), gp::DZ(), gp::DX());
956
957   aSurface[i++] = new Geom_CylindricalSurface(anAxis1, theR1);
958
959   // 2. Construct the internal surface of incident pipe.
960   aSurface[i++] = new Geom_CylindricalSurface(anAxis2, theR2);
961
962   // 3. Construct the internal surface of left reduction pipe.
963   if (theRL > aTolConf) {
964     aSurface[i++] = new Geom_CylindricalSurface(anAxis1, theRL);
965
966     if (theTransLenL > aTolConf) {
967       // 3.1. Construct the internal surface of left transition pipe.
968       gp_Pnt aPLeft (-theLen1, 0., 0.);
969       gp_Ax2 anAxisLeft (aPLeft, -gp::DX(), gp::DZ());
970       TopoDS_Shape aConeLeft =
971         MakeConicalFace(anAxisLeft, theR1, theRL, theTransLenL, theTrsf);
972
973       if (aConeLeft.IsNull() == Standard_False) {
974         aConicalFaces.Append(aConeLeft);
975       }
976     }
977   }
978
979   // 4. Construct the internal surface of right reduction pipe.
980   if (theRR > aTolConf) {
981     // There is no need to construct another cylinder of the same radius. Skip it.
982     if (Abs(theRR - theRL) > aTolConf) {
983       aSurface[i++] = new Geom_CylindricalSurface(anAxis1, theRR);
984     }
985
986     if (theTransLenL > aTolConf) {
987       // 4.1. Construct the internal surface of right transition pipe.
988       gp_Pnt aPRight (theLen1, 0., 0.);
989       gp_Ax2 anAxisRight (aPRight, gp::DX(), gp::DZ());
990       TopoDS_Shape aConeRight =
991         MakeConicalFace(anAxisRight, theR1, theRR, theTransLenR, theTrsf);
992
993       if (aConeRight.IsNull() == Standard_False) {
994         aConicalFaces.Append(aConeRight);
995       }
996     }
997   }
998
999   // 5. Construct the internal surface of incident reduction pipe.
1000   if (theRI > aTolConf) {
1001     aSurface[i++] = new Geom_CylindricalSurface(anAxis2, theRI);
1002
1003     if (theTransLenI > aTolConf) {
1004       // 5.1. Construct the internal surface of incident transition pipe.
1005       gp_Pnt aPInci (0., 0., theLen2);
1006       gp_Ax2 anAxisInci (aPInci, gp::DZ(), gp::DX());
1007       TopoDS_Shape aConeInci =
1008         MakeConicalFace(anAxisInci, theR2, theRI, theTransLenI, theTrsf);
1009
1010       if (aConeInci.IsNull() == Standard_False) {
1011         aConicalFaces.Append(aConeInci);
1012       }
1013     }
1014   }
1015
1016   // Get faces that are laying on cylindrical surfaces.
1017   TopTools_ListOfShape aFaces;
1018   gp_Trsf anInvTrsf = theTrsf.Inverted();
1019
1020   for (i = 0; i < aMaxNbSurf; i++) {
1021     if (aSurface[i].IsNull()) {
1022       break;
1023     }
1024
1025     aSurface[i]->Transform(theTrsf);
1026
1027     TopTools_ListOfShape aLocalFaces;
1028
1029     if (!GetFacesOnSurf(aShape, aSurface[i], aMaxTol, aLocalFaces)) {
1030       return false;
1031     }
1032
1033     if (i < 2) {
1034       // Check if the result contains outer cylinders.
1035       // It is required for main and incident pipes.
1036       TopTools_ListIteratorOfListOfShape anIter(aLocalFaces);
1037
1038       while (anIter.More()) {
1039         TopExp_Explorer anExp(anIter.Value(), TopAbs_VERTEX);
1040         Standard_Boolean isInside = Standard_False;
1041
1042         // Get a vertex from this shape
1043         if (anExp.More()) {
1044           TopoDS_Vertex aVtx = TopoDS::Vertex(anExp.Current());
1045
1046           if (aVtx.IsNull() == Standard_False) {
1047             gp_Pnt aPnt = BRep_Tool::Pnt(aVtx);
1048
1049             aPnt.Transform(anInvTrsf);
1050
1051             if (i == 0) {
1052               // Check if the point is inside the main pipe.
1053               isInside = (Abs(aPnt.X()) <= theLen1);
1054             } else { // i == 1
1055               // Check if the point is inside the incident pipe.
1056               isInside = (aPnt.Z() <= theLen2);
1057             }
1058           }
1059         }
1060
1061         if (isInside) {
1062           // Keep this face.
1063           anIter.Next();
1064         } else {
1065           // Remove this face.
1066           aLocalFaces.Remove(anIter);
1067         }
1068       }
1069     }
1070
1071     aFaces.Append(aLocalFaces);
1072   }
1073
1074   // Get faces that are laying on conical faces.
1075   if (aConicalFaces.IsEmpty() == Standard_False) {
1076     Handle(GEOM_Object) aCone =
1077       GetEngine()->AddObject(GetDocID(), GEOM_TSHAPE);
1078     Handle(GEOM_Function) aFunction =
1079       aCone->AddFunction(AdvancedEngine_PipeTShapeDriver::GetID(), TSHAPE_BASIC);
1080     TopTools_ListIteratorOfListOfShape aFIter(aConicalFaces);
1081     Handle(GEOM_Object) aConeFromShape;
1082
1083     for (; aFIter.More(); aFIter.Next()) {
1084       aFunction->SetValue(aFIter.Value());
1085       aConeFromShape = myShapesOperations->GetInPlace(theShape, aCone);
1086
1087       if (aConeFromShape.IsNull() == Standard_False) {
1088         aConeFromShape->GetLastFunction()->SetDescription("");
1089         TopoDS_Shape aConeFaces = aConeFromShape->GetValue();
1090         TopExp_Explorer anExp(aConeFaces, TopAbs_FACE);
1091
1092         for (; anExp.More(); anExp.Next()) {
1093           TopoDS_Face aConeFace = TopoDS::Face(anExp.Current());
1094
1095           if (aConeFace.IsNull() == Standard_False) {
1096             aFaces.Append(aConeFace);
1097           }
1098         }
1099       }
1100     }
1101   }
1102
1103   // Create a group of internal faces.
1104   if (aFaces.IsEmpty() == Standard_False) {
1105     Handle(GEOM_Object) aGroup = myGroupOperations->CreateGroup(theShape, TopAbs_FACE);
1106
1107     if (aGroup.IsNull() == Standard_False) {
1108       aGroup->GetLastFunction()->SetDescription("");
1109       aGroup->SetName("INTERNAL_FACES");
1110
1111       TopTools_IndexedMapOfShape anIndices;
1112       Handle(TColStd_HSequenceOfInteger) aSeqIDs = new TColStd_HSequenceOfInteger;
1113
1114       TopExp::MapShapes(aShape, anIndices);
1115
1116       TopTools_ListIteratorOfListOfShape anIter(aFaces);
1117
1118       for (; anIter.More(); anIter.Next()) {
1119         const TopoDS_Shape &aFace = anIter.Value();
1120         const Standard_Integer anIndex = anIndices.FindIndex(aFace);
1121
1122         if (anIndex > 0) {
1123           aSeqIDs->Append(anIndex);
1124         }
1125       }
1126
1127       myGroupOperations->UnionIDs(aGroup, aSeqIDs);
1128       aGroup->GetLastFunction()->SetDescription("");
1129       theSeq->Append(aGroup);
1130     }
1131   }
1132
1133   SetErrorCode(OK);
1134
1135   return true;
1136 }
1137
1138 bool AdvancedEngine_IOperations::MakePipeTShapePartition(Handle(GEOM_Object) theShape,
1139                                                          double theR1, double theW1, double theL1,
1140                                                          double theR2, double theW2, double theL2,
1141                                                          double theH, double theW,
1142                                                          double theRF, bool isNormal)
1143 {
1144   SetErrorCode(KO);
1145
1146   // Build tools for partition operation:
1147   // 1 face and 2 planes
1148   // Face
1149   Handle(GEOM_Object) arete_intersect_int, arete_intersect_ext;
1150   Handle(GEOM_Object) wire_t, wire_t2, face_t, face_t2;
1151   Handle(GEOM_Object) chan_racc;
1152   Handle(GEOM_Object) vi1, vi2;
1153   Handle(GEOM_Object) Te3;
1154
1155   try {
1156     OCC_CATCH_SIGNALS;
1157     Handle(GEOM_Object) Vector_Z = myBasicOperations->MakeVectorDXDYDZ(0, 0, 1);
1158     Vector_Z->GetLastFunction()->SetDescription("");
1159
1160     // Useful values
1161     double aSize = 2*(theL1 + theL2);
1162     double aR1Ext = theR1 + theW1;
1163     double aR2Ext = theR2 + theW2;
1164     double theVertCylinderRadius = aR2Ext + theW + theRF;
1165     double theHoriCylinderRadius = aR1Ext + theH + theRF;
1166
1167     // Common edges on internal cylinder
1168     Handle(GEOM_Object) box_i = my3DPrimOperations->MakeBoxDXDYDZ(theR2, theR2, theR1);
1169     box_i->GetLastFunction()->SetDescription("");
1170     box_i = myTransformOperations->TranslateDXDYDZ(box_i, -theR2, -theR2, 0);
1171     box_i->GetLastFunction()->SetDescription("");
1172
1173     Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1174     TCollection_AsciiString theDesc = aFunction->GetDescription();
1175     Handle(TColStd_HSequenceOfTransient) edges_i =
1176       myShapesOperations->GetShapesOnBox(box_i, theShape, TopAbs_EDGE, GEOMAlgo_ST_IN);
1177     // Recover previous description to get rid of Propagate dump
1178     aFunction->SetDescription(theDesc);
1179     if (edges_i.IsNull() || edges_i->Length() == 0) {
1180       SetErrorCode("Internal edges not found");
1181       return false;
1182     }
1183     for (int i=1; i<=edges_i->Length();i++) {
1184       Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(edges_i->Value(i));
1185       anObj->GetLastFunction()->SetDescription("");
1186     }
1187     arete_intersect_int = Handle(GEOM_Object)::DownCast(edges_i->Value(1));
1188
1189     // search for vertices located on both internal pipes
1190     aFunction = theShape->GetLastFunction();
1191     theDesc = aFunction->GetDescription();
1192     Handle(TColStd_HSequenceOfTransient) vertices_i =
1193       myShapesOperations->GetShapesOnBox(box_i, theShape, TopAbs_VERTEX, GEOMAlgo_ST_ONIN);
1194     // Recover previous description to get rid of Propagate dump
1195     aFunction->SetDescription(theDesc);
1196     if (vertices_i.IsNull() || vertices_i->Length() == 0) {
1197       SetErrorCode("Internal vertices not found");
1198       return false;
1199     }
1200
1201     double d1min = theR2+theW2, d2min=theR2+theW2;
1202     for (int i = 1; i <= vertices_i->Length(); i++) {
1203       Handle(GEOM_Object) v = Handle(GEOM_Object)::DownCast(vertices_i->Value(i));
1204       v->GetLastFunction()->SetDescription("");
1205       TopoDS_Vertex aVertex = TopoDS::Vertex(v->GetValue());
1206       gp_Pnt aP = BRep_Tool::Pnt(aVertex);
1207       if (Abs(aP.X()) <= Precision::Confusion()) {
1208         if (Abs(aP.Y()) < d1min) {
1209           vi1 = v;
1210           d1min = Abs(aP.Y());
1211         }
1212       } else if (Abs(aP.Y()) <= Precision::Confusion()) {
1213         if (Abs(aP.X()) < d2min) {
1214           vi2 = v;
1215           d2min = Abs(aP.X());
1216         }
1217       }
1218     }
1219     if (vi1.IsNull() || vi2.IsNull()) {
1220       SetErrorCode("Cannot find internal intersection vertices");
1221       return false;
1222     }
1223
1224     std::list<Handle(GEOM_Object)> theShapes;
1225
1226     if (isNormal) {
1227       Handle(GEOM_Object) ve1, ve2;
1228       TopoDS_Vertex vertex1, vertex2;
1229
1230       Handle(GEOM_Object) box_e = my3DPrimOperations->MakeBoxDXDYDZ(aR2Ext, aR2Ext, aR1Ext);
1231       box_e->GetLastFunction()->SetDescription("");
1232       box_e = myTransformOperations->TranslateDXDYDZ(box_e, -aR2Ext, -aR2Ext, 0);
1233       box_e->GetLastFunction()->SetDescription("");
1234
1235       // search for vertices located on both external pipes
1236       aFunction = theShape->GetLastFunction();
1237       theDesc = aFunction->GetDescription();
1238       Handle(TColStd_HSequenceOfTransient) vertices_e =
1239         myShapesOperations->GetShapesOnBox(box_e, theShape, TopAbs_VERTEX, GEOMAlgo_ST_ONIN);
1240       // Recover previous description to get rid of Propagate dump
1241       aFunction->SetDescription(theDesc);
1242       if (vertices_e.IsNull() || vertices_e->Length() == 0) {
1243         SetErrorCode("External vertices not found");
1244         return false;
1245       }
1246
1247       double d1max = 0, d2max = 0;
1248       for (int i = 1; i <= vertices_e->Length(); i++) {
1249         Handle(GEOM_Object) v = Handle(GEOM_Object)::DownCast(vertices_e->Value(i));
1250         v->GetLastFunction()->SetDescription("");
1251         TopoDS_Vertex aVertex = TopoDS::Vertex(v->GetValue());
1252         gp_Pnt aP = BRep_Tool::Pnt(aVertex);
1253         if (Abs(aP.X()) <= Precision::Confusion()) {
1254           if (Abs(aP.Y()) > d1max) {
1255             ve1 = v;
1256             vertex1 = aVertex;
1257             d1max = Abs(aP.Y());
1258           }
1259         } else if (Abs(aP.Y()) <= Precision::Confusion()) {
1260           if (Abs(aP.X()) > d2max) {
1261             ve2 = v;
1262             vertex2 = aVertex;
1263             d2max = Abs(aP.X());
1264           }
1265         }
1266       }
1267       if (ve1.IsNull() || ve2.IsNull()) {
1268         SetErrorCode("Cannot find external intersection vertices");
1269         return false;
1270       }
1271       Handle(GEOM_Object) edge_e1, edge_e2;
1272
1273       // Common edges on external cylinder
1274       aFunction = theShape->GetLastFunction();
1275       theDesc = aFunction->GetDescription();
1276       Handle(TColStd_HSequenceOfTransient) edges_e =
1277         myShapesOperations->GetShapesOnBox(box_e, theShape, TopAbs_EDGE, GEOMAlgo_ST_IN);
1278       // Recover previous description to get rid of Propagate dump
1279       aFunction->SetDescription(theDesc);
1280       if (edges_e.IsNull() || edges_e->Length() == 0) {
1281         SetErrorCode("External edges not found");
1282         return false;
1283       }
1284       ShapeAnalysis_Edge sae;
1285       for (int i=1; i<=edges_e->Length();i++) {
1286         Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(edges_e->Value(i));
1287         anObj->GetLastFunction()->SetDescription("");
1288         TopoDS_Edge anEdge = TopoDS::Edge(anObj->GetValue());
1289         if ( !anEdge.IsNull() && 
1290              (sae.FirstVertex(anEdge).IsSame(vertex1) || sae.LastVertex(anEdge).IsSame(vertex1)) && 
1291              (sae.FirstVertex(anEdge).IsSame(vertex2) || sae.LastVertex(anEdge).IsSame(vertex2))) {
1292           arete_intersect_ext = anObj;
1293         }
1294       }
1295
1296       edge_e1 = myBasicOperations->MakeLineTwoPnt(ve1, vi1);
1297       if (edge_e1.IsNull()) {
1298         SetErrorCode("Edge 1 could not be built");
1299         return false;
1300       }
1301
1302       edge_e2 = myBasicOperations->MakeLineTwoPnt(ve2, vi2);
1303       if (edge_e2.IsNull()) {
1304         SetErrorCode("Edge 2 could not be built");
1305         return false;
1306       }
1307
1308       edge_e1->GetLastFunction()->SetDescription("");
1309       edge_e2->GetLastFunction()->SetDescription("");
1310
1311       std::list<Handle(GEOM_Object)> edge_e_elist;
1312       edge_e_elist.push_back(arete_intersect_int);
1313       edge_e_elist.push_back(edge_e1);
1314       edge_e_elist.push_back(arete_intersect_ext);
1315       edge_e_elist.push_back(edge_e2);
1316       wire_t = myShapesOperations->MakeWire(edge_e_elist, 1e-7);
1317       if (wire_t.IsNull()) {
1318         SetErrorCode("Impossible to build wire");
1319         return false;
1320       }
1321       wire_t->GetLastFunction()->SetDescription("");
1322       face_t = myShapesOperations->MakeFace(wire_t, false);
1323       if (face_t.IsNull()) {
1324         SetErrorCode("Impossible to build face");
1325         return false;
1326       }
1327       face_t->GetLastFunction()->SetDescription("");
1328
1329       theShapes.push_back(theShape);
1330       theShapes.push_back(vi1);
1331       theShapes.push_back(vi2);
1332       theShapes.push_back(ve1);
1333       theShapes.push_back(ve2);
1334       theShapes.push_back(edge_e1);
1335       theShapes.push_back(edge_e2);
1336       theShapes.push_back(wire_t);
1337       theShapes.push_back(face_t);
1338     }
1339     else {
1340       Handle(GEOM_Object) P1, P2, P3, P4, P5, P6;
1341       int idP1, idP2, idP3, idP4;
1342       int PZX, PZY;
1343       double ZX=0, ZY=0;
1344       std::vector<int> LX;
1345       std::vector<int> LY;
1346       Handle(GEOM_Object) box_e = my3DPrimOperations->MakeBoxDXDYDZ
1347         (theVertCylinderRadius, theVertCylinderRadius, theHoriCylinderRadius);
1348       box_e->GetLastFunction()->SetDescription("");
1349       box_e = myTransformOperations->TranslateDXDYDZ
1350         (box_e, -theVertCylinderRadius, -theVertCylinderRadius, 0);
1351       box_e->GetLastFunction()->SetDescription("");
1352
1353       aFunction = theShape->GetLastFunction();
1354       theDesc = aFunction->GetDescription();
1355       Handle(TColStd_HSequenceOfTransient) extremVertices =
1356         myShapesOperations->GetShapesOnBox(box_e, theShape, TopAbs_VERTEX, GEOMAlgo_ST_ONIN);
1357       // Recover previous description to get rid of Propagate dump
1358       aFunction->SetDescription(theDesc);
1359
1360       if (extremVertices.IsNull() || extremVertices->Length() == 0) {
1361         if (theRF == 0)
1362           SetErrorCode("Vertices on chamfer not found");
1363         else
1364           SetErrorCode("Vertices on fillet not found");
1365         return false;
1366       }
1367
1368       theShapes.push_back(theShape);
1369       theShapes.push_back(box_e);
1370       if (extremVertices->Length() != 6) {
1371         //           for (int i=1; i<=extremVertices->Length(); i++){
1372         //             theShapes.push_back(Handle(GEOM_Object)::DownCast(extremVertices->Value(i)));
1373         //           }
1374         //           Handle(GEOM_Object) aCompound = myShapesOperations->MakeCompound(theShapes);
1375         //           TopoDS_Shape aCompoundShape = aCompound->GetValue();
1376         //           theShape->GetLastFunction()->SetValue(aCompoundShape);
1377         SetErrorCode("Bad number of vertices on chamfer found");
1378         return false;
1379       }
1380
1381       for (int i=1; i<=extremVertices->Length(); i++){
1382         Handle(GEOM_Object) aV = Handle(GEOM_Object)::DownCast(extremVertices->Value(i));
1383         aV->GetLastFunction()->SetDescription("");
1384         gp_Pnt aP = BRep_Tool::Pnt(TopoDS::Vertex(aV->GetValue()));
1385
1386         if (Abs(aP.X()) <= Precision::Confusion()) {
1387           if (Abs(aP.Y()) - theR2 > Precision::Confusion()) {
1388             LX.push_back(i);
1389             if  (aP.Z()-ZX > Precision::Confusion()) {
1390               ZX = aP.Z();
1391               PZX = i;
1392             }
1393           }
1394         }
1395         else {
1396           if (Abs(aP.X()) - theR2 > Precision::Confusion()) {
1397             LY.push_back(i);
1398             if (aP.Z() - ZY > Precision::Confusion()) {
1399               ZY = aP.Z();
1400               PZY = i;
1401             }
1402           }
1403         }
1404       }
1405
1406       idP2 = PZX;
1407       idP4 = PZY;
1408       idP1 = LX.at(0);
1409       if (LX.at(0) == PZX)
1410         idP1 = LX.at(1);
1411       idP3 = LY.at(0);
1412       if (LY.at(0) == PZY)
1413         idP3 = LY.at(1);
1414
1415       P1 = Handle(GEOM_Object)::DownCast(extremVertices->Value(idP1));
1416       P2 = Handle(GEOM_Object)::DownCast(extremVertices->Value(idP2));
1417       P3 = Handle(GEOM_Object)::DownCast(extremVertices->Value(idP3));
1418       P4 = Handle(GEOM_Object)::DownCast(extremVertices->Value(idP4));
1419
1420       Handle(GEOM_Object) Cote_1 = myBasicOperations->MakeLineTwoPnt(P1, vi1);
1421       if (Cote_1.IsNull()) {
1422         SetErrorCode("Impossible to build edge in thickness");
1423         return false;
1424       }
1425       Cote_1->GetLastFunction()->SetDescription("");
1426
1427       Handle(GEOM_Object) Cote_2 = myBasicOperations->MakeLineTwoPnt(vi2, P3);
1428       if (Cote_2.IsNull()) {
1429         SetErrorCode("Impossible to build edge in thickness");
1430         return false;
1431       }
1432       Cote_2->GetLastFunction()->SetDescription("");
1433
1434       // edge_chan_princ = arete du chanfrein (ou raccord) sur le tuyau principal
1435       // edge_chan_inc = arete du chanfrein (ou raccord) sur le tuyau incident
1436       //         std::cerr << "Getting chamfer edge on main pipe" << std::endl;
1437       Handle(GEOM_Object) edge_chan_princ = myBlocksOperations->GetEdge(theShape, P1, P3);
1438       if (edge_chan_princ.IsNull()) {
1439         SetErrorCode("Impossible to find edge on main pipe");
1440         return false;
1441       }
1442       edge_chan_princ->GetLastFunction()->SetDescription("");
1443
1444       Handle(GEOM_Object) edge_chan_inc = myBlocksOperations->GetEdge(theShape, P2, P4);
1445       if (edge_chan_inc.IsNull()) {
1446         SetErrorCode("Impossible to find edge on incident pipe");
1447         return false;
1448       }
1449       edge_chan_inc->GetLastFunction()->SetDescription("");
1450
1451       std::list<Handle(GEOM_Object)> edgeList1;
1452       edgeList1.push_back(edge_chan_princ);
1453       edgeList1.push_back(Cote_1);
1454       edgeList1.push_back(arete_intersect_int);
1455       edgeList1.push_back(Cote_2);
1456
1457       //         std::cerr << "Creating wire 1" << std::endl;
1458       wire_t = myShapesOperations->MakeWire(edgeList1, 1e-7);
1459       if (wire_t.IsNull()) {
1460         SetErrorCode("Impossible to build wire");
1461         return false;
1462       }
1463       wire_t->GetLastFunction()->SetDescription("");
1464
1465       //         std::cerr << "Creating face 1" << std::endl;
1466       face_t = myShapesOperations->MakeFace(wire_t, false);
1467       if (face_t.IsNull()) {
1468         SetErrorCode("Impossible to build face");
1469         return false;
1470       }
1471       face_t->GetLastFunction()->SetDescription("");
1472       theShapes.push_back(face_t);
1473
1474       // Create a prism from edge_chan_inc
1475       Handle(GEOM_Object) aPrismDir = myBasicOperations->MakeVectorDXDYDZ(1., 1., 0.);
1476
1477       if (aPrismDir.IsNull()) {
1478         SetErrorCode("Impossible to build Prism direction");
1479         return false;
1480       }
1481       aPrismDir->GetLastFunction()->SetDescription("");
1482       face_t2 = my3DPrimOperations->MakePrismVecH(edge_chan_inc, aPrismDir, theR2 + theW2);
1483
1484       if (face_t2.IsNull()) {
1485         SetErrorCode("Impossible to build face");
1486         return false;
1487       }
1488       face_t2->GetLastFunction()->SetDescription("");
1489       theShapes.push_back(face_t2);
1490     }
1491
1492     // Planes
1493     Handle(GEOM_Object) aP0 = myBasicOperations->MakePointXYZ(0, 0, 0);
1494     Handle(GEOM_Object) aVZ = myBasicOperations->MakeVectorDXDYDZ(0, 0, 1);
1495     Handle(GEOM_Object) aVXZ = myBasicOperations->MakeVectorDXDYDZ(aR1Ext, 0, 0.5*(theL1+theVertCylinderRadius));
1496     Handle(GEOM_Object) aPlnOZ = myBasicOperations->MakePlanePntVec(aP0, aVZ, aSize);
1497     Handle(GEOM_Object) aPlnOXZ = myBasicOperations->MakePlanePntVec(aP0, aVXZ, aSize);
1498     aP0->GetLastFunction()->SetDescription("");
1499     aVZ->GetLastFunction()->SetDescription("");
1500     aVXZ->GetLastFunction()->SetDescription("");
1501     aPlnOZ->GetLastFunction()->SetDescription("");
1502     aPlnOXZ->GetLastFunction()->SetDescription("");
1503     theShapes.push_back(aPlnOZ);
1504     theShapes.push_back(aPlnOXZ);
1505
1506     // Partition
1507     Handle(TColStd_HSequenceOfTransient) partitionShapes = new TColStd_HSequenceOfTransient;
1508     Handle(TColStd_HSequenceOfTransient) theTools = new TColStd_HSequenceOfTransient;
1509     Handle(TColStd_HSequenceOfTransient) theKeepInside = new TColStd_HSequenceOfTransient;
1510     Handle(TColStd_HSequenceOfTransient) theRemoveInside = new TColStd_HSequenceOfTransient;
1511     Handle(TColStd_HArray1OfInteger) theMaterials;
1512
1513     partitionShapes->Append(theShape);
1514     theTools->Append(aPlnOZ);
1515     if (Abs(aR1Ext - aR2Ext) > Precision::Confusion())
1516       theTools->Append(aPlnOXZ);
1517     theTools->Append(face_t);
1518     if (!isNormal)
1519       theTools->Append(face_t2);
1520
1521     Te3 = myBooleanOperations->MakePartition
1522               (partitionShapes, theTools, theKeepInside, theRemoveInside,
1523               TopAbs_SOLID, false, theMaterials, 0, false, Standard_False);
1524     if (Te3.IsNull()) {
1525       SetErrorCode("Impossible to build partition of TShape");
1526       return false;
1527     }
1528     Te3->GetLastFunction()->SetDescription("");
1529
1530     // Last verification: result should be a block
1531     std::list<GEOMImpl_IBlocksOperations::BCError> errList;
1532     if (!myBlocksOperations->CheckCompoundOfBlocks(Te3, -1, errList)) {
1533       SetErrorCode("TShape is not a compound of block");
1534       return false;
1535     }
1536
1537 //     // BEGIN Compound of created shapes - Only for debug purpose
1538 //     theShapes.clear();
1539 //     theShapes.push_back(theShape);
1540 //     theShapes.push_back(aPlnOZ);
1541 //     if (Abs(aR1Ext - aR2Ext) > Precision::Confusion() )
1542 //       theShapes.push_back(aPlnOXZ);
1543 //     theShapes.push_back(face_t);
1544 //     if (!isNormal)
1545 //       theShapes.push_back(face_t2);
1546 //
1547 //     Handle(GEOM_Object) aCompound = myShapesOperations->MakeCompound(theShapes);
1548 //     TopoDS_Shape aCompoundShape = aCompound->GetValue();
1549 //     theShape->GetLastFunction()->SetValue(aCompoundShape);
1550 //     // END Compound of created shapes - Only for debug purpose
1551
1552     TopoDS_Shape aShape = Te3->GetValue();
1553     theShape->GetLastFunction()->SetValue(aShape);
1554   }
1555   catch (Standard_Failure& aFail) {
1556     SetErrorCode(aFail.GetMessageString());
1557     return false;
1558   }
1559
1560   SetErrorCode(OK);
1561   return true;
1562 }
1563
1564 // Mirror and glue faces
1565 bool AdvancedEngine_IOperations::MakePipeTShapeMirrorAndGlue(Handle(GEOM_Object) theShape,
1566                                                              double theR1, double theW1, double theL1,
1567                                                              double theR2, double theW2, double theL2)
1568 {
1569   SetErrorCode(KO);
1570
1571   // Useful values
1572   double aSize = 2*(theL1 + theL2);
1573   double aR1Ext = theR1 + theW1;
1574
1575   // Planes
1576   Handle(GEOM_Object) aP0 = myBasicOperations->MakePointXYZ(0, 0, 0);
1577   aP0->GetLastFunction()->SetDescription("");
1578   Handle(GEOM_Object) aVX = myBasicOperations->MakeVectorDXDYDZ(1, 0, 0);
1579   Handle(GEOM_Object) aVY = myBasicOperations->MakeVectorDXDYDZ(0, 1, 0);
1580   aVX->GetLastFunction()->SetDescription("");
1581   aVY->GetLastFunction()->SetDescription("");
1582   Handle(GEOM_Object) aPlane_OX = myBasicOperations->MakePlanePntVec(aP0, aVX, 2*(aR1Ext + theL2));
1583   Handle(GEOM_Object) aPlane_OY = myBasicOperations->MakePlanePntVec(aP0, aVY, aSize);
1584   aPlane_OX->GetLastFunction()->SetDescription("");
1585   aPlane_OY->GetLastFunction()->SetDescription("");
1586
1587   Handle(GEOM_Object) Te4 = myTransformOperations->MirrorPlaneCopy(theShape, aPlane_OX);
1588   if (Te4.IsNull()) {
1589     SetErrorCode("Impossible to build mirror of quarter TShape");
1590     return false;
1591   }
1592
1593   Handle(GEOM_Object) Te5 = myTransformOperations->MirrorPlaneCopy(theShape, aPlane_OY);
1594   if (Te5.IsNull()) {
1595     SetErrorCode("Impossible to build mirror of half TShape");
1596     return false;
1597   }
1598
1599   Handle(GEOM_Object) Te6 = myTransformOperations->MirrorPlaneCopy(Te4, aPlane_OY);
1600   if (Te6.IsNull()) {
1601     SetErrorCode("Impossible to build mirror of half TShape");
1602     return false;
1603   }
1604
1605   std::list<Handle(GEOM_Object)> aShapesList;
1606   aShapesList.push_back(theShape);
1607   aShapesList.push_back(Te4);
1608   aShapesList.push_back(Te5);
1609   aShapesList.push_back(Te6);
1610   Handle(GEOM_Object) Te7 = myShapesOperations->MakeCompound(aShapesList);
1611   if (Te7.IsNull()) {
1612     SetErrorCode("Impossible to build compound");
1613     return false;
1614   }
1615
1616   // Copy source shape
1617   TopoDS_Shape aShapeCopy;
1618   TColStd_IndexedDataMapOfTransientTransient aMapTShapes;
1619   TNaming_CopyShape::CopyTool(Te7->GetValue(), aMapTShapes, aShapeCopy);
1620
1621   std::list<Handle(GEOM_Object)> Te7list( 1, Te7 );
1622   Handle(GEOM_Object) Te8 = myShapesOperations->MakeGlueFaces(Te7list, 1e-7, true);
1623   if (Te8.IsNull()) {
1624     SetErrorCode("Impossible to glue faces of TShape");
1625     return false;
1626   }
1627
1628   TopoDS_Shape aShape = Te8->GetValue();
1629   BRepCheck_Analyzer anAna (aShape, Standard_True);
1630
1631   if (!anAna.IsValid()) {
1632     // Try to do gluing with the tolerance equal to maximal
1633     // tolerance of vertices of the source shape.
1634     Standard_Real aTolMax = -RealLast();
1635
1636     for (TopExp_Explorer ExV (aShapeCopy, TopAbs_VERTEX); ExV.More(); ExV.Next()) {
1637       TopoDS_Vertex aVertex = TopoDS::Vertex(ExV.Current());
1638       Standard_Real aTol = BRep_Tool::Tolerance(aVertex);
1639
1640       if (aTol > aTolMax) {
1641         aTolMax = aTol;
1642       }
1643     }
1644
1645     // Perform gluing
1646     Te7->GetLastFunction()->SetValue(aShapeCopy);
1647     Te8 = myShapesOperations->MakeGlueFaces(Te7list, aTolMax, true);
1648
1649     if (Te8.IsNull()) {
1650       SetErrorCode("Impossible to glue faces of TShape");
1651       return false;
1652     }
1653
1654     aShape = Te8->GetValue();
1655   }
1656
1657
1658   theShape->GetLastFunction()->SetValue(aShape);
1659
1660   Te4->GetLastFunction()->SetDescription("");
1661   Te5->GetLastFunction()->SetDescription("");
1662   Te6->GetLastFunction()->SetDescription("");
1663   Te7->GetLastFunction()->SetDescription("");
1664   Te8->GetLastFunction()->SetDescription("");
1665
1666   SetErrorCode(OK);
1667   return true;
1668 }
1669
1670 //=======================================================================
1671 //function : MakePipeTShapeThicknessReduction
1672 //purpose  : Static method. Add thiskness reduction elements at the three
1673 //                          open ends of the T-Shape.
1674 //=======================================================================
1675 TopoDS_Shape AdvancedEngine_IOperations::MakePipeTShapeThicknessReduction
1676                                   (TopoDS_Shape theShape,
1677                                    double r1, double w1, double l1,
1678                                    double r2, double w2, double l2,
1679                                    double rL, double wL, double ltransL, double lthinL,
1680                                    double rR, double wR, double ltransR, double lthinR,
1681                                    double rI, double wI, double ltransI, double lthinI,
1682                                    bool fuseReductions)
1683 {
1684   // Add thickness reduction elements
1685   // at the three extremities: Left, Right and Incident
1686   //
1687   // ---------------------.
1688   //   W                   \
1689   // ---------------------. \
1690   //   ^                   \ '-----------------.
1691   //   |R                   \        Wthin     |
1692   //   |                     '-----------------'
1693   //   v                             Rthin
1694   // --.--.--.--.--.--.--.--.--.--.--.--.--.--.--
1695   //                     Ltrans    Lthin
1696
1697   TopoDS_Shape aResult = theShape;
1698   double aTol = Precision::Confusion();
1699
1700   gp_Vec aVX = gp::DX(), aVZ = gp::DZ();
1701
1702   // Left reduction (rL, wL, ltransL, lthinL)
1703   if (rL > aTol && wL > aTol && ltransL > aTol) {
1704     gp_Pnt aPLeft (-l1, 0, 0);
1705     gp_Ax2 anAxesLeft (aPLeft, -aVX, aVZ);
1706     TopoDS_Shape aReductionLeft = AdvancedEngine_IOperations::MakeThicknessReduction
1707       (anAxesLeft, r1, w1, rL, wL, ltransL, lthinL, fuseReductions);
1708
1709     if (fuseReductions) {
1710       BRepAlgoAPI_Fuse fuseL (aResult, aReductionLeft);
1711       if (!fuseL.IsDone())
1712         StdFail_NotDone::Raise("Cannot fuse Te with left reduction");
1713       aResult = fuseL.Shape();
1714     }
1715     else {
1716       BRep_Builder B;
1717       TopoDS_Compound C;
1718       B.MakeCompound(C);
1719       B.Add(C, aResult);
1720       B.Add(C, aReductionLeft);
1721       aResult = C;
1722     }
1723   }
1724
1725   // Right reduction
1726   if (rR > aTol && wR > aTol && ltransR > aTol) {
1727     gp_Pnt aPRight (l1, 0, 0);
1728     gp_Ax2 anAxesRight (aPRight, aVX, aVZ);
1729     TopoDS_Shape aReductionRight = AdvancedEngine_IOperations::MakeThicknessReduction
1730       (anAxesRight, r1, w1, rR, wR, ltransR, lthinR, fuseReductions);
1731
1732     if (fuseReductions) {
1733       BRepAlgoAPI_Fuse fuseR (aResult, aReductionRight);
1734       if (!fuseR.IsDone())
1735         StdFail_NotDone::Raise("Cannot fuse Te with right reduction");
1736       aResult = fuseR.Shape();
1737     }
1738     else {
1739       BRep_Builder B;
1740       TopoDS_Compound C;
1741       B.MakeCompound(C);
1742       B.Add(C, aResult);
1743       B.Add(C, aReductionRight);
1744       aResult = C;
1745     }
1746   }
1747
1748   // Incident reduction
1749   if (rI > aTol && wI > aTol && ltransI > aTol) {
1750     gp_Pnt aPInci (0, 0, l2);
1751     gp_Ax2 anAxesInci (aPInci, aVZ, aVX);
1752     TopoDS_Shape aReductionInci = AdvancedEngine_IOperations::MakeThicknessReduction
1753       (anAxesInci, r2, w2, rI, wI, ltransI, lthinI, fuseReductions);
1754
1755     if (fuseReductions) {
1756       BRepAlgoAPI_Fuse fuseInci (aResult, aReductionInci);
1757       if (!fuseInci.IsDone())
1758         StdFail_NotDone::Raise("Cannot fuse Te with incident reduction");
1759       aResult = fuseInci.Shape();
1760     }
1761     else {
1762       BRep_Builder B;
1763       TopoDS_Compound C;
1764       B.MakeCompound(C);
1765       B.Add(C, aResult);
1766       B.Add(C, aReductionInci);
1767       aResult = C;
1768     }
1769   }
1770
1771   // Get rid of extra compounds
1772   TopTools_ListOfShape listShapeRes;
1773   GEOMUtils::AddSimpleShapes(aResult, listShapeRes);
1774   aResult = listShapeRes.First(); // useful for the case "fuseReductions == true"
1775
1776   if (!fuseReductions && listShapeRes.Extent() > 1) {
1777     // Simplify T-Shape compound (get rid of sub-compounds) and glue duplicated faces
1778     BRep_Builder B;
1779     TopoDS_Compound C;
1780     B.MakeCompound(C);
1781
1782     TopTools_ListIteratorOfListOfShape itSub (listShapeRes);
1783     for (; itSub.More(); itSub.Next())
1784       B.Add(C, itSub.Value());
1785
1786     // GlueFaces
1787     aResult = GEOMImpl_GlueDriver::GlueFaces(C, Precision::Confusion(), Standard_True);
1788   }
1789
1790   return aResult;
1791 }
1792
1793 //=======================================================================
1794 //function : MakeThicknessReduction
1795 //purpose  : Static method. Create one thickness reduction element.
1796 //=======================================================================
1797 TopoDS_Shape AdvancedEngine_IOperations::MakeThicknessReduction (gp_Ax2 theAxes,
1798                                                                  const double R, const double W,
1799                                                                  const double Rthin, const double Wthin,
1800                                                                  const double Ltrans, const double Lthin,
1801                                                                  bool fuse)
1802 {
1803   double aTol = Precision::Confusion();
1804   if (Rthin < aTol || Wthin < aTol || Ltrans < aTol) {
1805     StdFail_NotDone::Raise("Cannot build thickness reduction: too small values");
1806   }
1807   bool isThinPart = (Lthin > aTol);
1808
1809   //     .
1810   //   W |\
1811   //     . \
1812   //   ^  \ '-----------------.
1813   //   |R  \|                 | Wthin
1814   //   |    '-----------------'
1815   //   v                        Rthin
1816   // --.--.--.--.--.--.--.--.--.--.--.--.--> theAxes.Direction()
1817   //     Ltrans     Lthin
1818
1819   double RExt = R + W;
1820   double RthinExt = Rthin + Wthin;
1821
1822   gp_Dir aNormal = theAxes.Direction();
1823   gp_Dir anXDir  = theAxes.XDirection();
1824   gp_Pnt aPntCyl (theAxes.Location().XYZ() + aNormal.XYZ()*Ltrans);
1825   gp_Ax2 anAxesCyl (aPntCyl, aNormal, anXDir);
1826
1827   // Build the transition part
1828   BRepPrimAPI_MakeCone ConeExt (theAxes, RExt, RthinExt, Ltrans);
1829   BRepPrimAPI_MakeCone ConeInt (theAxes, R, Rthin, Ltrans);
1830   ConeExt.Build();
1831   ConeInt.Build();
1832   if (!ConeExt.IsDone() || !ConeInt.IsDone())
1833     StdFail_NotDone::Raise("Cannot build cones of thickness reduction");
1834   BRepAlgoAPI_Cut cut1 (ConeExt.Shape(), ConeInt.Shape());
1835   if (!cut1.IsDone())
1836     StdFail_NotDone::Raise("Coudn't build transition part of thickness reduction");
1837   TopoDS_Shape aReduction = cut1.Shape();
1838
1839   // Build the thin part, if required
1840   TopoDS_Shape aThinPart;
1841   if (isThinPart) {
1842     BRepPrimAPI_MakeCylinder CExt (anAxesCyl, RthinExt, Lthin);
1843     BRepPrimAPI_MakeCylinder CInt (anAxesCyl, Rthin, Lthin);
1844     CExt.Build();
1845     CInt.Build();
1846     if (!CExt.IsDone() || !CInt.IsDone())
1847       StdFail_NotDone::Raise("Cannot build cylinders of thickness reduction");
1848     BRepAlgoAPI_Cut cut2 (CExt.Shape(), CInt.Shape());
1849     if (!cut2.IsDone())
1850       StdFail_NotDone::Raise("Coudn't build thin part of thickness reduction");
1851     aThinPart = cut2.Shape();
1852   }
1853
1854   // Join parts
1855   if (fuse) {
1856     if (isThinPart) {
1857       BRepAlgoAPI_Fuse fuse1 (aReduction, aThinPart);
1858       if (!fuse1.IsDone())
1859         StdFail_NotDone::Raise("Cannot fuse parts of thickness reduction");
1860       aReduction = fuse1.Shape();
1861     }
1862   }
1863   else {
1864     // Partition the reduction on blocks
1865     gp_Ax3 anAxesPln1 (aPntCyl, theAxes.XDirection(), aNormal);
1866     gp_Ax3 anAxesPln2 (aPntCyl, theAxes.YDirection(), aNormal);
1867     gp_Pln aPln1 (anAxesPln1);
1868     gp_Pln aPln2 (anAxesPln2);
1869     double aSize = Ltrans + Lthin + R + Rthin + Wthin; // to guarantee enough size in all directions
1870     TopoDS_Shape aTool1 = BRepBuilderAPI_MakeFace(aPln1, -aSize, +aSize, -aSize, +aSize).Shape();
1871     TopoDS_Shape aTool2 = BRepBuilderAPI_MakeFace(aPln2, -aSize, +aSize, -aSize, +aSize).Shape();
1872
1873     GEOMAlgo_Splitter PS;
1874     PS.AddArgument(aReduction);
1875     if (isThinPart)
1876       PS.AddArgument(aThinPart);
1877     PS.AddTool(aTool1);
1878     PS.AddTool(aTool2);
1879     PS.SetLimit(TopAbs_SOLID);
1880     PS.Perform();
1881
1882     aReduction = PS.Shape();
1883   }
1884
1885   return aReduction;
1886 }
1887
1888 //=============================================================================
1889 /*!
1890  *  MakePipeTShape
1891  *  \brief Create a T-shape object with specified caracteristics for the main and
1892  *         the incident pipes (radius, width, half-length).
1893  *         Center of the shape is (0,0,0). The main plane of the T-shape is XOY.
1894  *  \param theR1 Internal radius of main pipe
1895  *  \param theW1 Width of main pipe
1896  *  \param theL1 Half-length of main pipe
1897  *  \param theR2 Internal radius of incident pipe (R2 < R1)
1898  *  \param theW2 Width of incident pipe (R2+W2 < R1+W1)
1899  *  \param theL2 Half-length of incident pipe
1900  *  \param theHexMesh Boolean indicating if shape is prepared for hex mesh
1901  *  \return List of GEOM_Objects, containing the created shape and propagation groups.
1902  */
1903 //=============================================================================
1904 Handle(TColStd_HSequenceOfTransient)
1905   AdvancedEngine_IOperations::MakePipeTShape(double theR1, double theW1, double theL1,
1906                                              double theR2, double theW2, double theL2,
1907                                              double theRL, double theWL, double theLtransL, double theLthinL,
1908                                              double theRR, double theWR, double theLtransR, double theLthinR,
1909                                              double theRI, double theWI, double theLtransI, double theLthinI,
1910                                              bool theHexMesh)
1911 {
1912   MESSAGE("AdvancedEngine_IOperations::MakePipeTShape");
1913   SetErrorCode(KO);
1914   //Add a new object
1915   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_TSHAPE);
1916
1917   //Add a new shape function with parameters
1918   Handle(GEOM_Function) aFunction = aShape->AddFunction(AdvancedEngine_PipeTShapeDriver::GetID(), TSHAPE_BASIC);
1919   if (aFunction.IsNull()) return NULL;
1920
1921   //Check if the function is set correctly
1922   if (aFunction->GetDriverGUID() != AdvancedEngine_PipeTShapeDriver::GetID()) return NULL;
1923
1924   AdvancedEngine_IPipeTShape aData (aFunction);
1925
1926   aData.SetR1(theR1);
1927   aData.SetW1(theW1);
1928   aData.SetL1(theL1);
1929   aData.SetR2(theR2);
1930   aData.SetW2(theW2);
1931   aData.SetL2(theL2);
1932   aData.SetHexMesh(theHexMesh);
1933
1934   bool isTRL = (theRL + theWL + theLtransL + theLthinL) > Precision::Confusion();
1935   bool isTRR = (theRR + theWR + theLtransR + theLthinR) > Precision::Confusion();
1936   bool isTRI = (theRI + theWI + theLtransI + theLthinI) > Precision::Confusion();
1937
1938   //Compute the resulting value
1939   try {
1940     OCC_CATCH_SIGNALS;
1941     if (!GetSolver()->ComputeFunction(aFunction)) {
1942       SetErrorCode("TShape driver failed");
1943       return NULL;
1944     }
1945
1946     if (theHexMesh) {
1947       if (!MakePipeTShapePartition(aShape, theR1, theW1, theL1, theR2, theW2, theL2))
1948         return NULL;
1949       if (!MakePipeTShapeMirrorAndGlue(aShape, theR1, theW1, theL1, theR2, theW2, theL2))
1950         return NULL;
1951     }
1952
1953     if (isTRL || isTRR || isTRI) {
1954       // Add thickness reduction elements
1955       // at the three extremities: Left, Right and Incident
1956       TopoDS_Shape aResShape =
1957         MakePipeTShapeThicknessReduction(aShape->GetValue(), theR1, theW1, theL1, theR2, theW2, theL2,
1958                                          theRL, theWL, theLtransL, theLthinL,
1959                                          theRR, theWR, theLtransR, theLthinR,
1960                                          theRI, theWI, theLtransI, theLthinI,
1961                                          !theHexMesh);
1962       aFunction->SetValue(aResShape);
1963     }
1964   }
1965   catch (Standard_Failure& aFail) {
1966     SetErrorCode(aFail.GetMessageString());
1967     return NULL;
1968   }
1969
1970   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1971   aSeq->Append(aShape);
1972
1973   try {
1974     if (theHexMesh) {
1975       // Get the groups
1976       if (!MakeGroups(aShape, TSHAPE_BASIC, theR1, theW1, theL1, theR2, theW2, theL2,
1977                       0., 0., 0., aSeq, gp_Trsf()))
1978         return NULL;
1979     }
1980
1981     // Get internal group.
1982     if (!MakeInternalGroup(aShape, theR1, theL1, theR2, theL2, theRL, theLtransL,
1983                            theRR, theLtransR, theRI, theLtransI,
1984                            aSeq, gp_Trsf())) {
1985       return NULL;
1986     }
1987   }
1988   catch (Standard_Failure& aFail) {
1989     SetErrorCode(aFail.GetMessageString());
1990     return NULL;
1991   }
1992
1993   //Make a Python command
1994   TCollection_AsciiString anEntry, aListRes("[");
1995   // Iterate over the sequence aSeq
1996   Standard_Integer aNbGroups = aSeq->Length();
1997   Standard_Integer i = 1;
1998   for (; i <= aNbGroups; i++) {
1999     Handle(Standard_Transient) anItem = aSeq->Value(i);
2000     if (anItem.IsNull()) continue;
2001     Handle(GEOM_Object) aGroup = Handle(GEOM_Object)::DownCast(anItem);
2002     if (aGroup.IsNull()) continue;
2003     //Make a Python command
2004     TDF_Tool::Entry(aGroup->GetEntry(), anEntry);
2005     aListRes += anEntry + ", ";
2006   }
2007   aListRes.Trunc(aListRes.Length() - 2);
2008
2009   GEOM::TPythonDump pd (aFunction);
2010
2011   pd << aListRes.ToCString() << "] = geompy.MakePipeTShape("
2012      << theR1 << ", " << theW1 << ", " << theL1 << ", "
2013      << theR2 << ", " << theW2 << ", " << theL2 << ", "
2014      << theHexMesh;
2015
2016   // thickness reduction
2017   if (isTRL)
2018     pd << ", theRL=" << theRL << ", theWL=" << theWL
2019        << ", theLtransL=" << theLtransL << ", theLthinL=" << theLthinL;
2020   if (isTRR)
2021     pd << ", theRR=" << theRR << ", theWR=" << theWR
2022        << ", theLtransR=" << theLtransR << ", theLthinR=" << theLthinR;
2023   if (isTRI)
2024     pd << ", theRI=" << theRI << ", theWI=" << theWI
2025        << ", theLtransI=" << theLtransI << ", theLthinI=" << theLthinI;
2026
2027   pd << ")";
2028
2029   SetErrorCode(OK);
2030
2031   return aSeq;
2032 }
2033
2034 //=============================================================================
2035 /*!
2036  *  MakePipeTShapeWithPosition
2037  *  Create a T-shape object with specified caracteristics for the main and
2038  *  the incident pipes (radius, width, half-length).
2039  *  The extremities of the main pipe are located on junctions points P1 and P2.
2040  *  The extremity of the incident pipe is located on junction point P3.
2041  *  \param theR1 Internal radius of main pipe
2042  *  \param theW1 Width of main pipe
2043  *  \param theL1 Half-length of main pipe
2044  *  \param theR2 Internal radius of incident pipe (R2 < R1)
2045  *  \param theW2 Width of incident pipe (R2+W2 < R1+W1)
2046  *  \param theL2 Half-length of incident pipe
2047  *  \param theHexMesh Boolean indicating if shape is prepared for hex mesh
2048  *  \param theP1 1st junction point of main pipe
2049  *  \param theP2 2nd junction point of main pipe
2050  *  \param theP3 Junction point of incident pipe
2051  *  \return List of GEOM_Objects, containing the created shape and propagation groups..
2052  */
2053 //=============================================================================
2054 Handle(TColStd_HSequenceOfTransient)
2055 AdvancedEngine_IOperations::MakePipeTShapeWithPosition
2056                              (double theR1, double theW1, double theL1,
2057                               double theR2, double theW2, double theL2,
2058                               double theRL, double theWL, double theLtransL, double theLthinL,
2059                               double theRR, double theWR, double theLtransR, double theLthinR,
2060                               double theRI, double theWI, double theLtransI, double theLthinI,
2061                               bool theHexMesh,
2062                               Handle(GEOM_Object) theP1,
2063                               Handle(GEOM_Object) theP2,
2064                               Handle(GEOM_Object) theP3)
2065 {
2066   SetErrorCode(KO);
2067   //Add a new object
2068   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_TSHAPE);
2069   /////////////////
2070   // TSHAPE CODE
2071   /////////////////
2072   //Add a new shape function with parameters
2073   Handle(GEOM_Function) aFunction = aShape->AddFunction(AdvancedEngine_PipeTShapeDriver::GetID(), TSHAPE_BASIC);
2074   if (aFunction.IsNull()) return NULL;
2075
2076   //Check if the function is set correctly
2077   if (aFunction->GetDriverGUID() != AdvancedEngine_PipeTShapeDriver::GetID()) return NULL;
2078
2079   // Check new position
2080   if (!CheckCompatiblePosition(theL1, theL2, theP1, theP2, theP3, 0.01)) {
2081     return NULL;
2082   }
2083
2084   AdvancedEngine_IPipeTShape aData(aFunction);
2085
2086   aData.SetR1(theR1);
2087   aData.SetW1(theW1);
2088   aData.SetL1(theL1);
2089   aData.SetR2(theR2);
2090   aData.SetW2(theW2);
2091   aData.SetL2(theL2);
2092   aData.SetHexMesh(theHexMesh);
2093
2094   bool isTRL = (theRL + theWL + theLtransL + theLthinL) > Precision::Confusion();
2095   bool isTRR = (theRR + theWR + theLtransR + theLthinR) > Precision::Confusion();
2096   bool isTRI = (theRI + theWI + theLtransI + theLthinI) > Precision::Confusion();
2097
2098   //Compute the resulting value
2099   try {
2100     OCC_CATCH_SIGNALS;
2101     if (!GetSolver()->ComputeFunction(aFunction)) {
2102       SetErrorCode("TShape driver failed");
2103       return NULL;
2104     }
2105
2106     if (theHexMesh) {
2107       if (!MakePipeTShapePartition(aShape, theR1, theW1, theL1, theR2, theW2, theL2))
2108         return NULL;
2109       if (!MakePipeTShapeMirrorAndGlue(aShape, theR1, theW1, theL1, theR2, theW2, theL2))
2110         return NULL;
2111     }
2112
2113     if (isTRL || isTRR || isTRI) {
2114       // Add thickness reduction elements
2115       // at the three extremities: Left, Right and Incident
2116       TopoDS_Shape aResShape =
2117         MakePipeTShapeThicknessReduction(aShape->GetValue(), theR1, theW1, theL1, theR2, theW2, theL2,
2118                                          theRL, theWL, theLtransL, theLthinL,
2119                                          theRR, theWR, theLtransR, theLthinR,
2120                                          theRI, theWI, theLtransI, theLthinI,
2121                                          !theHexMesh);
2122       aFunction->SetValue(aResShape);
2123     }
2124   }
2125   catch (Standard_Failure& aFail) {
2126     SetErrorCode(aFail.GetMessageString());
2127     return NULL;
2128   }
2129
2130   TopoDS_Shape Te = aShape->GetValue();
2131
2132   // Set Position
2133   gp_Trsf aTrsf = GetPositionTrsf(theL1, theL2, theP1, theP2, theP3);
2134   BRepBuilderAPI_Transform aTransformation(Te, aTrsf, Standard_False);
2135   TopoDS_Shape aTrsf_Shape = aTransformation.Shape();
2136   aFunction->SetValue(aTrsf_Shape);
2137
2138   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
2139   aSeq->Append(aShape);
2140
2141   try {
2142     if (theHexMesh) {
2143       // Get the groups
2144       if (!MakeGroups(aShape,TSHAPE_BASIC, theR1, theW1, theL1, theR2, theW2, theL2,
2145                       0., 0., 0., aSeq, aTrsf)) {
2146         return NULL;
2147       }
2148     }
2149
2150     // Get internal group.
2151     if (!MakeInternalGroup(aShape, theR1, theL1, theR2, theL2, theRL, theLtransL,
2152                            theRR, theLtransR, theRI, theLtransI,
2153                            aSeq, aTrsf)) {
2154       return NULL;
2155     }
2156   }
2157   catch (Standard_Failure& aFail) {
2158     SetErrorCode(aFail.GetMessageString());
2159     return NULL;
2160   }
2161
2162   //Make a Python command
2163   TCollection_AsciiString anEntry, aListRes("[");
2164   // Iterate over the sequence aSeq
2165   Standard_Integer aNbGroups = aSeq->Length();
2166   Standard_Integer i = 1;
2167   for (; i <= aNbGroups; i++) {
2168     Handle(Standard_Transient) anItem = aSeq->Value(i);
2169     if (anItem.IsNull()) continue;
2170     Handle(GEOM_Object) aGroup = Handle(GEOM_Object)::DownCast(anItem);
2171     if (aGroup.IsNull()) continue;
2172     //Make a Python command
2173     TDF_Tool::Entry(aGroup->GetEntry(), anEntry);
2174     aListRes += anEntry + ", ";
2175   }
2176   aListRes.Trunc(aListRes.Length() - 2);
2177
2178   GEOM::TPythonDump pd (aFunction);
2179
2180   pd << aListRes.ToCString() << "] = geompy.MakePipeTShape("
2181      << theR1 << ", " << theW1 << ", " << theL1 << ", "
2182      << theR2 << ", " << theW2 << ", " << theL2 << ", "
2183      << theHexMesh << ", " << theP1 << ", " << theP2 << ", " << theP3;
2184
2185   // thickness reduction
2186   if (isTRL)
2187     pd << ", theRL=" << theRL << ", theWL=" << theWL
2188        << ", theLtransL=" << theLtransL << ", theLthinL=" << theLthinL;
2189   if (isTRR)
2190     pd << ", theRR=" << theRR << ", theWR=" << theWR
2191        << ", theLtransR=" << theLtransR << ", theLthinR=" << theLthinR;
2192   if (isTRI)
2193     pd << ", theRI=" << theRI << ", theWI=" << theWI
2194        << ", theLtransI=" << theLtransI << ", theLthinI=" << theLthinI;
2195
2196   pd << ")";
2197
2198   SetErrorCode(OK);
2199
2200   return aSeq;
2201 }
2202
2203 //=============================================================================
2204 /*!
2205  *  MakePipeTShapeChamfer
2206  *  Create a T-shape object with specified caracteristics for the main and
2207  *  the incident pipes (radius, width, half-length). A chamfer is created
2208  *  on the junction of the pipes.
2209  *  Center of the shape is (0,0,0). The main plane of the T-shape is XOY.
2210  *  \param theR1 Internal radius of main pipe
2211  *  \param theW1 Width of main pipe
2212  *  \param theL1 Half-length of main pipe
2213  *  \param theR2 Internal radius of incident pipe (R2 < R1)
2214  *  \param theW2 Width of incident pipe (R2+W2 < R1+W1)
2215  *  \param theL2 Half-length of incident pipe
2216  *  \param theH Height of chamfer.
2217  *  \param theW Width of chamfer.
2218  *  \param theHexMesh Boolean indicating if shape is prepared for hex mesh
2219  *  \return List of GEOM_Objects, containing the created shape and propagation groups.
2220  */
2221 //=============================================================================
2222 Handle(TColStd_HSequenceOfTransient)
2223 AdvancedEngine_IOperations::MakePipeTShapeChamfer
2224                              (double theR1, double theW1, double theL1,
2225                               double theR2, double theW2, double theL2,
2226                               double theRL, double theWL, double theLtransL, double theLthinL,
2227                               double theRR, double theWR, double theLtransR, double theLthinR,
2228                               double theRI, double theWI, double theLtransI, double theLthinI,
2229                               double theH, double theW,
2230                               bool theHexMesh)
2231 {
2232   SetErrorCode(KO);
2233   //Add a new object
2234   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_TSHAPE);
2235   //Add a new shape function with parameters
2236   Handle(GEOM_Function) aFunction = aShape->AddFunction(AdvancedEngine_PipeTShapeDriver::GetID(), TSHAPE_CHAMFER);
2237   if (aFunction.IsNull()) return NULL;
2238
2239   //Check if the function is set correctly
2240   if (aFunction->GetDriverGUID() != AdvancedEngine_PipeTShapeDriver::GetID()) return NULL;
2241
2242   AdvancedEngine_IPipeTShape aData(aFunction);
2243
2244   aData.SetR1(theR1);
2245   aData.SetW1(theW1);
2246   aData.SetL1(theL1);
2247   aData.SetR2(theR2);
2248   aData.SetW2(theW2);
2249   aData.SetL2(theL2);
2250   aData.SetH(theH);
2251   aData.SetW(theW);
2252   aData.SetHexMesh(theHexMesh);
2253
2254   bool isTRL = (theRL + theWL + theLtransL + theLthinL) > Precision::Confusion();
2255   bool isTRR = (theRR + theWR + theLtransR + theLthinR) > Precision::Confusion();
2256   bool isTRI = (theRI + theWI + theLtransI + theLthinI) > Precision::Confusion();
2257
2258   //Compute the resulting value
2259   try {
2260     OCC_CATCH_SIGNALS;
2261     if (!GetSolver()->ComputeFunction(aFunction)) {
2262       SetErrorCode("TShape driver failed");
2263       return NULL;
2264     }
2265   }
2266   catch (Standard_Failure& aFail) {
2267     SetErrorCode(aFail.GetMessageString());
2268     return NULL;
2269   }
2270
2271   // BEGIN of chamfer
2272   TopoDS_Shape aShapeShape = aShape->GetValue();
2273   TopTools_IndexedMapOfShape anEdgesIndices;
2274   TopExp::MapShapes(aShapeShape, anEdgesIndices);
2275   // Common edges on external cylinders
2276   Handle(GEOM_Object) box_e;
2277   if (theHexMesh) {
2278     box_e = my3DPrimOperations->MakeBoxDXDYDZ(theR2+theW2, theR2+theW2, theR1+theW1);
2279   }
2280   else {
2281     box_e = my3DPrimOperations->MakeBoxDXDYDZ(2*(theR2+theW2), 2*(theR2+theW2), theR1+theW1);
2282   }
2283   box_e->GetLastFunction()->SetDescription("");
2284   box_e = myTransformOperations->TranslateDXDYDZ(box_e, -(theR2+theW2), -(theR2+theW2), 0);
2285   box_e->GetLastFunction()->SetDescription("");
2286
2287   Handle(TColStd_HSequenceOfInteger) edges_e =
2288     myShapesOperations->GetShapesOnBoxIDs(box_e, aShape, TopAbs_EDGE, GEOMAlgo_ST_IN);
2289   box_e->GetLastFunction()->SetDescription("");
2290
2291   if (edges_e.IsNull() || edges_e->Length() == 0) {
2292     SetErrorCode("External edges not found");
2293     return NULL;
2294   }
2295   int nbEdgesInChamfer = 0;
2296   std::list<int> theEdges;
2297   for (int i=1; i<=edges_e->Length();i++) {
2298     int edgeID = edges_e->Value(i);
2299     TopoDS_Shape theEdge = anEdgesIndices.FindKey(edgeID);
2300     TopExp_Explorer Ex(theEdge,TopAbs_VERTEX);
2301     int iv=0;
2302     while (Ex.More()) {
2303       iv ++;
2304       gp_Pnt aPt = BRep_Tool::Pnt(TopoDS::Vertex(Ex.Current()));
2305       if (Abs(aPt.Z() - (theR1+theW1)) <= Precision::Confusion()) {
2306         nbEdgesInChamfer ++;
2307         theEdges.push_back(edgeID);
2308       }
2309       Ex.Next();
2310     }
2311     if (theHexMesh && nbEdgesInChamfer == 1)
2312       break;
2313   }
2314   Handle(GEOM_Object) aChamfer;
2315   try {
2316     aChamfer = myLocalOperations->MakeChamferEdges(aShape, theW, theH, theEdges);
2317   }
2318   catch (Standard_Failure& aFail) {
2319     SetErrorCode(aFail.GetMessageString());
2320     return NULL;
2321   }
2322   if (aChamfer.IsNull()) {
2323     SetErrorCode("Chamfer can not be computed on the given shape with the given parameters");
2324     return NULL;
2325   }
2326   aChamfer->GetLastFunction()->SetDescription("");
2327
2328   TopoDS_Shape aChamferShape = aChamfer->GetValue();
2329   aFunction->SetValue(aChamferShape);
2330   // END of chamfer
2331
2332   if (theHexMesh) {
2333     if (!MakePipeTShapePartition(aShape, theR1, theW1, theL1, theR2, theW2, theL2, theH, theW, 0, false))
2334       return NULL;
2335     if (!MakePipeTShapeMirrorAndGlue(aShape, theR1, theW1, theL1, theR2, theW2, theL2))
2336       return NULL;
2337   }
2338
2339   // Add thickness reduction elements
2340   // at the three extremities: Left, Right and Incident
2341   try {
2342     OCC_CATCH_SIGNALS;
2343     if (isTRL || isTRR || isTRI) {
2344       TopoDS_Shape aResShape =
2345         MakePipeTShapeThicknessReduction(aShape->GetValue(), theR1, theW1, theL1, theR2, theW2, theL2,
2346                                          theRL, theWL, theLtransL, theLthinL,
2347                                          theRR, theWR, theLtransR, theLthinR,
2348                                          theRI, theWI, theLtransI, theLthinI,
2349                                          !theHexMesh);
2350       aFunction->SetValue(aResShape);
2351     }
2352   }
2353   catch (Standard_Failure& aFail) {
2354     SetErrorCode(aFail.GetMessageString());
2355     return NULL;
2356   }
2357
2358   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
2359   aSeq->Append(aShape);
2360
2361   try {
2362     if (theHexMesh) {
2363       // Get the groups
2364       if (!MakeGroups(aShape, TSHAPE_CHAMFER, theR1, theW1, theL1, theR2, theW2, theL2,
2365                       theH, theW, 0., aSeq, gp_Trsf()))
2366         return NULL;
2367     }
2368
2369     // Get internal group.
2370     if (!MakeInternalGroup(aShape, theR1, theL1, theR2, theL2, theRL, theLtransL,
2371                            theRR, theLtransR, theRI, theLtransI,
2372                            aSeq, gp_Trsf())) {
2373       return NULL;
2374     }
2375   }
2376   catch (Standard_Failure& aFail) {
2377     SetErrorCode(aFail.GetMessageString());
2378     return NULL;
2379   }
2380
2381   //Make a Python command
2382   TCollection_AsciiString anEntry, aListRes("[");
2383   // Iterate over the sequence aSeq
2384   Standard_Integer aNbGroups = aSeq->Length();
2385   Standard_Integer i = 1;
2386   for (; i <= aNbGroups; i++) {
2387     Handle(Standard_Transient) anItem = aSeq->Value(i);
2388     if (anItem.IsNull()) continue;
2389     Handle(GEOM_Object) aGroup = Handle(GEOM_Object)::DownCast(anItem);
2390     if (aGroup.IsNull()) continue;
2391     //Make a Python command
2392     TDF_Tool::Entry(aGroup->GetEntry(), anEntry);
2393     aListRes += anEntry + ", ";
2394   }
2395   aListRes.Trunc(aListRes.Length() - 2);
2396
2397   GEOM::TPythonDump pd (aFunction);
2398
2399   pd << aListRes.ToCString() << "] = geompy.MakePipeTShapeChamfer("
2400      << theR1 << ", " << theW1 << ", " << theL1 << ", "
2401      << theR2 << ", " << theW2 << ", " << theL2 << ", "
2402      << theH << ", " << theW << ", " << theHexMesh;
2403
2404   // thickness reduction
2405   if (isTRL)
2406     pd << ", theRL=" << theRL << ", theWL=" << theWL
2407        << ", theLtransL=" << theLtransL << ", theLthinL=" << theLthinL;
2408   if (isTRR)
2409     pd << ", theRR=" << theRR << ", theWR=" << theWR
2410        << ", theLtransR=" << theLtransR << ", theLthinR=" << theLthinR;
2411   if (isTRI)
2412     pd << ", theRI=" << theRI << ", theWI=" << theWI
2413        << ", theLtransI=" << theLtransI << ", theLthinI=" << theLthinI;
2414
2415   pd << ")";
2416
2417   SetErrorCode(OK);
2418
2419   return aSeq;
2420 }
2421
2422 //=============================================================================
2423 /*!
2424  *  MakePipeTShapeChamferWithPosition
2425  *  Create a T-shape object with specified caracteristics for the main and
2426  *  the incident pipes (radius, width, half-length). A chamfer is created
2427  *  on the junction of the pipes.
2428  *  The extremities of the main pipe are located on junctions points P1 and P2.
2429  *  The extremity of the incident pipe is located on junction point P3.
2430  *  \param theR1 Internal radius of main pipe
2431  *  \param theW1 Width of main pipe
2432  *  \param theL1 Half-length of main pipe
2433  *  \param theR2 Internal radius of incident pipe (R2 < R1)
2434  *  \param theW2 Width of incident pipe (R2+W2 < R1+W1)
2435  *  \param theL2 Half-length of incident pipe
2436  *  \param theH Height of chamfer.
2437  *  \param theW Width of chamfer.
2438  *  \param theHexMesh Boolean indicating if shape is prepared for hex mesh
2439  *  \param theP1 1st junction point of main pipe
2440  *  \param theP2 2nd junction point of main pipe
2441  *  \param theP3 Junction point of incident pipe
2442  *  \return List of GEOM_Objects, containing the created shape and propagation groups.
2443  */
2444 //=============================================================================
2445 Handle(TColStd_HSequenceOfTransient)
2446 AdvancedEngine_IOperations::MakePipeTShapeChamferWithPosition
2447                              (double theR1, double theW1, double theL1,
2448                               double theR2, double theW2, double theL2,
2449                               double theRL, double theWL, double theLtransL, double theLthinL,
2450                               double theRR, double theWR, double theLtransR, double theLthinR,
2451                               double theRI, double theWI, double theLtransI, double theLthinI,
2452                               double theH, double theW,
2453                               bool theHexMesh,
2454                               Handle(GEOM_Object) theP1,
2455                               Handle(GEOM_Object) theP2,
2456                               Handle(GEOM_Object) theP3)
2457 {
2458   SetErrorCode(KO);
2459   //Add a new object
2460   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_TSHAPE);
2461   //Add a new shape function with parameters
2462   Handle(GEOM_Function) aFunction = aShape->AddFunction(AdvancedEngine_PipeTShapeDriver::GetID(), TSHAPE_CHAMFER);
2463   if (aFunction.IsNull()) return NULL;
2464
2465   //Check if the function is set correctly
2466   if (aFunction->GetDriverGUID() != AdvancedEngine_PipeTShapeDriver::GetID()) return NULL;
2467
2468   // Check new position
2469   if (!CheckCompatiblePosition(theL1, theL2, theP1, theP2, theP3, 0.01)) {
2470     return NULL;
2471   }
2472
2473   AdvancedEngine_IPipeTShape aData(aFunction);
2474
2475   aData.SetR1(theR1);
2476   aData.SetW1(theW1);
2477   aData.SetL1(theL1);
2478   aData.SetR2(theR2);
2479   aData.SetW2(theW2);
2480   aData.SetL2(theL2);
2481   aData.SetH(theH);
2482   aData.SetW(theW);
2483   aData.SetHexMesh(theHexMesh);
2484
2485   bool isTRL = (theRL + theWL + theLtransL + theLthinL) > Precision::Confusion();
2486   bool isTRR = (theRR + theWR + theLtransR + theLthinR) > Precision::Confusion();
2487   bool isTRI = (theRI + theWI + theLtransI + theLthinI) > Precision::Confusion();
2488
2489   //Compute the resulting value
2490   try {
2491     OCC_CATCH_SIGNALS;
2492     if (!GetSolver()->ComputeFunction(aFunction)) {
2493       SetErrorCode("TShape driver failed");
2494       return NULL;
2495     }
2496   }
2497   catch (Standard_Failure& aFail) {
2498     SetErrorCode(aFail.GetMessageString());
2499     return NULL;
2500   }
2501
2502   // BEGIN of chamfer
2503   TopoDS_Shape aShapeShape = aShape->GetValue();
2504   TopTools_IndexedMapOfShape anEdgesIndices;
2505   TopExp::MapShapes(aShapeShape, anEdgesIndices);
2506   // Common edges on external cylinders
2507   Handle(GEOM_Object) box_e;
2508   if (theHexMesh) {
2509     box_e = my3DPrimOperations->MakeBoxDXDYDZ(theR2+theW2, theR2+theW2, theR1+theW1);
2510   }
2511   else {
2512     box_e = my3DPrimOperations->MakeBoxDXDYDZ(2*(theR2+theW2), 2*(theR2+theW2), theR1+theW1);
2513   }
2514   box_e->GetLastFunction()->SetDescription("");
2515   box_e = myTransformOperations->TranslateDXDYDZ(box_e, -(theR2+theW2), -(theR2+theW2), 0);
2516   box_e->GetLastFunction()->SetDescription("");
2517
2518   Handle(TColStd_HSequenceOfInteger) edges_e =
2519     myShapesOperations->GetShapesOnBoxIDs(box_e, aShape, TopAbs_EDGE, GEOMAlgo_ST_IN);
2520   box_e->GetLastFunction()->SetDescription("");
2521
2522   if (edges_e.IsNull() || edges_e->Length() == 0) {
2523     SetErrorCode("External edges not found");
2524     return NULL;
2525   }
2526   int nbEdgesInChamfer = 0;
2527   std::list<int> theEdges;
2528   for (int i=1; i<=edges_e->Length();i++) {
2529     int edgeID = edges_e->Value(i);
2530     TopoDS_Shape theEdge = anEdgesIndices.FindKey(edgeID);
2531     TopExp_Explorer Ex(theEdge,TopAbs_VERTEX);
2532     while (Ex.More()) {
2533       gp_Pnt aPt = BRep_Tool::Pnt(TopoDS::Vertex(Ex.Current()));
2534       if (Abs(aPt.Z() - (theR1+theW1)) <= Precision::Confusion()) {
2535         nbEdgesInChamfer ++;
2536         theEdges.push_back(edgeID);
2537       }
2538       Ex.Next();
2539     }
2540     if (theHexMesh && nbEdgesInChamfer == 1)
2541       break;
2542   }
2543   Handle(GEOM_Object) aChamfer;
2544   try {
2545     aChamfer = myLocalOperations->MakeChamferEdges(aShape, theW, theH, theEdges);
2546   }
2547   catch (Standard_Failure& aFail) {
2548     SetErrorCode(aFail.GetMessageString());
2549     return NULL;
2550   }
2551   if (aChamfer.IsNull()) {
2552     SetErrorCode("Chamfer can not be computed on the given shape with the given parameters");
2553     return NULL;
2554   }
2555   aChamfer->GetLastFunction()->SetDescription("");
2556
2557   TopoDS_Shape aChamferShape = aChamfer->GetValue();
2558   aFunction->SetValue(aChamferShape);
2559   // END of chamfer
2560
2561   if (theHexMesh) {
2562     if (!MakePipeTShapePartition(aShape, theR1, theW1, theL1, theR2, theW2, theL2, theH, theW, 0, false))
2563       return NULL;
2564     if (!MakePipeTShapeMirrorAndGlue(aShape, theR1, theW1, theL1, theR2, theW2, theL2))
2565       return NULL;
2566   }
2567
2568   // Add thickness reduction elements
2569   // at the three extremities: Left, Right and Incident
2570   try {
2571     OCC_CATCH_SIGNALS;
2572     if (isTRL || isTRR || isTRI) {
2573       TopoDS_Shape aResShape =
2574         MakePipeTShapeThicknessReduction(aShape->GetValue(), theR1, theW1, theL1, theR2, theW2, theL2,
2575                                          theRL, theWL, theLtransL, theLthinL,
2576                                          theRR, theWR, theLtransR, theLthinR,
2577                                          theRI, theWI, theLtransI, theLthinI,
2578                                          !theHexMesh);
2579       aFunction->SetValue(aResShape);
2580     }
2581   }
2582   catch (Standard_Failure& aFail) {
2583     SetErrorCode(aFail.GetMessageString());
2584     return NULL;
2585   }
2586
2587   // Set Position
2588   gp_Trsf aTrsf = GetPositionTrsf(theL1, theL2, theP1, theP2, theP3);
2589   BRepBuilderAPI_Transform aTransformation (aShape->GetValue(), aTrsf, Standard_False);
2590   TopoDS_Shape aTrsf_Shape = aTransformation.Shape();
2591   aFunction->SetValue(aTrsf_Shape);
2592
2593   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
2594   aSeq->Append(aShape);
2595
2596   try {
2597     if (theHexMesh) {
2598       // Get the groups
2599       if (!MakeGroups(aShape, TSHAPE_CHAMFER, theR1, theW1, theL1, theR2, theW2, theL2,
2600                       theH, theW, 0., aSeq, aTrsf))
2601         return NULL;
2602     }
2603
2604     // Get internal group.
2605     if (!MakeInternalGroup(aShape, theR1, theL1, theR2, theL2, theRL, theLtransL,
2606                            theRR, theLtransR, theRI, theLtransI,
2607                            aSeq, aTrsf)) {
2608       return NULL;
2609     }
2610   }
2611   catch (Standard_Failure& aFail) {
2612     SetErrorCode(aFail.GetMessageString());
2613     return NULL;
2614   }
2615
2616   //Make a Python command
2617   TCollection_AsciiString anEntry, aListRes("[");
2618   // Iterate over the sequence aSeq
2619   Standard_Integer aNbGroups = aSeq->Length();
2620   Standard_Integer i = 1;
2621   for (; i <= aNbGroups; i++) {
2622     Handle(Standard_Transient) anItem = aSeq->Value(i);
2623     if (anItem.IsNull()) continue;
2624     Handle(GEOM_Object) aGroup = Handle(GEOM_Object)::DownCast(anItem);
2625     if (aGroup.IsNull()) continue;
2626     //Make a Python command
2627     TDF_Tool::Entry(aGroup->GetEntry(), anEntry);
2628     aListRes += anEntry + ", ";
2629   }
2630   aListRes.Trunc(aListRes.Length() - 2);
2631
2632   GEOM::TPythonDump pd (aFunction);
2633
2634   pd << aListRes.ToCString() << "] = geompy.MakePipeTShapeChamfer("
2635      << theR1 << ", " << theW1 << ", " << theL1 << ", "
2636      << theR2 << ", " << theW2 << ", " << theL2 << ", "
2637      << theH << ", " << theW << ", " << theHexMesh << ", "
2638      << theP1 << ", " << theP2 << ", " << theP3;
2639
2640   // thickness reduction
2641   if (isTRL)
2642     pd << ", theRL=" << theRL << ", theWL=" << theWL
2643        << ", theLtransL=" << theLtransL << ", theLthinL=" << theLthinL;
2644   if (isTRR)
2645     pd << ", theRR=" << theRR << ", theWR=" << theWR
2646        << ", theLtransR=" << theLtransR << ", theLthinR=" << theLthinR;
2647   if (isTRI)
2648     pd << ", theRI=" << theRI << ", theWI=" << theWI
2649        << ", theLtransI=" << theLtransI << ", theLthinI=" << theLthinI;
2650
2651   pd << ")";
2652
2653   SetErrorCode(OK);
2654
2655   return aSeq;
2656 }
2657
2658 //=============================================================================
2659 /*!
2660  *  MakePipeTShapeFillet
2661  *  Create a T-shape object with specified caracteristics for the main and
2662  *  the incident pipes (radius, width, half-length). A fillet is created
2663  *  on the junction of the pipes.
2664  *  Center of the shape is (0,0,0). The main plane of the T-shape is XOY.
2665  *  \param theR1 Internal radius of main pipe
2666  *  \param theW1 Width of main pipe
2667  *  \param theL1 Half-length of main pipe
2668  *  \param theR2 Internal radius of incident pipe (R2 < R1)
2669  *  \param theW2 Width of incident pipe (R2+W2 < R1+W1)
2670  *  \param theL2 Half-length of incident pipe
2671  *  \param theRF Radius of curvature of fillet.
2672  *  \param theHexMesh Boolean indicating if shape is prepared for hex mesh
2673  *  \return List of GEOM_Objects, containing the created shape and propagation groups.
2674  */
2675 //=============================================================================
2676 Handle(TColStd_HSequenceOfTransient)
2677 AdvancedEngine_IOperations::MakePipeTShapeFillet
2678                              (double theR1, double theW1, double theL1,
2679                               double theR2, double theW2, double theL2,
2680                               double theRL, double theWL, double theLtransL, double theLthinL,
2681                               double theRR, double theWR, double theLtransR, double theLthinR,
2682                               double theRI, double theWI, double theLtransI, double theLthinI,
2683                               double theRF, bool theHexMesh)
2684 {
2685   SetErrorCode(KO);
2686   //Add a new object
2687   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_TSHAPE);
2688   //Add a new shape function with parameters
2689   Handle(GEOM_Function) aFunction = aShape->AddFunction(AdvancedEngine_PipeTShapeDriver::GetID(), TSHAPE_FILLET);
2690   if (aFunction.IsNull()) return NULL;
2691
2692   //Check if the function is set correctly
2693   if (aFunction->GetDriverGUID() != AdvancedEngine_PipeTShapeDriver::GetID()) return NULL;
2694
2695   AdvancedEngine_IPipeTShape aData(aFunction);
2696
2697   aData.SetR1(theR1);
2698   aData.SetW1(theW1);
2699   aData.SetL1(theL1);
2700   aData.SetR2(theR2);
2701   aData.SetW2(theW2);
2702   aData.SetL2(theL2);
2703   aData.SetRF(theRF);
2704   aData.SetHexMesh(theHexMesh);
2705
2706   bool isTRL = (theRL + theWL + theLtransL + theLthinL) > Precision::Confusion();
2707   bool isTRR = (theRR + theWR + theLtransR + theLthinR) > Precision::Confusion();
2708   bool isTRI = (theRI + theWI + theLtransI + theLthinI) > Precision::Confusion();
2709
2710   //Compute the resulting value
2711   try {
2712     OCC_CATCH_SIGNALS;
2713     if (!GetSolver()->ComputeFunction(aFunction)) {
2714       SetErrorCode("TShape driver failed");
2715       return NULL;
2716     }
2717   }
2718   catch (Standard_Failure& aFail) {
2719     SetErrorCode(aFail.GetMessageString());
2720     return NULL;
2721   }
2722
2723   // BEGIN of fillet
2724   TopoDS_Shape aShapeShape = aShape->GetValue();
2725   TopTools_IndexedMapOfShape anEdgesIndices;
2726   TopExp::MapShapes(aShapeShape, anEdgesIndices);
2727   // Common edges on external cylinders
2728   Handle(GEOM_Object) box_e;
2729   if (theHexMesh) {
2730     box_e = my3DPrimOperations->MakeBoxDXDYDZ(theR2+theW2, theR2+theW2, theR1+theW1);
2731   }
2732   else {
2733     box_e = my3DPrimOperations->MakeBoxDXDYDZ(2*(theR2+theW2), 2*(theR2+theW2), theR1+theW1);
2734   }
2735   box_e->GetLastFunction()->SetDescription("");
2736   box_e = myTransformOperations->TranslateDXDYDZ(box_e, -(theR2+theW2), -(theR2+theW2), 0);
2737   box_e->GetLastFunction()->SetDescription("");
2738
2739   Handle(TColStd_HSequenceOfInteger) edges_e =
2740     myShapesOperations->GetShapesOnBoxIDs(box_e, aShape, TopAbs_EDGE, GEOMAlgo_ST_IN);
2741   box_e->GetLastFunction()->SetDescription("");
2742
2743   if (edges_e.IsNull() || edges_e->Length() == 0) {
2744     SetErrorCode("External edges not found");
2745     return NULL;
2746   }
2747   int nbEdgesInFillet = 0;
2748   std::list<int> theEdges;
2749   for (int i=1; i<=edges_e->Length();i++) {
2750     int edgeID = edges_e->Value(i);
2751     TopoDS_Shape theEdge = anEdgesIndices.FindKey(edgeID);
2752     TopExp_Explorer Ex(theEdge,TopAbs_VERTEX);
2753     while (Ex.More()) {
2754       gp_Pnt aPt = BRep_Tool::Pnt(TopoDS::Vertex(Ex.Current()));
2755       if (Abs(aPt.Z() - (theR1+theW1)) <= Precision::Confusion()) {
2756         nbEdgesInFillet ++;
2757         theEdges.push_back(edgeID);
2758       }
2759       Ex.Next();
2760     }
2761     if (theHexMesh && nbEdgesInFillet == 1)
2762       break;
2763   }
2764
2765   Handle(GEOM_Object) aFillet;
2766   try {
2767     aFillet = myLocalOperations->MakeFilletEdges(aShape, theRF, theEdges);
2768   }
2769   catch (Standard_Failure& aFail) {
2770     SetErrorCode(aFail.GetMessageString());
2771     return NULL;
2772   }
2773   if (aFillet.IsNull()) {
2774     //SetErrorCode("Fillet can not be computed on the given shape with the given parameters");
2775     SetErrorCode(myLocalOperations->GetErrorCode());
2776     return NULL;
2777   }
2778   aFillet->GetLastFunction()->SetDescription("");
2779
2780   TopoDS_Shape aFilletShape = aFillet->GetValue();
2781
2782 #ifdef FILLET_FIX_TOLERANCE
2783   // VSR: 30/12/2014: temporary workaround about Fillet problem
2784   if (theHexMesh) {
2785     GEOMUtils::FixShapeTolerance(aFilletShape, TopAbs_FACE);
2786   }
2787   else {
2788     GEOMUtils::FixShapeCurves(aFilletShape);
2789   }
2790 #endif
2791
2792   aFunction->SetValue(aFilletShape);
2793   // END of fillet
2794
2795 // VSR: debug issues 0021568 and 0021550 (15/05/2012) - BEGIN (1)
2796 // the following block, when enabled, leads to partitioning problems
2797 #if 0
2798 // VSR: debug issues 0021568 and 0021550 (15/05/2012) - END (1)
2799   // BEGIN: Limit tolerances (debug)
2800   Handle(GEOM_Object) aCorr1 = myHealingOperations->LimitTolerance(aShape, 1e-07);
2801   TopoDS_Shape aCorr1Shape = aCorr1->GetValue();
2802   aShape->GetLastFunction()->SetValue(aCorr1Shape);
2803   aCorr1->GetLastFunction()->SetDescription("");
2804   // END: Limit tolerances (debug)
2805 // VSR: debug issues 0021568 and 0021550 (15/05/2012) - BEGIN (2)
2806 #endif
2807 // VSR: debug issues 0021568 and 0021550 (15/05/2012) - END (2)
2808
2809   if (theHexMesh) {
2810     if (!MakePipeTShapePartition(aShape, theR1, theW1, theL1, theR2, theW2, theL2, 0, 0, theRF, false))
2811       return NULL;
2812     if (!MakePipeTShapeMirrorAndGlue(aShape, theR1, theW1, theL1, theR2, theW2, theL2))
2813       return NULL;
2814   }
2815
2816   // Add thickness reduction elements
2817   // at the three extremities: Left, Right and Incident
2818   try {
2819     OCC_CATCH_SIGNALS;
2820     if (isTRL || isTRR || isTRI) {
2821       TopoDS_Shape aResShape =
2822         MakePipeTShapeThicknessReduction(aShape->GetValue(), theR1, theW1, theL1, theR2, theW2, theL2,
2823                                          theRL, theWL, theLtransL, theLthinL,
2824                                          theRR, theWR, theLtransR, theLthinR,
2825                                          theRI, theWI, theLtransI, theLthinI,
2826                                          !theHexMesh);
2827       aFunction->SetValue(aResShape);
2828     }
2829   }
2830   catch (Standard_Failure& aFail) {
2831     SetErrorCode(aFail.GetMessageString());
2832     return NULL;
2833   }
2834
2835   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
2836   aSeq->Append(aShape);
2837
2838   try {
2839     if (theHexMesh) {
2840       // Get the groups
2841       if (!MakeGroups(aShape, TSHAPE_FILLET, theR1, theW1, theL1, theR2, theW2, theL2,
2842                       0., 0., theRF, aSeq, gp_Trsf()))
2843         return NULL;
2844     }
2845
2846     // Get internal group.
2847     if (!MakeInternalGroup(aShape, theR1, theL1, theR2, theL2, theRL, theLtransL,
2848                            theRR, theLtransR, theRI, theLtransI,
2849                            aSeq, gp_Trsf())) {
2850       return NULL;
2851     }
2852   }
2853   catch (Standard_Failure& aFail) {
2854     SetErrorCode(aFail.GetMessageString());
2855     return NULL;
2856   }
2857
2858   //Make a Python command
2859   TCollection_AsciiString anEntry, aListRes("[");
2860   // Iterate over the sequence aSeq
2861   Standard_Integer aNbGroups = aSeq->Length();
2862   Standard_Integer i = 1;
2863   for (; i <= aNbGroups; i++) {
2864     Handle(Standard_Transient) anItem = aSeq->Value(i);
2865     if (anItem.IsNull()) continue;
2866     Handle(GEOM_Object) aGroup = Handle(GEOM_Object)::DownCast(anItem);
2867     if (aGroup.IsNull()) continue;
2868     //Make a Python command
2869     TDF_Tool::Entry(aGroup->GetEntry(), anEntry);
2870     aListRes += anEntry + ", ";
2871   }
2872   aListRes.Trunc(aListRes.Length() - 2);
2873
2874   GEOM::TPythonDump pd (aFunction);
2875
2876   pd << aListRes.ToCString() << "] = geompy.MakePipeTShapeFillet("
2877      << theR1 << ", " << theW1 << ", " << theL1 << ", "
2878      << theR2 << ", " << theW2 << ", " << theL2 << ", "
2879      << theRF << ", " << theHexMesh;
2880
2881   // thickness reduction
2882   if (isTRL)
2883     pd << ", theRL=" << theRL << ", theWL=" << theWL
2884        << ", theLtransL=" << theLtransL << ", theLthinL=" << theLthinL;
2885   if (isTRR)
2886     pd << ", theRR=" << theRR << ", theWR=" << theWR
2887        << ", theLtransR=" << theLtransR << ", theLthinR=" << theLthinR;
2888   if (isTRI)
2889     pd << ", theRI=" << theRI << ", theWI=" << theWI
2890        << ", theLtransI=" << theLtransI << ", theLthinI=" << theLthinI;
2891
2892   pd << ")";
2893
2894   SetErrorCode(OK);
2895
2896   return aSeq;
2897 }
2898
2899 //=============================================================================
2900 /*!
2901  *  MakePipeTShapeFilletWithPosition
2902  *  \brief Create a T-shape object with specified caracteristics for the main and
2903  *  the incident pipes (radius, width, half-length). A fillet is created
2904  *  on the junction of the pipes.
2905  *  The extremities of the main pipe are located on junctions points P1 and P2.
2906  *  The extremity of the incident pipe is located on junction point P3.
2907  *  \param theR1 Internal radius of main pipe
2908  *  \param theW1 Width of main pipe
2909  *  \param theL1 Half-length of main pipe
2910  *  \param theR2 Internal radius of incident pipe (R2 < R1)
2911  *  \param theW2 Width of incident pipe (R2+W2 < R1+W1)
2912  *  \param theL2 Half-length of incident pipe
2913  *  \param theRF Radius of curvature of fillet
2914  *  \param theHexMesh Boolean indicating if shape is prepared for hex mesh
2915  *  \param theP1 1st junction point of main pipe
2916  *  \param theP2 2nd junction point of main pipe
2917  *  \param theP3 Junction point of incident pipe
2918  *  \return List of GEOM_Objects, containing the created shape and propagation groups.
2919  */
2920 //=============================================================================
2921 Handle(TColStd_HSequenceOfTransient)
2922 AdvancedEngine_IOperations::MakePipeTShapeFilletWithPosition
2923                              (double theR1, double theW1, double theL1,
2924                               double theR2, double theW2, double theL2,
2925                               double theRL, double theWL, double theLtransL, double theLthinL,
2926                               double theRR, double theWR, double theLtransR, double theLthinR,
2927                               double theRI, double theWI, double theLtransI, double theLthinI,
2928                               double theRF, bool theHexMesh,
2929                               Handle(GEOM_Object) theP1,
2930                               Handle(GEOM_Object) theP2,
2931                               Handle(GEOM_Object) theP3)
2932 {
2933   SetErrorCode(KO);
2934   //Add a new object
2935   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_TSHAPE);
2936   //Add a new shape function with parameters
2937   Handle(GEOM_Function) aFunction = aShape->AddFunction(AdvancedEngine_PipeTShapeDriver::GetID(), TSHAPE_FILLET);
2938   if (aFunction.IsNull()) return NULL;
2939
2940   //Check if the function is set correctly
2941   if (aFunction->GetDriverGUID() != AdvancedEngine_PipeTShapeDriver::GetID()) return NULL;
2942
2943   // Check new position
2944   if (!CheckCompatiblePosition(theL1, theL2, theP1, theP2, theP3, 0.01)) {
2945     return NULL;
2946   }
2947
2948   AdvancedEngine_IPipeTShape aData(aFunction);
2949
2950   aData.SetR1(theR1);
2951   aData.SetW1(theW1);
2952   aData.SetL1(theL1);
2953   aData.SetR2(theR2);
2954   aData.SetW2(theW2);
2955   aData.SetL2(theL2);
2956   aData.SetRF(theRF);
2957   aData.SetHexMesh(theHexMesh);
2958
2959   bool isTRL = (theRL + theWL + theLtransL + theLthinL) > Precision::Confusion();
2960   bool isTRR = (theRR + theWR + theLtransR + theLthinR) > Precision::Confusion();
2961   bool isTRI = (theRI + theWI + theLtransI + theLthinI) > Precision::Confusion();
2962
2963   //Compute the resulting value
2964   try {
2965     OCC_CATCH_SIGNALS;
2966     if (!GetSolver()->ComputeFunction(aFunction)) {
2967       SetErrorCode("TShape driver failed");
2968       return NULL;
2969     }
2970   }
2971   catch (Standard_Failure& aFail) {
2972     SetErrorCode(aFail.GetMessageString());
2973     return NULL;
2974   }
2975
2976   // BEGIN of fillet
2977   TopoDS_Shape aShapeShape = aShape->GetValue();
2978   TopTools_IndexedMapOfShape anEdgesIndices;
2979   TopExp::MapShapes(aShapeShape, anEdgesIndices);
2980   // Common edges on external cylinders
2981   Handle(GEOM_Object) box_e;
2982   if (theHexMesh) {
2983     box_e = my3DPrimOperations->MakeBoxDXDYDZ(theR2+theW2, theR2+theW2, theR1+theW1);
2984   }
2985   else {
2986     box_e = my3DPrimOperations->MakeBoxDXDYDZ(2*(theR2+theW2), 2*(theR2+theW2), theR1+theW1);
2987   }
2988   box_e->GetLastFunction()->SetDescription("");
2989   box_e = myTransformOperations->TranslateDXDYDZ(box_e, -(theR2+theW2), -(theR2+theW2), 0);
2990   box_e->GetLastFunction()->SetDescription("");
2991
2992   Handle(TColStd_HSequenceOfInteger) edges_e =
2993     myShapesOperations->GetShapesOnBoxIDs(box_e, aShape, TopAbs_EDGE, GEOMAlgo_ST_IN);
2994   box_e->GetLastFunction()->SetDescription("");
2995
2996   if (edges_e.IsNull() || edges_e->Length() == 0) {
2997     SetErrorCode("External edges not found");
2998     return NULL;
2999   }
3000   int nbEdgesInFillet = 0;
3001   std::list<int> theEdges;
3002   for (int i=1; i<=edges_e->Length();i++) {
3003     int edgeID = edges_e->Value(i);
3004     TopoDS_Shape theEdge = anEdgesIndices.FindKey(edgeID);
3005     TopExp_Explorer Ex(theEdge,TopAbs_VERTEX);
3006     while (Ex.More()) {
3007       gp_Pnt aPt = BRep_Tool::Pnt(TopoDS::Vertex(Ex.Current()));
3008       if (Abs(aPt.Z() - (theR1+theW1)) <= Precision::Confusion()) {
3009         nbEdgesInFillet ++;
3010         theEdges.push_back(edgeID);
3011       }
3012       Ex.Next();
3013     }
3014     if (theHexMesh && nbEdgesInFillet == 1)
3015       break;
3016   }
3017
3018   Handle(GEOM_Object) aFillet;
3019   try {
3020     aFillet = myLocalOperations->MakeFilletEdges(aShape, theRF, theEdges);
3021   }
3022   catch (Standard_Failure& aFail) {
3023     SetErrorCode(aFail.GetMessageString());
3024     return NULL;
3025   }
3026   if (aFillet.IsNull()) {
3027     SetErrorCode("Fillet can not be computed on the given shape with the given parameters");
3028     return NULL;
3029   }
3030   aFillet->GetLastFunction()->SetDescription("");
3031
3032   TopoDS_Shape aFilletShape = aFillet->GetValue();
3033
3034 #ifdef FILLET_FIX_TOLERANCE
3035   // VSR: 30/12/2014: temporary workaround about Fillet problem
3036   if (theHexMesh) {
3037     GEOMUtils::FixShapeTolerance(aFilletShape, TopAbs_FACE);
3038   }
3039   else {
3040     GEOMUtils::FixShapeCurves(aFilletShape);
3041   }
3042 #endif
3043
3044   aFunction->SetValue(aFilletShape);
3045   // END of fillet
3046
3047 // VSR: debug issues 0021568 and 0021550 (15/05/2012) - BEGIN (3)
3048 // the following block, when enabled, leads to partitioning problems
3049 #if 0
3050 // VSR: debug issues 0021568 and 0021550 (15/05/2012) - END (3)
3051   // BEGIN: Limit tolerances (debug)
3052   Handle(GEOM_Object) aCorr1 = myHealingOperations->LimitTolerance(aShape, 1e-07);
3053   TopoDS_Shape aCorr1Shape = aCorr1->GetValue();
3054   aShape->GetLastFunction()->SetValue(aCorr1Shape);
3055   aCorr1->GetLastFunction()->SetDescription("");
3056   // END: Limit tolerances (debug)
3057 // VSR: debug issues 0021568 and 0021550 (15/05/2012) - BEGIN (4)
3058 #endif
3059 // VSR: debug issues 0021568 and 0021550 (15/05/2012) - END (4)
3060
3061   if (theHexMesh) {
3062     if (!MakePipeTShapePartition(aShape, theR1, theW1, theL1, theR2, theW2, theL2, 0, 0, theRF, false))
3063       return NULL;
3064     if (!MakePipeTShapeMirrorAndGlue(aShape, theR1, theW1, theL1, theR2, theW2, theL2))
3065       return NULL;
3066   }
3067
3068   // Add thickness reduction elements
3069   // at the three extremities: Left, Right and Incident
3070   try {
3071     OCC_CATCH_SIGNALS;
3072     if (isTRL || isTRR || isTRI) {
3073       TopoDS_Shape aResShape =
3074         MakePipeTShapeThicknessReduction(aShape->GetValue(), theR1, theW1, theL1, theR2, theW2, theL2,
3075                                          theRL, theWL, theLtransL, theLthinL,
3076                                          theRR, theWR, theLtransR, theLthinR,
3077                                          theRI, theWI, theLtransI, theLthinI,
3078                                          !theHexMesh);
3079       aFunction->SetValue(aResShape);
3080     }
3081   }
3082   catch (Standard_Failure& aFail) {
3083     SetErrorCode(aFail.GetMessageString());
3084     return NULL;
3085   }
3086
3087   // Set Position
3088   gp_Trsf aTrsf = GetPositionTrsf(theL1, theL2, theP1, theP2, theP3);
3089   BRepBuilderAPI_Transform aTransformation (aShape->GetValue(), aTrsf, Standard_False);
3090   TopoDS_Shape aTrsf_Shape = aTransformation.Shape();
3091   aFunction->SetValue(aTrsf_Shape);
3092
3093   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
3094   aSeq->Append(aShape);
3095
3096   try {
3097     if (theHexMesh) {
3098       // Get the groups
3099       if (!MakeGroups(aShape, TSHAPE_FILLET, theR1, theW1, theL1, theR2, theW2, theL2,
3100                       0., 0., theRF, aSeq, aTrsf))
3101         return NULL;
3102     }
3103
3104     // Get internal group.
3105     if (!MakeInternalGroup(aShape, theR1, theL1, theR2, theL2, theRL, theLtransL,
3106                            theRR, theLtransR, theRI, theLtransI,
3107                            aSeq, aTrsf)) {
3108       return NULL;
3109     }
3110   }
3111   catch (Standard_Failure& aFail) {
3112     SetErrorCode(aFail.GetMessageString());
3113     return NULL;
3114   }
3115
3116   //Make a Python command
3117   TCollection_AsciiString anEntry, aListRes("[");
3118   // Iterate over the sequence aSeq
3119   Standard_Integer aNbGroups = aSeq->Length();
3120   Standard_Integer i = 1;
3121   for (; i <= aNbGroups; i++) {
3122     Handle(Standard_Transient) anItem = aSeq->Value(i);
3123     if (anItem.IsNull()) continue;
3124     Handle(GEOM_Object) aGroup = Handle(GEOM_Object)::DownCast(anItem);
3125     if (aGroup.IsNull()) continue;
3126     //Make a Python command
3127     TDF_Tool::Entry(aGroup->GetEntry(), anEntry);
3128     aListRes += anEntry + ", ";
3129   }
3130   aListRes.Trunc(aListRes.Length() - 2);
3131
3132   GEOM::TPythonDump pd (aFunction);
3133
3134   pd << aListRes.ToCString() << "] = geompy.MakePipeTShapeFillet("
3135      << theR1 << ", " << theW1 << ", " << theL1 << ", "
3136      << theR2  << ", " << theW2 << ", " << theL2 << ", "
3137      << theRF << ", " << theHexMesh << ", "
3138      << theP1 << ", " << theP2 << ", " << theP3;
3139
3140   // thickness reduction
3141   if (isTRL)
3142     pd << ", theRL=" << theRL << ", theWL=" << theWL
3143        << ", theLtransL=" << theLtransL << ", theLthinL=" << theLthinL;
3144   if (isTRR)
3145     pd << ", theRR=" << theRR << ", theWR=" << theWR
3146        << ", theLtransR=" << theLtransR << ", theLthinR=" << theLthinR;
3147   if (isTRI)
3148     pd << ", theRI=" << theRI << ", theWI=" << theWI
3149        << ", theLtransI=" << theLtransI << ", theLthinI=" << theLthinI;
3150
3151   pd << ")";
3152
3153   SetErrorCode(OK);
3154
3155   return aSeq;
3156 }
3157
3158 //=============================================================================
3159 /*!
3160  *  This function allows to create a disk already divided into blocks. It can be
3161  *  used to create divided pipes for later meshing in hexaedra.
3162  *  \param theR Radius of the disk
3163  *  \param theRatio Relative size of the central square diagonal against the disk diameter
3164  *  \param theOrientation Plane on which the disk will be built
3165  *  \param thePattern The division pattern of the disk (hexagon or square in the center)
3166  *  \return New GEOM_Object, containing the created shape.
3167  */
3168 //=============================================================================
3169 Handle(GEOM_Object) AdvancedEngine_IOperations::MakeDividedDisk (double theR, double theRatio, 
3170                                                                  int theOrientation, int thePattern)
3171 {
3172   SetErrorCode(KO);
3173   
3174   if (theOrientation != 1 &&
3175       theOrientation != 2 &&
3176       theOrientation != 3)
3177   {
3178     SetErrorCode("theOrientation must be 1(=OXY), 2(=OYZ) or 3(=OZX)");
3179     return NULL;
3180   }
3181   //Add a new object
3182   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_DIVIDEDDISK);
3183
3184   //Add a new shape function with parameters
3185   Handle(GEOM_Function) aFunction = aShape->AddFunction(AdvancedEngine_DividedDiskDriver::GetID(), DIVIDEDDISK_R_RATIO);
3186   if (aFunction.IsNull()) return NULL;
3187
3188   //Check if the function is set correctly
3189   if (aFunction->GetDriverGUID() != AdvancedEngine_DividedDiskDriver::GetID()) return NULL;
3190
3191   AdvancedEngine_IDividedDisk aData (aFunction);
3192
3193   aData.SetR(theR);
3194   aData.SetRatio(theRatio);
3195   aData.SetOrientation(theOrientation);
3196   aData.SetType(thePattern);
3197
3198   //Compute the resulting value
3199   try {
3200     OCC_CATCH_SIGNALS;
3201     if (!GetSolver()->ComputeFunction(aFunction)) {
3202       SetErrorCode("DividedDisk driver failed");
3203       return NULL;
3204     }
3205   }
3206   catch (Standard_Failure& aFail) {
3207     SetErrorCode(aFail.GetMessageString());
3208     return NULL;
3209   }
3210   
3211   std::string aPatternStr;
3212   
3213   switch(thePattern)
3214   {
3215     case 0:
3216       aPatternStr = "GEOM.SQUARE";
3217       break;
3218     case 1:
3219       aPatternStr = "GEOM.HEXAGON";
3220       break;
3221   }
3222   
3223   //Make a Python command
3224   GEOM::TPythonDump(aFunction) << aShape << " = geompy.MakeDividedDisk(" << theR << ", " << theOrientation << ", " << aPatternStr.c_str() << ")";
3225
3226   SetErrorCode(OK);
3227
3228   return aShape;
3229 }
3230
3231 //=============================================================================
3232 /*!
3233  *  This function allows to create a disk already divided into blocks. It can be
3234  *  used to create divided pipes for later meshing in hexaedra.
3235  *  \param theR Radius of the disk
3236  *  \param theRatio Relative size of the central square diagonal against the disk diameter
3237  *  \return New GEOM_Object, containing the created shape.
3238  */
3239 //=============================================================================
3240 Handle(GEOM_Object) AdvancedEngine_IOperations::MakeDividedDiskPntVecR (Handle(GEOM_Object) thePnt, 
3241                                                                         Handle(GEOM_Object) theVec, 
3242                                                                         double theR, 
3243                                                                         double theRatio,
3244                                                                         int    thePattern)
3245 {
3246   SetErrorCode(KO);
3247
3248   //Add a new object
3249   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_DIVIDEDDISK);
3250
3251   //Add a new shape function with parameters
3252   Handle(GEOM_Function) aFunction = aShape->AddFunction(AdvancedEngine_DividedDiskDriver::GetID(), DIVIDEDDISK_R_VECTOR_PNT);
3253   if (aFunction.IsNull()) return NULL;
3254
3255   //Check if the function is set correctly
3256   if (aFunction->GetDriverGUID() != AdvancedEngine_DividedDiskDriver::GetID()) return NULL;
3257
3258   AdvancedEngine_IDividedDisk aData (aFunction);
3259   
3260   Handle(GEOM_Function) aRefPnt = thePnt->GetLastFunction();
3261   Handle(GEOM_Function) aRefVec = theVec->GetLastFunction();
3262
3263   if (aRefPnt.IsNull() || aRefVec.IsNull()) return NULL;
3264
3265   aData.SetCenter(aRefPnt);
3266   aData.SetVector(aRefVec);
3267
3268   aData.SetR(theR);
3269   aData.SetRatio(theRatio);
3270   aData.SetType(thePattern);
3271
3272   //Compute the resulting value
3273   try {
3274     OCC_CATCH_SIGNALS;
3275     if (!GetSolver()->ComputeFunction(aFunction)) {
3276       SetErrorCode("DividedDisk driver failed");
3277       return NULL;
3278     }
3279   }
3280   catch (Standard_Failure& aFail) {
3281     SetErrorCode(aFail.GetMessageString());
3282     return NULL;
3283   }
3284   
3285   std::string aPatternStr;
3286   
3287   switch(thePattern)
3288   {
3289     case 0:
3290       aPatternStr = "GEOM.SQUARE";
3291       break;
3292     case 1:
3293       aPatternStr = "GEOM.HEXAGON";
3294       break;
3295   }
3296   
3297
3298   //Make a Python command
3299   GEOM::TPythonDump(aFunction) << aShape << " = geompy.MakeDividedDiskPntVecR(" << thePnt << ", " << theVec << ", " << theR << ", " << aPatternStr.c_str() << ")";
3300
3301   SetErrorCode(OK);
3302
3303   return aShape;
3304 }
3305
3306 //=============================================================================
3307 /*!
3308  *  Builds a cylinder prepared for hexa meshes
3309  *  \param theR Radius of the cylinder
3310  *  \param theH Height of the cylinder
3311  *  \return New GEOM_Object, containing the created shape.
3312  */
3313 //=============================================================================
3314 Handle(GEOM_Object) AdvancedEngine_IOperations::MakeDividedCylinder (double theR, 
3315                                                                      double theH,
3316                                                                      int    thePattern)
3317 {
3318   SetErrorCode(KO);
3319   
3320   //Add a new object
3321   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_DIVIDEDCYLINDER);
3322
3323   Handle(GEOM_Object) aBaseShape = MakeDividedDisk(theR, 67.0, 1, thePattern);
3324   aBaseShape->GetLastFunction()->SetDescription("");   // Erase dump of MakeDividedDisk
3325   
3326   aShape = my3DPrimOperations->MakePrismDXDYDZ(aBaseShape,0.0,0.0,theH, -1.0);
3327         
3328   Handle(GEOM_Function) aFunction =  aShape->GetLastFunction();
3329   aFunction->SetDescription("");   // Erase dump of MakePrismDXDYDZ
3330   aShape->SetType(GEOM_DIVIDEDCYLINDER);
3331   
3332   std::string aPatternStr;
3333   
3334   switch(thePattern)
3335   {
3336     case 0:
3337       aPatternStr = "GEOM.SQUARE";
3338       break;
3339     case 1:
3340       aPatternStr = "GEOM.HEXAGON";
3341       break;
3342   }
3343   
3344   //Make a Python command
3345   GEOM::TPythonDump(aFunction) << aShape << " = geompy.MakeDividedCylinder(" << theR << ", " << theH << ", " << aPatternStr.c_str() << ")";
3346
3347   SetErrorCode(OK);
3348
3349   return aShape;
3350 }
3351 //=============================================================================
3352 /*!
3353  *  Create a smoothing surface from a set of points
3354  *  \param thelPoints list of points or compounds of points
3355  *  \param theNbMax maximum number of Bezier pieces in the resulting surface.
3356  *  \param theDegMax maximum degree of the resulting BSpline surface
3357  *  \param theDMax specifies maximum value of the GeomPlate_PlateG0Criterion criterion.
3358  *  \return New GEOM_Object, containing the created shape.
3359  */
3360 //=============================================================================
3361 Handle(GEOM_Object) AdvancedEngine_IOperations::MakeSmoothingSurface (std::list<Handle(GEOM_Object)> thelPoints, 
3362                                                                       int                            theNbMax,
3363                                                                       int                            theDegMax,
3364                                                                       double                         theDMax)
3365 {
3366   SetErrorCode(KO);
3367
3368   //Add a new object
3369   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_SMOOTHINGSURFACE);
3370
3371   //Add a new shape function with parameters
3372   Handle(GEOM_Function) aFunction = aShape->AddFunction(AdvancedEngine_SmoothingSurfaceDriver::GetID(), SMOOTHINGSURFACE_LPOINTS);
3373   if (aFunction.IsNull()) return NULL;
3374
3375   //Check if the function is set correctly
3376   if (aFunction->GetDriverGUID() != AdvancedEngine_SmoothingSurfaceDriver::GetID()) return NULL;
3377
3378   AdvancedEngine_ISmoothingSurface aData (aFunction);
3379
3380   int aLen = thelPoints.size();
3381   aData.SetLength(aLen);
3382   int ind = 1;
3383   std::list<Handle(GEOM_Object)>::iterator it = thelPoints.begin();
3384   for (; it != thelPoints.end(); it++, ind++) {
3385     Handle(GEOM_Function) aRefObj = (*it)->GetLastFunction();
3386     if (aRefObj.IsNull()) {
3387       SetErrorCode("NULL point or compound for bSplineFaceShape");
3388       return NULL;
3389     }
3390     aData.SetPntOrComp(ind, aRefObj);
3391   }
3392
3393   aData.SetNbMax(theNbMax);
3394   aData.SetDegMax(theDegMax);
3395   aData.SetDMax(theDMax);
3396
3397   //Compute the resulting value
3398   try {
3399     OCC_CATCH_SIGNALS;
3400     if (!GetSolver()->ComputeFunction(aFunction)) {
3401       SetErrorCode("SmoothingSurface driver failed");
3402       return NULL;
3403     }
3404   }
3405   catch (Standard_Failure& aFail) {
3406     SetErrorCode(aFail.GetMessageString());
3407     return NULL;
3408   }
3409
3410   //Make a Python command
3411   GEOM::TPythonDump pd (aFunction);
3412   pd << aShape << " = geompy.MakeSmoothingSurface([";
3413   it = thelPoints.begin();
3414   pd << (*it++);
3415   while (it != thelPoints.end()) {
3416     pd << ", " << (*it++);
3417   }
3418   pd << "], "
3419      << theNbMax << ", "
3420      << theDegMax << ", "
3421      << theDMax <<")";
3422
3423   SetErrorCode(OK);
3424
3425   return aShape;
3426 }