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