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