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