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