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 the
1240  *  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  *  Create a T-shape object with specified caracteristics for the main and the
1373  *  incident pipes (radius, width, half-length).
1374  *  Center of the shape is (0,0,0). The main plane of the T-shape is XOY.
1375  *  \param theR1 Internal radius of main pipe
1376  *  \param theW1 Width of main pipe
1377  *  \param theL1 Half-length of main pipe
1378  *  \param theR2 Internal radius of incident pipe (R2 < R1)
1379  *  \param theW2 Width of incident pipe (R2+W2 < R1+W1)
1380  *  \param theL2 Half-length of incident pipe
1381  *  \param theHexMesh Boolean indicating if shape is prepared for hex mesh
1382  *  \param theP1 1st junction point of main pipe
1383  *  \param theP2 2nd junction point of main pipe
1384  *  \param theP3 Junction point of incident pipe
1385  *  \return List of GEOM_Objects, containing the created shape and propagation groups..
1386  */
1387 //=============================================================================
1388 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IAdvancedOperations::MakePipeTShapeWithPosition(double theR1,
1389         double theW1, double theL1, double theR2, double theW2, double theL2, bool theHexMesh,
1390         Handle(GEOM_Object) theP1, Handle(GEOM_Object) theP2, Handle(GEOM_Object) theP3) {
1391     SetErrorCode(KO);
1392     //Add a new object
1393     Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_TSHAPE);
1394     /////////////////
1395     // TSHAPE CODE
1396     /////////////////
1397     //Add a new shape function with parameters
1398     Handle(GEOM_Function) aFunction = aShape->AddFunction(GEOMImpl_PipeTShapeDriver::GetID(), TSHAPE_BASIC);
1399     if (aFunction.IsNull()) return NULL;
1400
1401     //Check if the function is set correctly
1402     if (aFunction->GetDriverGUID() != GEOMImpl_PipeTShapeDriver::GetID()) return NULL;
1403
1404     // Check new position
1405     if (!CheckCompatiblePosition(theL1, theL2, theP1, theP2, theP3, 0.01)) {
1406         return NULL;
1407     }
1408
1409     GEOMImpl_IPipeTShape aData(aFunction);
1410
1411     aData.SetR1(theR1);
1412     aData.SetW1(theW1);
1413     aData.SetL1(theL1);
1414     aData.SetR2(theR2);
1415     aData.SetW2(theW2);
1416     aData.SetL2(theL2);
1417     aData.SetHexMesh(theHexMesh);
1418
1419     //Compute the resulting value
1420     try {
1421 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1422         OCC_CATCH_SIGNALS;
1423 #endif
1424         if (!GetSolver()->ComputeFunction(aFunction)) {
1425             SetErrorCode("TShape driver failed");
1426             return NULL;
1427         }
1428     } catch (Standard_Failure) {
1429         Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1430         SetErrorCode(aFail->GetMessageString());
1431         return NULL;
1432     }
1433
1434     GEOMImpl_IBasicOperations* aBasicOperations = new GEOMImpl_IBasicOperations(GetEngine(), GetDocID());
1435     GEOMImpl_IBooleanOperations* aBooleanOperations = new GEOMImpl_IBooleanOperations(GetEngine(), GetDocID());
1436     GEOMImpl_IShapesOperations* aShapesOperations = new GEOMImpl_IShapesOperations(GetEngine(), GetDocID());
1437     GEOMImpl_ITransformOperations* aTransformOperations = new GEOMImpl_ITransformOperations(GetEngine(), GetDocID());
1438     GEOMImpl_IBlocksOperations* aBlocksOperations = new GEOMImpl_IBlocksOperations(GetEngine(), GetDocID());
1439     GEOMImpl_I3DPrimOperations* a3DPrimOperations = new GEOMImpl_I3DPrimOperations(GetEngine(), GetDocID());
1440     std::vector<GEOM_IOperations*> theOperations;
1441     theOperations.push_back(a3DPrimOperations);
1442     theOperations.push_back(aBasicOperations);
1443     theOperations.push_back(aBlocksOperations);
1444     theOperations.push_back(aBooleanOperations);
1445     theOperations.push_back(aShapesOperations);
1446     theOperations.push_back(aTransformOperations);
1447     
1448     if (theHexMesh) {
1449         std::cerr << "Creating partition" << std::endl;
1450         if (!MakePipeTShapePartition(/*theOperations, */aShape, theR1, theW1, theL1, theR2, theW2, theL2))
1451           return NULL;
1452         std::cerr << "Done" << std::endl;
1453         std::cerr << "Creating mirrors and glue" << std::endl;
1454         if (!MakePipeTShapeMirrorAndGlue(/*theOperations, */aShape, theR1, theW1, theL1, theR2, theW2, theL2))
1455           return NULL;
1456         std::cerr << "Done" << std::endl;
1457     }
1458
1459     TopoDS_Shape Te = aShape->GetValue();
1460
1461     // Set Position
1462     gp_Trsf aTrsf = GetPositionTrsf(theL1, theL2, theP1, theP2, theP3);
1463     BRepBuilderAPI_Transform aTransformation(Te, aTrsf, Standard_False);
1464     TopoDS_Shape aTrsf_Shape = aTransformation.Shape();
1465     aFunction->SetValue(aTrsf_Shape);
1466     Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1467     aSeq->Append(aShape);
1468
1469     if (theHexMesh) {
1470         //
1471         // Get the groups: BEGIN
1472         //
1473         if (!MakeGroups(/*theOperations, */aShape,TSHAPE_BASIC, theR1, theW1, theL1, theR2, theW2, theL2, aSeq, aTrsf)) {
1474 //            SetErrorCode("Make groups failed");
1475             return NULL;
1476         }
1477
1478         TCollection_AsciiString aListRes, anEntry;
1479         // Iterate over the sequence aSeq
1480         Standard_Integer aNbGroups = aSeq->Length();
1481         Standard_Integer i = 2;
1482         for (; i <= aNbGroups; i++) {
1483             Handle(Standard_Transient) anItem = aSeq->Value(i);
1484             if (anItem.IsNull()) continue;
1485             Handle(GEOM_Object) aGroup = Handle(GEOM_Object)::DownCast(anItem);
1486             if (aGroup.IsNull()) continue;
1487             //Make a Python command
1488             TDF_Tool::Entry(aGroup->GetEntry(), anEntry);
1489             aListRes += anEntry + ", ";
1490         }
1491
1492         aListRes.Trunc(aListRes.Length() - 2);
1493
1494         //Make a Python command
1495         GEOM::TPythonDump(aFunction) << "[" << aShape << ", " << aListRes.ToCString() << "] = geompy.MakePipeTShape("
1496                 << theR1 << ", " << theW1 << ", " << theL1 << ", " << theR2 << ", " << theW2 << ", " << theL2 << ", "
1497                 << theHexMesh << ", " << theP1 << ", " << theP2 << ", " << theP3 << ")";
1498     }
1499     //
1500     // Get the groups: END
1501     //
1502
1503     else {
1504         //Make a Python command
1505         GEOM::TPythonDump(aFunction) << "[" << aShape << "] = geompy.MakePipeTShape(" << theR1 << ", " << theW1 << ", "
1506                 << theL1 << ", " << theR2 << ", " << theW2 << ", " << theL2 << ", " << theHexMesh << ", " << theP1
1507                 << ", " << theP2 << ", " << theP3 << ")";
1508     }
1509
1510     SetErrorCode(OK);
1511
1512     return aSeq;
1513 }
1514
1515 //=============================================================================
1516 /*!
1517  *  Create a T-shape object with specified caracteristics for the main and the
1518  *  incident pipes (radius, width, half-length).
1519  *  Center of the shape is (0,0,0). The main plane of the T-shape is XOY.
1520  *  \param theR1 Internal radius of main pipe
1521  *  \param theW1 Width of main pipe
1522  *  \param theL1 Half-length of main pipe
1523  *  \param theR2 Internal radius of incident pipe (R2 < R1)
1524  *  \param theW2 Width of incident pipe (R2+W2 < R1+W1)
1525  *  \param theL2 Half-length of incident pipe
1526  *  \param theH Height of chamfer.
1527  *  \param theW Width of chamfer.
1528  *  \param theHexMesh Boolean indicating if shape is prepared for hex mesh
1529  *  \return List of GEOM_Objects, containing the created shape and propagation groups.
1530  */
1531 //=============================================================================
1532 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IAdvancedOperations::MakePipeTShapeChamfer(double theR1, double theW1,
1533         double theL1, double theR2, double theW2, double theL2, double theH, double theW, bool theHexMesh) {
1534     SetErrorCode(KO);
1535     //Add a new object
1536     Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_TSHAPE);
1537     //Add a new shape function with parameters
1538     Handle(GEOM_Function) aFunction = aShape->AddFunction(GEOMImpl_PipeTShapeDriver::GetID(), TSHAPE_CHAMFER);
1539     if (aFunction.IsNull()) return NULL;
1540
1541     //Check if the function is set correctly
1542     if (aFunction->GetDriverGUID() != GEOMImpl_PipeTShapeDriver::GetID()) return NULL;
1543
1544     GEOMImpl_IPipeTShape aData(aFunction);
1545
1546     aData.SetR1(theR1);
1547     aData.SetW1(theW1);
1548     aData.SetL1(theL1);
1549     aData.SetR2(theR2);
1550     aData.SetW2(theW2);
1551     aData.SetL2(theL2);
1552     aData.SetH(theH);
1553     aData.SetW(theW);
1554     aData.SetHexMesh(theHexMesh);
1555
1556     //Compute the resulting value
1557     try {
1558 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1559         OCC_CATCH_SIGNALS;
1560 #endif
1561         if (!GetSolver()->ComputeFunction(aFunction)) {
1562             SetErrorCode("TShape driver failed");
1563             return NULL;
1564         }
1565     } catch (Standard_Failure) {
1566         Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1567         SetErrorCode(aFail->GetMessageString());
1568         return NULL;
1569     }
1570
1571     GEOMImpl_IBasicOperations* aBasicOperations = new GEOMImpl_IBasicOperations(GetEngine(), GetDocID());
1572     GEOMImpl_IBooleanOperations* aBooleanOperations = new GEOMImpl_IBooleanOperations(GetEngine(), GetDocID());
1573     GEOMImpl_IShapesOperations* aShapesOperations = new GEOMImpl_IShapesOperations(GetEngine(), GetDocID());
1574     GEOMImpl_ITransformOperations* aTransformOperations = new GEOMImpl_ITransformOperations(GetEngine(), GetDocID());
1575     GEOMImpl_IBlocksOperations* aBlocksOperations = new GEOMImpl_IBlocksOperations(GetEngine(), GetDocID());
1576     GEOMImpl_I3DPrimOperations* a3DPrimOperations = new GEOMImpl_I3DPrimOperations(GetEngine(), GetDocID());
1577     GEOMImpl_ILocalOperations* aLocalOperations = new GEOMImpl_ILocalOperations(GetEngine(), GetDocID());
1578     std::vector<GEOM_IOperations*> theOperations;
1579     theOperations.push_back(a3DPrimOperations);
1580     theOperations.push_back(aBasicOperations);
1581     theOperations.push_back(aBlocksOperations);
1582     theOperations.push_back(aBooleanOperations);
1583     theOperations.push_back(aShapesOperations);
1584     theOperations.push_back(aTransformOperations);
1585
1586     // BEGIN of chamfer
1587     TopoDS_Shape aShapeShape = aShape->GetValue();
1588     TopTools_IndexedMapOfShape anEdgesIndices;
1589     TopExp::MapShapes(aShapeShape, anEdgesIndices);
1590     // Common edges on external cylinders
1591     Handle(GEOM_Object) box_e;
1592     if (theHexMesh) {
1593       box_e = a3DPrimOperations->MakeBoxDXDYDZ(theR2+theW2, theR2+theW2, theR1+theW1);
1594     }
1595     else {
1596       box_e = a3DPrimOperations->MakeBoxDXDYDZ(2*(theR2+theW2), 2*(theR2+theW2), theR1+theW1);
1597     }
1598     box_e->GetLastFunction()->SetDescription("");
1599     box_e = aTransformOperations->TranslateDXDYDZ(box_e, -(theR2+theW2), -(theR2+theW2), 0);
1600     box_e->GetLastFunction()->SetDescription("");
1601     
1602     Handle(TColStd_HSequenceOfInteger) edges_e = aShapesOperations->GetShapesOnBoxIDs(box_e, aShape, TopAbs_EDGE, GEOMAlgo_ST_IN);
1603     box_e->GetLastFunction()->SetDescription("");
1604
1605     if (edges_e.IsNull() || edges_e->Length() == 0) {
1606 //        std::cerr << "Internal edges not found" << std::endl;
1607         SetErrorCode("External edges not found");
1608         return false;
1609     }
1610 //    std::cerr << "External edges found" << std::endl;
1611     int nbEdgesInChamfer = 0;
1612     std::list<int> theEdges;
1613     for (int i=1; i<=edges_e->Length();i++) {
1614 //         Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(edges_e->Value(i));
1615 //         anObj->GetLastFunction()->SetDescription("");
1616         int edgeID = edges_e->Value(i);
1617 //         std::cerr << "Edge #" << edgeID << std::endl;
1618         TopoDS_Shape theEdge = anEdgesIndices.FindKey(edgeID);
1619         TopExp_Explorer Ex(theEdge,TopAbs_VERTEX);
1620         int iv=0;
1621         while (Ex.More()) {
1622           iv ++;
1623           gp_Pnt aPt = BRep_Tool::Pnt(TopoDS::Vertex(Ex.Current()));
1624 //           std::cerr << "Vertex #" << iv << ": aPt.Z() - (theR1+theW1) = " << aPt.Z() - (theR1+theW1) << std::endl;
1625           if (Abs(aPt.Z() - (theR1+theW1)) <= Precision::Confusion()) {
1626             nbEdgesInChamfer ++;
1627             theEdges.push_back(edgeID);
1628 //             std::cerr << "Edge #" << edgeID << " added" << std::endl;
1629           }
1630           Ex.Next();
1631         }
1632         if (theHexMesh && nbEdgesInChamfer == 1)
1633           break;
1634     }
1635     Handle(GEOM_Object) aChamfer;
1636     try {
1637       aChamfer = aLocalOperations->MakeChamferEdges(aShape, theW, theH, theEdges);
1638     }
1639     catch (Standard_Failure) {
1640       Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1641       SetErrorCode(aFail->GetMessageString());
1642       return NULL;
1643     }
1644     if (aChamfer.IsNull()) {
1645         SetErrorCode("Chamfer can not be computed on the given shape with the given parameters");
1646         return NULL;
1647     }
1648     aChamfer->GetLastFunction()->SetDescription("");
1649     
1650     TopoDS_Shape aChamferShape = aChamfer->GetValue();
1651     aFunction->SetValue(aChamferShape);
1652     // END of chamfer
1653
1654     bool doMesh = false;
1655     if (theHexMesh) {
1656         doMesh = true;
1657         std::cerr << "Creating partition" << std::endl;
1658         if (!MakePipeTShapePartition(/*theOperations, */aShape, theR1, theW1, theL1, theR2, theW2, theL2, theH, theW, 0, false)) {
1659             std::cerr << "PipeTShape partition failed" << std::endl;
1660             doMesh = false;
1661 //             return NULL;
1662         }
1663         std::cerr << "Done" << std::endl;
1664         std::cerr << "Creating mirrors and glue" << std::endl;
1665         if (!MakePipeTShapeMirrorAndGlue(/*theOperations, */aShape, theR1, theW1, theL1, theR2, theW2, theL2)) {
1666           std::cerr << "PipeTShape mirrors and glue failed" << std::endl;
1667           doMesh = false;
1668 //           return NULL;
1669         }
1670         std::cerr << "Done" << std::endl;
1671     }
1672
1673     Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1674     aSeq->Append(aShape);
1675
1676     if (doMesh) {
1677 //
1678 //         Get the groups: BEGIN
1679 //
1680         if (!MakeGroups(/*theOperations, */aShape, TSHAPE_CHAMFER, theR1, theW1, theL1, theR2, theW2, theL2, aSeq, gp_Trsf())) {
1681             //Make a Python command
1682             GEOM::TPythonDump(aFunction) << "[" << aShape << "] = geompy.MakePipeTShapeChamfer(" << theR1 << ", " << theW1
1683                     << ", " << theL1 << ", " << theR2 << ", " << theW2 << ", " << theL2 << ", " << theH << ", " << theW
1684                     << ", " << theHexMesh << ")";
1685 //            return NULL;
1686         }
1687         else {
1688             TCollection_AsciiString aListRes, anEntry;
1689             // Iterate over the sequence aSeq
1690             Standard_Integer aNbGroups = aSeq->Length();
1691             Standard_Integer i = 2;
1692             for (; i <= aNbGroups; i++) {
1693                 Handle(Standard_Transient) anItem = aSeq->Value(i);
1694                 if (anItem.IsNull()) continue;
1695                 Handle(GEOM_Object) aGroup = Handle(GEOM_Object)::DownCast(anItem);
1696                 if (aGroup.IsNull()) continue;
1697                 //Make a Python command
1698                 TDF_Tool::Entry(aGroup->GetEntry(), anEntry);
1699                 aListRes += anEntry + ", ";
1700             }
1701
1702             aListRes.Trunc(aListRes.Length() - 2);
1703
1704             //Make a Python command
1705             GEOM::TPythonDump(aFunction) << "[" << aShape << ", " << aListRes.ToCString()
1706                     << "] = geompy.MakePipeTShapeChamfer(" << theR1 << ", " << theW1 << ", " << theL1 << ", " << theR2
1707                     << ", " << theW2 << ", " << theL2 << ", " << theH << ", " << theW << ", " << theHexMesh << ")";
1708         }
1709     }
1710 //
1711 //     Get the groups: END
1712 //
1713     else {
1714         //Make a Python command
1715         GEOM::TPythonDump(aFunction) << "[" << aShape << "] = geompy.MakePipeTShapeChamfer(" << theR1 << ", " << theW1
1716                 << ", " << theL1 << ", " << theR2 << ", " << theW2 << ", " << theL2 << ", " << theH << ", " << theW
1717                 << ", " << theHexMesh << ")";
1718     }
1719
1720     SetErrorCode(OK);
1721
1722     return aSeq;
1723 }
1724
1725 //=============================================================================
1726 /*!
1727  *  Create a T-shape object with specified caracteristics for the main and the
1728  *  incident pipes (radius, width, half-length).
1729  *  The T-shape is placed at junction points P1, P2 and P3.
1730  *  \param theR1 Internal radius of main pipe
1731  *  \param theW1 Width of main pipe
1732  *  \param theL1 Half-length of main pipe
1733  *  \param theR2 Internal radius of incident pipe (R2 < R1)
1734  *  \param theW2 Width of incident pipe (R2+W2 < R1+W1)
1735  *  \param theL2 Half-length of incident pipe
1736  *  \param theH Height of chamfer.
1737  *  \param theW Width of chamfer.
1738  *  \param theHexMesh Boolean indicating if shape is prepared for hex mesh
1739  *  \param theP1 1st junction point of main pipe
1740  *  \param theP2 2nd junction point of main pipe
1741  *  \param theP3 Junction point of incident pipe
1742  *  \return List of GEOM_Objects, containing the created shape and propagation groups.
1743  */
1744 //=============================================================================
1745 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IAdvancedOperations::MakePipeTShapeChamferWithPosition(double theR1,
1746         double theW1, double theL1, double theR2, double theW2, double theL2, double theH, double theW,
1747         bool theHexMesh, Handle(GEOM_Object) theP1, Handle(GEOM_Object) theP2, Handle(GEOM_Object) theP3) {
1748     SetErrorCode(KO);
1749     //Add a new object
1750     Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_TSHAPE);
1751     //Add a new shape function with parameters
1752     Handle(GEOM_Function) aFunction = aShape->AddFunction(GEOMImpl_PipeTShapeDriver::GetID(), TSHAPE_CHAMFER);
1753     if (aFunction.IsNull()) return NULL;
1754
1755     //Check if the function is set correctly
1756     if (aFunction->GetDriverGUID() != GEOMImpl_PipeTShapeDriver::GetID()) return NULL;
1757
1758     // Check new position
1759     if (!CheckCompatiblePosition(theL1, theL2, theP1, theP2, theP3, 0.01)) {
1760         return NULL;
1761     }
1762
1763     GEOMImpl_IPipeTShape aData(aFunction);
1764
1765     aData.SetR1(theR1);
1766     aData.SetW1(theW1);
1767     aData.SetL1(theL1);
1768     aData.SetR2(theR2);
1769     aData.SetW2(theW2);
1770     aData.SetL2(theL2);
1771     aData.SetH(theH);
1772     aData.SetW(theW);
1773     aData.SetHexMesh(theHexMesh);
1774
1775     //Compute the resulting value
1776     try {
1777 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1778         OCC_CATCH_SIGNALS;
1779 #endif
1780         if (!GetSolver()->ComputeFunction(aFunction)) {
1781             SetErrorCode("TShape driver failed");
1782             return NULL;
1783         }
1784     } catch (Standard_Failure) {
1785         Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1786         SetErrorCode(aFail->GetMessageString());
1787         return NULL;
1788     }
1789
1790     GEOMImpl_IBasicOperations* aBasicOperations = new GEOMImpl_IBasicOperations(GetEngine(), GetDocID());
1791     GEOMImpl_IBooleanOperations* aBooleanOperations = new GEOMImpl_IBooleanOperations(GetEngine(), GetDocID());
1792     GEOMImpl_IShapesOperations* aShapesOperations = new GEOMImpl_IShapesOperations(GetEngine(), GetDocID());
1793     GEOMImpl_ITransformOperations* aTransformOperations = new GEOMImpl_ITransformOperations(GetEngine(), GetDocID());
1794     GEOMImpl_IBlocksOperations* aBlocksOperations = new GEOMImpl_IBlocksOperations(GetEngine(), GetDocID());
1795     GEOMImpl_I3DPrimOperations* a3DPrimOperations = new GEOMImpl_I3DPrimOperations(GetEngine(), GetDocID());
1796     GEOMImpl_ILocalOperations* aLocalOperations = new GEOMImpl_ILocalOperations(GetEngine(), GetDocID());
1797     std::vector<GEOM_IOperations*> theOperations;
1798     theOperations.push_back(a3DPrimOperations);
1799     theOperations.push_back(aBasicOperations);
1800     theOperations.push_back(aBlocksOperations);
1801     theOperations.push_back(aBooleanOperations);
1802     theOperations.push_back(aShapesOperations);
1803     theOperations.push_back(aTransformOperations);
1804
1805     // BEGIN of chamfer
1806     TopoDS_Shape aShapeShape = aShape->GetValue();
1807     TopTools_IndexedMapOfShape anEdgesIndices;
1808     TopExp::MapShapes(aShapeShape, anEdgesIndices);
1809     // Common edges on external cylinders
1810     Handle(GEOM_Object) box_e;
1811     if (theHexMesh) {
1812       box_e = a3DPrimOperations->MakeBoxDXDYDZ(theR2+theW2, theR2+theW2, theR1+theW1);
1813     }
1814     else {
1815       box_e = a3DPrimOperations->MakeBoxDXDYDZ(2*(theR2+theW2), 2*(theR2+theW2), theR1+theW1);
1816     }
1817     box_e->GetLastFunction()->SetDescription("");
1818     box_e = aTransformOperations->TranslateDXDYDZ(box_e, -(theR2+theW2), -(theR2+theW2), 0);
1819     box_e->GetLastFunction()->SetDescription("");
1820     
1821     Handle(TColStd_HSequenceOfInteger) edges_e = aShapesOperations->GetShapesOnBoxIDs(box_e, aShape, TopAbs_EDGE, GEOMAlgo_ST_IN);
1822     box_e->GetLastFunction()->SetDescription("");
1823
1824     if (edges_e.IsNull() || edges_e->Length() == 0) {
1825 //        std::cerr << "Internal edges not found" << std::endl;
1826         SetErrorCode("External edges not found");
1827         return false;
1828     }
1829 //    std::cerr << "External edges found" << std::endl;
1830     int nbEdgesInChamfer = 0;
1831     std::list<int> theEdges;
1832     for (int i=1; i<=edges_e->Length();i++) {
1833 //         Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(edges_e->Value(i));
1834 //         anObj->GetLastFunction()->SetDescription("");
1835         int edgeID = edges_e->Value(i);
1836         TopoDS_Shape theEdge = anEdgesIndices.FindKey(edgeID);
1837         TopExp_Explorer Ex(theEdge,TopAbs_VERTEX);
1838         while (Ex.More()) {
1839           gp_Pnt aPt = BRep_Tool::Pnt(TopoDS::Vertex(Ex.Current()));
1840           if (Abs(aPt.Z() - (theR1+theW1)) <= Precision::Confusion()) {
1841             nbEdgesInChamfer ++;
1842             theEdges.push_back(edgeID);
1843           }
1844           Ex.Next();
1845         }
1846         if (theHexMesh && nbEdgesInChamfer == 1)
1847           break;
1848     }
1849     Handle(GEOM_Object) aChamfer;
1850     try {
1851       aChamfer = aLocalOperations->MakeChamferEdges(aShape, theW, theH, theEdges);
1852     }
1853     catch (Standard_Failure) {
1854       Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1855       SetErrorCode(aFail->GetMessageString());
1856       return NULL;
1857     }
1858     if (aChamfer.IsNull()) {
1859         SetErrorCode("Chamfer can not be computed on the given shape with the given parameters");
1860         return NULL;
1861     }
1862     aChamfer->GetLastFunction()->SetDescription("");
1863     
1864     TopoDS_Shape aChamferShape = aChamfer->GetValue();
1865     aFunction->SetValue(aChamferShape);
1866     // END of chamfer
1867     
1868     if (theHexMesh) {
1869         std::cerr << "Creating partition" << std::endl;
1870         if (!MakePipeTShapePartition(/*theOperations, */aShape, theR1, theW1, theL1, theR2, theW2, theL2, theH, theW, 0, false))
1871           return NULL;
1872         std::cerr << "Done" << std::endl;
1873         std::cerr << "Creating mirrors and glue" << std::endl;
1874         if (!MakePipeTShapeMirrorAndGlue(/*theOperations, */aShape, theR1, theW1, theL1, theR2, theW2, theL2))
1875           return NULL;
1876         std::cerr << "Done" << std::endl;
1877     }
1878
1879     TopoDS_Shape Te = aShape->GetValue();
1880
1881     // Set Position
1882     gp_Trsf aTrsf = GetPositionTrsf(theL1, theL2, theP1, theP2, theP3);
1883     BRepBuilderAPI_Transform aTransformation(Te, aTrsf, Standard_False);
1884     TopoDS_Shape aTrsf_Shape = aTransformation.Shape();
1885     aFunction->SetValue(aTrsf_Shape);
1886     Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
1887     aSeq->Append(aShape);
1888     if (theHexMesh) {
1889         /*
1890          * Get the groups: BEGIN
1891          */
1892         if (!MakeGroups(/*theOperations, */aShape, TSHAPE_CHAMFER, theR1, theW1, theL1, theR2, theW2, theL2, aSeq, aTrsf))
1893             return NULL;
1894
1895         TCollection_AsciiString aListRes, anEntry;
1896         // Iterate over the sequence aSeq
1897         Standard_Integer aNbGroups = aSeq->Length();
1898         Standard_Integer i = 2;
1899         for (; i <= aNbGroups; i++) {
1900             Handle(Standard_Transient) anItem = aSeq->Value(i);
1901             if (anItem.IsNull()) continue;
1902             Handle(GEOM_Object) aGroup = Handle(GEOM_Object)::DownCast(anItem);
1903             if (aGroup.IsNull()) continue;
1904             //Make a Python command
1905             TDF_Tool::Entry(aGroup->GetEntry(), anEntry);
1906             aListRes += anEntry + ", ";
1907         }
1908
1909         aListRes.Trunc(aListRes.Length() - 2);
1910
1911         //Make a Python command
1912         GEOM::TPythonDump(aFunction) << "[" << aShape << ", " << aListRes.ToCString()
1913                 << "] = geompy.MakePipeTShapeChamfer(" << theR1 << ", " << theW1 << ", " << theL1 << ", " << theR2
1914                 << ", " << theW2 << ", " << theL2 << ", " << theH << ", " << theW << ", " << theHexMesh << ", "
1915                 << theP1 << ", " << theP2 << ", " << theP3 << ")";
1916     }
1917     /*
1918      * Get the groups: END
1919      */
1920     else {
1921         //Make a Python command
1922         GEOM::TPythonDump(aFunction) << "[" << aShape << "] = geompy.MakePipeTShapeChamfer(" << theR1 << ", " << theW1
1923                 << ", " << theL1 << ", " << theR2 << ", " << theW2 << ", " << theL2 << ", " << theH << ", " << theW
1924                 << ", " << theHexMesh << ", " << theP1 << ", " << theP2 << ", " << theP3 << ")";
1925     }
1926
1927     SetErrorCode(OK);
1928
1929     return aSeq;
1930 }
1931
1932 //=============================================================================
1933 /*!
1934  *  Create a T-shape object with specified caracteristics for the main and the
1935  *  incident pipes (radius, width, half-length).A fillet is created on
1936  *  the junction of the pipes.
1937  *  Center of the shape is (0,0,0). The main plane of the T-shape is XOY.
1938  *  \param theR1 Internal radius of main pipe
1939  *  \param theW1 Width of main pipe
1940  *  \param theL1 Half-length of main pipe
1941  *  \param theR2 Internal radius of incident pipe (R2 < R1)
1942  *  \param theW2 Width of incident pipe (R2+W2 < R1+W1)
1943  *  \param theL2 Half-length of incident pipe
1944  *  \param theRF Radius of curvature of fillet.
1945  *  \param theHexMesh Boolean indicating if shape is prepared for hex mesh
1946  *  \return List of GEOM_Objects, containing the created shape and propagation groups.
1947  */
1948 //=============================================================================
1949 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IAdvancedOperations::MakePipeTShapeFillet(double theR1, double theW1,
1950         double theL1, double theR2, double theW2, double theL2, double theRF, bool theHexMesh) {
1951     SetErrorCode(KO);
1952     //Add a new object
1953     Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_TSHAPE);
1954     //Add a new shape function with parameters
1955     Handle(GEOM_Function) aFunction = aShape->AddFunction(GEOMImpl_PipeTShapeDriver::GetID(), TSHAPE_FILLET);
1956     if (aFunction.IsNull()) return NULL;
1957
1958     //Check if the function is set correctly
1959     if (aFunction->GetDriverGUID() != GEOMImpl_PipeTShapeDriver::GetID()) return NULL;
1960
1961     GEOMImpl_IPipeTShape aData(aFunction);
1962
1963     aData.SetR1(theR1);
1964     aData.SetW1(theW1);
1965     aData.SetL1(theL1);
1966     aData.SetR2(theR2);
1967     aData.SetW2(theW2);
1968     aData.SetL2(theL2);
1969     aData.SetRF(theRF);
1970     aData.SetHexMesh(theHexMesh);
1971
1972     //Compute the resulting value
1973     try {
1974 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1975         OCC_CATCH_SIGNALS;
1976 #endif
1977         if (!GetSolver()->ComputeFunction(aFunction)) {
1978             SetErrorCode("TShape driver failed");
1979             return NULL;
1980         }
1981     } catch (Standard_Failure) {
1982         Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1983         SetErrorCode(aFail->GetMessageString());
1984         return NULL;
1985     }
1986
1987     GEOMImpl_IBasicOperations* aBasicOperations = new GEOMImpl_IBasicOperations(GetEngine(), GetDocID());
1988     GEOMImpl_IBooleanOperations* aBooleanOperations = new GEOMImpl_IBooleanOperations(GetEngine(), GetDocID());
1989     GEOMImpl_IShapesOperations* aShapesOperations = new GEOMImpl_IShapesOperations(GetEngine(), GetDocID());
1990     GEOMImpl_ITransformOperations* aTransformOperations = new GEOMImpl_ITransformOperations(GetEngine(), GetDocID());
1991     GEOMImpl_IBlocksOperations* aBlocksOperations = new GEOMImpl_IBlocksOperations(GetEngine(), GetDocID());
1992     GEOMImpl_I3DPrimOperations* a3DPrimOperations = new GEOMImpl_I3DPrimOperations(GetEngine(), GetDocID());
1993     GEOMImpl_ILocalOperations* aLocalOperations = new GEOMImpl_ILocalOperations(GetEngine(), GetDocID());
1994     std::vector<GEOM_IOperations*> theOperations;
1995     theOperations.push_back(a3DPrimOperations);
1996     theOperations.push_back(aBasicOperations);
1997     theOperations.push_back(aBlocksOperations);
1998     theOperations.push_back(aBooleanOperations);
1999     theOperations.push_back(aShapesOperations);
2000     theOperations.push_back(aTransformOperations);
2001
2002     // BEGIN of fillet
2003     TopoDS_Shape aShapeShape = aShape->GetValue();
2004     TopTools_IndexedMapOfShape anEdgesIndices;
2005     TopExp::MapShapes(aShapeShape, anEdgesIndices);
2006     // Common edges on external cylinders
2007     Handle(GEOM_Object) box_e;
2008     if (theHexMesh) {
2009       box_e = a3DPrimOperations->MakeBoxDXDYDZ(theR2+theW2, theR2+theW2, theR1+theW1);
2010     }
2011     else {
2012       box_e = a3DPrimOperations->MakeBoxDXDYDZ(2*(theR2+theW2), 2*(theR2+theW2), theR1+theW1);
2013     }
2014     box_e->GetLastFunction()->SetDescription("");
2015     box_e = aTransformOperations->TranslateDXDYDZ(box_e, -(theR2+theW2), -(theR2+theW2), 0);
2016     box_e->GetLastFunction()->SetDescription("");
2017     
2018     Handle(TColStd_HSequenceOfInteger) edges_e = aShapesOperations->GetShapesOnBoxIDs(box_e, aShape, TopAbs_EDGE, GEOMAlgo_ST_IN);
2019     box_e->GetLastFunction()->SetDescription("");
2020
2021     if (edges_e.IsNull() || edges_e->Length() == 0) {
2022 //        std::cerr << "Internal edges not found" << std::endl;
2023         SetErrorCode("External edges not found");
2024         return false;
2025     }
2026 //    std::cerr << "External edges found" << std::endl;
2027     int nbEdgesInFillet = 0;
2028     std::list<int> theEdges;
2029     for (int i=1; i<=edges_e->Length();i++) {
2030 //         Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(edges_e->Value(i));
2031 //         anObj->GetLastFunction()->SetDescription("");
2032         int edgeID = edges_e->Value(i);
2033         TopoDS_Shape theEdge = anEdgesIndices.FindKey(edgeID);
2034         TopExp_Explorer Ex(theEdge,TopAbs_VERTEX);
2035         while (Ex.More()) {
2036           gp_Pnt aPt = BRep_Tool::Pnt(TopoDS::Vertex(Ex.Current()));
2037           if (Abs(aPt.Z() - (theR1+theW1)) <= Precision::Confusion()) {
2038             nbEdgesInFillet ++;
2039             theEdges.push_back(edgeID);
2040           }
2041           Ex.Next();
2042         }
2043         if (theHexMesh && nbEdgesInFillet == 1)
2044           break;
2045     }
2046
2047     Handle(GEOM_Object) aFillet;
2048     try {
2049         aFillet = aLocalOperations->MakeFilletEdges(aShape, theRF, theEdges);
2050     }
2051     catch (Standard_Failure) {
2052       Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2053       SetErrorCode(aFail->GetMessageString());
2054       return NULL;
2055     }
2056     if (aFillet.IsNull()) {
2057         SetErrorCode("Fillet can not be computed on the given shape with the given parameters");
2058         return NULL;
2059     }
2060     aFillet->GetLastFunction()->SetDescription("");
2061     
2062     TopoDS_Shape aFilletShape = aFillet->GetValue();
2063     aFunction->SetValue(aFilletShape);
2064     // END of fillet
2065
2066     if (theHexMesh) {
2067         std::cerr << "Creating partition" << std::endl;
2068         if (!MakePipeTShapePartition(/*theOperations, */aShape, theR1, theW1, theL1, theR2, theW2, theL2, 0, 0, theRF, false))
2069           return NULL;
2070         std::cerr << "Done" << std::endl;
2071         std::cerr << "Creating mirrors and glue" << std::endl;
2072         if (!MakePipeTShapeMirrorAndGlue(/*theOperations, */aShape, theR1, theW1, theL1, theR2, theW2, theL2))
2073           return NULL;
2074         std::cerr << "Done" << std::endl;
2075     }
2076
2077     Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
2078     aSeq->Append(aShape);
2079     if (theHexMesh) {
2080         /*
2081          * Get the groups: BEGIN
2082          */
2083         if (!MakeGroups(/*theOperations, */aShape, TSHAPE_FILLET, theR1, theW1, theL1, theR2, theW2, theL2, aSeq, gp_Trsf()))
2084             return NULL;
2085
2086         TCollection_AsciiString aListRes, anEntry;
2087         // Iterate over the sequence aSeq
2088         Standard_Integer aNbGroups = aSeq->Length();
2089         Standard_Integer i = 2;
2090         for (; i <= aNbGroups; i++) {
2091             Handle(Standard_Transient) anItem = aSeq->Value(i);
2092             if (anItem.IsNull()) continue;
2093             Handle(GEOM_Object) aGroup = Handle(GEOM_Object)::DownCast(anItem);
2094             if (aGroup.IsNull()) continue;
2095             //Make a Python command
2096             TDF_Tool::Entry(aGroup->GetEntry(), anEntry);
2097             aListRes += anEntry + ", ";
2098         }
2099
2100         aListRes.Trunc(aListRes.Length() - 2);
2101
2102         //Make a Python command
2103         GEOM::TPythonDump(aFunction) << "[" << aShape << ", " << aListRes.ToCString()
2104                 << "] = geompy.MakePipeTShapeFillet(" << theR1 << ", " << theW1 << ", " << theL1 << ", " << theR2
2105                 << ", " << theW2 << ", " << theL2 << ", " << theRF << ", " << theHexMesh << ")";
2106     }
2107     /*
2108      * Get the groups: END
2109      */
2110     else {
2111         //Make a Python command
2112         GEOM::TPythonDump(aFunction) << "[" << aShape << "] = geompy.MakePipeTShapeFillet(" << theR1 << ", " << theW1
2113                 << ", " << theL1 << ", " << theR2 << ", " << theW2 << ", " << theL2 << ", " << theRF << ", "
2114                 << theHexMesh << ")";
2115     }
2116
2117
2118     SetErrorCode(OK);
2119
2120     return aSeq;
2121
2122 }
2123
2124 //=============================================================================
2125 /*!
2126  *  Create a T-shape object with specified caracteristics for the main and the
2127  *  incident pipes (radius, width, half-length). A fillet is created on
2128  *  the junction of the pipes.
2129  *  The T-shape is placed at junction points P1, P2 and P3.
2130  *  \param theR1 Internal radius of main pipe
2131  *  \param theW1 Width of main pipe
2132  *  \param theL1 Half-length of main pipe
2133  *  \param theR2 Internal radius of incident pipe (R2 < R1)
2134  *  \param theW2 Width of incident pipe (R2+W2 < R1+W1)
2135  *  \param theL2 Half-length of incident pipe
2136  *  \param theRF Radius of curvature of fillet
2137  *  \param theHexMesh Boolean indicating if shape is prepared for hex mesh
2138  *  \param theP1 1st junction point of main pipe
2139  *  \param theP2 2nd junction point of main pipe
2140  *  \param theP3 Junction point of incident pipe
2141  *  \return List of GEOM_Objects, containing the created shape and propagation groups.
2142  */
2143 //=============================================================================
2144 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IAdvancedOperations::MakePipeTShapeFilletWithPosition(double theR1,
2145         double theW1, double theL1, double theR2, double theW2, double theL2, double theRF, bool theHexMesh,
2146         Handle(GEOM_Object) theP1, Handle(GEOM_Object) theP2, Handle(GEOM_Object) theP3) {
2147     SetErrorCode(KO);
2148     //Add a new object
2149     Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_TSHAPE);
2150     //Add a new shape function with parameters
2151     Handle(GEOM_Function) aFunction = aShape->AddFunction(GEOMImpl_PipeTShapeDriver::GetID(), TSHAPE_FILLET);
2152     if (aFunction.IsNull()) return NULL;
2153
2154     //Check if the function is set correctly
2155     if (aFunction->GetDriverGUID() != GEOMImpl_PipeTShapeDriver::GetID()) return NULL;
2156
2157     // Check new position
2158     if (!CheckCompatiblePosition(theL1, theL2, theP1, theP2, theP3, 0.01)) {
2159         return NULL;
2160     }
2161
2162     GEOMImpl_IPipeTShape aData(aFunction);
2163
2164     aData.SetR1(theR1);
2165     aData.SetW1(theW1);
2166     aData.SetL1(theL1);
2167     aData.SetR2(theR2);
2168     aData.SetW2(theW2);
2169     aData.SetL2(theL2);
2170     aData.SetRF(theRF);
2171     aData.SetHexMesh(theHexMesh);
2172
2173     //Compute the resulting value
2174     try {
2175 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
2176         OCC_CATCH_SIGNALS;
2177 #endif
2178         if (!GetSolver()->ComputeFunction(aFunction)) {
2179             SetErrorCode("TShape driver failed");
2180             return NULL;
2181         }
2182     } catch (Standard_Failure) {
2183         Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2184         SetErrorCode(aFail->GetMessageString());
2185         return NULL;
2186     }
2187
2188     GEOMImpl_IBasicOperations* aBasicOperations = new GEOMImpl_IBasicOperations(GetEngine(), GetDocID());
2189     GEOMImpl_IBooleanOperations* aBooleanOperations = new GEOMImpl_IBooleanOperations(GetEngine(), GetDocID());
2190     GEOMImpl_IShapesOperations* aShapesOperations = new GEOMImpl_IShapesOperations(GetEngine(), GetDocID());
2191     GEOMImpl_ITransformOperations* aTransformOperations = new GEOMImpl_ITransformOperations(GetEngine(), GetDocID());
2192     GEOMImpl_IBlocksOperations* aBlocksOperations = new GEOMImpl_IBlocksOperations(GetEngine(), GetDocID());
2193     GEOMImpl_I3DPrimOperations* a3DPrimOperations = new GEOMImpl_I3DPrimOperations(GetEngine(), GetDocID());
2194     GEOMImpl_ILocalOperations* aLocalOperations = new GEOMImpl_ILocalOperations(GetEngine(), GetDocID());
2195     std::vector<GEOM_IOperations*> theOperations;
2196     theOperations.push_back(a3DPrimOperations);
2197     theOperations.push_back(aBasicOperations);
2198     theOperations.push_back(aBlocksOperations);
2199     theOperations.push_back(aBooleanOperations);
2200     theOperations.push_back(aShapesOperations);
2201     theOperations.push_back(aTransformOperations);
2202
2203     // BEGIN of fillet
2204     TopoDS_Shape aShapeShape = aShape->GetValue();
2205     TopTools_IndexedMapOfShape anEdgesIndices;
2206     TopExp::MapShapes(aShapeShape, anEdgesIndices);
2207     // Common edges on external cylinders
2208     Handle(GEOM_Object) box_e;
2209     if (theHexMesh) {
2210       box_e = a3DPrimOperations->MakeBoxDXDYDZ(theR2+theW2, theR2+theW2, theR1+theW1);
2211     }
2212     else {
2213       box_e = a3DPrimOperations->MakeBoxDXDYDZ(2*(theR2+theW2), 2*(theR2+theW2), theR1+theW1);
2214     }
2215     box_e->GetLastFunction()->SetDescription("");
2216     box_e = aTransformOperations->TranslateDXDYDZ(box_e, -(theR2+theW2), -(theR2+theW2), 0);
2217     box_e->GetLastFunction()->SetDescription("");
2218     
2219     Handle(TColStd_HSequenceOfInteger) edges_e = aShapesOperations->GetShapesOnBoxIDs(box_e, aShape, TopAbs_EDGE, GEOMAlgo_ST_IN);
2220     box_e->GetLastFunction()->SetDescription("");
2221
2222     if (edges_e.IsNull() || edges_e->Length() == 0) {
2223 //        std::cerr << "Internal edges not found" << std::endl;
2224         SetErrorCode("External edges not found");
2225         return false;
2226     }
2227 //    std::cerr << "External edges found" << std::endl;
2228     int nbEdgesInFillet = 0;
2229     std::list<int> theEdges;
2230     for (int i=1; i<=edges_e->Length();i++) {
2231 //         Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(edges_e->Value(i));
2232 //         anObj->GetLastFunction()->SetDescription("");
2233         int edgeID = edges_e->Value(i);
2234         TopoDS_Shape theEdge = anEdgesIndices.FindKey(edgeID);
2235         TopExp_Explorer Ex(theEdge,TopAbs_VERTEX);
2236         while (Ex.More()) {
2237           gp_Pnt aPt = BRep_Tool::Pnt(TopoDS::Vertex(Ex.Current()));
2238           if (Abs(aPt.Z() - (theR1+theW1)) <= Precision::Confusion()) {
2239             nbEdgesInFillet ++;
2240             theEdges.push_back(edgeID);
2241           }
2242           Ex.Next();
2243         }
2244         if (theHexMesh && nbEdgesInFillet == 1)
2245           break;
2246     }
2247
2248     Handle(GEOM_Object) aFillet;
2249     try {
2250         aFillet = aLocalOperations->MakeFilletEdges(aShape, theRF, theEdges);
2251     }
2252     catch (Standard_Failure) {
2253       Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2254       SetErrorCode(aFail->GetMessageString());
2255       return NULL;
2256     }
2257     if (aFillet.IsNull()) {
2258         SetErrorCode("Fillet can not be computed on the given shape with the given parameters");
2259         return NULL;
2260     }
2261     aFillet->GetLastFunction()->SetDescription("");
2262     
2263     TopoDS_Shape aFilletShape = aFillet->GetValue();
2264     aFunction->SetValue(aFilletShape);
2265     // END of fillet
2266
2267     if (theHexMesh) {
2268         std::cerr << "Creating partition" << std::endl;
2269         if (!MakePipeTShapePartition(/*theOperations, */aShape, theR1, theW1, theL1, theR2, theW2, theL2, 0, 0, theRF, false))
2270           return NULL;
2271         std::cerr << "Done" << std::endl;
2272         std::cerr << "Creating mirrors and glue" << std::endl;
2273         if (!MakePipeTShapeMirrorAndGlue(/*theOperations, */aShape, theR1, theW1, theL1, theR2, theW2, theL2))
2274           return NULL;
2275         std::cerr << "Done" << std::endl;
2276     }
2277
2278     TopoDS_Shape Te = aShape->GetValue();
2279
2280     // Set Position
2281     gp_Trsf aTrsf = GetPositionTrsf(theL1, theL2, theP1, theP2, theP3);
2282     BRepBuilderAPI_Transform aTransformation(Te, aTrsf, Standard_False);
2283     TopoDS_Shape aTrsf_Shape = aTransformation.Shape();
2284     aFunction->SetValue(aTrsf_Shape);
2285     Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
2286     aSeq->Append(aShape);
2287     if (theHexMesh) {
2288         /*
2289          * Get the groups: BEGIN
2290          */
2291         if (!MakeGroups(/*theOperations, */aShape, TSHAPE_FILLET, theR1, theW1, theL1, theR2, theW2, theL2, aSeq, aTrsf))
2292             return NULL;
2293
2294         TCollection_AsciiString aListRes, anEntry;
2295         // Iterate over the sequence aSeq
2296         Standard_Integer aNbGroups = aSeq->Length();
2297         Standard_Integer i = 2;
2298         for (; i <= aNbGroups; i++) {
2299             Handle(Standard_Transient) anItem = aSeq->Value(i);
2300             if (anItem.IsNull()) continue;
2301             Handle(GEOM_Object) aGroup = Handle(GEOM_Object)::DownCast(anItem);
2302             if (aGroup.IsNull()) continue;
2303             //Make a Python command
2304             TDF_Tool::Entry(aGroup->GetEntry(), anEntry);
2305             aListRes += anEntry + ", ";
2306         }
2307
2308         aListRes.Trunc(aListRes.Length() - 2);
2309
2310         //Make a Python command
2311         GEOM::TPythonDump(aFunction) << "[" << aShape << ", " << aListRes.ToCString()
2312                 << "] = geompy.MakePipeTShapeFillet(" << theR1 << ", " << theW1 << ", " << theL1 << ", " << theR2
2313                 << ", " << theW2 << ", " << theL2 << ", " << theRF << ", " << theHexMesh << ", " << theP1 << ", "
2314                 << theP2 << ", " << theP3 << ")";
2315     }
2316     /*
2317      * Get the groups: END
2318      */
2319     else {
2320         //Make a Python command
2321         GEOM::TPythonDump(aFunction) << "[" << aShape << "] = geompy.MakePipeTShapeFillet(" << theR1 << ", " << theW1
2322                 << ", " << theL1 << ", " << theR2 << ", " << theW2 << ", " << theL2 << ", " << theRF << ", "
2323                 << theHexMesh << ", " << theP1 << ", " << theP2 << ", " << theP3 << ")";
2324     }
2325
2326     SetErrorCode(OK);
2327
2328     return aSeq;
2329 }
2330
2331 /*@@ insert new functions before this line @@*/