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