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