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