]> SALOME platform Git repositories - modules/geom.git/blob - src/GEOMImpl/GEOMImpl_IAdvancedOperations.cxx
Salome HOME
Merge from V6_3_BR 15/07/2011
[modules/geom.git] / src / GEOMImpl / GEOMImpl_IAdvancedOperations.cxx
1 // Copyright (C) 2007-2011  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.
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   : GEOMImpl_IAdvancedOperations.cxx
20 //  Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
21
22 #include <Standard_Stream.hxx>
23 #include "GEOMImpl_Types.hxx"
24 #include "GEOMImpl_IAdvancedOperations.hxx"
25 #include "GEOMImpl_IBasicOperations.hxx"
26 #include "GEOMImpl_IBooleanOperations.hxx"
27 #include "GEOMImpl_IShapesOperations.hxx"
28 #include "GEOMImpl_ITransformOperations.hxx"
29 #include "GEOMImpl_IBlocksOperations.hxx"
30 #include "GEOMImpl_I3DPrimOperations.hxx"
31 #include "GEOMImpl_ILocalOperations.hxx"
32 #include "GEOMImpl_IHealingOperations.hxx"
33
34 #include "GEOMImpl_Gen.hxx"
35
36 #include <utilities.h>
37 #include <OpUtil.hxx>
38 #include <Utils_ExceptHandlers.hxx>
39
40 #include "GEOM_Function.hxx"
41 #include "GEOM_PythonDump.hxx"
42
43 #include "GEOMImpl_PipeTShapeDriver.hxx"
44 #include "GEOMImpl_IPipeTShape.hxx"
45 /*@@ insert new functions before this line @@ do not remove this line @@ do not remove this line @@*/
46
47 #include <TopExp.hxx>
48 #include <TopExp_Explorer.hxx>
49 #include <TopoDS.hxx>
50 #include <TopoDS_Vertex.hxx>
51 #include <TopTools_IndexedMapOfShape.hxx>
52
53 #include <gp_Pnt.hxx>
54 #include <gp_Vec.hxx>
55 #include <gp_Ax3.hxx>
56 #include <BRepBuilderAPI_Transform.hxx>
57 #include <BRep_Tool.hxx>
58 #include <cmath>
59
60 #include <TFunction_DriverTable.hxx>
61 #include <TFunction_Driver.hxx>
62 #include <TFunction_Logbook.hxx>
63 #include <TDF_Tool.hxx>
64 #include <Standard_Failure.hxx>
65 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
66
67 #define HALF_LENGTH_MAIN_PIPE     "Main pipe half length" //"Tuyau principal - demi longueur"
68 #define HALF_LENGTH_INCIDENT_PIPE "Incident pipe half length" //"Tuyau incident - demi longueur"
69 #define CIRCULAR_QUARTER_PIPE     "Circular quarter of pipe" //"Circulaire - quart de tuyau"
70 #define THICKNESS                 "Thickness" //"Epaisseur"
71 #define FLANGE                    "Flange" // "Collerette"
72 #define CHAMFER_OR_FILLET         "Chamfer or fillet" //"Chanfrein ou Raccord"
73 #define JUNCTION_FACE_1           "Junction 1" //"Face de jonction 1"
74 #define JUNCTION_FACE_2           "Junction 2" //"Face de jonction 2"
75 #define JUNCTION_FACE_3           "Junction 3" //"Face de jonction 3"
76
77 //=============================================================================
78 /*!
79  *  Constructor
80  */
81 //=============================================================================
82 GEOMImpl_IAdvancedOperations::GEOMImpl_IAdvancedOperations(GEOM_Engine* theEngine, int theDocID) :
83   GEOM_IOperations(theEngine, theDocID)
84 {
85   MESSAGE("GEOMImpl_IAdvancedOperations::GEOMImpl_IAdvancedOperations");
86   myBasicOperations     = new GEOMImpl_IBasicOperations(GetEngine(), GetDocID());
87   myBooleanOperations   = new GEOMImpl_IBooleanOperations(GetEngine(), GetDocID());
88   myShapesOperations    = new GEOMImpl_IShapesOperations(GetEngine(), GetDocID());
89   myTransformOperations = new GEOMImpl_ITransformOperations(GetEngine(), GetDocID());
90   myBlocksOperations    = new GEOMImpl_IBlocksOperations(GetEngine(), GetDocID());
91   my3DPrimOperations    = new GEOMImpl_I3DPrimOperations(GetEngine(), GetDocID());
92   myLocalOperations     = new GEOMImpl_ILocalOperations(GetEngine(), GetDocID());
93   myHealingOperations   = new GEOMImpl_IHealingOperations(GetEngine(), GetDocID());
94 }
95
96 //=============================================================================
97 /*!
98  *  Destructor
99  */
100 //=============================================================================
101 GEOMImpl_IAdvancedOperations::~GEOMImpl_IAdvancedOperations()
102 {
103   MESSAGE("GEOMImpl_IAdvancedOperations::~GEOMImpl_IAdvancedOperations");
104   delete myBasicOperations;
105   delete myBooleanOperations;
106   delete myShapesOperations;
107   delete myTransformOperations;
108   delete myBlocksOperations;
109   delete my3DPrimOperations;
110   delete myLocalOperations;
111   delete myHealingOperations;
112 }
113
114 //=============================================================================
115 /*!
116  *  SetPosition
117  */
118 //=============================================================================
119 gp_Trsf GEOMImpl_IAdvancedOperations::GetPositionTrsf(double theL1, double theL2,
120                                                       Handle(GEOM_Object) theP1,
121                                                       Handle(GEOM_Object) theP2,
122                                                       Handle(GEOM_Object) theP3)
123 {
124   // Old Local Coordinates System oldLCS
125   gp_Pnt P0(0, 0, 0);
126   gp_Pnt P1(-theL1, 0, 0);
127   gp_Pnt P2(theL1, 0, 0);
128   gp_Pnt P3(0, 0, theL2);
129
130   gp_Dir oldX(gp_Vec(P1, P2));
131   gp_Dir oldZ(gp_Vec(P0, P3));
132   gp_Ax3 oldLCS(P0, oldZ, oldX);
133
134   // New Local Coordinates System newLCS
135   double LocX, LocY, LocZ;
136   gp_Pnt newP1 = BRep_Tool::Pnt(TopoDS::Vertex(theP1->GetValue()));
137   gp_Pnt newP2 = BRep_Tool::Pnt(TopoDS::Vertex(theP2->GetValue()));
138   gp_Pnt newP3 = BRep_Tool::Pnt(TopoDS::Vertex(theP3->GetValue()));
139   LocX = (newP1.X() + newP2.X()) / 2.;
140   LocY = (newP1.Y() + newP2.Y()) / 2.;
141   LocZ = (newP1.Z() + newP2.Z()) / 2.;
142   gp_Pnt newO(LocX, LocY, LocZ);
143
144   gp_Dir newX(gp_Vec(newP1, newP2)); // P1P2 Vector
145   gp_Dir newZ(gp_Vec(newO, newP3)); // OP3 Vector
146   gp_Ax3 newLCS = gp_Ax3(newO, newZ, newX);
147
148   gp_Trsf aTrsf;
149   aTrsf.SetDisplacement(oldLCS, newLCS);
150
151   return aTrsf;
152 }
153
154 //=============================================================================
155 /*!
156  *  CheckCompatiblePosition
157  *
158  */
159 //=============================================================================
160 bool GEOMImpl_IAdvancedOperations::CheckCompatiblePosition(double& theL1, double& theL2,
161                                                            Handle(GEOM_Object) theP1,
162                                                            Handle(GEOM_Object) theP2,
163                                                            Handle(GEOM_Object) theP3,
164                                                            double theTolerance)
165 {
166   SetErrorCode(KO);
167   gp_Pnt P1 = BRep_Tool::Pnt(TopoDS::Vertex(theP1->GetValue()));
168   gp_Pnt P2 = BRep_Tool::Pnt(TopoDS::Vertex(theP2->GetValue()));
169   gp_Pnt P3 = BRep_Tool::Pnt(TopoDS::Vertex(theP3->GetValue()));
170
171   double d12 = P1.Distance(P2);
172   double d13 = P1.Distance(P3);
173   double d23 = P2.Distance(P3);
174   //    double d2 = newO.Distance(P3);
175
176   if (Abs(d12) <= Precision::Confusion()) {
177     SetErrorCode("Junctions points P1 and P2 are identical");
178     return false;
179   }
180   if (Abs(d13) <= Precision::Confusion()) {
181     SetErrorCode("Junctions points P1 and P3 are identical");
182     return false;
183   }
184   if (Abs(d23) <= Precision::Confusion()) {
185     SetErrorCode("Junctions points P2 and P3 are identical");
186     return false;
187   }
188
189
190   double newL1 = 0.5 * d12;
191   double newL2 = sqrt(pow(d13,2)-pow(newL1,2));
192   //
193   // theL1*(1-theTolerance) <= newL1 <= theL1*(1+theTolerance)
194   //
195   if (fabs(newL1 - theL1) > Precision::Approximation()) {
196     if ( (newL1 * (1 - theTolerance) -theL1 <= Precision::Approximation()) &&
197          (newL1 * (1 + theTolerance) -theL1 >= Precision::Approximation()) ) {
198       //            std::cerr << "theL1 = newL1" << std::endl;
199       theL1 = newL1;
200     } else {
201       theL1 = -1;
202       SetErrorCode("Dimension for main pipe (L1) is incompatible with new position");
203       return false;
204     }
205   }
206
207   //
208   // theL2*(1-theTolerance) <= newL2  <= theL2*(1+theTolerance)
209   //
210   if (fabs(newL2 - theL2) > Precision::Approximation()) {
211     if ( (newL2 * (1 - theTolerance) -theL2 <= Precision::Approximation()) &&
212          (newL2 * (1 + theTolerance) -theL2 >= Precision::Approximation()) ) {
213       theL2 = newL2;
214     } else {
215       theL2 = -1;
216       SetErrorCode("Dimension for incident pipe (L2) is incompatible with new position");
217       return false;
218     }
219   }
220
221   SetErrorCode(OK);
222   return true;
223
224 }
225
226 //=============================================================================
227 /*!
228  *  Generate the propagation groups of a Pipe T-Shape used for hexa mesh
229  */
230 //=============================================================================
231 bool GEOMImpl_IAdvancedOperations::MakeGroups(Handle(GEOM_Object) theShape, int shapeType,
232                                               double theR1, double theW1, double theL1,
233                                               double theR2, double theW2, double theL2,
234                                               Handle(TColStd_HSequenceOfTransient) theSeq,
235                                               gp_Trsf aTrsf)
236 {
237   SetErrorCode(KO);
238
239   if (theShape.IsNull()) return false;
240
241   TopoDS_Shape aShape = theShape->GetValue();
242   if (aShape.IsNull()) {
243     SetErrorCode("Shape is not defined");
244     return false;
245   }
246
247   gp_Trsf aTrsfInv = aTrsf.Inverted();
248
249   int expectedGroups = 0;
250   if (shapeType == TSHAPE_BASIC)
251     if (Abs(theR2+theW2-theR1-theW1) <= Precision::Approximation())
252       expectedGroups = 10;
253     else
254       expectedGroups = 11;
255   else if (shapeType == TSHAPE_CHAMFER || shapeType == TSHAPE_FILLET)
256     expectedGroups = 12;
257
258   double aR1Ext = theR1 + theW1;
259   double aR2Ext = theR2 + theW2;
260
261   /////////////////////////
262   //// Groups of Faces ////
263   /////////////////////////
264
265   //
266   // Comment the following lines when GetInPlace bug is solved
267   // == BEGIN
268   // Workaround of GetInPlace bug
269   // Create a bounding box that fits the shape
270   Handle(GEOM_Object) aBox = my3DPrimOperations->MakeBoxDXDYDZ(2*theL1, 2*aR1Ext, aR1Ext+theL2);
271   aBox->GetLastFunction()->SetDescription("");
272   myTransformOperations->TranslateDXDYDZ(aBox, -theL1, -aR1Ext, -aR1Ext);
273   aBox->GetLastFunction()->SetDescription("");
274   // Apply transformation to box
275   BRepBuilderAPI_Transform aTransformationBox(aBox->GetValue(), aTrsf, Standard_False);
276   TopoDS_Shape aBoxShapeTrsf = aTransformationBox.Shape();
277   aBox->GetLastFunction()->SetValue(aBoxShapeTrsf);
278
279   // Get the shell of the box
280   Handle(GEOM_Object) aShell = Handle(GEOM_Object)::DownCast
281     (myShapesOperations->MakeExplode(aBox, TopAbs_SHELL, true)->Value(1));
282   aBox->GetLastFunction()->SetDescription("");
283   aShell->GetLastFunction()->SetDescription("");
284   // Get the common shapes between shell and shape
285   Handle(GEOM_Object) aCommonCompound = myBooleanOperations->MakeBoolean (theShape, aShell, 1); // MakeCommon
286   if (aCommonCompound.IsNull()) {
287     SetErrorCode(myBooleanOperations->GetErrorCode());
288     return false;
289   }
290   aCommonCompound->GetLastFunction()->SetDescription("");
291   // Explode the faces of common shapes => 3 faces
292   Handle(TColStd_HSequenceOfTransient) aCommonFaces =
293     myShapesOperations->MakeExplode(aCommonCompound, TopAbs_FACE, true);
294   aCommonCompound->GetLastFunction()->SetDescription("");
295   std::list<Handle(GEOM_Object)> aCompoundOfFacesList;
296
297   for (int i=0 ; i<= aCommonFaces->Length()-4 ; i+=4) {
298     std::list<Handle(GEOM_Object)> aFacesList;
299     for (int j = 1 ; j <= 4 ; j++) {
300       Handle(GEOM_Object) aFace = Handle(GEOM_Object)::DownCast(aCommonFaces->Value(i+j)); // Junction faces
301       if (!aFace.IsNull()) {
302         aFace->GetLastFunction()->SetDescription("");
303         aFacesList.push_back(aFace);
304       }
305     }
306     Handle(GEOM_Object) aCompoundOfFaces = myShapesOperations->MakeCompound(aFacesList);
307     if (!aCompoundOfFaces.IsNull()) {
308       aCompoundOfFaces->GetLastFunction()->SetDescription("");
309       aCompoundOfFacesList.push_back(aCompoundOfFaces);
310     }
311   }
312
313   if (aCompoundOfFacesList.size() == 3) {
314     Handle(GEOM_Object) aPln1 = aCompoundOfFacesList.front();
315     aCompoundOfFacesList.pop_front();
316     Handle(GEOM_Object) aPln2 = aCompoundOfFacesList.front();
317     aCompoundOfFacesList.pop_front();
318     Handle(GEOM_Object) aPln3 = aCompoundOfFacesList.front();
319     aCompoundOfFacesList.pop_front();
320     // == END
321     //
322
323
324     //     Uncomment the following lines when GetInPlace bug is solved
325     //     == BEGIN
326 //     Handle(GEOM_Object) aP1 = myBasicOperations->MakePointXYZ(-theL1, 0, 0);
327 //     Handle(GEOM_Object) aP2 = myBasicOperations->MakePointXYZ(-0, 0, theL2);
328 //     Handle(GEOM_Object) aP3 = myBasicOperations->MakePointXYZ(theL1, 0, 0);
329 //     aP1->GetLastFunction()->SetDescription("");
330 //     aP2->GetLastFunction()->SetDescription("");
331 //     aP3->GetLastFunction()->SetDescription("");
332 //     Handle(GEOM_Object) aV1 = myBasicOperations->MakeVectorDXDYDZ(-1, 0, 0);
333 //     Handle(GEOM_Object) aV2 = myBasicOperations->MakeVectorDXDYDZ(0, 0, 1);
334 //     Handle(GEOM_Object) aV3 = myBasicOperations->MakeVectorDXDYDZ(1, 0, 0);
335 //     aV1->GetLastFunction()->SetDescription("");
336 //     aV2->GetLastFunction()->SetDescription("");
337 //     aV3->GetLastFunction()->SetDescription("");
338 //     Handle(GEOM_Object) aPln1 = myBasicOperations->MakePlanePntVec(aP1, aV1, 2*(aR1Ext+theL2));
339 //     Handle(GEOM_Object) aPln2 = myBasicOperations->MakePlanePntVec(aP2, aV2, 2*(aR2Ext));
340 //     Handle(GEOM_Object) aPln3 = myBasicOperations->MakePlanePntVec(aP3, aV3, 2*(aR1Ext+theL2));
341 //     aPln1->GetLastFunction()->SetDescription("");
342 //     aPln2->GetLastFunction()->SetDescription("");
343 //     aPln3->GetLastFunction()->SetDescription("");
344 //
345 //     BRepBuilderAPI_Transform aTransformation1(aPln1->GetValue(), aTrsf, Standard_False);
346 //     TopoDS_Shape aTrsf_Shape1 = aTransformation1.Shape();
347 //     aPln1->GetLastFunction()->SetValue(aTrsf_Shape1);
348 //     BRepBuilderAPI_Transform aTransformation2(aPln2->GetValue(), aTrsf, Standard_False);
349 //     TopoDS_Shape aTrsf_Shape2 = aTransformation2.Shape();
350 //     aPln2->GetLastFunction()->SetValue(aTrsf_Shape2);
351 //     BRepBuilderAPI_Transform aTransformation3(aPln3->GetValue(), aTrsf, Standard_False);
352 //     TopoDS_Shape aTrsf_Shape3 = aTransformation3.Shape();
353 //     aPln3->GetLastFunction()->SetValue(aTrsf_Shape3);
354     //     == END
355     //
356
357     Handle(GEOM_Object) junctionFaces1 = myShapesOperations->GetInPlace(theShape, aPln1);
358     if (junctionFaces1.IsNull())
359       junctionFaces1 = myShapesOperations->GetShapesOnShapeAsCompound
360         (aPln1, theShape, TopAbs_FACE,  GEOMAlgo_ST_ONIN);
361     if (!junctionFaces1.IsNull()) {
362       junctionFaces1->GetLastFunction()->SetDescription("");
363       junctionFaces1->SetName("JUNCTION_FACE_1");
364       theSeq->Append(junctionFaces1);
365     }
366     else {
367       SetErrorCode("Junction face 1 not found");
368       //        theSeq->Append(aPln1);
369       //        return false;
370     }
371     Handle(GEOM_Object) junctionFaces2 = myShapesOperations->GetInPlace(theShape, aPln2);
372     if (junctionFaces2.IsNull())
373       junctionFaces2 = myShapesOperations->GetShapesOnShapeAsCompound
374         (aPln2, theShape, TopAbs_FACE,  GEOMAlgo_ST_ONIN);
375     if (!junctionFaces2.IsNull()) {
376       junctionFaces2->GetLastFunction()->SetDescription("");
377       junctionFaces2->SetName("JUNCTION_FACE_2");
378       theSeq->Append(junctionFaces2);
379     }
380     else {
381       SetErrorCode("Junction face 2 not found");
382       //        theSeq->Append(aPln2);
383       //        return false;
384     }
385     Handle(GEOM_Object) junctionFaces3 = myShapesOperations->GetInPlace(theShape, aPln3);
386     if (junctionFaces3.IsNull())
387       junctionFaces3 = myShapesOperations->GetShapesOnShapeAsCompound
388         (aPln3, theShape, TopAbs_FACE,  GEOMAlgo_ST_ONIN);
389     if (!junctionFaces3.IsNull()) {
390       junctionFaces3->GetLastFunction()->SetDescription("");
391       junctionFaces3->SetName("JUNCTION_FACE_3");
392       theSeq->Append(junctionFaces3);
393     }
394     else {
395       SetErrorCode("Junction face 3 not found");
396       //        theSeq->Append(aPln3);
397       //        return false;
398     }
399   // Comment the following lines when GetInPlace bug is solved
400   // == BEGIN
401   }
402   //     == END
403   /////////////////////////
404   //// Groups of Edges ////
405   /////////////////////////
406   // Result of propagate
407
408   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
409
410   TCollection_AsciiString theDesc = aFunction->GetDescription();
411   Handle(TColStd_HSequenceOfTransient) aSeqPropagate = myBlocksOperations->Propagate(theShape);
412   if (aSeqPropagate.IsNull() || aSeqPropagate->Length() == 0) {
413     SetErrorCode("Propagation groups not found");
414     return false;
415   }
416   Standard_Integer nbEdges, aNbGroups = aSeqPropagate->Length();
417   // Recover previous description to get rid of Propagate dump
418   aFunction->SetDescription(theDesc);
419
420   bool addGroup;
421   bool circularFoundAndAdded = false;
422   bool circularFound10 = false;
423   bool incidentPipeFound = false;
424   bool mainPipeFound = false;
425   bool mainPipeFoundAndAdded = false;
426   bool radialFound =false;
427   bool flangeFound = false;
428   bool flangeFoundAndAdded = false;
429   bool chamferOrFilletFound = false;
430
431   for (int i=1 ; i<= aNbGroups; i++) {
432     addGroup = false;
433
434     Handle(GEOM_Object) aGroup = Handle(GEOM_Object)::DownCast(aSeqPropagate->Value(i));
435     if(aGroup.IsNull())
436       continue;
437
438     TopoDS_Shape aGroupShape = aGroup->GetValue();
439     BRepBuilderAPI_Transform aTransformationShapeInv(aGroupShape, aTrsfInv, Standard_False);
440     TopoDS_Shape aGroupShapeTrsfInv = aTransformationShapeInv.Shape();
441
442     TopTools_IndexedMapOfShape anEdgesMap;
443     TopExp::MapShapes(aGroupShapeTrsfInv,TopAbs_EDGE, anEdgesMap);
444     nbEdges = anEdgesMap.Extent();
445
446     if (shapeType == TSHAPE_BASIC) {
447       if ((nbEdges == 21) || /*R1Ext = R2Ext*/(nbEdges == 17)){
448         addGroup = true;
449         aGroup->SetName("THICKNESS");
450       }
451       else if (nbEdges == 6) {
452         if (!circularFoundAndAdded) {
453           circularFoundAndAdded = true;
454           addGroup = true;
455           aGroup->SetName("CIRCULAR_QUARTER_PIPE");
456         }
457       }
458       else if (nbEdges == 8) {
459         incidentPipeFound = true;
460         mainPipeFound = false;
461         radialFound =false;
462         flangeFound = false;
463
464         TopExp_Explorer Ex(aGroupShapeTrsfInv,TopAbs_VERTEX);
465         while (Ex.More()) {
466           gp_Pnt aP =  BRep_Tool::Pnt(TopoDS::Vertex(Ex.Current()));
467           double x=aP.X(), y=aP.Y(), z=aP.Z();
468
469
470           if ((Abs(x) > aR2Ext + Precision::Confusion()) ||
471               (Abs(y) > aR2Ext + Precision::Confusion())) {
472             incidentPipeFound = false;
473           }
474
475           if ( z < -Precision::Confusion()) {
476             // length of main pipe
477             mainPipeFound = true;
478             if (!mainPipeFoundAndAdded) {
479               mainPipeFoundAndAdded = true;
480               addGroup = true;
481               aGroup->SetName("HALF_LENGTH_MAIN_PIPE");
482             }
483           }
484
485           else if (Abs(x) > (theL1-Precision::Confusion())) {
486             // discretisation circulaire
487             radialFound = true;
488             if (!circularFoundAndAdded) {
489               circularFoundAndAdded = true;
490               addGroup = true;
491               aGroup->SetName("CIRCULAR_QUARTER_PIPE");
492             }
493           }
494           Ex.Next();
495         }
496         if (incidentPipeFound) {
497           addGroup = true;
498           aGroup->SetName("HALF_LENGTH_INCIDENT_PIPE");
499         }
500         if (!addGroup && (!incidentPipeFound &&
501                           !radialFound &&
502                           !mainPipeFound &&
503                           !flangeFound)) {
504           // Flange (collerette)
505           flangeFound = true;
506           addGroup = true;
507           aGroup->SetName("FLANGE");
508         }
509       }
510       else
511         continue;
512     }
513     else if (shapeType == TSHAPE_CHAMFER || shapeType == TSHAPE_FILLET) {
514       if (nbEdges == 25) {
515         addGroup = true;
516         aGroup->SetName("THICKNESS");
517       }
518       else if ((nbEdges == 10) || (nbEdges == 6)) {
519         if (!circularFoundAndAdded) {
520           addGroup = true;
521           circularFoundAndAdded = true;
522           aGroup->SetName("CIRCULAR_QUARTER_PIPE");
523           if (nbEdges == 10) {
524             circularFound10 = true;
525           }
526         }
527         else if (!circularFound10 && nbEdges == 10) {
528           circularFound10 = true;
529           addGroup = true;
530           aGroup->SetName("CIRCULAR_QUARTER_PIPE");
531         }
532       }
533       else if (nbEdges == 8) {
534         incidentPipeFound = true;
535         mainPipeFound = true;
536         flangeFound = false;
537
538         bool isNearZ0 = false;
539         bool isBelowZ0 = false;
540
541         TopExp_Explorer Ex (aGroupShapeTrsfInv,TopAbs_VERTEX);
542         while (Ex.More()) {
543           gp_Pnt aP = BRep_Tool::Pnt(TopoDS::Vertex(Ex.Current()));
544           double x=aP.X(), y=aP.Y(), z=aP.Z();
545
546           // tuy_princ_long_avant & tuy_princ_long_apres
547           //bool isMain = (((z < Precision::Confusion()) || (x < Precision::Confusion())) &&
548           //               ((y <= aR1Ext + Precision::Confusion()) ||
549           //                (y <= -(aR1Ext + Precision::Confusion())) ||
550           //                (y <= theR1 + Precision::Confusion()) ||
551           //                (y == -(theR1 + Precision::Confusion()))));
552           bool isMain = ((z < Precision::Confusion() || x < Precision::Confusion()) &&
553                          (fabs(y) > theR1 - Precision::Confusion() ||
554                           fabs(y) < Precision::Confusion()));
555
556           if (!isMain) {
557             mainPipeFound = false;
558           }
559
560           // collerette
561           //if (z < Precision::Confusion() && !isMain) {
562           //  flangeFound = true;
563           //  if (!flangeFoundAndAdded) {
564           //    flangeFoundAndAdded = true;
565           //    addGroup = true;
566           //    aGroup->SetName("FLANGE");
567           //  }
568           //}
569           if (fabs(z) < Precision::Confusion()) isNearZ0 = true;
570           if (z < - Precision::Confusion()) isBelowZ0 = true;
571
572           // tuyau incident
573           if ((Abs(x) > aR2Ext + Precision::Confusion()) ||
574               (Abs(y) > aR2Ext + Precision::Confusion())) {
575             incidentPipeFound = false;
576           }
577           Ex.Next();
578         }
579         if (mainPipeFound) {
580           addGroup = true;
581           aGroup->SetName("HALF_LENGTH_MAIN_PIPE");
582         }
583         if (incidentPipeFound) {
584           addGroup = true;
585           aGroup->SetName("HALF_LENGTH_INCIDENT_PIPE");
586         }
587         if (isNearZ0 && !isBelowZ0) {
588           flangeFound = true;
589           if (!flangeFoundAndAdded) {
590             flangeFoundAndAdded = true;
591             addGroup = true;
592             aGroup->SetName("FLANGE");
593           }
594         }
595         if (!addGroup && (!incidentPipeFound &&
596                           !mainPipeFound &&
597                           !flangeFound &&
598                           !chamferOrFilletFound)) {
599           addGroup = true;
600           chamferOrFilletFound = true;
601           if (shapeType == TSHAPE_CHAMFER)
602             aGroup->SetName("CHAMFER");
603           else
604             aGroup->SetName("FILLET");
605         }
606       }
607       else
608         continue;
609     }
610     // Add group to the list
611     if (addGroup)
612       theSeq->Append(aGroup);
613   }
614
615   SetErrorCode(OK);
616   return true;
617 }
618
619 bool GEOMImpl_IAdvancedOperations::MakePipeTShapePartition(Handle(GEOM_Object) theShape,
620                                                            double theR1, double theW1, double theL1,
621                                                            double theR2, double theW2, double theL2,
622                                                            double theH, double theW,
623                                                            double theRF, bool isNormal)
624 {
625   SetErrorCode(KO);
626
627   // Build tools for partition operation:
628   // 1 face and 2 planes
629   // Face
630   Handle(GEOM_Object) arete_intersect_int;
631   Handle(GEOM_Object) wire_t, wire_t2, face_t, face_t2;
632   Handle(GEOM_Object) chan_racc;
633   Handle(GEOM_Object) vi1, vi2;
634
635   Handle(GEOM_Object) Vector_Z = myBasicOperations->MakeVectorDXDYDZ(0, 0, 1);
636   Vector_Z->GetLastFunction()->SetDescription("");
637
638   // Useful values
639   double aSize = 2*(theL1 + theL2);
640   double aR1Ext = theR1 + theW1;
641   double aR2Ext = theR2 + theW2;
642   double theVertCylinderRadius = aR2Ext + theW + theRF;
643   double theHoriCylinderRadius = aR1Ext + theH + theRF;
644
645   // Common edges on internal cylinder
646   Handle(GEOM_Object) box_i = my3DPrimOperations->MakeBoxDXDYDZ(theR2, theR2, theR1);
647   box_i->GetLastFunction()->SetDescription("");
648   box_i = myTransformOperations->TranslateDXDYDZ(box_i, -theR2, -theR2, 0);
649   box_i->GetLastFunction()->SetDescription("");
650
651   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
652   TCollection_AsciiString theDesc = aFunction->GetDescription();
653   Handle(TColStd_HSequenceOfTransient) edges_i =
654     myShapesOperations->GetShapesOnBox(box_i, theShape, TopAbs_EDGE, GEOMAlgo_ST_IN);
655   // Recover previous description to get rid of Propagate dump
656   aFunction->SetDescription(theDesc);
657   if (edges_i.IsNull() || edges_i->Length() == 0) {
658     SetErrorCode("Internal edges not found");
659     return false;
660   }
661   for (int i=1; i<=edges_i->Length();i++) {
662     Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(edges_i->Value(i));
663     anObj->GetLastFunction()->SetDescription("");
664   }
665   arete_intersect_int = Handle(GEOM_Object)::DownCast(edges_i->Value(1));
666
667   // search for vertices located on both internal pipes
668   aFunction = theShape->GetLastFunction();
669   theDesc = aFunction->GetDescription();
670   Handle(TColStd_HSequenceOfTransient) vertices_i =
671     myShapesOperations->GetShapesOnBox(box_i, theShape, TopAbs_VERTEX, GEOMAlgo_ST_ONIN);
672   // Recover previous description to get rid of Propagate dump
673   aFunction->SetDescription(theDesc);
674   if (vertices_i.IsNull() || vertices_i->Length() == 0) {
675     SetErrorCode("Internal vertices not found");
676     return false;
677   }
678
679   for (int i = 1; i <= vertices_i->Length(); i++) {
680     Handle(GEOM_Object) v = Handle(GEOM_Object)::DownCast(vertices_i->Value(i));
681     v->GetLastFunction()->SetDescription("");
682     TopoDS_Vertex aVertex = TopoDS::Vertex(v->GetValue());
683     gp_Pnt aP = BRep_Tool::Pnt(aVertex);
684     if (Abs(aP.X()) <= Precision::Confusion()) {
685       if (Abs(aP.Y()) - theR2 <= Precision::Confusion())
686         vi1 = v;
687     } else if (Abs(aP.Y()) <= Precision::Confusion()) {
688       if (Abs(aP.X()) - theR1 <= Precision::Confusion())
689         vi2 = v;
690     }
691   }
692
693   std::list<Handle(GEOM_Object)> theShapes;
694
695   if (isNormal) {
696     Handle(GEOM_Object) ve1, ve2;
697
698     Handle(GEOM_Object) box_e = my3DPrimOperations->MakeBoxDXDYDZ(aR2Ext, aR2Ext, aR1Ext);
699     box_e->GetLastFunction()->SetDescription("");
700     box_e = myTransformOperations->TranslateDXDYDZ(box_e, -aR2Ext, -aR2Ext, 0);
701     box_e->GetLastFunction()->SetDescription("");
702     // Common edges on external cylinder
703     aFunction = theShape->GetLastFunction();
704     theDesc = aFunction->GetDescription();
705     Handle(TColStd_HSequenceOfTransient) edges_e =
706       myShapesOperations->GetShapesOnBox(box_e, theShape, TopAbs_EDGE, GEOMAlgo_ST_IN);
707     // Recover previous description to get rid of Propagate dump
708     aFunction->SetDescription(theDesc);
709     if (edges_e.IsNull() || edges_e->Length() == 0) {
710       SetErrorCode("External edges not found");
711       return false;
712     }
713     for (int i=1; i<=edges_e->Length();i++) {
714       Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(edges_e->Value(i));
715       anObj->GetLastFunction()->SetDescription("");
716     }
717
718     // search for vertices located on both external pipes
719     aFunction = theShape->GetLastFunction();
720     theDesc = aFunction->GetDescription();
721     Handle(TColStd_HSequenceOfTransient) vertices_e =
722       myShapesOperations->GetShapesOnBox(box_e, theShape, TopAbs_VERTEX, GEOMAlgo_ST_ONIN);
723     // Recover previous description to get rid of Propagate dump
724     aFunction->SetDescription(theDesc);
725     if (vertices_e.IsNull() || vertices_e->Length() == 0) {
726       SetErrorCode("External vertices not found");
727       return false;
728     }
729
730     for (int i = 1; i <= vertices_e->Length(); i++) {
731       Handle(GEOM_Object) v = Handle(GEOM_Object)::DownCast(vertices_e->Value(i));
732       v->GetLastFunction()->SetDescription("");
733       TopoDS_Vertex aVertex = TopoDS::Vertex(v->GetValue());
734       gp_Pnt aP = BRep_Tool::Pnt(aVertex);
735       if (Abs(aP.X()) <= Precision::Confusion()) {
736         if (Abs(aP.Y()) - theR2 > Precision::Confusion())
737           ve1 = v;
738       } else if (Abs(aP.Y()) <= Precision::Confusion()) {
739         if (Abs(aP.X()) - theR2 > Precision::Confusion())
740           ve2 = v;
741       }
742     }
743     Handle(GEOM_Object) edge_e1, edge_e2;
744     try {
745 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
746       OCC_CATCH_SIGNALS;
747 #endif
748       edge_e1 = myBasicOperations->MakeLineTwoPnt(ve1, vi1);
749       if (edge_e1.IsNull()) {
750         SetErrorCode("Edge 1 could not be built");
751         return false;
752       }
753     } catch (Standard_Failure) {
754       Handle(Standard_Failure) aFail = Standard_Failure::Caught();
755       SetErrorCode(aFail->GetMessageString());
756       return false;
757     }
758
759     try {
760 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
761       OCC_CATCH_SIGNALS;
762 #endif
763       edge_e2 = myBasicOperations->MakeLineTwoPnt(ve2, vi2);
764       if (edge_e2.IsNull()) {
765         SetErrorCode("Edge 2 could not be built");
766         return false;
767       }
768     } catch (Standard_Failure) {
769       Handle(Standard_Failure) aFail = Standard_Failure::Caught();
770       SetErrorCode(aFail->GetMessageString());
771       return false;
772     }
773
774     edge_e1->GetLastFunction()->SetDescription("");
775     edge_e2->GetLastFunction()->SetDescription("");
776
777     std::list<Handle(GEOM_Object)> edge_e_elist;
778     edge_e_elist.push_back(arete_intersect_int);
779     edge_e_elist.push_back(edge_e1);
780     edge_e_elist.push_back(Handle(GEOM_Object)::DownCast(edges_e->Value(1)));
781     edge_e_elist.push_back(edge_e2);
782     wire_t = myShapesOperations->MakeWire(edge_e_elist, 1e-7);
783     if (wire_t.IsNull()) {
784       SetErrorCode("Impossible to build wire");
785       return false;
786     }
787     wire_t->GetLastFunction()->SetDescription("");
788     face_t = myShapesOperations->MakeFace(wire_t, false);
789     if (face_t.IsNull()) {
790       SetErrorCode("Impossible to build face");
791       return false;
792     }
793     face_t->GetLastFunction()->SetDescription("");
794   }
795   else {
796     Handle(GEOM_Object) P1, P2, P3, P4, P5, P6;
797     int idP1, idP2, idP3, idP4;
798     int PZX, PZY;
799     double ZX=0, ZY=0;
800     std::vector<int> LX;
801     std::vector<int> LY;
802     Handle(GEOM_Object) box_e = my3DPrimOperations->MakeBoxDXDYDZ
803       (theVertCylinderRadius, theVertCylinderRadius, theHoriCylinderRadius);
804     box_e->GetLastFunction()->SetDescription("");
805     box_e = myTransformOperations->TranslateDXDYDZ
806       (box_e, -theVertCylinderRadius, -theVertCylinderRadius, 0);
807     box_e->GetLastFunction()->SetDescription("");
808
809     aFunction = theShape->GetLastFunction();
810     theDesc = aFunction->GetDescription();
811     Handle(TColStd_HSequenceOfTransient) extremVertices =
812       myShapesOperations->GetShapesOnBox(box_e, theShape, TopAbs_VERTEX, GEOMAlgo_ST_ONIN);
813     // Recover previous description to get rid of Propagate dump
814     aFunction->SetDescription(theDesc);
815
816     if (extremVertices.IsNull() || extremVertices->Length() == 0) {
817       if (theRF == 0)
818         SetErrorCode("Vertices on chamfer not found");
819       else
820         SetErrorCode("Vertices on fillet not found");
821       return false;
822     }
823
824     theShapes.push_back(theShape);
825     theShapes.push_back(box_e);
826     if (extremVertices->Length() != 6) {
827       //           for (int i=1; i<=extremVertices->Length(); i++){
828       //             theShapes.push_back(Handle(GEOM_Object)::DownCast(extremVertices->Value(i)));
829       //           }
830       //           Handle(GEOM_Object) aCompound = myShapesOperations->MakeCompound(theShapes);
831       //           TopoDS_Shape aCompoundShape = aCompound->GetValue();
832       //           theShape->GetLastFunction()->SetValue(aCompoundShape);
833       SetErrorCode("Bad number of vertices on chamfer found");
834       return false;
835     }
836
837     for (int i=1; i<=extremVertices->Length(); i++){
838       Handle(GEOM_Object) aV = Handle(GEOM_Object)::DownCast(extremVertices->Value(i));
839       aV->GetLastFunction()->SetDescription("");
840       gp_Pnt aP = BRep_Tool::Pnt(TopoDS::Vertex(aV->GetValue()));
841
842       if (Abs(aP.X()) <= Precision::Confusion()) {
843         if (Abs(aP.Y()) - theR2 > Precision::Confusion()) {
844           LX.push_back(i);
845           if  (aP.Z()-ZX > Precision::Confusion()) {
846             ZX = aP.Z();
847             PZX = i;
848           }
849         }
850       }
851       else {
852         if (Abs(aP.X()) - theR2 > Precision::Confusion()) {
853           LY.push_back(i);
854           if (aP.Z() - ZY > Precision::Confusion()) {
855             ZY = aP.Z();
856             PZY = i;
857           }
858         }
859       }
860     }
861
862     idP2 = PZX;
863     idP4 = PZY;
864     idP1 = LX.at(0);
865     if (LX.at(0) == PZX)
866       idP1 = LX.at(1);
867     idP3 = LY.at(0);
868     if (LY.at(0) == PZY)
869       idP3 = LY.at(1);
870
871     P1 = Handle(GEOM_Object)::DownCast(extremVertices->Value(idP1));
872     P2 = Handle(GEOM_Object)::DownCast(extremVertices->Value(idP2));
873     P3 = Handle(GEOM_Object)::DownCast(extremVertices->Value(idP3));
874     P4 = Handle(GEOM_Object)::DownCast(extremVertices->Value(idP4));
875
876     Handle(GEOM_Object) Cote_1 = myBasicOperations->MakeLineTwoPnt(P1, vi1);
877     if (Cote_1.IsNull()) {
878       SetErrorCode("Impossible to build edge in thickness");
879       return false;
880     }
881     Cote_1->GetLastFunction()->SetDescription("");
882
883     Handle(GEOM_Object) Cote_2 = myBasicOperations->MakeLineTwoPnt(vi2, P3);
884     if (Cote_2.IsNull()) {
885       SetErrorCode("Impossible to build edge in thickness");
886       return false;
887     }
888     Cote_2->GetLastFunction()->SetDescription("");
889
890     // edge_chan_princ = arete du chanfrein (ou raccord) sur le tuyau principal
891     // edge_chan_inc = arete du chanfrein (ou raccord) sur le tuyau incident
892     //         std::cerr << "Getting chamfer edge on main pipe" << std::endl;
893     Handle(GEOM_Object) edge_chan_princ = myBlocksOperations->GetEdge(theShape, P1, P3);
894     if (edge_chan_princ.IsNull()) {
895       SetErrorCode("Impossible to find edge on main pipe");
896       return false;
897     }
898     edge_chan_princ->GetLastFunction()->SetDescription("");
899
900     Handle(GEOM_Object) edge_chan_inc = myBlocksOperations->GetEdge(theShape, P2, P4);
901     if (edge_chan_inc.IsNull()) {
902       SetErrorCode("Impossible to find edge on incident pipe");
903       return false;
904     }
905     edge_chan_inc->GetLastFunction()->SetDescription("");
906
907     std::list<Handle(GEOM_Object)> edgeList1;
908     edgeList1.push_back(edge_chan_princ);
909     edgeList1.push_back(Cote_1);
910     edgeList1.push_back(arete_intersect_int);
911     edgeList1.push_back(Cote_2);
912
913     //         std::cerr << "Creating wire 1" << std::endl;
914     wire_t = myShapesOperations->MakeWire(edgeList1, 1e-7);
915     if (wire_t.IsNull()) {
916       SetErrorCode("Impossible to build wire");
917       return false;
918     }
919     wire_t->GetLastFunction()->SetDescription("");
920
921     //         std::cerr << "Creating face 1" << std::endl;
922     face_t = myShapesOperations->MakeFace(wire_t, false);
923     if (face_t.IsNull()) {
924       SetErrorCode("Impossible to build face");
925       return false;
926     }
927     face_t->GetLastFunction()->SetDescription("");
928     theShapes.push_back(face_t);
929
930     gp_Pnt aP2 = BRep_Tool::Pnt(TopoDS::Vertex(P2->GetValue()));
931     gp_Pnt aP5 = BRep_Tool::Pnt(TopoDS::Vertex(vi1->GetValue()));
932     double deltaZ = aP2.Z() - aP5.Z();
933     //         std::cerr << "Creating new point from vi1 with deltaZ = " << deltaZ << std::endl;
934     Handle(GEOM_Object) P5bis = myTransformOperations->TranslateDXDYDZCopy(vi1, 0, 0, deltaZ);
935     if (P5bis.IsNull()) {
936       SetErrorCode("Impossible to translate vertex");
937       return false;
938     }
939     P5bis->GetLastFunction()->SetDescription("");
940
941     gp_Pnt aP4 = BRep_Tool::Pnt(TopoDS::Vertex(P4->GetValue()));
942     gp_Pnt aP6 = BRep_Tool::Pnt(TopoDS::Vertex(vi2->GetValue()));
943     deltaZ = aP4.Z() - aP6.Z();
944     //         std::cerr << "Creating new point from vi2 with deltaZ = " << deltaZ << std::endl;
945     Handle(GEOM_Object) P6bis = myTransformOperations->TranslateDXDYDZCopy(vi2, 0, 0, deltaZ);
946     if (P6bis.IsNull()) {
947       SetErrorCode("Impossible to translate vertex");
948       return false;
949     }
950     P6bis->GetLastFunction()->SetDescription("");
951
952     //         std::cerr << "Creating new line 1 from 2 previous points" << std::endl;
953     Handle(GEOM_Object) Cote_3 = myBasicOperations->MakeLineTwoPnt(P5bis, P2);
954     if (Cote_3.IsNull()) {
955       SetErrorCode("Impossible to build edge in thickness");
956       return false;
957     }
958     Cote_3->GetLastFunction()->SetDescription("");
959
960     //         std::cerr << "Creating new line 2 from 2 previous points" << std::endl;
961     Handle(GEOM_Object) Cote_4 = myBasicOperations->MakeLineTwoPnt(P6bis, P4);
962     if (Cote_4.IsNull()) {
963       SetErrorCode("Impossible to build edge in thickness");
964       return false;
965     }
966     Cote_4->GetLastFunction()->SetDescription("");
967
968     //         std::cerr << "Creating new line 3 from 2 previous points" << std::endl;
969     Handle(GEOM_Object) Cote_5 = myBasicOperations->MakeLineTwoPnt(P5bis, P6bis);
970     if (Cote_4.IsNull()) {
971       SetErrorCode("Impossible to build edge in thickness");
972       return false;
973     }
974     Cote_5->GetLastFunction()->SetDescription("");
975
976     //std::list<Handle(GEOM_Object)> edgeList2;
977     //edgeList2.push_back(edge_chan_inc);
978     //edgeList2.push_back(Cote_3);
979     //edgeList2.push_back(Cote_5);
980     //edgeList2.push_back(Cote_4);
981     //         std::cerr << "Creating wire 2" << std::endl;
982     //wire_t2 = myShapesOperations->MakeWire(edgeList2, 1e-7);
983     //if (wire_t2.IsNull()) {
984     //  SetErrorCode("Impossible to build wire");
985     //  return false;
986     //}
987     //wire_t2->GetLastFunction()->SetDescription("");
988     //         std::cerr << "Creating face 2" << std::endl;
989     //face_t2 = myShapesOperations->MakeFace(wire_t2, false);
990     face_t2 = my3DPrimOperations->MakePrismVecH(edge_chan_inc, Cote_4, - 2.0*theR2);
991     if (face_t2.IsNull()) {
992       SetErrorCode("Impossible to build face");
993       return false;
994     }
995     face_t2->GetLastFunction()->SetDescription("");
996     theShapes.push_back(face_t2);
997   }
998
999   // Planes
1000   Handle(GEOM_Object) aP0 = myBasicOperations->MakePointXYZ(0, 0, 0);
1001   Handle(GEOM_Object) aVZ = myBasicOperations->MakeVectorDXDYDZ(0, 0, 1);
1002   Handle(GEOM_Object) aVXZ = myBasicOperations->MakeVectorDXDYDZ(aR1Ext, 0, 0.5*(theL1+theVertCylinderRadius));
1003   Handle(GEOM_Object) aPlnOZ = myBasicOperations->MakePlanePntVec(aP0, aVZ, aSize);
1004   Handle(GEOM_Object) aPlnOXZ = myBasicOperations->MakePlanePntVec(aP0, aVXZ, aSize);
1005   aP0->GetLastFunction()->SetDescription("");
1006   aVZ->GetLastFunction()->SetDescription("");
1007   aVXZ->GetLastFunction()->SetDescription("");
1008   aPlnOZ->GetLastFunction()->SetDescription("");
1009   aPlnOXZ->GetLastFunction()->SetDescription("");
1010   theShapes.push_back(aPlnOZ);
1011   theShapes.push_back(aPlnOXZ);
1012
1013   // Partition
1014   Handle(TColStd_HSequenceOfTransient) partitionShapes = new TColStd_HSequenceOfTransient;
1015   Handle(TColStd_HSequenceOfTransient) theTools = new TColStd_HSequenceOfTransient;
1016   Handle(TColStd_HSequenceOfTransient) theKeepInside = new TColStd_HSequenceOfTransient;
1017   Handle(TColStd_HSequenceOfTransient) theRemoveInside = new TColStd_HSequenceOfTransient;
1018   Handle(TColStd_HArray1OfInteger) theMaterials;
1019   partitionShapes->Append(theShape);
1020   theTools->Append(aPlnOZ);
1021   if (Abs(aR1Ext - aR2Ext) > Precision::Confusion() )
1022     theTools->Append(aPlnOXZ);
1023   theTools->Append(face_t);
1024   if (!isNormal)
1025     theTools->Append(face_t2);
1026
1027   Handle(GEOM_Object) Te3 = myBooleanOperations->MakePartition
1028     (partitionShapes, theTools, theKeepInside, theRemoveInside,
1029      TopAbs_SOLID, false, theMaterials, 0, false);
1030   if (Te3.IsNull()) {
1031     SetErrorCode("Impossible to build partition of TShape");
1032     //         Handle(GEOM_Object) aCompound = myShapesOperations->MakeCompound(theShapes);
1033     //         TopoDS_Shape aCompoundShape = aCompound->GetValue();
1034     //         theShape->GetLastFunction()->SetValue(aCompoundShape);
1035     return false;
1036   }
1037   Te3->GetLastFunction()->SetDescription("");
1038
1039   // Last verification: result should be a block
1040   std::list<GEOMImpl_IBlocksOperations::BCError> errList;
1041   if (!myBlocksOperations->CheckCompoundOfBlocks(Te3,errList)) {
1042     SetErrorCode("TShape is not a block");
1043     return false;
1044   }
1045   TopoDS_Shape aShape = Te3->GetValue();
1046   theShape->GetLastFunction()->SetValue(aShape);
1047
1048   SetErrorCode(OK);
1049   return true;
1050 }
1051
1052 // Mirror and glue faces
1053 bool GEOMImpl_IAdvancedOperations::MakePipeTShapeMirrorAndGlue(Handle(GEOM_Object) theShape,
1054                                                                double theR1, double theW1, double theL1,
1055                                                                double theR2, double theW2, double theL2)
1056 {
1057   SetErrorCode(KO);
1058
1059   // Useful values
1060   double aSize = 2*(theL1 + theL2);
1061   double aR1Ext = theR1 + theW1;
1062
1063   // Planes
1064   Handle(GEOM_Object) aP0 = myBasicOperations->MakePointXYZ(0, 0, 0);
1065   aP0->GetLastFunction()->SetDescription("");
1066   Handle(GEOM_Object) aVX = myBasicOperations->MakeVectorDXDYDZ(1, 0, 0);
1067   Handle(GEOM_Object) aVY = myBasicOperations->MakeVectorDXDYDZ(0, 1, 0);
1068   aVX->GetLastFunction()->SetDescription("");
1069   aVY->GetLastFunction()->SetDescription("");
1070   Handle(GEOM_Object) aPlane_OX = myBasicOperations->MakePlanePntVec(aP0, aVX, 2*(aR1Ext + theL2));
1071   Handle(GEOM_Object) aPlane_OY = myBasicOperations->MakePlanePntVec(aP0, aVY, aSize);
1072   aPlane_OX->GetLastFunction()->SetDescription("");
1073   aPlane_OY->GetLastFunction()->SetDescription("");
1074
1075   Handle(GEOM_Object) Te4 = myTransformOperations->MirrorPlaneCopy(theShape, aPlane_OX);
1076   if (Te4.IsNull()) {
1077     SetErrorCode("Impossible to build mirror of quarter TShape");
1078     return false;
1079   }
1080
1081   Handle(GEOM_Object) Te5 = myTransformOperations->MirrorPlaneCopy(theShape, aPlane_OY);
1082   if (Te5.IsNull()) {
1083     SetErrorCode("Impossible to build mirror of half TShape");
1084     return false;
1085   }
1086
1087   Handle(GEOM_Object) Te6 = myTransformOperations->MirrorPlaneCopy(Te4, aPlane_OY);
1088   if (Te6.IsNull()) {
1089     SetErrorCode("Impossible to build mirror of half TShape");
1090     return false;
1091   }
1092
1093   std::list<Handle(GEOM_Object)> aShapesList;
1094   aShapesList.push_back(theShape);
1095   aShapesList.push_back(Te4);
1096   aShapesList.push_back(Te5);
1097   aShapesList.push_back(Te6);
1098   Handle(GEOM_Object) Te7 = myShapesOperations->MakeCompound(aShapesList);
1099   if (Te7.IsNull()) {
1100     SetErrorCode("Impossible to build compound");
1101     return false;
1102   }
1103
1104   Handle(GEOM_Object) Te8 = myShapesOperations->MakeGlueFaces(Te7, 1e-7, true);
1105   if (Te8.IsNull()) {
1106     SetErrorCode("Impossible to glue faces of TShape");
1107     return false;
1108   }
1109
1110   TopoDS_Shape aShape = Te8->GetValue();
1111
1112   theShape->GetLastFunction()->SetValue(aShape);
1113
1114   Te4->GetLastFunction()->SetDescription("");
1115   Te5->GetLastFunction()->SetDescription("");
1116   Te6->GetLastFunction()->SetDescription("");
1117   Te7->GetLastFunction()->SetDescription("");
1118   Te8->GetLastFunction()->SetDescription("");
1119
1120   SetErrorCode(OK);
1121   return true;
1122 }
1123
1124 //=============================================================================
1125 /*!
1126  *  MakePipeTShape
1127  *  Create a T-shape object with specified caracteristics for the main and
1128  *  the incident pipes (radius, width, half-length).
1129  *  Center of the shape is (0,0,0). The main plane of the T-shape is XOY.
1130  *  \param theR1 Internal radius of main pipe
1131  *  \param theW1 Width of main pipe
1132  *  \param theL1 Half-length of main pipe
1133  *  \param theR2 Internal radius of incident pipe (R2 < R1)
1134  *  \param theW2 Width of incident pipe (R2+W2 < R1+W1)
1135  *  \param theL2 Half-length of incident pipe
1136  *  \param theHexMesh Boolean indicating if shape is prepared for hex mesh
1137  *  \return List of GEOM_Objects, containing the created shape and propagation groups.
1138  */
1139 //=============================================================================
1140 Handle(TColStd_HSequenceOfTransient)
1141 GEOMImpl_IAdvancedOperations::MakePipeTShape(double theR1, double theW1, double theL1,
1142                                              double theR2, double theW2, double theL2,
1143                                              bool theHexMesh)
1144 {
1145   MESSAGE("GEOMImpl_IAdvancedOperations::MakePipeTShape");
1146   SetErrorCode(KO);
1147   //Add a new object
1148   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_TSHAPE);
1149
1150   //Add a new shape function with parameters
1151   Handle(GEOM_Function) aFunction = aShape->AddFunction(GEOMImpl_PipeTShapeDriver::GetID(), TSHAPE_BASIC);
1152   if (aFunction.IsNull()) return NULL;
1153
1154   //Check if the function is set correctly
1155   if (aFunction->GetDriverGUID() != GEOMImpl_PipeTShapeDriver::GetID()) return NULL;
1156
1157   GEOMImpl_IPipeTShape aData(aFunction);
1158
1159   aData.SetR1(theR1);
1160   aData.SetW1(theW1);
1161   aData.SetL1(theL1);
1162   aData.SetR2(theR2);
1163   aData.SetW2(theW2);
1164   aData.SetL2(theL2);
1165   aData.SetHexMesh(theHexMesh);
1166
1167   //Compute the resulting value
1168   try {
1169 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1170     OCC_CATCH_SIGNALS;
1171 #endif
1172     if (!GetSolver()->ComputeFunction(aFunction)) {
1173       SetErrorCode("TShape driver failed");
1174       return NULL;
1175     }
1176   } catch (Standard_Failure) {
1177     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1178     SetErrorCode(aFail->GetMessageString());
1179     return NULL;
1180   }
1181
1182   if (theHexMesh) {
1183     if (!MakePipeTShapePartition(aShape, theR1, theW1, theL1, theR2, theW2, theL2))
1184       return NULL;
1185     if (!MakePipeTShapeMirrorAndGlue(aShape, theR1, theW1, theL1, theR2, theW2, theL2))
1186       return NULL;
1187   }
1188
1189   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1190   aSeq->Append(aShape);
1191
1192   if (theHexMesh) {
1193     /*
1194      * Get the groups: BEGIN
1195      */
1196     try {
1197       if (!MakeGroups(aShape, TSHAPE_BASIC, theR1, theW1, theL1, theR2, theW2, theL2, aSeq, gp_Trsf()))
1198         return NULL;
1199     }
1200     catch (Standard_Failure) {
1201       Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1202       SetErrorCode(aFail->GetMessageString());
1203       return NULL;
1204     }
1205
1206     TCollection_AsciiString aListRes, anEntry;
1207     // Iterate over the sequence aSeq
1208     Standard_Integer aNbGroups = aSeq->Length();
1209     Standard_Integer i = 2;
1210     for (; i <= aNbGroups; i++) {
1211       Handle(Standard_Transient) anItem = aSeq->Value(i);
1212       if (anItem.IsNull()) continue;
1213       Handle(GEOM_Object) aGroup = Handle(GEOM_Object)::DownCast(anItem);
1214       if (aGroup.IsNull()) continue;
1215       //Make a Python command
1216       TDF_Tool::Entry(aGroup->GetEntry(), anEntry);
1217       aListRes += anEntry + ", ";
1218     }
1219
1220     aListRes.Trunc(aListRes.Length() - 2);
1221
1222     //Make a Python command
1223     GEOM::TPythonDump(aFunction)
1224       << "[" << aShape << ", " << aListRes.ToCString() << "] = geompy.MakePipeTShape("
1225       << theR1 << ", " << theW1 << ", " << theL1 << ", " << theR2 << ", " << theW2 << ", " << theL2 << ", "
1226       << theHexMesh << ")";
1227   }
1228   /*
1229    * Get the groups: END
1230    */
1231   else {
1232     //Make a Python command
1233     GEOM::TPythonDump(aFunction)
1234       << "[" << aShape << "] = geompy.MakePipeTShape(" << theR1 << ", " << theW1 << ", "
1235       << theL1 << ", " << theR2 << ", " << theW2 << ", " << theL2 << ", " << theHexMesh << ")";
1236   }
1237
1238   SetErrorCode(OK);
1239
1240   return aSeq;
1241 }
1242
1243 //=============================================================================
1244 /*!
1245  *  MakePipeTShapeWithPosition
1246  *  Create a T-shape object with specified caracteristics for the main and
1247  *  the incident pipes (radius, width, half-length).
1248  *  The extremities of the main pipe are located on junctions points P1 and P2.
1249  *  The extremity of the incident pipe is located on junction point P3.
1250  *  \param theR1 Internal radius of main pipe
1251  *  \param theW1 Width of main pipe
1252  *  \param theL1 Half-length of main pipe
1253  *  \param theR2 Internal radius of incident pipe (R2 < R1)
1254  *  \param theW2 Width of incident pipe (R2+W2 < R1+W1)
1255  *  \param theL2 Half-length of incident pipe
1256  *  \param theHexMesh Boolean indicating if shape is prepared for hex mesh
1257  *  \param theP1 1st junction point of main pipe
1258  *  \param theP2 2nd junction point of main pipe
1259  *  \param theP3 Junction point of incident pipe
1260  *  \return List of GEOM_Objects, containing the created shape and propagation groups..
1261  */
1262 //=============================================================================
1263 Handle(TColStd_HSequenceOfTransient)
1264 GEOMImpl_IAdvancedOperations::MakePipeTShapeWithPosition(double theR1, double theW1, double theL1,
1265                                                          double theR2, double theW2, double theL2,
1266                                                          bool theHexMesh,
1267                                                          Handle(GEOM_Object) theP1,
1268                                                          Handle(GEOM_Object) theP2,
1269                                                          Handle(GEOM_Object) theP3)
1270 {
1271   SetErrorCode(KO);
1272   //Add a new object
1273   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_TSHAPE);
1274   /////////////////
1275   // TSHAPE CODE
1276   /////////////////
1277   //Add a new shape function with parameters
1278   Handle(GEOM_Function) aFunction = aShape->AddFunction(GEOMImpl_PipeTShapeDriver::GetID(), TSHAPE_BASIC);
1279   if (aFunction.IsNull()) return NULL;
1280
1281   //Check if the function is set correctly
1282   if (aFunction->GetDriverGUID() != GEOMImpl_PipeTShapeDriver::GetID()) return NULL;
1283
1284   // Check new position
1285   if (!CheckCompatiblePosition(theL1, theL2, theP1, theP2, theP3, 0.01)) {
1286     return NULL;
1287   }
1288
1289   GEOMImpl_IPipeTShape aData(aFunction);
1290
1291   aData.SetR1(theR1);
1292   aData.SetW1(theW1);
1293   aData.SetL1(theL1);
1294   aData.SetR2(theR2);
1295   aData.SetW2(theW2);
1296   aData.SetL2(theL2);
1297   aData.SetHexMesh(theHexMesh);
1298
1299   //Compute the resulting value
1300   try {
1301 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1302     OCC_CATCH_SIGNALS;
1303 #endif
1304     if (!GetSolver()->ComputeFunction(aFunction)) {
1305       SetErrorCode("TShape driver failed");
1306       return NULL;
1307     }
1308   } catch (Standard_Failure) {
1309     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1310     SetErrorCode(aFail->GetMessageString());
1311     return NULL;
1312   }
1313
1314   if (theHexMesh) {
1315     if (!MakePipeTShapePartition(aShape, theR1, theW1, theL1, theR2, theW2, theL2))
1316       return NULL;
1317     if (!MakePipeTShapeMirrorAndGlue(aShape, theR1, theW1, theL1, theR2, theW2, theL2))
1318       return NULL;
1319   }
1320
1321   TopoDS_Shape Te = aShape->GetValue();
1322
1323   // Set Position
1324   gp_Trsf aTrsf = GetPositionTrsf(theL1, theL2, theP1, theP2, theP3);
1325   BRepBuilderAPI_Transform aTransformation(Te, aTrsf, Standard_False);
1326   TopoDS_Shape aTrsf_Shape = aTransformation.Shape();
1327   aFunction->SetValue(aTrsf_Shape);
1328   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1329   aSeq->Append(aShape);
1330
1331   if (theHexMesh) {
1332     //
1333     // Get the groups: BEGIN
1334     //
1335     try {
1336       if (!MakeGroups(aShape,TSHAPE_BASIC, theR1, theW1, theL1, theR2, theW2, theL2, aSeq, aTrsf)) {
1337         return NULL;
1338       }
1339     }
1340     catch (Standard_Failure) {
1341       Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1342       SetErrorCode(aFail->GetMessageString());
1343       return NULL;
1344     }
1345
1346     TCollection_AsciiString aListRes, anEntry;
1347     // Iterate over the sequence aSeq
1348     Standard_Integer aNbGroups = aSeq->Length();
1349     Standard_Integer i = 2;
1350     for (; i <= aNbGroups; i++) {
1351       Handle(Standard_Transient) anItem = aSeq->Value(i);
1352       if (anItem.IsNull()) continue;
1353       Handle(GEOM_Object) aGroup = Handle(GEOM_Object)::DownCast(anItem);
1354       if (aGroup.IsNull()) continue;
1355       //Make a Python command
1356       TDF_Tool::Entry(aGroup->GetEntry(), anEntry);
1357       aListRes += anEntry + ", ";
1358     }
1359
1360     aListRes.Trunc(aListRes.Length() - 2);
1361
1362     //Make a Python command
1363     GEOM::TPythonDump(aFunction)
1364       << "[" << aShape << ", " << aListRes.ToCString() << "] = geompy.MakePipeTShape("
1365       << theR1 << ", " << theW1 << ", " << theL1 << ", " << theR2 << ", " << theW2 << ", " << theL2 << ", "
1366       << theHexMesh << ", " << theP1 << ", " << theP2 << ", " << theP3 << ")";
1367   }
1368   //
1369   // Get the groups: END
1370   //
1371
1372   else {
1373     //Make a Python command
1374     GEOM::TPythonDump(aFunction)
1375       << "[" << aShape << "] = geompy.MakePipeTShape(" << theR1 << ", " << theW1 << ", "
1376       << theL1 << ", " << theR2 << ", " << theW2 << ", " << theL2 << ", " << theHexMesh << ", " << theP1
1377       << ", " << theP2 << ", " << theP3 << ")";
1378   }
1379
1380   SetErrorCode(OK);
1381
1382   return aSeq;
1383 }
1384
1385 //=============================================================================
1386 /*!
1387  *  MakePipeTShapeChamfer
1388  *  Create a T-shape object with specified caracteristics for the main and
1389  *  the incident pipes (radius, width, half-length). A chamfer is created
1390  *  on the junction of the pipes.
1391  *  Center of the shape is (0,0,0). The main plane of the T-shape is XOY.
1392  *  \param theR1 Internal radius of main pipe
1393  *  \param theW1 Width of main pipe
1394  *  \param theL1 Half-length of main pipe
1395  *  \param theR2 Internal radius of incident pipe (R2 < R1)
1396  *  \param theW2 Width of incident pipe (R2+W2 < R1+W1)
1397  *  \param theL2 Half-length of incident pipe
1398  *  \param theH Height of chamfer.
1399  *  \param theW Width of chamfer.
1400  *  \param theHexMesh Boolean indicating if shape is prepared for hex mesh
1401  *  \return List of GEOM_Objects, containing the created shape and propagation groups.
1402  */
1403 //=============================================================================
1404 Handle(TColStd_HSequenceOfTransient)
1405 GEOMImpl_IAdvancedOperations::MakePipeTShapeChamfer(double theR1, double theW1, double theL1,
1406                                                     double theR2, double theW2, double theL2,
1407                                                     double theH, double theW,
1408                                                     bool theHexMesh)
1409 {
1410   SetErrorCode(KO);
1411   //Add a new object
1412   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_TSHAPE);
1413   //Add a new shape function with parameters
1414   Handle(GEOM_Function) aFunction = aShape->AddFunction(GEOMImpl_PipeTShapeDriver::GetID(), TSHAPE_CHAMFER);
1415   if (aFunction.IsNull()) return NULL;
1416
1417   //Check if the function is set correctly
1418   if (aFunction->GetDriverGUID() != GEOMImpl_PipeTShapeDriver::GetID()) return NULL;
1419
1420   GEOMImpl_IPipeTShape aData(aFunction);
1421
1422   aData.SetR1(theR1);
1423   aData.SetW1(theW1);
1424   aData.SetL1(theL1);
1425   aData.SetR2(theR2);
1426   aData.SetW2(theW2);
1427   aData.SetL2(theL2);
1428   aData.SetH(theH);
1429   aData.SetW(theW);
1430   aData.SetHexMesh(theHexMesh);
1431
1432   //Compute the resulting value
1433   try {
1434 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1435     OCC_CATCH_SIGNALS;
1436 #endif
1437     if (!GetSolver()->ComputeFunction(aFunction)) {
1438       SetErrorCode("TShape driver failed");
1439       return NULL;
1440     }
1441   } catch (Standard_Failure) {
1442     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1443     SetErrorCode(aFail->GetMessageString());
1444     return NULL;
1445   }
1446
1447   // BEGIN of chamfer
1448   TopoDS_Shape aShapeShape = aShape->GetValue();
1449   TopTools_IndexedMapOfShape anEdgesIndices;
1450   TopExp::MapShapes(aShapeShape, anEdgesIndices);
1451   // Common edges on external cylinders
1452   Handle(GEOM_Object) box_e;
1453   if (theHexMesh) {
1454     box_e = my3DPrimOperations->MakeBoxDXDYDZ(theR2+theW2, theR2+theW2, theR1+theW1);
1455   }
1456   else {
1457     box_e = my3DPrimOperations->MakeBoxDXDYDZ(2*(theR2+theW2), 2*(theR2+theW2), theR1+theW1);
1458   }
1459   box_e->GetLastFunction()->SetDescription("");
1460   box_e = myTransformOperations->TranslateDXDYDZ(box_e, -(theR2+theW2), -(theR2+theW2), 0);
1461   box_e->GetLastFunction()->SetDescription("");
1462
1463   Handle(TColStd_HSequenceOfInteger) edges_e =
1464     myShapesOperations->GetShapesOnBoxIDs(box_e, aShape, TopAbs_EDGE, GEOMAlgo_ST_IN);
1465   box_e->GetLastFunction()->SetDescription("");
1466
1467   if (edges_e.IsNull() || edges_e->Length() == 0) {
1468     SetErrorCode("External edges not found");
1469     return NULL;
1470   }
1471   int nbEdgesInChamfer = 0;
1472   std::list<int> theEdges;
1473   for (int i=1; i<=edges_e->Length();i++) {
1474     int edgeID = edges_e->Value(i);
1475     TopoDS_Shape theEdge = anEdgesIndices.FindKey(edgeID);
1476     TopExp_Explorer Ex(theEdge,TopAbs_VERTEX);
1477     int iv=0;
1478     while (Ex.More()) {
1479       iv ++;
1480       gp_Pnt aPt = BRep_Tool::Pnt(TopoDS::Vertex(Ex.Current()));
1481       if (Abs(aPt.Z() - (theR1+theW1)) <= Precision::Confusion()) {
1482         nbEdgesInChamfer ++;
1483         theEdges.push_back(edgeID);
1484       }
1485       Ex.Next();
1486     }
1487     if (theHexMesh && nbEdgesInChamfer == 1)
1488       break;
1489   }
1490   Handle(GEOM_Object) aChamfer;
1491   try {
1492     aChamfer = myLocalOperations->MakeChamferEdges(aShape, theW, theH, theEdges);
1493   }
1494   catch (Standard_Failure) {
1495     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1496     SetErrorCode(aFail->GetMessageString());
1497     return NULL;
1498   }
1499   if (aChamfer.IsNull()) {
1500     SetErrorCode("Chamfer can not be computed on the given shape with the given parameters");
1501     return NULL;
1502   }
1503   aChamfer->GetLastFunction()->SetDescription("");
1504
1505   TopoDS_Shape aChamferShape = aChamfer->GetValue();
1506   aFunction->SetValue(aChamferShape);
1507   // END of chamfer
1508
1509   //   bool doMesh = false;
1510   if (theHexMesh) {
1511     //        doMesh = true;
1512     if (!MakePipeTShapePartition(aShape, theR1, theW1, theL1, theR2, theW2, theL2, theH, theW, 0, false)) {
1513       MESSAGE("PipeTShape partition failed");
1514       //            doMesh = false;
1515       return NULL;
1516     }
1517     if (!MakePipeTShapeMirrorAndGlue(aShape, theR1, theW1, theL1, theR2, theW2, theL2)) {
1518       MESSAGE("PipeTShape mirrors and glue failed");
1519       //          doMesh = false;
1520       return NULL;
1521     }
1522   }
1523
1524   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1525   aSeq->Append(aShape);
1526
1527   //    if (doMesh) {
1528   if (theHexMesh) {
1529     //
1530     //         Get the groups: BEGIN
1531     //
1532     //if (!MakeGroups(aShape, TSHAPE_CHAMFER, theR1, theW1, theL1, theR2, theW2, theL2, aSeq, gp_Trsf())) {
1533     //  //Make a Python command
1534     //  GEOM::TPythonDump(aFunction)
1535     //    << "[" << aShape << "] = geompy.MakePipeTShapeChamfer(" << theR1 << ", " << theW1
1536     //    << ", " << theL1 << ", " << theR2 << ", " << theW2 << ", " << theL2 << ", " << theH << ", " << theW
1537     //    << ", " << theHexMesh << ")";
1538     //}
1539     //else {
1540     try {
1541       if (!MakeGroups(aShape, TSHAPE_CHAMFER, theR1, theW1, theL1, theR2, theW2, theL2, aSeq, gp_Trsf()))
1542         return NULL;
1543     }
1544     catch (Standard_Failure) {
1545       Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1546       SetErrorCode(aFail->GetMessageString());
1547       return NULL;
1548     }
1549
1550     TCollection_AsciiString aListRes, anEntry;
1551     // Iterate over the sequence aSeq
1552     Standard_Integer aNbGroups = aSeq->Length();
1553     Standard_Integer i = 2;
1554     for (; i <= aNbGroups; i++) {
1555       Handle(Standard_Transient) anItem = aSeq->Value(i);
1556       if (anItem.IsNull()) continue;
1557       Handle(GEOM_Object) aGroup = Handle(GEOM_Object)::DownCast(anItem);
1558       if (aGroup.IsNull()) continue;
1559       //Make a Python command
1560       TDF_Tool::Entry(aGroup->GetEntry(), anEntry);
1561       aListRes += anEntry + ", ";
1562     }
1563
1564     aListRes.Trunc(aListRes.Length() - 2);
1565
1566     //Make a Python command
1567     GEOM::TPythonDump(aFunction)
1568       << "[" << aShape << ", " << aListRes.ToCString()
1569       << "] = geompy.MakePipeTShapeChamfer(" << theR1 << ", " << theW1 << ", " << theL1 << ", " << theR2
1570       << ", " << theW2 << ", " << theL2 << ", " << theH << ", " << theW << ", " << theHexMesh << ")";
1571     //}
1572   }
1573   //
1574   //     Get the groups: END
1575   //
1576   else {
1577     //Make a Python command
1578     GEOM::TPythonDump(aFunction)
1579       << "[" << aShape << "] = geompy.MakePipeTShapeChamfer(" << theR1 << ", " << theW1
1580       << ", " << theL1 << ", " << theR2 << ", " << theW2 << ", " << theL2 << ", " << theH << ", " << theW
1581       << ", " << theHexMesh << ")";
1582   }
1583
1584   SetErrorCode(OK);
1585
1586   return aSeq;
1587 }
1588
1589 //=============================================================================
1590 /*!
1591  *  MakePipeTShapeChamferWithPosition
1592  *  Create a T-shape object with specified caracteristics for the main and
1593  *  the incident pipes (radius, width, half-length). A chamfer is created
1594  *  on the junction of the pipes.
1595  *  The extremities of the main pipe are located on junctions points P1 and P2.
1596  *  The extremity of the incident pipe is located on junction point P3.
1597  *  \param theR1 Internal radius of main pipe
1598  *  \param theW1 Width of main pipe
1599  *  \param theL1 Half-length of main pipe
1600  *  \param theR2 Internal radius of incident pipe (R2 < R1)
1601  *  \param theW2 Width of incident pipe (R2+W2 < R1+W1)
1602  *  \param theL2 Half-length of incident pipe
1603  *  \param theH Height of chamfer.
1604  *  \param theW Width of chamfer.
1605  *  \param theHexMesh Boolean indicating if shape is prepared for hex mesh
1606  *  \param theP1 1st junction point of main pipe
1607  *  \param theP2 2nd junction point of main pipe
1608  *  \param theP3 Junction point of incident pipe
1609  *  \return List of GEOM_Objects, containing the created shape and propagation groups.
1610  */
1611 //=============================================================================
1612 Handle(TColStd_HSequenceOfTransient)
1613 GEOMImpl_IAdvancedOperations::MakePipeTShapeChamferWithPosition(double theR1, double theW1, double theL1,
1614                                                                 double theR2, double theW2, double theL2,
1615                                                                 double theH, double theW,
1616                                                                 bool theHexMesh,
1617                                                                 Handle(GEOM_Object) theP1,
1618                                                                 Handle(GEOM_Object) theP2,
1619                                                                 Handle(GEOM_Object) theP3)
1620 {
1621   SetErrorCode(KO);
1622   //Add a new object
1623   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_TSHAPE);
1624   //Add a new shape function with parameters
1625   Handle(GEOM_Function) aFunction = aShape->AddFunction(GEOMImpl_PipeTShapeDriver::GetID(), TSHAPE_CHAMFER);
1626   if (aFunction.IsNull()) return NULL;
1627
1628   //Check if the function is set correctly
1629   if (aFunction->GetDriverGUID() != GEOMImpl_PipeTShapeDriver::GetID()) return NULL;
1630
1631   // Check new position
1632   if (!CheckCompatiblePosition(theL1, theL2, theP1, theP2, theP3, 0.01)) {
1633     return NULL;
1634   }
1635
1636   GEOMImpl_IPipeTShape aData(aFunction);
1637
1638   aData.SetR1(theR1);
1639   aData.SetW1(theW1);
1640   aData.SetL1(theL1);
1641   aData.SetR2(theR2);
1642   aData.SetW2(theW2);
1643   aData.SetL2(theL2);
1644   aData.SetH(theH);
1645   aData.SetW(theW);
1646   aData.SetHexMesh(theHexMesh);
1647
1648   //Compute the resulting value
1649   try {
1650 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1651     OCC_CATCH_SIGNALS;
1652 #endif
1653     if (!GetSolver()->ComputeFunction(aFunction)) {
1654       SetErrorCode("TShape driver failed");
1655       return NULL;
1656     }
1657   } catch (Standard_Failure) {
1658     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1659     SetErrorCode(aFail->GetMessageString());
1660     return NULL;
1661   }
1662
1663   // BEGIN of chamfer
1664   TopoDS_Shape aShapeShape = aShape->GetValue();
1665   TopTools_IndexedMapOfShape anEdgesIndices;
1666   TopExp::MapShapes(aShapeShape, anEdgesIndices);
1667   // Common edges on external cylinders
1668   Handle(GEOM_Object) box_e;
1669   if (theHexMesh) {
1670     box_e = my3DPrimOperations->MakeBoxDXDYDZ(theR2+theW2, theR2+theW2, theR1+theW1);
1671   }
1672   else {
1673     box_e = my3DPrimOperations->MakeBoxDXDYDZ(2*(theR2+theW2), 2*(theR2+theW2), theR1+theW1);
1674   }
1675   box_e->GetLastFunction()->SetDescription("");
1676   box_e = myTransformOperations->TranslateDXDYDZ(box_e, -(theR2+theW2), -(theR2+theW2), 0);
1677   box_e->GetLastFunction()->SetDescription("");
1678
1679   Handle(TColStd_HSequenceOfInteger) edges_e =
1680     myShapesOperations->GetShapesOnBoxIDs(box_e, aShape, TopAbs_EDGE, GEOMAlgo_ST_IN);
1681   box_e->GetLastFunction()->SetDescription("");
1682
1683   if (edges_e.IsNull() || edges_e->Length() == 0) {
1684     SetErrorCode("External edges not found");
1685     return NULL;
1686   }
1687   int nbEdgesInChamfer = 0;
1688   std::list<int> theEdges;
1689   for (int i=1; i<=edges_e->Length();i++) {
1690     int edgeID = edges_e->Value(i);
1691     TopoDS_Shape theEdge = anEdgesIndices.FindKey(edgeID);
1692     TopExp_Explorer Ex(theEdge,TopAbs_VERTEX);
1693     while (Ex.More()) {
1694       gp_Pnt aPt = BRep_Tool::Pnt(TopoDS::Vertex(Ex.Current()));
1695       if (Abs(aPt.Z() - (theR1+theW1)) <= Precision::Confusion()) {
1696         nbEdgesInChamfer ++;
1697         theEdges.push_back(edgeID);
1698       }
1699       Ex.Next();
1700     }
1701     if (theHexMesh && nbEdgesInChamfer == 1)
1702       break;
1703   }
1704   Handle(GEOM_Object) aChamfer;
1705   try {
1706     aChamfer = myLocalOperations->MakeChamferEdges(aShape, theW, theH, theEdges);
1707   }
1708   catch (Standard_Failure) {
1709     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1710     SetErrorCode(aFail->GetMessageString());
1711     return NULL;
1712   }
1713   if (aChamfer.IsNull()) {
1714     SetErrorCode("Chamfer can not be computed on the given shape with the given parameters");
1715     return NULL;
1716   }
1717   aChamfer->GetLastFunction()->SetDescription("");
1718
1719   TopoDS_Shape aChamferShape = aChamfer->GetValue();
1720   aFunction->SetValue(aChamferShape);
1721   // END of chamfer
1722
1723   if (theHexMesh) {
1724     if (!MakePipeTShapePartition(aShape, theR1, theW1, theL1, theR2, theW2, theL2, theH, theW, 0, false))
1725       return NULL;
1726     if (!MakePipeTShapeMirrorAndGlue(aShape, theR1, theW1, theL1, theR2, theW2, theL2))
1727       return NULL;
1728   }
1729
1730   TopoDS_Shape Te = aShape->GetValue();
1731
1732   // Set Position
1733   gp_Trsf aTrsf = GetPositionTrsf(theL1, theL2, theP1, theP2, theP3);
1734   BRepBuilderAPI_Transform aTransformation(Te, aTrsf, Standard_False);
1735   TopoDS_Shape aTrsf_Shape = aTransformation.Shape();
1736   aFunction->SetValue(aTrsf_Shape);
1737   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1738   aSeq->Append(aShape);
1739   if (theHexMesh) {
1740     /*
1741      * Get the groups: BEGIN
1742      */
1743     try {
1744       if (!MakeGroups(aShape, TSHAPE_CHAMFER, theR1, theW1, theL1, theR2, theW2, theL2, aSeq, aTrsf))
1745         return NULL;
1746     }
1747     catch (Standard_Failure) {
1748       Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1749       SetErrorCode(aFail->GetMessageString());
1750       return NULL;
1751     }
1752
1753     TCollection_AsciiString aListRes, anEntry;
1754     // Iterate over the sequence aSeq
1755     Standard_Integer aNbGroups = aSeq->Length();
1756     Standard_Integer i = 2;
1757     for (; i <= aNbGroups; i++) {
1758       Handle(Standard_Transient) anItem = aSeq->Value(i);
1759       if (anItem.IsNull()) continue;
1760       Handle(GEOM_Object) aGroup = Handle(GEOM_Object)::DownCast(anItem);
1761       if (aGroup.IsNull()) continue;
1762       //Make a Python command
1763       TDF_Tool::Entry(aGroup->GetEntry(), anEntry);
1764       aListRes += anEntry + ", ";
1765     }
1766
1767     aListRes.Trunc(aListRes.Length() - 2);
1768
1769     //Make a Python command
1770     GEOM::TPythonDump(aFunction)
1771       << "[" << aShape << ", " << aListRes.ToCString()
1772       << "] = geompy.MakePipeTShapeChamfer(" << theR1 << ", " << theW1 << ", " << theL1 << ", " << theR2
1773       << ", " << theW2 << ", " << theL2 << ", " << theH << ", " << theW << ", " << theHexMesh << ", "
1774       << theP1 << ", " << theP2 << ", " << theP3 << ")";
1775   }
1776   /*
1777    * Get the groups: END
1778    */
1779   else {
1780     //Make a Python command
1781     GEOM::TPythonDump(aFunction)
1782       << "[" << aShape << "] = geompy.MakePipeTShapeChamfer(" << theR1 << ", " << theW1
1783       << ", " << theL1 << ", " << theR2 << ", " << theW2 << ", " << theL2 << ", " << theH << ", " << theW
1784       << ", " << theHexMesh << ", " << theP1 << ", " << theP2 << ", " << theP3 << ")";
1785   }
1786
1787   SetErrorCode(OK);
1788
1789   return aSeq;
1790 }
1791
1792 //=============================================================================
1793 /*!
1794  *  MakePipeTShapeFillet
1795  *  Create a T-shape object with specified caracteristics for the main and
1796  *  the incident pipes (radius, width, half-length). A fillet is created
1797  *  on the junction of the pipes.
1798  *  Center of the shape is (0,0,0). The main plane of the T-shape is XOY.
1799  *  \param theR1 Internal radius of main pipe
1800  *  \param theW1 Width of main pipe
1801  *  \param theL1 Half-length of main pipe
1802  *  \param theR2 Internal radius of incident pipe (R2 < R1)
1803  *  \param theW2 Width of incident pipe (R2+W2 < R1+W1)
1804  *  \param theL2 Half-length of incident pipe
1805  *  \param theRF Radius of curvature of fillet.
1806  *  \param theHexMesh Boolean indicating if shape is prepared for hex mesh
1807  *  \return List of GEOM_Objects, containing the created shape and propagation groups.
1808  */
1809 //=============================================================================
1810 Handle(TColStd_HSequenceOfTransient)
1811 GEOMImpl_IAdvancedOperations::MakePipeTShapeFillet(double theR1, double theW1, double theL1,
1812                                                    double theR2, double theW2, double theL2,
1813                                                    double theRF, bool theHexMesh)
1814 {
1815   SetErrorCode(KO);
1816   //Add a new object
1817   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_TSHAPE);
1818   //Add a new shape function with parameters
1819   Handle(GEOM_Function) aFunction = aShape->AddFunction(GEOMImpl_PipeTShapeDriver::GetID(), TSHAPE_FILLET);
1820   if (aFunction.IsNull()) return NULL;
1821
1822   //Check if the function is set correctly
1823   if (aFunction->GetDriverGUID() != GEOMImpl_PipeTShapeDriver::GetID()) return NULL;
1824
1825   GEOMImpl_IPipeTShape aData(aFunction);
1826
1827   aData.SetR1(theR1);
1828   aData.SetW1(theW1);
1829   aData.SetL1(theL1);
1830   aData.SetR2(theR2);
1831   aData.SetW2(theW2);
1832   aData.SetL2(theL2);
1833   aData.SetRF(theRF);
1834   aData.SetHexMesh(theHexMesh);
1835
1836   //Compute the resulting value
1837   try {
1838 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1839     OCC_CATCH_SIGNALS;
1840 #endif
1841     if (!GetSolver()->ComputeFunction(aFunction)) {
1842       SetErrorCode("TShape driver failed");
1843       return NULL;
1844     }
1845   } catch (Standard_Failure) {
1846     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1847     SetErrorCode(aFail->GetMessageString());
1848     return NULL;
1849   }
1850
1851   // BEGIN of fillet
1852   TopoDS_Shape aShapeShape = aShape->GetValue();
1853   TopTools_IndexedMapOfShape anEdgesIndices;
1854   TopExp::MapShapes(aShapeShape, anEdgesIndices);
1855   // Common edges on external cylinders
1856   Handle(GEOM_Object) box_e;
1857   if (theHexMesh) {
1858     box_e = my3DPrimOperations->MakeBoxDXDYDZ(theR2+theW2, theR2+theW2, theR1+theW1);
1859   }
1860   else {
1861     box_e = my3DPrimOperations->MakeBoxDXDYDZ(2*(theR2+theW2), 2*(theR2+theW2), theR1+theW1);
1862   }
1863   box_e->GetLastFunction()->SetDescription("");
1864   box_e = myTransformOperations->TranslateDXDYDZ(box_e, -(theR2+theW2), -(theR2+theW2), 0);
1865   box_e->GetLastFunction()->SetDescription("");
1866
1867   Handle(TColStd_HSequenceOfInteger) edges_e =
1868     myShapesOperations->GetShapesOnBoxIDs(box_e, aShape, TopAbs_EDGE, GEOMAlgo_ST_IN);
1869   box_e->GetLastFunction()->SetDescription("");
1870
1871   if (edges_e.IsNull() || edges_e->Length() == 0) {
1872     SetErrorCode("External edges not found");
1873     return NULL;
1874   }
1875   int nbEdgesInFillet = 0;
1876   std::list<int> theEdges;
1877   for (int i=1; i<=edges_e->Length();i++) {
1878     int edgeID = edges_e->Value(i);
1879     TopoDS_Shape theEdge = anEdgesIndices.FindKey(edgeID);
1880     TopExp_Explorer Ex(theEdge,TopAbs_VERTEX);
1881     while (Ex.More()) {
1882       gp_Pnt aPt = BRep_Tool::Pnt(TopoDS::Vertex(Ex.Current()));
1883       if (Abs(aPt.Z() - (theR1+theW1)) <= Precision::Confusion()) {
1884         nbEdgesInFillet ++;
1885         theEdges.push_back(edgeID);
1886       }
1887       Ex.Next();
1888     }
1889     if (theHexMesh && nbEdgesInFillet == 1)
1890       break;
1891   }
1892
1893   Handle(GEOM_Object) aFillet;
1894   try {
1895     aFillet = myLocalOperations->MakeFilletEdges(aShape, theRF, theEdges);
1896   }
1897   catch (Standard_Failure) {
1898     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1899     SetErrorCode(aFail->GetMessageString());
1900     return NULL;
1901   }
1902   if (aFillet.IsNull()) {
1903     //SetErrorCode("Fillet can not be computed on the given shape with the given parameters");
1904     SetErrorCode(myLocalOperations->GetErrorCode());
1905     return NULL;
1906   }
1907   aFillet->GetLastFunction()->SetDescription("");
1908
1909   TopoDS_Shape aFilletShape = aFillet->GetValue();
1910   aFunction->SetValue(aFilletShape);
1911   // END of fillet
1912
1913   // BEGIN: Limit tolerances (debug)
1914   Handle(GEOM_Object) aCorr1 = myHealingOperations->LimitTolerance(aShape, 1e-07);
1915   TopoDS_Shape aCorr1Shape = aCorr1->GetValue();
1916   aShape->GetLastFunction()->SetValue(aCorr1Shape);
1917   aCorr1->GetLastFunction()->SetDescription("");
1918   // END: Limit tolerances (debug)
1919
1920   if (theHexMesh) {
1921     if (!MakePipeTShapePartition(aShape, theR1, theW1, theL1, theR2, theW2, theL2, 0, 0, theRF, false))
1922       return NULL;
1923     if (!MakePipeTShapeMirrorAndGlue(aShape, theR1, theW1, theL1, theR2, theW2, theL2))
1924       return NULL;
1925   }
1926
1927   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1928   aSeq->Append(aShape);
1929   if (theHexMesh) {
1930     /*
1931      * Get the groups: BEGIN
1932      */
1933     try {
1934       if (!MakeGroups(aShape, TSHAPE_FILLET, theR1, theW1, theL1, theR2, theW2, theL2, aSeq, gp_Trsf()))
1935         return NULL;
1936     }
1937     catch (Standard_Failure) {
1938       Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1939       SetErrorCode(aFail->GetMessageString());
1940       return NULL;
1941     }
1942
1943     TCollection_AsciiString aListRes, anEntry;
1944     // Iterate over the sequence aSeq
1945     Standard_Integer aNbGroups = aSeq->Length();
1946     Standard_Integer i = 2;
1947     for (; i <= aNbGroups; i++) {
1948       Handle(Standard_Transient) anItem = aSeq->Value(i);
1949       if (anItem.IsNull()) continue;
1950       Handle(GEOM_Object) aGroup = Handle(GEOM_Object)::DownCast(anItem);
1951       if (aGroup.IsNull()) continue;
1952       //Make a Python command
1953       TDF_Tool::Entry(aGroup->GetEntry(), anEntry);
1954       aListRes += anEntry + ", ";
1955     }
1956
1957     aListRes.Trunc(aListRes.Length() - 2);
1958
1959     //Make a Python command
1960     GEOM::TPythonDump(aFunction)
1961       << "[" << aShape << ", " << aListRes.ToCString()
1962       << "] = geompy.MakePipeTShapeFillet(" << theR1 << ", " << theW1 << ", " << theL1 << ", " << theR2
1963       << ", " << theW2 << ", " << theL2 << ", " << theRF << ", " << theHexMesh << ")";
1964   }
1965   /*
1966    * Get the groups: END
1967    */
1968   else {
1969     //Make a Python command
1970     GEOM::TPythonDump(aFunction)
1971       << "[" << aShape << "] = geompy.MakePipeTShapeFillet(" << theR1 << ", " << theW1
1972       << ", " << theL1 << ", " << theR2 << ", " << theW2 << ", " << theL2 << ", " << theRF << ", "
1973       << theHexMesh << ")";
1974   }
1975
1976   SetErrorCode(OK);
1977
1978   return aSeq;
1979 }
1980
1981 //=============================================================================
1982 /*!
1983  *  MakePipeTShapeFilletWithPosition
1984  *  Create a T-shape object with specified caracteristics for the main and
1985  *  the incident pipes (radius, width, half-length). A fillet is created
1986  *  on the junction of the pipes.
1987  *  The extremities of the main pipe are located on junctions points P1 and P2.
1988  *  The extremity of the incident pipe is located on junction point P3.
1989  *  \param theR1 Internal radius of main pipe
1990  *  \param theW1 Width of main pipe
1991  *  \param theL1 Half-length of main pipe
1992  *  \param theR2 Internal radius of incident pipe (R2 < R1)
1993  *  \param theW2 Width of incident pipe (R2+W2 < R1+W1)
1994  *  \param theL2 Half-length of incident pipe
1995  *  \param theRF Radius of curvature of fillet
1996  *  \param theHexMesh Boolean indicating if shape is prepared for hex mesh
1997  *  \param theP1 1st junction point of main pipe
1998  *  \param theP2 2nd junction point of main pipe
1999  *  \param theP3 Junction point of incident pipe
2000  *  \return List of GEOM_Objects, containing the created shape and propagation groups.
2001  */
2002 //=============================================================================
2003 Handle(TColStd_HSequenceOfTransient)
2004 GEOMImpl_IAdvancedOperations::MakePipeTShapeFilletWithPosition(double theR1, double theW1, double theL1,
2005                                                                double theR2, double theW2, double theL2,
2006                                                                double theRF, bool theHexMesh,
2007                                                                Handle(GEOM_Object) theP1,
2008                                                                Handle(GEOM_Object) theP2,
2009                                                                Handle(GEOM_Object) theP3)
2010 {
2011   SetErrorCode(KO);
2012   //Add a new object
2013   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_TSHAPE);
2014   //Add a new shape function with parameters
2015   Handle(GEOM_Function) aFunction = aShape->AddFunction(GEOMImpl_PipeTShapeDriver::GetID(), TSHAPE_FILLET);
2016   if (aFunction.IsNull()) return NULL;
2017
2018   //Check if the function is set correctly
2019   if (aFunction->GetDriverGUID() != GEOMImpl_PipeTShapeDriver::GetID()) return NULL;
2020
2021   // Check new position
2022   if (!CheckCompatiblePosition(theL1, theL2, theP1, theP2, theP3, 0.01)) {
2023     return NULL;
2024   }
2025
2026   GEOMImpl_IPipeTShape aData(aFunction);
2027
2028   aData.SetR1(theR1);
2029   aData.SetW1(theW1);
2030   aData.SetL1(theL1);
2031   aData.SetR2(theR2);
2032   aData.SetW2(theW2);
2033   aData.SetL2(theL2);
2034   aData.SetRF(theRF);
2035   aData.SetHexMesh(theHexMesh);
2036
2037   //Compute the resulting value
2038   try {
2039 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
2040     OCC_CATCH_SIGNALS;
2041 #endif
2042     if (!GetSolver()->ComputeFunction(aFunction)) {
2043       SetErrorCode("TShape driver failed");
2044       return NULL;
2045     }
2046   } catch (Standard_Failure) {
2047     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2048     SetErrorCode(aFail->GetMessageString());
2049     return NULL;
2050   }
2051
2052   // BEGIN of fillet
2053   TopoDS_Shape aShapeShape = aShape->GetValue();
2054   TopTools_IndexedMapOfShape anEdgesIndices;
2055   TopExp::MapShapes(aShapeShape, anEdgesIndices);
2056   // Common edges on external cylinders
2057   Handle(GEOM_Object) box_e;
2058   if (theHexMesh) {
2059     box_e = my3DPrimOperations->MakeBoxDXDYDZ(theR2+theW2, theR2+theW2, theR1+theW1);
2060   }
2061   else {
2062     box_e = my3DPrimOperations->MakeBoxDXDYDZ(2*(theR2+theW2), 2*(theR2+theW2), theR1+theW1);
2063   }
2064   box_e->GetLastFunction()->SetDescription("");
2065   box_e = myTransformOperations->TranslateDXDYDZ(box_e, -(theR2+theW2), -(theR2+theW2), 0);
2066   box_e->GetLastFunction()->SetDescription("");
2067
2068   Handle(TColStd_HSequenceOfInteger) edges_e =
2069     myShapesOperations->GetShapesOnBoxIDs(box_e, aShape, TopAbs_EDGE, GEOMAlgo_ST_IN);
2070   box_e->GetLastFunction()->SetDescription("");
2071
2072   if (edges_e.IsNull() || edges_e->Length() == 0) {
2073     SetErrorCode("External edges not found");
2074     return NULL;
2075   }
2076   int nbEdgesInFillet = 0;
2077   std::list<int> theEdges;
2078   for (int i=1; i<=edges_e->Length();i++) {
2079     int edgeID = edges_e->Value(i);
2080     TopoDS_Shape theEdge = anEdgesIndices.FindKey(edgeID);
2081     TopExp_Explorer Ex(theEdge,TopAbs_VERTEX);
2082     while (Ex.More()) {
2083       gp_Pnt aPt = BRep_Tool::Pnt(TopoDS::Vertex(Ex.Current()));
2084       if (Abs(aPt.Z() - (theR1+theW1)) <= Precision::Confusion()) {
2085         nbEdgesInFillet ++;
2086         theEdges.push_back(edgeID);
2087       }
2088       Ex.Next();
2089     }
2090     if (theHexMesh && nbEdgesInFillet == 1)
2091       break;
2092   }
2093
2094   Handle(GEOM_Object) aFillet;
2095   try {
2096     aFillet = myLocalOperations->MakeFilletEdges(aShape, theRF, theEdges);
2097   }
2098   catch (Standard_Failure) {
2099     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2100     SetErrorCode(aFail->GetMessageString());
2101     return NULL;
2102   }
2103   if (aFillet.IsNull()) {
2104     SetErrorCode("Fillet can not be computed on the given shape with the given parameters");
2105     return NULL;
2106   }
2107   aFillet->GetLastFunction()->SetDescription("");
2108
2109   TopoDS_Shape aFilletShape = aFillet->GetValue();
2110   aFunction->SetValue(aFilletShape);
2111   // END of fillet
2112
2113   // BEGIN: Limit tolerances (debug)
2114   Handle(GEOM_Object) aCorr1 = myHealingOperations->LimitTolerance(aShape, 1e-07);
2115   TopoDS_Shape aCorr1Shape = aCorr1->GetValue();
2116   aShape->GetLastFunction()->SetValue(aCorr1Shape);
2117   aCorr1->GetLastFunction()->SetDescription("");
2118   // END: Limit tolerances (debug)
2119
2120   if (theHexMesh) {
2121     if (!MakePipeTShapePartition(aShape, theR1, theW1, theL1, theR2, theW2, theL2, 0, 0, theRF, false))
2122       return NULL;
2123     if (!MakePipeTShapeMirrorAndGlue(aShape, theR1, theW1, theL1, theR2, theW2, theL2))
2124       return NULL;
2125   }
2126
2127   TopoDS_Shape Te = aShape->GetValue();
2128
2129   // Set Position
2130   gp_Trsf aTrsf = GetPositionTrsf(theL1, theL2, theP1, theP2, theP3);
2131   BRepBuilderAPI_Transform aTransformation(Te, aTrsf, Standard_False);
2132   TopoDS_Shape aTrsf_Shape = aTransformation.Shape();
2133   aFunction->SetValue(aTrsf_Shape);
2134   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
2135   aSeq->Append(aShape);
2136   if (theHexMesh) {
2137     /*
2138      * Get the groups: BEGIN
2139      */
2140     try {
2141       if (!MakeGroups(aShape, TSHAPE_FILLET, theR1, theW1, theL1, theR2, theW2, theL2, aSeq, aTrsf))
2142         return NULL;
2143     }
2144     catch (Standard_Failure) {
2145       Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2146       SetErrorCode(aFail->GetMessageString());
2147       return NULL;
2148     }
2149
2150     TCollection_AsciiString aListRes, anEntry;
2151     // Iterate over the sequence aSeq
2152     Standard_Integer aNbGroups = aSeq->Length();
2153     Standard_Integer i = 2;
2154     for (; i <= aNbGroups; i++) {
2155       Handle(Standard_Transient) anItem = aSeq->Value(i);
2156       if (anItem.IsNull()) continue;
2157       Handle(GEOM_Object) aGroup = Handle(GEOM_Object)::DownCast(anItem);
2158       if (aGroup.IsNull()) continue;
2159       //Make a Python command
2160       TDF_Tool::Entry(aGroup->GetEntry(), anEntry);
2161       aListRes += anEntry + ", ";
2162     }
2163
2164     aListRes.Trunc(aListRes.Length() - 2);
2165
2166     //Make a Python command
2167     GEOM::TPythonDump(aFunction)
2168       << "[" << aShape << ", " << aListRes.ToCString()
2169       << "] = geompy.MakePipeTShapeFillet(" << theR1 << ", " << theW1 << ", " << theL1 << ", " << theR2
2170       << ", " << theW2 << ", " << theL2 << ", " << theRF << ", " << theHexMesh << ", " << theP1 << ", "
2171       << theP2 << ", " << theP3 << ")";
2172   }
2173   /*
2174    * Get the groups: END
2175    */
2176   else {
2177     //Make a Python command
2178     GEOM::TPythonDump(aFunction)
2179       << "[" << aShape << "] = geompy.MakePipeTShapeFillet(" << theR1 << ", " << theW1
2180       << ", " << theL1 << ", " << theR2 << ", " << theW2 << ", " << theL2 << ", " << theRF << ", "
2181       << theHexMesh << ", " << theP1 << ", " << theP2 << ", " << theP3 << ")";
2182   }
2183
2184   SetErrorCode(OK);
2185
2186   return aSeq;
2187 }
2188
2189 /*@@ insert new functions before this line @@ do not remove this line @@ do not remove this line @@*/