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