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