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