]> SALOME platform Git repositories - modules/geom.git/blob - src/AdvancedEngine/AdvancedEngine_IOperations.cxx
Salome HOME
0022746: [EDF] Improvement of Glue Faces and Glue Edges operations
[modules/geom.git] / src / AdvancedEngine / AdvancedEngine_IOperations.cxx
1 // Copyright (C) 2007-2014  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, or (at your option) any later version.
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 //  File   : AdvancedEngine_IOperations.cxx
20 //  Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
21
22 #include "AdvancedEngine_IOperations.hxx"
23 #include "AdvancedEngine_PipeTShapeDriver.hxx"
24 #include "AdvancedEngine_IPipeTShape.hxx"
25 #include "AdvancedEngine_DividedDiskDriver.hxx"
26 #include "AdvancedEngine_IDividedDisk.hxx"
27 #include "AdvancedEngine_SmoothingSurfaceDriver.hxx"
28 #include "AdvancedEngine_ISmoothingSurface.hxx"
29
30 #include <Basics_OCCTVersion.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 #include "GEOMUtils.hxx"
39 #include "GEOMAlgo_Splitter.hxx"
40 #include "GEOMAlgo_FinderShapeOn1.hxx"
41
42 #include "GEOMImpl_Gen.hxx"
43 #include "GEOMImpl_Types.hxx"
44
45 #include "GEOMImpl_IBasicOperations.hxx"
46 #include "GEOMImpl_IBooleanOperations.hxx"
47 #include "GEOMImpl_IShapesOperations.hxx"
48 #include "GEOMImpl_ITransformOperations.hxx"
49 #include "GEOMImpl_IBlocksOperations.hxx"
50 #include "GEOMImpl_I3DPrimOperations.hxx"
51 #include "GEOMImpl_ILocalOperations.hxx"
52 #include "GEOMImpl_IHealingOperations.hxx"
53 #include "GEOMImpl_IGroupOperations.hxx"
54 #include "GEOMImpl_GlueDriver.hxx"
55
56 #include <TDF_Tool.hxx>
57 #include <TFunction_DriverTable.hxx>
58 #include <TFunction_Driver.hxx>
59 #include <TFunction_Logbook.hxx>
60 #include <TNaming_CopyShape.hxx>
61
62 #include <TopExp.hxx>
63 #include <TopExp_Explorer.hxx>
64 #include <TopoDS.hxx>
65 #include <TopoDS_Vertex.hxx>
66 #include <TopTools_IndexedMapOfShape.hxx>
67 #include <TopTools_ListIteratorOfListOfShape.hxx>
68 #include <TColStd_IndexedDataMapOfTransientTransient.hxx>
69
70 #include <BRep_Builder.hxx>
71 #include <BRep_Tool.hxx>
72
73 #include <BRepAdaptor_Surface.hxx>
74 #include <BRepAlgoAPI_Cut.hxx>
75 #include <BRepAlgoAPI_Fuse.hxx>
76 #include <BRepBuilderAPI_MakeFace.hxx>
77 #include <BRepBuilderAPI_MakeVertex.hxx>
78 #include <BRepBuilderAPI_Transform.hxx>
79 #include <BRepPrimAPI_MakeCone.hxx>
80 #include <BRepPrimAPI_MakeCylinder.hxx>
81
82 #include <gp_Ax3.hxx>
83 #include <gp_Pln.hxx>
84 #include <gp_Pnt.hxx>
85 #include <gp_Vec.hxx>
86 #include <GC_MakeConicalSurface.hxx>
87 #include <Geom_CylindricalSurface.hxx>
88
89 #include <ShapeAnalysis_Edge.hxx>
90
91 #include <cmath>
92
93 #include "AdvancedEngine_Types.hxx"
94
95 #include <Standard_Stream.hxx>
96 #include <Standard_Failure.hxx>
97 #include <StdFail_NotDone.hxx>
98 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
99
100 #define HALF_LENGTH_MAIN_PIPE     "Main pipe half length" //"Tuyau principal - demi longueur"
101 #define HALF_LENGTH_INCIDENT_PIPE "Incident pipe half length" //"Tuyau incident - demi longueur"
102 #define CIRCULAR_QUARTER_PIPE     "Circular quarter of pipe" //"Circulaire - quart de tuyau"
103 #define THICKNESS                 "Thickness" //"Epaisseur"
104 #define FLANGE                    "Flange" // "Collerette"
105 #define CHAMFER_OR_FILLET         "Chamfer or fillet" //"Chanfrein ou Raccord"
106 #define JUNCTION_FACE_1           "Junction 1" //"Face de jonction 1"
107 #define JUNCTION_FACE_2           "Junction 2" //"Face de jonction 2"
108 #define JUNCTION_FACE_3           "Junction 3" //"Face de jonction 3"
109
110 #define FIND_GROUPS_BY_POINTS 1
111
112 //=============================================================================
113 /*!
114  *  Constructor
115  */
116 //=============================================================================
117 AdvancedEngine_IOperations::AdvancedEngine_IOperations(GEOM_Engine* theEngine, int theDocID) :
118   GEOM_IOperations(theEngine, theDocID)
119 {
120   MESSAGE("AdvancedEngine_IOperations::AdvancedEngine_IOperations");
121   myBasicOperations     = new GEOMImpl_IBasicOperations(GetEngine(), GetDocID());
122   myBooleanOperations   = new GEOMImpl_IBooleanOperations(GetEngine(), GetDocID());
123   myShapesOperations    = new GEOMImpl_IShapesOperations(GetEngine(), GetDocID());
124   myTransformOperations = new GEOMImpl_ITransformOperations(GetEngine(), GetDocID());
125   myBlocksOperations    = new GEOMImpl_IBlocksOperations(GetEngine(), GetDocID());
126   my3DPrimOperations    = new GEOMImpl_I3DPrimOperations(GetEngine(), GetDocID());
127   myLocalOperations     = new GEOMImpl_ILocalOperations(GetEngine(), GetDocID());
128   myHealingOperations   = new GEOMImpl_IHealingOperations(GetEngine(), GetDocID());
129   myGroupOperations     = new GEOMImpl_IGroupOperations(GetEngine(), GetDocID());
130 }
131
132 //=============================================================================
133 /*!
134  *  Destructor
135  */
136 //=============================================================================
137 AdvancedEngine_IOperations::~AdvancedEngine_IOperations()
138 {
139   MESSAGE("AdvancedEngine_IOperations::~AdvancedEngine_IOperations");
140   delete myBasicOperations;
141   delete myBooleanOperations;
142   delete myShapesOperations;
143   delete myTransformOperations;
144   delete myBlocksOperations;
145   delete my3DPrimOperations;
146   delete myLocalOperations;
147   delete myHealingOperations;
148   delete myGroupOperations;
149 }
150
151 //=============================================================================
152 /*!
153  *  SetPosition
154  */
155 //=============================================================================
156 gp_Trsf AdvancedEngine_IOperations::GetPositionTrsf(double theL1, double theL2,
157                                                     Handle(GEOM_Object) theP1,
158                                                     Handle(GEOM_Object) theP2,
159                                                     Handle(GEOM_Object) theP3)
160 {
161   // Old Local Coordinates System oldLCS
162   gp_Pnt P0(0, 0, 0);
163   gp_Pnt P1(-theL1, 0, 0);
164   gp_Pnt P2(theL1, 0, 0);
165   gp_Pnt P3(0, 0, theL2);
166
167   gp_Dir oldX(gp_Vec(P1, P2));
168   gp_Dir oldZ(gp_Vec(P0, P3));
169   gp_Ax3 oldLCS(P0, oldZ, oldX);
170
171   // New Local Coordinates System newLCS
172   double LocX, LocY, LocZ;
173   gp_Pnt newP1 = BRep_Tool::Pnt(TopoDS::Vertex(theP1->GetValue()));
174   gp_Pnt newP2 = BRep_Tool::Pnt(TopoDS::Vertex(theP2->GetValue()));
175   gp_Pnt newP3 = BRep_Tool::Pnt(TopoDS::Vertex(theP3->GetValue()));
176   LocX = (newP1.X() + newP2.X()) / 2.;
177   LocY = (newP1.Y() + newP2.Y()) / 2.;
178   LocZ = (newP1.Z() + newP2.Z()) / 2.;
179   gp_Pnt newO(LocX, LocY, LocZ);
180
181   gp_Dir newX(gp_Vec(newP1, newP2)); // P1P2 Vector
182   gp_Dir newZ(gp_Vec(newO, newP3)); // OP3 Vector
183   gp_Ax3 newLCS = gp_Ax3(newO, newZ, newX);
184
185   gp_Trsf aTrsf;
186   aTrsf.SetDisplacement(oldLCS, newLCS);
187
188   return aTrsf;
189 }
190
191 //=============================================================================
192 /*!
193  *  CheckCompatiblePosition
194  *
195  */
196 //=============================================================================
197 bool AdvancedEngine_IOperations::CheckCompatiblePosition(double& theL1, double& theL2,
198                                                          Handle(GEOM_Object) theP1,
199                                                          Handle(GEOM_Object) theP2,
200                                                          Handle(GEOM_Object) theP3,
201                                                          double theTolerance)
202 {
203   SetErrorCode(KO);
204   gp_Pnt P1 = BRep_Tool::Pnt(TopoDS::Vertex(theP1->GetValue()));
205   gp_Pnt P2 = BRep_Tool::Pnt(TopoDS::Vertex(theP2->GetValue()));
206   gp_Pnt P3 = BRep_Tool::Pnt(TopoDS::Vertex(theP3->GetValue()));
207
208   double d12 = P1.Distance(P2);
209   double d13 = P1.Distance(P3);
210   double d23 = P2.Distance(P3);
211   //    double d2 = newO.Distance(P3);
212
213   if (Abs(d12) <= Precision::Confusion()) {
214     SetErrorCode("Junctions points P1 and P2 are identical");
215     return false;
216   }
217   if (Abs(d13) <= Precision::Confusion()) {
218     SetErrorCode("Junctions points P1 and P3 are identical");
219     return false;
220   }
221   if (Abs(d23) <= Precision::Confusion()) {
222     SetErrorCode("Junctions points P2 and P3 are identical");
223     return false;
224   }
225
226
227   double newL1 = 0.5 * d12;
228   double newL2 = sqrt(pow(d13,2)-pow(newL1,2));
229   //
230   // theL1*(1-theTolerance) <= newL1 <= theL1*(1+theTolerance)
231   //
232   if (fabs(newL1 - theL1) > Precision::Approximation()) {
233     if ( (newL1 * (1 - theTolerance) -theL1 <= Precision::Approximation()) &&
234          (newL1 * (1 + theTolerance) -theL1 >= Precision::Approximation()) ) {
235       //            std::cerr << "theL1 = newL1" << std::endl;
236       theL1 = newL1;
237     } else {
238       theL1 = -1;
239       SetErrorCode("Dimension for main pipe (L1) is incompatible with new position");
240       return false;
241     }
242   }
243
244   //
245   // theL2*(1-theTolerance) <= newL2  <= theL2*(1+theTolerance)
246   //
247   if (fabs(newL2 - theL2) > Precision::Approximation()) {
248     if ( (newL2 * (1 - theTolerance) -theL2 <= Precision::Approximation()) &&
249          (newL2 * (1 + theTolerance) -theL2 >= Precision::Approximation()) ) {
250       theL2 = newL2;
251     } else {
252       theL2 = -1;
253       SetErrorCode("Dimension for incident pipe (L2) is incompatible with new position");
254       return false;
255     }
256   }
257
258   SetErrorCode(OK);
259   return true;
260
261 }
262
263 //=============================================================================
264 /*!
265  *  Generate the propagation groups of a Pipe T-Shape used for hexa mesh
266  */
267 //=============================================================================
268 bool AdvancedEngine_IOperations::MakeGroups(Handle(GEOM_Object) theShape, int shapeType,
269                                             double theR1, double theW1, double theL1,
270                                             double theR2, double theW2, double theL2,
271                                             double theH, double theW, double theRF,
272                                             Handle(TColStd_HSequenceOfTransient) theSeq,
273                                             gp_Trsf aTrsf)
274 {
275   SetErrorCode(KO);
276
277   if (theShape.IsNull()) return false;
278
279   TopoDS_Shape aShape = theShape->GetValue();
280   if (aShape.IsNull()) {
281     SetErrorCode("Shape is not defined");
282     return false;
283   }
284
285   gp_Trsf aTrsfInv = aTrsf.Inverted();
286
287 //   int expectedGroups = 0;
288 //   if (shapeType == TSHAPE_BASIC)
289 //     if (Abs(theR2+theW2-theR1-theW1) <= Precision::Approximation())
290 //       expectedGroups = 10;
291 //     else
292 //       expectedGroups = 11;
293 //   else if (shapeType == TSHAPE_CHAMFER || shapeType == TSHAPE_FILLET)
294 //     expectedGroups = 12;
295
296   double aR1Ext = theR1 + theW1;
297   double aR2Ext = theR2 + theW2;
298
299   /////////////////////////
300   //// Groups of Faces ////
301   /////////////////////////
302
303   //
304   // Comment the following lines when GetInPlace bug is solved
305   // == BEGIN
306   // Workaround of GetInPlace bug
307   // Create a bounding box that fits the shape
308   Handle(GEOM_Object) aBox = my3DPrimOperations->MakeBoxDXDYDZ(2*theL1, 2*aR1Ext, aR1Ext+theL2);
309   aBox->GetLastFunction()->SetDescription("");
310   myTransformOperations->TranslateDXDYDZ(aBox, -theL1, -aR1Ext, -aR1Ext);
311   aBox->GetLastFunction()->SetDescription("");
312   // Apply transformation to box
313   BRepBuilderAPI_Transform aTransformationBox(aBox->GetValue(), aTrsf, Standard_False);
314   TopoDS_Shape aBoxShapeTrsf = aTransformationBox.Shape();
315   aBox->GetLastFunction()->SetValue(aBoxShapeTrsf);
316
317   // Get the shell of the box
318   Handle(GEOM_Object) aShell = Handle(GEOM_Object)::DownCast
319     (myShapesOperations->MakeExplode(aBox, TopAbs_SHELL, true)->Value(1));
320   aBox->GetLastFunction()->SetDescription("");
321   aShell->GetLastFunction()->SetDescription("");
322   // Get the common shapes between shell and shape
323   Handle(GEOM_Object) aCommonCompound = myBooleanOperations->MakeBoolean
324                             (theShape, aShell, 1, Standard_False); // MakeCommon
325   if (aCommonCompound.IsNull()) {
326     SetErrorCode(myBooleanOperations->GetErrorCode());
327     return false;
328   }
329   aCommonCompound->GetLastFunction()->SetDescription("");
330   // Explode the faces of common shapes => 3 faces
331   Handle(TColStd_HSequenceOfTransient) aCommonFaces =
332     myShapesOperations->MakeExplode(aCommonCompound, TopAbs_FACE, true);
333   aCommonCompound->GetLastFunction()->SetDescription("");
334   std::list<Handle(GEOM_Object)> aCompoundOfFacesList;
335
336   for (int i=0 ; i<= aCommonFaces->Length()-4 ; i+=4) {
337     std::list<Handle(GEOM_Object)> aFacesList;
338     for (int j = 1 ; j <= 4 ; j++) {
339       Handle(GEOM_Object) aFace = Handle(GEOM_Object)::DownCast(aCommonFaces->Value(i+j)); // Junction faces
340       if (!aFace.IsNull()) {
341         aFace->GetLastFunction()->SetDescription("");
342         aFacesList.push_back(aFace);
343       }
344     }
345     Handle(GEOM_Object) aCompoundOfFaces = myShapesOperations->MakeCompound(aFacesList);
346     if (!aCompoundOfFaces.IsNull()) {
347       aCompoundOfFaces->GetLastFunction()->SetDescription("");
348       aCompoundOfFacesList.push_back(aCompoundOfFaces);
349     }
350   }
351
352   if (aCompoundOfFacesList.size() == 3) {
353     Handle(GEOM_Object) aPln1 = aCompoundOfFacesList.front();
354     aCompoundOfFacesList.pop_front();
355     Handle(GEOM_Object) aPln2 = aCompoundOfFacesList.front();
356     aCompoundOfFacesList.pop_front();
357     Handle(GEOM_Object) aPln3 = aCompoundOfFacesList.front();
358     aCompoundOfFacesList.pop_front();
359     // == END
360     //
361
362
363     //     Uncomment the following lines when GetInPlace bug is solved
364     //     == BEGIN
365 //     Handle(GEOM_Object) aP1 = myBasicOperations->MakePointXYZ(-theL1, 0, 0);
366 //     Handle(GEOM_Object) aP2 = myBasicOperations->MakePointXYZ(-0, 0, theL2);
367 //     Handle(GEOM_Object) aP3 = myBasicOperations->MakePointXYZ(theL1, 0, 0);
368 //     aP1->GetLastFunction()->SetDescription("");
369 //     aP2->GetLastFunction()->SetDescription("");
370 //     aP3->GetLastFunction()->SetDescription("");
371 //     Handle(GEOM_Object) aV1 = myBasicOperations->MakeVectorDXDYDZ(-1, 0, 0);
372 //     Handle(GEOM_Object) aV2 = myBasicOperations->MakeVectorDXDYDZ(0, 0, 1);
373 //     Handle(GEOM_Object) aV3 = myBasicOperations->MakeVectorDXDYDZ(1, 0, 0);
374 //     aV1->GetLastFunction()->SetDescription("");
375 //     aV2->GetLastFunction()->SetDescription("");
376 //     aV3->GetLastFunction()->SetDescription("");
377 //     Handle(GEOM_Object) aPln1 = myBasicOperations->MakePlanePntVec(aP1, aV1, 2*(aR1Ext+theL2));
378 //     Handle(GEOM_Object) aPln2 = myBasicOperations->MakePlanePntVec(aP2, aV2, 2*(aR2Ext));
379 //     Handle(GEOM_Object) aPln3 = myBasicOperations->MakePlanePntVec(aP3, aV3, 2*(aR1Ext+theL2));
380 //     aPln1->GetLastFunction()->SetDescription("");
381 //     aPln2->GetLastFunction()->SetDescription("");
382 //     aPln3->GetLastFunction()->SetDescription("");
383 //
384 //     BRepBuilderAPI_Transform aTransformation1(aPln1->GetValue(), aTrsf, Standard_False);
385 //     TopoDS_Shape aTrsf_Shape1 = aTransformation1.Shape();
386 //     aPln1->GetLastFunction()->SetValue(aTrsf_Shape1);
387 //     BRepBuilderAPI_Transform aTransformation2(aPln2->GetValue(), aTrsf, Standard_False);
388 //     TopoDS_Shape aTrsf_Shape2 = aTransformation2.Shape();
389 //     aPln2->GetLastFunction()->SetValue(aTrsf_Shape2);
390 //     BRepBuilderAPI_Transform aTransformation3(aPln3->GetValue(), aTrsf, Standard_False);
391 //     TopoDS_Shape aTrsf_Shape3 = aTransformation3.Shape();
392 //     aPln3->GetLastFunction()->SetValue(aTrsf_Shape3);
393     //     == END
394     //
395
396     Handle(GEOM_Object) junctionFaces1 = myShapesOperations->GetInPlace(theShape, aPln1);
397     if (junctionFaces1.IsNull())
398       junctionFaces1 = myShapesOperations->GetShapesOnShapeAsCompound
399         (aPln1, theShape, TopAbs_FACE,  GEOMAlgo_ST_ONIN);
400     if (!junctionFaces1.IsNull()) {
401       junctionFaces1->GetLastFunction()->SetDescription("");
402       junctionFaces1->SetName("JUNCTION_FACE_1");
403       theSeq->Append(junctionFaces1);
404     }
405     else {
406       SetErrorCode("Junction face 1 not found");
407       //        theSeq->Append(aPln1);
408       //        return false;
409     }
410     Handle(GEOM_Object) junctionFaces2 = myShapesOperations->GetInPlace(theShape, aPln2);
411     if (junctionFaces2.IsNull())
412       junctionFaces2 = myShapesOperations->GetShapesOnShapeAsCompound
413         (aPln2, theShape, TopAbs_FACE,  GEOMAlgo_ST_ONIN);
414     if (!junctionFaces2.IsNull()) {
415       junctionFaces2->GetLastFunction()->SetDescription("");
416       junctionFaces2->SetName("JUNCTION_FACE_2");
417       theSeq->Append(junctionFaces2);
418     }
419     else {
420       SetErrorCode("Junction face 2 not found");
421       //        theSeq->Append(aPln2);
422       //        return false;
423     }
424     Handle(GEOM_Object) junctionFaces3 = myShapesOperations->GetInPlace(theShape, aPln3);
425     if (junctionFaces3.IsNull())
426       junctionFaces3 = myShapesOperations->GetShapesOnShapeAsCompound
427         (aPln3, theShape, TopAbs_FACE,  GEOMAlgo_ST_ONIN);
428     if (!junctionFaces3.IsNull()) {
429       junctionFaces3->GetLastFunction()->SetDescription("");
430       junctionFaces3->SetName("JUNCTION_FACE_3");
431       theSeq->Append(junctionFaces3);
432     }
433     else {
434       SetErrorCode("Junction face 3 not found");
435       //        theSeq->Append(aPln3);
436       //        return false;
437     }
438   // Comment the following lines when GetInPlace bug is solved
439   // == BEGIN
440   }
441   //     == END
442
443   /////////////////////////
444   //// Groups of Edges ////
445   /////////////////////////
446   // Result of propagate
447
448   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
449
450   TCollection_AsciiString theDesc = aFunction->GetDescription();
451   Handle(TColStd_HSequenceOfTransient) aSeqPropagate = myBlocksOperations->Propagate(theShape);
452   if (aSeqPropagate.IsNull() || aSeqPropagate->Length() == 0) {
453     SetErrorCode("Propagation groups not found");
454     return false;
455   }
456   Standard_Integer aNbGroups = aSeqPropagate->Length();
457   // Recover previous description to get rid of Propagate dump
458   aFunction->SetDescription(theDesc);
459
460 #ifdef FIND_GROUPS_BY_POINTS
461   // BEGIN: new groups search
462
463   //              W2  R2
464   //            .----.-----.----.
465   //           e|    |  |  |    |
466   //            |    |  |  |    |
467   //            .    |  |  |    .
468   //         g / ''..|  |  |..'' \
469   //       f  /      '''''''      \
470   //  .---.--'..     |  |  |     ..'--.---.
471   //  |a    \   '''...........'''   /     |
472   //  |-------\------'  |  '------/-------.
473   //  |         \       |       /         |
474   // c|           \     |     /           |
475   //  |    R1       \   |   /             |
476   //  |               \ | /               |
477   //  ._________________|_________________.
478   //  |       L1        |                 |
479   //  |                 |                 |
480   //  |                 |                 |
481   // b|                 |                 |
482   //  |                 |                 |
483   //  |-----------------|-----------------|
484   //  |    W1           |                 |
485   //  '-----------------'-----------------'
486   //          d
487
488   // "Thickness" group (a)
489   gp_Pnt aPntA (-theL1, 0, theR1 + theW1/2.);
490   aPntA.Transform(aTrsf);
491   BRepBuilderAPI_MakeVertex mkVertexA (aPntA);
492   TopoDS_Vertex aVertA = TopoDS::Vertex(mkVertexA.Shape());
493   TopoDS_Shape anEdgeA = GEOMUtils::GetEdgeNearPoint(aShape, aVertA);
494
495   // "Circular quarter of pipe" group (b)
496   gp_Pnt aPntB (-theL1, -aR1Ext * sin(M_PI/4.), -aR1Ext * sin(M_PI/4.));
497   aPntB.Transform(aTrsf);
498   BRepBuilderAPI_MakeVertex mkVertexB (aPntB);
499   TopoDS_Vertex aVertB = TopoDS::Vertex(mkVertexB.Shape());
500   TopoDS_Shape anEdgeB = GEOMUtils::GetEdgeNearPoint(aShape, aVertB);
501
502   // "Circular quarter of pipe" group (c)
503   gp_Pnt aPntC (-theL1, -aR1Ext * sin(M_PI/4.), aR1Ext * sin(M_PI/4.));
504   aPntC.Transform(aTrsf);
505   BRepBuilderAPI_MakeVertex mkVertexC (aPntC);
506   TopoDS_Vertex aVertC = TopoDS::Vertex(mkVertexC.Shape());
507   TopoDS_Shape anEdgeC = GEOMUtils::GetEdgeNearPoint(aShape, aVertC);
508
509   // "Main pipe half length" group (d)
510   gp_Pnt aPntD (-theL1/2., 0, -aR1Ext);
511   aPntD.Transform(aTrsf);
512   BRepBuilderAPI_MakeVertex mkVertexD (aPntD);
513   TopoDS_Vertex aVertD = TopoDS::Vertex(mkVertexD.Shape());
514   TopoDS_Shape anEdgeD = GEOMUtils::GetEdgeNearPoint(aShape, aVertD);
515
516   // "Incident pipe half length" group (e)
517   double aTol10 = Precision::Confusion() * 10.;
518   gp_Pnt aPntE (-aR2Ext, 0, theL2 - aTol10);
519   aPntE.Transform(aTrsf);
520   BRepBuilderAPI_MakeVertex mkVertexE (aPntE);
521   TopoDS_Vertex aVertE = TopoDS::Vertex(mkVertexE.Shape());
522   TopoDS_Shape anEdgeE = GEOMUtils::GetEdgeNearPoint(aShape, aVertE);
523
524   // "Flange" group (f)
525   double aFx = - aR2Ext - aTol10;
526   if (shapeType == TSHAPE_CHAMFER)
527     aFx -= theW;
528   else if (shapeType == TSHAPE_FILLET)
529     aFx -= theRF;
530   gp_Pnt aPntF (aFx, 0, aR1Ext);
531   aPntF.Transform(aTrsf);
532   BRepBuilderAPI_MakeVertex mkVertexF (aPntF);
533   TopoDS_Vertex aVertF = TopoDS::Vertex(mkVertexF.Shape());
534   TopoDS_Shape anEdgeF = GEOMUtils::GetEdgeNearPoint(aShape, aVertF);
535
536   // "Chamfer or Fillet" group (g)
537   TopoDS_Shape anEdgeG;
538   if (shapeType == TSHAPE_CHAMFER) {
539     gp_Pnt aPntG (-aR2Ext - theW/2., 0, aR1Ext + theH/2.);
540     aPntG.Transform(aTrsf);
541     BRepBuilderAPI_MakeVertex mkVertexG (aPntG);
542     TopoDS_Vertex aVertG = TopoDS::Vertex(mkVertexG.Shape());
543     anEdgeG = GEOMUtils::GetEdgeNearPoint(aShape, aVertG);
544   }
545   else if (shapeType == TSHAPE_FILLET) {
546     gp_Pnt aPntG (-aR2Ext - theRF/2., 0, aR1Ext + theRF/2.);
547     aPntG.Transform(aTrsf);
548     BRepBuilderAPI_MakeVertex mkVertexG (aPntG);
549     TopoDS_Vertex aVertG = TopoDS::Vertex(mkVertexG.Shape());
550     anEdgeG = GEOMUtils::GetEdgeNearPoint(aShape, aVertG);
551   }
552
553   for (int i = 1 ; i <= aNbGroups; i++) {
554     Handle(GEOM_Object) aGroup = Handle(GEOM_Object)::DownCast(aSeqPropagate->Value(i));
555     if (aGroup.IsNull())
556       continue;
557
558     TopoDS_Shape aGroupShape = aGroup->GetValue();
559     TopTools_IndexedMapOfShape anEdgesMap;
560     TopExp::MapShapes(aGroupShape, TopAbs_EDGE, anEdgesMap);
561
562     if (anEdgesMap.Contains(anEdgeA)) { // a
563       aGroup->SetName("THICKNESS");
564       theSeq->Append(aGroup);
565     }
566     else if (anEdgesMap.Contains(anEdgeB)) { // b
567       aGroup->SetName("CIRCULAR_QUARTER_PIPE");
568       theSeq->Append(aGroup);
569     }
570     else if (anEdgesMap.Contains(anEdgeC)) { // c
571       aGroup->SetName("CIRCULAR_QUARTER_PIPE");
572       theSeq->Append(aGroup);
573     }
574     else if (anEdgesMap.Contains(anEdgeD)) { // d
575       aGroup->SetName("HALF_LENGTH_MAIN_PIPE");
576       theSeq->Append(aGroup);
577     }
578     else if (anEdgesMap.Contains(anEdgeE)) { // e
579       aGroup->SetName("HALF_LENGTH_INCIDENT_PIPE");
580       theSeq->Append(aGroup);
581     }
582     else if (anEdgesMap.Contains(anEdgeF)) { // f
583       aGroup->SetName("FLANGE");
584       theSeq->Append(aGroup);
585     }
586     else if (shapeType == TSHAPE_CHAMFER) { // g
587       if (anEdgesMap.Contains(anEdgeG)) {
588         aGroup->SetName("CHAMFER");
589         theSeq->Append(aGroup);
590       }
591     }
592     else if (shapeType == TSHAPE_FILLET) { // g
593       if (anEdgesMap.Contains(anEdgeG)) {
594         aGroup->SetName("FILLET");
595         theSeq->Append(aGroup);
596       }
597     }
598     else {
599     }
600   }
601   // END: new groups search
602 #else
603   bool addGroup;
604   bool circularFoundAndAdded = false;
605   bool circularFound10 = false;
606   bool incidentPipeFound = false;
607   bool mainPipeFound = false;
608   bool mainPipeFoundAndAdded = false;
609   bool radialFound =false;
610   bool flangeFound = false;
611   bool flangeFoundAndAdded = false;
612   bool chamferOrFilletFound = false;
613
614   for (int i = 1 ; i <= aNbGroups; i++) {
615     addGroup = false;
616
617     Handle(GEOM_Object) aGroup = Handle(GEOM_Object)::DownCast(aSeqPropagate->Value(i));
618     if (aGroup.IsNull())
619       continue;
620
621     TopoDS_Shape aGroupShape = aGroup->GetValue();
622     BRepBuilderAPI_Transform aTransformationShapeInv (aGroupShape, aTrsfInv, Standard_False);
623     TopoDS_Shape aGroupShapeTrsfInv = aTransformationShapeInv.Shape();
624
625     TopTools_IndexedMapOfShape anEdgesMap;
626     TopExp::MapShapes(aGroupShapeTrsfInv,TopAbs_EDGE, anEdgesMap);
627     Standard_Integer nbEdges = anEdgesMap.Extent();
628
629     if (shapeType == TSHAPE_BASIC) {
630       if ((nbEdges >= 21) || /*R1Ext = R2Ext*/(nbEdges == 17)) { // 17, 17+8*{1,2,3}, 21, 21+8*{1,2,3}
631         addGroup = true;
632         aGroup->SetName("THICKNESS");
633       }
634       else if (nbEdges == 6) {
635         if (!circularFoundAndAdded) {
636           circularFoundAndAdded = true;
637           addGroup = true;
638           aGroup->SetName("CIRCULAR_QUARTER_PIPE");
639         }
640       }
641       else if (nbEdges == 8) {
642         incidentPipeFound = true;
643         mainPipeFound = false;
644         radialFound = false;
645         flangeFound = false;
646
647         TopExp_Explorer Ex(aGroupShapeTrsfInv,TopAbs_VERTEX);
648         while (Ex.More()) {
649           gp_Pnt aP =  BRep_Tool::Pnt(TopoDS::Vertex(Ex.Current()));
650           double x=aP.X(), y=aP.Y(), z=aP.Z();
651
652
653           if ((Abs(x) > aR2Ext + Precision::Confusion()) ||
654               (Abs(y) > aR2Ext + Precision::Confusion())) {
655             incidentPipeFound = false;
656           }
657
658           if ( z < -Precision::Confusion()) {
659             // length of main pipe
660             mainPipeFound = true;
661             if (!mainPipeFoundAndAdded) {
662               mainPipeFoundAndAdded = true;
663               addGroup = true;
664               aGroup->SetName("HALF_LENGTH_MAIN_PIPE");
665             }
666           }
667
668           else if (Abs(x) > (theL1-Precision::Confusion())) {
669             // discretisation circulaire
670             radialFound = true;
671             if (!circularFoundAndAdded) {
672               circularFoundAndAdded = true;
673               addGroup = true;
674               aGroup->SetName("CIRCULAR_QUARTER_PIPE");
675             }
676           }
677           Ex.Next();
678         }
679         if (incidentPipeFound) {
680           addGroup = true;
681           aGroup->SetName("HALF_LENGTH_INCIDENT_PIPE");
682         }
683         if (!addGroup && (!incidentPipeFound &&
684                           !radialFound &&
685                           !mainPipeFound &&
686                           !flangeFound)) {
687           // Flange (collerette)
688           flangeFound = true;
689           addGroup = true;
690           aGroup->SetName("FLANGE");
691         }
692       }
693       else
694         continue;
695     }
696     else if (shapeType == TSHAPE_CHAMFER || shapeType == TSHAPE_FILLET) {
697       if (nbEdges >= 25) { // 25, 25+8, 25+16, 25+24
698         addGroup = true;
699         aGroup->SetName("THICKNESS");
700       }
701       else if ((nbEdges == 10) || (nbEdges == 6)) {
702         if (!circularFoundAndAdded) {
703           addGroup = true;
704           circularFoundAndAdded = true;
705           aGroup->SetName("CIRCULAR_QUARTER_PIPE");
706           if (nbEdges == 10) {
707             circularFound10 = true;
708           }
709         }
710         else if (!circularFound10 && nbEdges == 10) {
711           circularFound10 = true;
712           addGroup = true;
713           aGroup->SetName("CIRCULAR_QUARTER_PIPE");
714         }
715       }
716       else if (nbEdges == 8) {
717         incidentPipeFound = true;
718         mainPipeFound = true;
719         flangeFound = false;
720
721         bool isNearZ0 = false;
722         bool isBelowZ0 = false;
723
724         TopExp_Explorer Ex (aGroupShapeTrsfInv,TopAbs_VERTEX);
725         while (Ex.More()) {
726           gp_Pnt aP = BRep_Tool::Pnt(TopoDS::Vertex(Ex.Current()));
727           double x=aP.X(), y=aP.Y(), z=aP.Z();
728
729           // tuy_princ_long_avant & tuy_princ_long_apres
730           //bool isMain = (((z < Precision::Confusion()) || (x < Precision::Confusion())) &&
731           //               ((y <= aR1Ext + Precision::Confusion()) ||
732           //                (y <= -(aR1Ext + Precision::Confusion())) ||
733           //                (y <= theR1 + Precision::Confusion()) ||
734           //                (y == -(theR1 + Precision::Confusion()))));
735           bool isMain = ((z < Precision::Confusion() || x < Precision::Confusion()) &&
736                          (fabs(y) > theR1 - Precision::Confusion() ||
737                           fabs(y) < Precision::Confusion()));
738
739           if (!isMain) {
740             mainPipeFound = false;
741           }
742
743           // collerette
744           //if (z < Precision::Confusion() && !isMain) {
745           //  flangeFound = true;
746           //  if (!flangeFoundAndAdded) {
747           //    flangeFoundAndAdded = true;
748           //    addGroup = true;
749           //    aGroup->SetName("FLANGE");
750           //  }
751           //}
752           if (fabs(z) < Precision::Confusion()) isNearZ0 = true;
753           if (z < - Precision::Confusion()) isBelowZ0 = true;
754
755           // tuyau incident
756           if ((Abs(x) > aR2Ext + Precision::Confusion()) ||
757               (Abs(y) > aR2Ext + Precision::Confusion())) {
758             incidentPipeFound = false;
759           }
760           Ex.Next();
761         }
762         if (mainPipeFound) {
763           addGroup = true;
764           aGroup->SetName("HALF_LENGTH_MAIN_PIPE");
765         }
766         if (incidentPipeFound) {
767           addGroup = true;
768           aGroup->SetName("HALF_LENGTH_INCIDENT_PIPE");
769         }
770         if (isNearZ0 && !isBelowZ0) {
771           flangeFound = true;
772           if (!flangeFoundAndAdded) {
773             flangeFoundAndAdded = true;
774             addGroup = true;
775             aGroup->SetName("FLANGE");
776           }
777         }
778         if (!addGroup && (!incidentPipeFound &&
779                           !mainPipeFound &&
780                           !flangeFound &&
781                           !chamferOrFilletFound)) {
782           addGroup = true;
783           chamferOrFilletFound = true;
784           if (shapeType == TSHAPE_CHAMFER)
785             aGroup->SetName("CHAMFER");
786           else
787             aGroup->SetName("FILLET");
788         }
789       }
790       else
791         continue;
792     }
793     // Add group to the list
794     if (addGroup)
795       theSeq->Append(aGroup);
796   }
797 #endif
798
799   SetErrorCode(OK);
800   return true;
801 }
802
803 //=============================================================================
804 /*!
805  *  Return faces that are laying on surface.
806  */
807 //=============================================================================
808 bool AdvancedEngine_IOperations::GetFacesOnSurf
809                      (const TopoDS_Shape &theShape,
810                       const Handle_Geom_Surface& theSurface,
811                       const Standard_Real theTolerance,
812                       TopTools_ListOfShape &theFaces)
813 {
814   GEOMAlgo_FinderShapeOn1 aFinder;
815
816   aFinder.SetShape(theShape);
817   aFinder.SetTolerance(theTolerance);
818   aFinder.SetSurface(theSurface);
819   aFinder.SetShapeType(TopAbs_FACE);
820   aFinder.SetState(GEOMAlgo_ST_ON);
821
822   // Sets the minimal number of inner points for the faces that do not have own
823   // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
824   // Default value=3
825   aFinder.SetNbPntsMin(3);
826   // Sets the maximal number of inner points for edges or faces.
827   // It is usefull for the cases when this number is very big (e.g =2000) to improve
828   // the performance. If this value =0, all inner points will be taken into account.
829   // Default value=0
830   aFinder.SetNbPntsMax(100);
831   aFinder.Perform();
832
833   // Interprete results
834   Standard_Integer iErr = aFinder.ErrorStatus();
835   // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
836   if (iErr) {
837     MESSAGE(" iErr : " << iErr);
838     TCollection_AsciiString aMsg (" iErr : ");
839     aMsg += TCollection_AsciiString(iErr);
840     SetErrorCode(aMsg);
841     return false;
842   }
843   Standard_Integer iWrn = aFinder.WarningStatus();
844   // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
845   if (iWrn) {
846     MESSAGE(" *** iWrn : " << iWrn);
847   }
848
849   const TopTools_ListOfShape &aListRes = aFinder.Shapes(); // the result
850   TopTools_ListIteratorOfListOfShape anIter (aListRes);
851
852   for (; anIter.More(); anIter.Next()) {
853     theFaces.Append(anIter.Value());
854   }
855
856   return true;
857 }
858
859 //=============================================================================
860 /*!
861  *  Creates and returns conical face.
862  */
863 //=============================================================================
864 TopoDS_Shape AdvancedEngine_IOperations::MakeConicalFace
865                                   (const gp_Ax2 &theAxis,
866                                    const double theRadius,
867                                    const double theRadiusThin,
868                                    const double theHeight,
869                                    const gp_Trsf &theTrsf)
870 {
871   BRepPrimAPI_MakeCone aMkCone (theAxis, theRadius, theRadiusThin, theHeight);
872   TopoDS_Shape aResult;
873   
874   aMkCone.Build();
875   if (aMkCone.IsDone()) {
876     TopExp_Explorer anExp(aMkCone.Shape(), TopAbs_FACE);
877
878     for (; anExp.More(); anExp.Next()) {
879       TopoDS_Face aFace = TopoDS::Face(anExp.Current());
880
881       if (aFace.IsNull() == Standard_False) {
882         BRepAdaptor_Surface anAdaptor(aFace, Standard_False);
883
884         if (anAdaptor.GetType() == GeomAbs_Cone) {
885           // This is a conical face. Transform and return it.
886           BRepBuilderAPI_Transform aTransf(aFace, theTrsf, Standard_False);
887           
888           aResult = aTransf.Shape();
889           break;
890         }
891       }
892     }
893   }
894
895   return aResult;
896 }
897
898 //=============================================================================
899 /*!
900  *  Generate the internal group of a Pipe T-Shape
901  */
902 //=============================================================================
903 bool AdvancedEngine_IOperations::MakeInternalGroup
904                       (const Handle(GEOM_Object) &theShape,
905                        const double theR1, const double theLen1,
906                        const double theR2, const double theLen2,
907                        const double theRL, double theTransLenL,
908                        const double theRR, double theTransLenR,
909                        const double theRI, double theTransLenI,
910                        const Handle(TColStd_HSequenceOfTransient) &theSeq,
911                        const gp_Trsf &theTrsf)
912 {
913   SetErrorCode(KO);
914
915   if (theShape.IsNull()) {
916     return false;
917   }
918
919   TopoDS_Shape aShape = theShape->GetValue();
920
921   if (aShape.IsNull()) {
922     SetErrorCode("Shape is not defined");
923     return false;
924   }
925
926   // Compute tolerance
927   Standard_Real aMaxTol = -RealLast();
928   TopExp_Explorer anExp(aShape, TopAbs_VERTEX);
929
930   for (; anExp.More(); anExp.Next()) {
931     TopoDS_Vertex aVertex = TopoDS::Vertex(anExp.Current());
932
933     if (aVertex.IsNull() == Standard_False) {
934       const Standard_Real aTol = BRep_Tool::Tolerance(aVertex);
935
936       if (aTol > aMaxTol) {
937         aMaxTol = aTol;
938       }
939     }
940   }
941
942   // Construct internal surfaces.
943   Standard_Integer i = 0;
944   const Standard_Integer aMaxNbSurf = 5;
945   Handle(Geom_Surface) aSurface[aMaxNbSurf];
946   TopTools_ListOfShape aConicalFaces;
947   Standard_Real aTolConf = Precision::Confusion();
948
949   // 1. Construct the internal surface of main pipe.
950   gp_Ax2 anAxis1 (gp::Origin(), gp::DX(), gp::DZ());
951   gp_Ax2 anAxis2 (gp::Origin(), gp::DZ(), gp::DX());
952
953   aSurface[i++] = new Geom_CylindricalSurface(anAxis1, theR1);
954
955   // 2. Construct the internal surface of incident pipe.
956   aSurface[i++] = new Geom_CylindricalSurface(anAxis2, theR2);
957
958   // 3. Construct the internal surface of left reduction pipe.
959   if (theRL > aTolConf) {
960     aSurface[i++] = new Geom_CylindricalSurface(anAxis1, theRL);
961
962     if (theTransLenL > aTolConf) {
963       // 3.1. Construct the internal surface of left transition pipe.
964       gp_Pnt aPLeft (-theLen1, 0., 0.);
965       gp_Ax2 anAxisLeft (aPLeft, -gp::DX(), gp::DZ());
966       TopoDS_Shape aConeLeft =
967         MakeConicalFace(anAxisLeft, theR1, theRL, theTransLenL, theTrsf);
968
969       if (aConeLeft.IsNull() == Standard_False) {
970         aConicalFaces.Append(aConeLeft);
971       }
972     }
973   }
974
975   // 4. Construct the internal surface of right reduction pipe.
976   if (theRR > aTolConf) {
977     // There is no need to construct another cylinder of the same radius. Skip it.
978     if (Abs(theRR - theRL) > aTolConf) {
979       aSurface[i++] = new Geom_CylindricalSurface(anAxis1, theRR);
980     }
981
982     if (theTransLenL > aTolConf) {
983       // 4.1. Construct the internal surface of right transition pipe.
984       gp_Pnt aPRight (theLen1, 0., 0.);
985       gp_Ax2 anAxisRight (aPRight, gp::DX(), gp::DZ());
986       TopoDS_Shape aConeRight =
987         MakeConicalFace(anAxisRight, theR1, theRR, theTransLenR, theTrsf);
988
989       if (aConeRight.IsNull() == Standard_False) {
990         aConicalFaces.Append(aConeRight);
991       }
992     }
993   }
994
995   // 5. Construct the internal surface of incident reduction pipe.
996   if (theRI > aTolConf) {
997     aSurface[i++] = new Geom_CylindricalSurface(anAxis2, theRI);
998
999     if (theTransLenI > aTolConf) {
1000       // 5.1. Construct the internal surface of incident transition pipe.
1001       gp_Pnt aPInci (0., 0., theLen2);
1002       gp_Ax2 anAxisInci (aPInci, gp::DZ(), gp::DX());
1003       TopoDS_Shape aConeInci =
1004         MakeConicalFace(anAxisInci, theR2, theRI, theTransLenI, theTrsf);
1005
1006       if (aConeInci.IsNull() == Standard_False) {
1007         aConicalFaces.Append(aConeInci);
1008       }
1009     }
1010   }
1011
1012   // Get faces that are laying on cylindrical surfaces.
1013   TopTools_ListOfShape aFaces;
1014   gp_Trsf anInvTrsf = theTrsf.Inverted();
1015
1016   for (i = 0; i < aMaxNbSurf; i++) {
1017     if (aSurface[i].IsNull()) {
1018       break;
1019     }
1020
1021     aSurface[i]->Transform(theTrsf);
1022
1023     TopTools_ListOfShape aLocalFaces;
1024
1025     if (!GetFacesOnSurf(aShape, aSurface[i], aMaxTol, aLocalFaces)) {
1026       return false;
1027     }
1028
1029     if (i < 2) {
1030       // Check if the result contains outer cylinders.
1031       // It is required for main and incident pipes.
1032       TopTools_ListIteratorOfListOfShape anIter(aLocalFaces);
1033
1034       while (anIter.More()) {
1035         TopExp_Explorer anExp(anIter.Value(), TopAbs_VERTEX);
1036         Standard_Boolean isInside = Standard_False;
1037
1038         // Get a vertex from this shape
1039         if (anExp.More()) {
1040           TopoDS_Vertex aVtx = TopoDS::Vertex(anExp.Current());
1041
1042           if (aVtx.IsNull() == Standard_False) {
1043             gp_Pnt aPnt = BRep_Tool::Pnt(aVtx);
1044
1045             aPnt.Transform(anInvTrsf);
1046
1047             if (i == 0) {
1048               // Check if the point is inside the main pipe.
1049               isInside = (Abs(aPnt.X()) <= theLen1);
1050             } else { // i == 1
1051               // Check if the point is inside the incident pipe.
1052               isInside = (aPnt.Z() <= theLen2);
1053             }
1054           }
1055         }
1056
1057         if (isInside) {
1058           // Keep this face.
1059           anIter.Next();
1060         } else {
1061           // Remove this face.
1062           aLocalFaces.Remove(anIter);
1063         }
1064       }
1065     }
1066
1067     aFaces.Append(aLocalFaces);
1068   }
1069
1070   // Get faces that are laying on conical faces.
1071   if (aConicalFaces.IsEmpty() == Standard_False) {
1072     Handle(GEOM_Object) aCone =
1073       GetEngine()->AddObject(GetDocID(), GEOM_TSHAPE);
1074     Handle(GEOM_Function) aFunction =
1075       aCone->AddFunction(AdvancedEngine_PipeTShapeDriver::GetID(), TSHAPE_BASIC);
1076     TopTools_ListIteratorOfListOfShape aFIter(aConicalFaces);
1077     Handle(GEOM_Object) aConeFromShape;
1078
1079     for (; aFIter.More(); aFIter.Next()) {
1080       aFunction->SetValue(aFIter.Value());
1081       aConeFromShape = myShapesOperations->GetInPlace(theShape, aCone);
1082
1083       if (aConeFromShape.IsNull() == Standard_False) {
1084         aConeFromShape->GetLastFunction()->SetDescription("");
1085         TopoDS_Shape aConeFaces = aConeFromShape->GetValue();
1086         TopExp_Explorer anExp(aConeFaces, TopAbs_FACE);
1087
1088         for (; anExp.More(); anExp.Next()) {
1089           TopoDS_Face aConeFace = TopoDS::Face(anExp.Current());
1090
1091           if (aConeFace.IsNull() == Standard_False) {
1092             aFaces.Append(aConeFace);
1093           }
1094         }
1095       }
1096     }
1097   }
1098
1099   // Create a group of internal faces.
1100   if (aFaces.IsEmpty() == Standard_False) {
1101     Handle(GEOM_Object) aGroup = myGroupOperations->CreateGroup(theShape, TopAbs_FACE);
1102
1103     if (aGroup.IsNull() == Standard_False) {
1104       aGroup->GetLastFunction()->SetDescription("");
1105       aGroup->SetName("INTERNAL_FACES");
1106
1107       TopTools_IndexedMapOfShape anIndices;
1108       Handle(TColStd_HSequenceOfInteger) aSeqIDs = new TColStd_HSequenceOfInteger;
1109
1110       TopExp::MapShapes(aShape, anIndices);
1111
1112       TopTools_ListIteratorOfListOfShape anIter(aFaces);
1113
1114       for (; anIter.More(); anIter.Next()) {
1115         const TopoDS_Shape &aFace = anIter.Value();
1116         const Standard_Integer anIndex = anIndices.FindIndex(aFace);
1117
1118         if (anIndex > 0) {
1119           aSeqIDs->Append(anIndex);
1120         }
1121       }
1122
1123       myGroupOperations->UnionIDs(aGroup, aSeqIDs);
1124       aGroup->GetLastFunction()->SetDescription("");
1125       theSeq->Append(aGroup);
1126     }
1127   }
1128
1129   SetErrorCode(OK);
1130
1131   return true;
1132 }
1133
1134 bool AdvancedEngine_IOperations::MakePipeTShapePartition(Handle(GEOM_Object) theShape,
1135                                                          double theR1, double theW1, double theL1,
1136                                                          double theR2, double theW2, double theL2,
1137                                                          double theH, double theW,
1138                                                          double theRF, bool isNormal)
1139 {
1140   SetErrorCode(KO);
1141
1142   // Build tools for partition operation:
1143   // 1 face and 2 planes
1144   // Face
1145   Handle(GEOM_Object) arete_intersect_int, arete_intersect_ext;
1146   Handle(GEOM_Object) wire_t, wire_t2, face_t, face_t2;
1147   Handle(GEOM_Object) chan_racc;
1148   Handle(GEOM_Object) vi1, vi2;
1149   Handle(GEOM_Object) Te3;
1150
1151   try {
1152     OCC_CATCH_SIGNALS;
1153     Handle(GEOM_Object) Vector_Z = myBasicOperations->MakeVectorDXDYDZ(0, 0, 1);
1154     Vector_Z->GetLastFunction()->SetDescription("");
1155
1156     // Useful values
1157     double aSize = 2*(theL1 + theL2);
1158     double aR1Ext = theR1 + theW1;
1159     double aR2Ext = theR2 + theW2;
1160     double theVertCylinderRadius = aR2Ext + theW + theRF;
1161     double theHoriCylinderRadius = aR1Ext + theH + theRF;
1162
1163     // Common edges on internal cylinder
1164     Handle(GEOM_Object) box_i = my3DPrimOperations->MakeBoxDXDYDZ(theR2, theR2, theR1);
1165     box_i->GetLastFunction()->SetDescription("");
1166     box_i = myTransformOperations->TranslateDXDYDZ(box_i, -theR2, -theR2, 0);
1167     box_i->GetLastFunction()->SetDescription("");
1168
1169     Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1170     TCollection_AsciiString theDesc = aFunction->GetDescription();
1171     Handle(TColStd_HSequenceOfTransient) edges_i =
1172       myShapesOperations->GetShapesOnBox(box_i, theShape, TopAbs_EDGE, GEOMAlgo_ST_IN);
1173     // Recover previous description to get rid of Propagate dump
1174     aFunction->SetDescription(theDesc);
1175     if (edges_i.IsNull() || edges_i->Length() == 0) {
1176       SetErrorCode("Internal edges not found");
1177       return false;
1178     }
1179     for (int i=1; i<=edges_i->Length();i++) {
1180       Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(edges_i->Value(i));
1181       anObj->GetLastFunction()->SetDescription("");
1182     }
1183     arete_intersect_int = Handle(GEOM_Object)::DownCast(edges_i->Value(1));
1184
1185     // search for vertices located on both internal pipes
1186     aFunction = theShape->GetLastFunction();
1187     theDesc = aFunction->GetDescription();
1188     Handle(TColStd_HSequenceOfTransient) vertices_i =
1189       myShapesOperations->GetShapesOnBox(box_i, theShape, TopAbs_VERTEX, GEOMAlgo_ST_ONIN);
1190     // Recover previous description to get rid of Propagate dump
1191     aFunction->SetDescription(theDesc);
1192     if (vertices_i.IsNull() || vertices_i->Length() == 0) {
1193       SetErrorCode("Internal vertices not found");
1194       return false;
1195     }
1196
1197     double d1min = theR2+theW2, d2min=theR2+theW2;
1198     for (int i = 1; i <= vertices_i->Length(); i++) {
1199       Handle(GEOM_Object) v = Handle(GEOM_Object)::DownCast(vertices_i->Value(i));
1200       v->GetLastFunction()->SetDescription("");
1201       TopoDS_Vertex aVertex = TopoDS::Vertex(v->GetValue());
1202       gp_Pnt aP = BRep_Tool::Pnt(aVertex);
1203       if (Abs(aP.X()) <= Precision::Confusion()) {
1204         if (Abs(aP.Y()) < d1min) {
1205           vi1 = v;
1206           d1min = Abs(aP.Y());
1207         }
1208       } else if (Abs(aP.Y()) <= Precision::Confusion()) {
1209         if (Abs(aP.X()) < d2min) {
1210           vi2 = v;
1211           d2min = Abs(aP.X());
1212         }
1213       }
1214     }
1215     if (vi1.IsNull() || vi2.IsNull()) {
1216       SetErrorCode("Cannot find internal intersection vertices");
1217       return false;
1218     }
1219
1220     std::list<Handle(GEOM_Object)> theShapes;
1221
1222     if (isNormal) {
1223       Handle(GEOM_Object) ve1, ve2;
1224       TopoDS_Vertex vertex1, vertex2;
1225
1226       Handle(GEOM_Object) box_e = my3DPrimOperations->MakeBoxDXDYDZ(aR2Ext, aR2Ext, aR1Ext);
1227       box_e->GetLastFunction()->SetDescription("");
1228       box_e = myTransformOperations->TranslateDXDYDZ(box_e, -aR2Ext, -aR2Ext, 0);
1229       box_e->GetLastFunction()->SetDescription("");
1230
1231       // search for vertices located on both external pipes
1232       aFunction = theShape->GetLastFunction();
1233       theDesc = aFunction->GetDescription();
1234       Handle(TColStd_HSequenceOfTransient) vertices_e =
1235         myShapesOperations->GetShapesOnBox(box_e, theShape, TopAbs_VERTEX, GEOMAlgo_ST_ONIN);
1236       // Recover previous description to get rid of Propagate dump
1237       aFunction->SetDescription(theDesc);
1238       if (vertices_e.IsNull() || vertices_e->Length() == 0) {
1239         SetErrorCode("External vertices not found");
1240         return false;
1241       }
1242
1243       double d1max = 0, d2max = 0;
1244       for (int i = 1; i <= vertices_e->Length(); i++) {
1245         Handle(GEOM_Object) v = Handle(GEOM_Object)::DownCast(vertices_e->Value(i));
1246         v->GetLastFunction()->SetDescription("");
1247         TopoDS_Vertex aVertex = TopoDS::Vertex(v->GetValue());
1248         gp_Pnt aP = BRep_Tool::Pnt(aVertex);
1249         if (Abs(aP.X()) <= Precision::Confusion()) {
1250           if (Abs(aP.Y()) > d1max) {
1251             ve1 = v;
1252             vertex1 = aVertex;
1253             d1max = Abs(aP.Y());
1254           }
1255         } else if (Abs(aP.Y()) <= Precision::Confusion()) {
1256           if (Abs(aP.X()) > d2max) {
1257             ve2 = v;
1258             vertex2 = aVertex;
1259             d2max = Abs(aP.X());
1260           }
1261         }
1262       }
1263       if (ve1.IsNull() || ve2.IsNull()) {
1264         SetErrorCode("Cannot find external intersection vertices");
1265         return false;
1266       }
1267       Handle(GEOM_Object) edge_e1, edge_e2;
1268
1269       // Common edges on external cylinder
1270       aFunction = theShape->GetLastFunction();
1271       theDesc = aFunction->GetDescription();
1272       Handle(TColStd_HSequenceOfTransient) edges_e =
1273         myShapesOperations->GetShapesOnBox(box_e, theShape, TopAbs_EDGE, GEOMAlgo_ST_IN);
1274       // Recover previous description to get rid of Propagate dump
1275       aFunction->SetDescription(theDesc);
1276       if (edges_e.IsNull() || edges_e->Length() == 0) {
1277         SetErrorCode("External edges not found");
1278         return false;
1279       }
1280       ShapeAnalysis_Edge sae;
1281       for (int i=1; i<=edges_e->Length();i++) {
1282         Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(edges_e->Value(i));
1283         anObj->GetLastFunction()->SetDescription("");
1284         TopoDS_Edge anEdge = TopoDS::Edge(anObj->GetValue());
1285         if ( !anEdge.IsNull() && 
1286              (sae.FirstVertex(anEdge).IsSame(vertex1) || sae.LastVertex(anEdge).IsSame(vertex1)) && 
1287              (sae.FirstVertex(anEdge).IsSame(vertex2) || sae.LastVertex(anEdge).IsSame(vertex2))) {
1288           arete_intersect_ext = anObj;
1289         }
1290       }
1291
1292       edge_e1 = myBasicOperations->MakeLineTwoPnt(ve1, vi1);
1293       if (edge_e1.IsNull()) {
1294         SetErrorCode("Edge 1 could not be built");
1295         return false;
1296       }
1297
1298       edge_e2 = myBasicOperations->MakeLineTwoPnt(ve2, vi2);
1299       if (edge_e2.IsNull()) {
1300         SetErrorCode("Edge 2 could not be built");
1301         return false;
1302       }
1303
1304       edge_e1->GetLastFunction()->SetDescription("");
1305       edge_e2->GetLastFunction()->SetDescription("");
1306
1307       std::list<Handle(GEOM_Object)> edge_e_elist;
1308       edge_e_elist.push_back(arete_intersect_int);
1309       edge_e_elist.push_back(edge_e1);
1310       edge_e_elist.push_back(arete_intersect_ext);
1311       edge_e_elist.push_back(edge_e2);
1312       wire_t = myShapesOperations->MakeWire(edge_e_elist, 1e-7);
1313       if (wire_t.IsNull()) {
1314         SetErrorCode("Impossible to build wire");
1315         return false;
1316       }
1317       wire_t->GetLastFunction()->SetDescription("");
1318       face_t = myShapesOperations->MakeFace(wire_t, false);
1319       if (face_t.IsNull()) {
1320         SetErrorCode("Impossible to build face");
1321         return false;
1322       }
1323       face_t->GetLastFunction()->SetDescription("");
1324
1325       theShapes.push_back(theShape);
1326       theShapes.push_back(vi1);
1327       theShapes.push_back(vi2);
1328       theShapes.push_back(ve1);
1329       theShapes.push_back(ve2);
1330       theShapes.push_back(edge_e1);
1331       theShapes.push_back(edge_e2);
1332       theShapes.push_back(wire_t);
1333       theShapes.push_back(face_t);
1334     }
1335     else {
1336       Handle(GEOM_Object) P1, P2, P3, P4, P5, P6;
1337       int idP1, idP2, idP3, idP4;
1338       int PZX, PZY;
1339       double ZX=0, ZY=0;
1340       std::vector<int> LX;
1341       std::vector<int> LY;
1342       Handle(GEOM_Object) box_e = my3DPrimOperations->MakeBoxDXDYDZ
1343         (theVertCylinderRadius, theVertCylinderRadius, theHoriCylinderRadius);
1344       box_e->GetLastFunction()->SetDescription("");
1345       box_e = myTransformOperations->TranslateDXDYDZ
1346         (box_e, -theVertCylinderRadius, -theVertCylinderRadius, 0);
1347       box_e->GetLastFunction()->SetDescription("");
1348
1349       aFunction = theShape->GetLastFunction();
1350       theDesc = aFunction->GetDescription();
1351       Handle(TColStd_HSequenceOfTransient) extremVertices =
1352         myShapesOperations->GetShapesOnBox(box_e, theShape, TopAbs_VERTEX, GEOMAlgo_ST_ONIN);
1353       // Recover previous description to get rid of Propagate dump
1354       aFunction->SetDescription(theDesc);
1355
1356       if (extremVertices.IsNull() || extremVertices->Length() == 0) {
1357         if (theRF == 0)
1358           SetErrorCode("Vertices on chamfer not found");
1359         else
1360           SetErrorCode("Vertices on fillet not found");
1361         return false;
1362       }
1363
1364       theShapes.push_back(theShape);
1365       theShapes.push_back(box_e);
1366       if (extremVertices->Length() != 6) {
1367         //           for (int i=1; i<=extremVertices->Length(); i++){
1368         //             theShapes.push_back(Handle(GEOM_Object)::DownCast(extremVertices->Value(i)));
1369         //           }
1370         //           Handle(GEOM_Object) aCompound = myShapesOperations->MakeCompound(theShapes);
1371         //           TopoDS_Shape aCompoundShape = aCompound->GetValue();
1372         //           theShape->GetLastFunction()->SetValue(aCompoundShape);
1373         SetErrorCode("Bad number of vertices on chamfer found");
1374         return false;
1375       }
1376
1377       for (int i=1; i<=extremVertices->Length(); i++){
1378         Handle(GEOM_Object) aV = Handle(GEOM_Object)::DownCast(extremVertices->Value(i));
1379         aV->GetLastFunction()->SetDescription("");
1380         gp_Pnt aP = BRep_Tool::Pnt(TopoDS::Vertex(aV->GetValue()));
1381
1382         if (Abs(aP.X()) <= Precision::Confusion()) {
1383           if (Abs(aP.Y()) - theR2 > Precision::Confusion()) {
1384             LX.push_back(i);
1385             if  (aP.Z()-ZX > Precision::Confusion()) {
1386               ZX = aP.Z();
1387               PZX = i;
1388             }
1389           }
1390         }
1391         else {
1392           if (Abs(aP.X()) - theR2 > Precision::Confusion()) {
1393             LY.push_back(i);
1394             if (aP.Z() - ZY > Precision::Confusion()) {
1395               ZY = aP.Z();
1396               PZY = i;
1397             }
1398           }
1399         }
1400       }
1401
1402       idP2 = PZX;
1403       idP4 = PZY;
1404       idP1 = LX.at(0);
1405       if (LX.at(0) == PZX)
1406         idP1 = LX.at(1);
1407       idP3 = LY.at(0);
1408       if (LY.at(0) == PZY)
1409         idP3 = LY.at(1);
1410
1411       P1 = Handle(GEOM_Object)::DownCast(extremVertices->Value(idP1));
1412       P2 = Handle(GEOM_Object)::DownCast(extremVertices->Value(idP2));
1413       P3 = Handle(GEOM_Object)::DownCast(extremVertices->Value(idP3));
1414       P4 = Handle(GEOM_Object)::DownCast(extremVertices->Value(idP4));
1415
1416       Handle(GEOM_Object) Cote_1 = myBasicOperations->MakeLineTwoPnt(P1, vi1);
1417       if (Cote_1.IsNull()) {
1418         SetErrorCode("Impossible to build edge in thickness");
1419         return false;
1420       }
1421       Cote_1->GetLastFunction()->SetDescription("");
1422
1423       Handle(GEOM_Object) Cote_2 = myBasicOperations->MakeLineTwoPnt(vi2, P3);
1424       if (Cote_2.IsNull()) {
1425         SetErrorCode("Impossible to build edge in thickness");
1426         return false;
1427       }
1428       Cote_2->GetLastFunction()->SetDescription("");
1429
1430       // edge_chan_princ = arete du chanfrein (ou raccord) sur le tuyau principal
1431       // edge_chan_inc = arete du chanfrein (ou raccord) sur le tuyau incident
1432       //         std::cerr << "Getting chamfer edge on main pipe" << std::endl;
1433       Handle(GEOM_Object) edge_chan_princ = myBlocksOperations->GetEdge(theShape, P1, P3);
1434       if (edge_chan_princ.IsNull()) {
1435         SetErrorCode("Impossible to find edge on main pipe");
1436         return false;
1437       }
1438       edge_chan_princ->GetLastFunction()->SetDescription("");
1439
1440       Handle(GEOM_Object) edge_chan_inc = myBlocksOperations->GetEdge(theShape, P2, P4);
1441       if (edge_chan_inc.IsNull()) {
1442         SetErrorCode("Impossible to find edge on incident pipe");
1443         return false;
1444       }
1445       edge_chan_inc->GetLastFunction()->SetDescription("");
1446
1447       std::list<Handle(GEOM_Object)> edgeList1;
1448       edgeList1.push_back(edge_chan_princ);
1449       edgeList1.push_back(Cote_1);
1450       edgeList1.push_back(arete_intersect_int);
1451       edgeList1.push_back(Cote_2);
1452
1453       //         std::cerr << "Creating wire 1" << std::endl;
1454       wire_t = myShapesOperations->MakeWire(edgeList1, 1e-7);
1455       if (wire_t.IsNull()) {
1456         SetErrorCode("Impossible to build wire");
1457         return false;
1458       }
1459       wire_t->GetLastFunction()->SetDescription("");
1460
1461       //         std::cerr << "Creating face 1" << std::endl;
1462       face_t = myShapesOperations->MakeFace(wire_t, false);
1463       if (face_t.IsNull()) {
1464         SetErrorCode("Impossible to build face");
1465         return false;
1466       }
1467       face_t->GetLastFunction()->SetDescription("");
1468       theShapes.push_back(face_t);
1469
1470       gp_Pnt aP2 = BRep_Tool::Pnt(TopoDS::Vertex(P2->GetValue()));
1471       gp_Pnt aP5 = BRep_Tool::Pnt(TopoDS::Vertex(vi1->GetValue()));
1472       double deltaZ = aP2.Z() - aP5.Z();
1473       //         std::cerr << "Creating new point from vi1 with deltaZ = " << deltaZ << std::endl;
1474       Handle(GEOM_Object) P5bis = myTransformOperations->TranslateDXDYDZCopy(vi1, 0, 0, deltaZ);
1475       if (P5bis.IsNull()) {
1476         SetErrorCode("Impossible to translate vertex");
1477         return false;
1478       }
1479       P5bis->GetLastFunction()->SetDescription("");
1480
1481       gp_Pnt aP4 = BRep_Tool::Pnt(TopoDS::Vertex(P4->GetValue()));
1482       gp_Pnt aP6 = BRep_Tool::Pnt(TopoDS::Vertex(vi2->GetValue()));
1483       deltaZ = aP4.Z() - aP6.Z();
1484       //         std::cerr << "Creating new point from vi2 with deltaZ = " << deltaZ << std::endl;
1485       Handle(GEOM_Object) P6bis = myTransformOperations->TranslateDXDYDZCopy(vi2, 0, 0, deltaZ);
1486       if (P6bis.IsNull()) {
1487         SetErrorCode("Impossible to translate vertex");
1488         return false;
1489       }
1490       P6bis->GetLastFunction()->SetDescription("");
1491
1492       //         std::cerr << "Creating new line 1 from 2 previous points" << std::endl;
1493       Handle(GEOM_Object) Cote_3 = myBasicOperations->MakeLineTwoPnt(P5bis, P2);
1494       if (Cote_3.IsNull()) {
1495         SetErrorCode("Impossible to build edge in thickness");
1496         return false;
1497       }
1498       Cote_3->GetLastFunction()->SetDescription("");
1499
1500       //         std::cerr << "Creating new line 2 from 2 previous points" << std::endl;
1501       Handle(GEOM_Object) Cote_4 = myBasicOperations->MakeLineTwoPnt(P6bis, P4);
1502       if (Cote_4.IsNull()) {
1503         SetErrorCode("Impossible to build edge in thickness");
1504         return false;
1505       }
1506       Cote_4->GetLastFunction()->SetDescription("");
1507
1508       //         std::cerr << "Creating new line 3 from 2 previous points" << std::endl;
1509       Handle(GEOM_Object) Cote_5 = myBasicOperations->MakeLineTwoPnt(P5bis, P6bis);
1510       if (Cote_4.IsNull()) {
1511         SetErrorCode("Impossible to build edge in thickness");
1512         return false;
1513       }
1514       Cote_5->GetLastFunction()->SetDescription("");
1515
1516       //std::list<Handle(GEOM_Object)> edgeList2;
1517       //edgeList2.push_back(edge_chan_inc);
1518       //edgeList2.push_back(Cote_3);
1519       //edgeList2.push_back(Cote_5);
1520       //edgeList2.push_back(Cote_4);
1521       //         std::cerr << "Creating wire 2" << std::endl;
1522       //wire_t2 = myShapesOperations->MakeWire(edgeList2, 1e-7);
1523       //if (wire_t2.IsNull()) {
1524       //  SetErrorCode("Impossible to build wire");
1525       //  return false;
1526       //}
1527       //wire_t2->GetLastFunction()->SetDescription("");
1528       //         std::cerr << "Creating face 2" << std::endl;
1529       //face_t2 = myShapesOperations->MakeFace(wire_t2, false);
1530
1531       // Mantis issue 0021682
1532       face_t2 = my3DPrimOperations->MakePrismVecH(edge_chan_inc, Cote_4, - (theR2 + theW2));
1533       //face_t2 = my3DPrimOperations->MakePrismVecH(edge_chan_inc, Cote_4, - 2.0*theR2);
1534       if (face_t2.IsNull()) {
1535         SetErrorCode("Impossible to build face");
1536         return false;
1537       }
1538       face_t2->GetLastFunction()->SetDescription("");
1539       theShapes.push_back(face_t2);
1540     }
1541
1542     // Planes
1543     Handle(GEOM_Object) aP0 = myBasicOperations->MakePointXYZ(0, 0, 0);
1544     Handle(GEOM_Object) aVZ = myBasicOperations->MakeVectorDXDYDZ(0, 0, 1);
1545     Handle(GEOM_Object) aVXZ = myBasicOperations->MakeVectorDXDYDZ(aR1Ext, 0, 0.5*(theL1+theVertCylinderRadius));
1546     Handle(GEOM_Object) aPlnOZ = myBasicOperations->MakePlanePntVec(aP0, aVZ, aSize);
1547     Handle(GEOM_Object) aPlnOXZ = myBasicOperations->MakePlanePntVec(aP0, aVXZ, aSize);
1548     aP0->GetLastFunction()->SetDescription("");
1549     aVZ->GetLastFunction()->SetDescription("");
1550     aVXZ->GetLastFunction()->SetDescription("");
1551     aPlnOZ->GetLastFunction()->SetDescription("");
1552     aPlnOXZ->GetLastFunction()->SetDescription("");
1553     theShapes.push_back(aPlnOZ);
1554     theShapes.push_back(aPlnOXZ);
1555
1556     // Partition
1557     Handle(TColStd_HSequenceOfTransient) partitionShapes = new TColStd_HSequenceOfTransient;
1558     Handle(TColStd_HSequenceOfTransient) theTools = new TColStd_HSequenceOfTransient;
1559     Handle(TColStd_HSequenceOfTransient) theKeepInside = new TColStd_HSequenceOfTransient;
1560     Handle(TColStd_HSequenceOfTransient) theRemoveInside = new TColStd_HSequenceOfTransient;
1561     Handle(TColStd_HArray1OfInteger) theMaterials;
1562
1563     partitionShapes->Append(theShape);
1564     theTools->Append(aPlnOZ);
1565     if (Abs(aR1Ext - aR2Ext) > Precision::Confusion())
1566       theTools->Append(aPlnOXZ);
1567     theTools->Append(face_t);
1568     if (!isNormal)
1569       theTools->Append(face_t2);
1570
1571     Te3 = myBooleanOperations->MakePartition
1572               (partitionShapes, theTools, theKeepInside, theRemoveInside,
1573               TopAbs_SOLID, false, theMaterials, 0, false, Standard_False);
1574     if (Te3.IsNull()) {
1575       SetErrorCode("Impossible to build partition of TShape");
1576       return false;
1577     }
1578     Te3->GetLastFunction()->SetDescription("");
1579
1580     // Last verification: result should be a block
1581     std::list<GEOMImpl_IBlocksOperations::BCError> errList;
1582     if (!myBlocksOperations->CheckCompoundOfBlocks(Te3,errList)) {
1583       SetErrorCode("TShape is not a compound of block");
1584       return false;
1585     }
1586
1587 //     // BEGIN Compound of created shapes - Only for debug purpose
1588 //     theShapes.clear();
1589 //     theShapes.push_back(theShape);
1590 //     theShapes.push_back(aPlnOZ);
1591 //     if (Abs(aR1Ext - aR2Ext) > Precision::Confusion() )
1592 //       theShapes.push_back(aPlnOXZ);
1593 //     theShapes.push_back(face_t);
1594 //     if (!isNormal)
1595 //       theShapes.push_back(face_t2);
1596 //
1597 //     Handle(GEOM_Object) aCompound = myShapesOperations->MakeCompound(theShapes);
1598 //     TopoDS_Shape aCompoundShape = aCompound->GetValue();
1599 //     theShape->GetLastFunction()->SetValue(aCompoundShape);
1600 //     // END Compound of created shapes - Only for debug purpose
1601
1602     TopoDS_Shape aShape = Te3->GetValue();
1603     theShape->GetLastFunction()->SetValue(aShape);
1604   }
1605   catch (Standard_Failure) {
1606     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1607     SetErrorCode(aFail->GetMessageString());
1608     return false;
1609   }
1610
1611   SetErrorCode(OK);
1612   return true;
1613 }
1614
1615 // Mirror and glue faces
1616 bool AdvancedEngine_IOperations::MakePipeTShapeMirrorAndGlue(Handle(GEOM_Object) theShape,
1617                                                              double theR1, double theW1, double theL1,
1618                                                              double theR2, double theW2, double theL2)
1619 {
1620   SetErrorCode(KO);
1621
1622   // Useful values
1623   double aSize = 2*(theL1 + theL2);
1624   double aR1Ext = theR1 + theW1;
1625
1626   // Planes
1627   Handle(GEOM_Object) aP0 = myBasicOperations->MakePointXYZ(0, 0, 0);
1628   aP0->GetLastFunction()->SetDescription("");
1629   Handle(GEOM_Object) aVX = myBasicOperations->MakeVectorDXDYDZ(1, 0, 0);
1630   Handle(GEOM_Object) aVY = myBasicOperations->MakeVectorDXDYDZ(0, 1, 0);
1631   aVX->GetLastFunction()->SetDescription("");
1632   aVY->GetLastFunction()->SetDescription("");
1633   Handle(GEOM_Object) aPlane_OX = myBasicOperations->MakePlanePntVec(aP0, aVX, 2*(aR1Ext + theL2));
1634   Handle(GEOM_Object) aPlane_OY = myBasicOperations->MakePlanePntVec(aP0, aVY, aSize);
1635   aPlane_OX->GetLastFunction()->SetDescription("");
1636   aPlane_OY->GetLastFunction()->SetDescription("");
1637
1638   Handle(GEOM_Object) Te4 = myTransformOperations->MirrorPlaneCopy(theShape, aPlane_OX);
1639   if (Te4.IsNull()) {
1640     SetErrorCode("Impossible to build mirror of quarter TShape");
1641     return false;
1642   }
1643
1644   Handle(GEOM_Object) Te5 = myTransformOperations->MirrorPlaneCopy(theShape, aPlane_OY);
1645   if (Te5.IsNull()) {
1646     SetErrorCode("Impossible to build mirror of half TShape");
1647     return false;
1648   }
1649
1650   Handle(GEOM_Object) Te6 = myTransformOperations->MirrorPlaneCopy(Te4, aPlane_OY);
1651   if (Te6.IsNull()) {
1652     SetErrorCode("Impossible to build mirror of half TShape");
1653     return false;
1654   }
1655
1656   std::list<Handle(GEOM_Object)> aShapesList;
1657   aShapesList.push_back(theShape);
1658   aShapesList.push_back(Te4);
1659   aShapesList.push_back(Te5);
1660   aShapesList.push_back(Te6);
1661   Handle(GEOM_Object) Te7 = myShapesOperations->MakeCompound(aShapesList);
1662   if (Te7.IsNull()) {
1663     SetErrorCode("Impossible to build compound");
1664     return false;
1665   }
1666
1667   // Copy source shape
1668   TopoDS_Shape aShapeCopy;
1669   TColStd_IndexedDataMapOfTransientTransient aMapTShapes;
1670   TNaming_CopyShape::CopyTool(Te7->GetValue(), aMapTShapes, aShapeCopy);
1671
1672   std::list<Handle(GEOM_Object)> Te7list( 1, Te7 );
1673   Handle(GEOM_Object) Te8 = myShapesOperations->MakeGlueFaces(Te7list, 1e-7, true);
1674   if (Te8.IsNull()) {
1675     SetErrorCode("Impossible to glue faces of TShape");
1676     return false;
1677   }
1678
1679   TopoDS_Shape aShape = Te8->GetValue();
1680   BRepCheck_Analyzer anAna (aShape, Standard_True);
1681
1682   if (!anAna.IsValid()) {
1683     // Try to do gluing with the tolerance equal to maximal
1684     // tolerance of vertices of the source shape.
1685     Standard_Real aTolMax = -RealLast();
1686
1687     for (TopExp_Explorer ExV (aShapeCopy, TopAbs_VERTEX); ExV.More(); ExV.Next()) {
1688       TopoDS_Vertex aVertex = TopoDS::Vertex(ExV.Current());
1689       Standard_Real aTol = BRep_Tool::Tolerance(aVertex);
1690
1691       if (aTol > aTolMax) {
1692         aTolMax = aTol;
1693       }
1694     }
1695
1696     // Perform gluing
1697     Te7->GetLastFunction()->SetValue(aShapeCopy);
1698     Te8 = myShapesOperations->MakeGlueFaces(Te7list, aTolMax, true);
1699
1700     if (Te8.IsNull()) {
1701       SetErrorCode("Impossible to glue faces of TShape");
1702       return false;
1703     }
1704
1705     aShape = Te8->GetValue();
1706   }
1707
1708
1709   theShape->GetLastFunction()->SetValue(aShape);
1710
1711   Te4->GetLastFunction()->SetDescription("");
1712   Te5->GetLastFunction()->SetDescription("");
1713   Te6->GetLastFunction()->SetDescription("");
1714   Te7->GetLastFunction()->SetDescription("");
1715   Te8->GetLastFunction()->SetDescription("");
1716
1717   SetErrorCode(OK);
1718   return true;
1719 }
1720
1721 //=======================================================================
1722 //function : MakePipeTShapeThicknessReduction
1723 //purpose  : Static method. Add thiskness reduction elements at the three
1724 //                          open ends of the T-Shape.
1725 //=======================================================================
1726 TopoDS_Shape AdvancedEngine_IOperations::MakePipeTShapeThicknessReduction
1727                                   (TopoDS_Shape theShape,
1728                                    double r1, double w1, double l1,
1729                                    double r2, double w2, double l2,
1730                                    double rL, double wL, double ltransL, double lthinL,
1731                                    double rR, double wR, double ltransR, double lthinR,
1732                                    double rI, double wI, double ltransI, double lthinI,
1733                                    bool fuseReductions)
1734 {
1735   // Add thickness reduction elements
1736   // at the three extremities: Left, Right and Incident
1737   //
1738   // ---------------------.
1739   //   W                   \
1740   // ---------------------. \
1741   //   ^                   \ '-----------------.
1742   //   |R                   \        Wthin     |
1743   //   |                     '-----------------'
1744   //   v                             Rthin
1745   // --.--.--.--.--.--.--.--.--.--.--.--.--.--.--
1746   //                     Ltrans    Lthin
1747
1748   TopoDS_Shape aResult = theShape;
1749   double aTol = Precision::Confusion();
1750
1751   gp_Vec aVX = gp::DX(), aVZ = gp::DZ();
1752
1753   // Left reduction (rL, wL, ltransL, lthinL)
1754   if (rL > aTol && wL > aTol && ltransL > aTol) {
1755     gp_Pnt aPLeft (-l1, 0, 0);
1756     gp_Ax2 anAxesLeft (aPLeft, -aVX, aVZ);
1757     TopoDS_Shape aReductionLeft = AdvancedEngine_IOperations::MakeThicknessReduction
1758       (anAxesLeft, r1, w1, rL, wL, ltransL, lthinL, fuseReductions);
1759
1760     if (fuseReductions) {
1761       BRepAlgoAPI_Fuse fuseL (aResult, aReductionLeft);
1762       if (!fuseL.IsDone())
1763         StdFail_NotDone::Raise("Cannot fuse Te with left reduction");
1764       aResult = fuseL.Shape();
1765     }
1766     else {
1767       BRep_Builder B;
1768       TopoDS_Compound C;
1769       B.MakeCompound(C);
1770       B.Add(C, aResult);
1771       B.Add(C, aReductionLeft);
1772       aResult = C;
1773     }
1774   }
1775
1776   // Right reduction
1777   if (rR > aTol && wR > aTol && ltransR > aTol) {
1778     gp_Pnt aPRight (l1, 0, 0);
1779     gp_Ax2 anAxesRight (aPRight, aVX, aVZ);
1780     TopoDS_Shape aReductionRight = AdvancedEngine_IOperations::MakeThicknessReduction
1781       (anAxesRight, r1, w1, rR, wR, ltransR, lthinR, fuseReductions);
1782
1783     if (fuseReductions) {
1784       BRepAlgoAPI_Fuse fuseR (aResult, aReductionRight);
1785       if (!fuseR.IsDone())
1786         StdFail_NotDone::Raise("Cannot fuse Te with right reduction");
1787       aResult = fuseR.Shape();
1788     }
1789     else {
1790       BRep_Builder B;
1791       TopoDS_Compound C;
1792       B.MakeCompound(C);
1793       B.Add(C, aResult);
1794       B.Add(C, aReductionRight);
1795       aResult = C;
1796     }
1797   }
1798
1799   // Incident reduction
1800   if (rI > aTol && wI > aTol && ltransI > aTol) {
1801     gp_Pnt aPInci (0, 0, l2);
1802     gp_Ax2 anAxesInci (aPInci, aVZ, aVX);
1803     TopoDS_Shape aReductionInci = AdvancedEngine_IOperations::MakeThicknessReduction
1804       (anAxesInci, r2, w2, rI, wI, ltransI, lthinI, fuseReductions);
1805
1806     if (fuseReductions) {
1807       BRepAlgoAPI_Fuse fuseInci (aResult, aReductionInci);
1808       if (!fuseInci.IsDone())
1809         StdFail_NotDone::Raise("Cannot fuse Te with incident reduction");
1810       aResult = fuseInci.Shape();
1811     }
1812     else {
1813       BRep_Builder B;
1814       TopoDS_Compound C;
1815       B.MakeCompound(C);
1816       B.Add(C, aResult);
1817       B.Add(C, aReductionInci);
1818       aResult = C;
1819     }
1820   }
1821
1822   // Get rid of extra compounds
1823   TopTools_ListOfShape listShapeRes;
1824   GEOMUtils::AddSimpleShapes(aResult, listShapeRes);
1825   aResult = listShapeRes.First(); // useful for the case "fuseReductions == true"
1826
1827   if (!fuseReductions && listShapeRes.Extent() > 1) {
1828     // Simplify T-Shape compound (get rid of sub-compounds) and glue duplicated faces
1829     BRep_Builder B;
1830     TopoDS_Compound C;
1831     B.MakeCompound(C);
1832
1833     TopTools_ListIteratorOfListOfShape itSub (listShapeRes);
1834     for (; itSub.More(); itSub.Next())
1835       B.Add(C, itSub.Value());
1836
1837     // GlueFaces
1838     aResult = GEOMImpl_GlueDriver::GlueFaces(C, Precision::Confusion(), Standard_True);
1839   }
1840
1841   return aResult;
1842 }
1843
1844 //=======================================================================
1845 //function : MakeThicknessReduction
1846 //purpose  : Static method. Create one thickness reduction element.
1847 //=======================================================================
1848 TopoDS_Shape AdvancedEngine_IOperations::MakeThicknessReduction (gp_Ax2 theAxes,
1849                                                                  const double R, const double W,
1850                                                                  const double Rthin, const double Wthin,
1851                                                                  const double Ltrans, const double Lthin,
1852                                                                  bool fuse)
1853 {
1854   double aTol = Precision::Confusion();
1855   if (Rthin < aTol || Wthin < aTol || Ltrans < aTol) {
1856     StdFail_NotDone::Raise("Cannot build thickness reduction: too small values");
1857   }
1858   bool isThinPart = (Lthin > aTol);
1859
1860   //     .
1861   //   W |\
1862   //     . \
1863   //   ^  \ '-----------------.
1864   //   |R  \|                 | Wthin
1865   //   |    '-----------------'
1866   //   v                        Rthin
1867   // --.--.--.--.--.--.--.--.--.--.--.--.--> theAxes.Direction()
1868   //     Ltrans     Lthin
1869
1870   double RExt = R + W;
1871   double RthinExt = Rthin + Wthin;
1872
1873   gp_Dir aNormal = theAxes.Direction();
1874   gp_Dir anXDir  = theAxes.XDirection();
1875   gp_Pnt aPntCyl (theAxes.Location().XYZ() + aNormal.XYZ()*Ltrans);
1876   gp_Ax2 anAxesCyl (aPntCyl, aNormal, anXDir);
1877
1878   // Build the transition part
1879   BRepPrimAPI_MakeCone ConeExt (theAxes, RExt, RthinExt, Ltrans);
1880   BRepPrimAPI_MakeCone ConeInt (theAxes, R, Rthin, Ltrans);
1881   ConeExt.Build();
1882   ConeInt.Build();
1883   if (!ConeExt.IsDone() || !ConeInt.IsDone())
1884     StdFail_NotDone::Raise("Cannot build cones of thickness reduction");
1885   BRepAlgoAPI_Cut cut1 (ConeExt.Shape(), ConeInt.Shape());
1886   if (!cut1.IsDone())
1887     StdFail_NotDone::Raise("Coudn't build transition part of thickness reduction");
1888   TopoDS_Shape aReduction = cut1.Shape();
1889
1890   // Build the thin part, if required
1891   TopoDS_Shape aThinPart;
1892   if (isThinPart) {
1893     BRepPrimAPI_MakeCylinder CExt (anAxesCyl, RthinExt, Lthin);
1894     BRepPrimAPI_MakeCylinder CInt (anAxesCyl, Rthin, Lthin);
1895     CExt.Build();
1896     CInt.Build();
1897     if (!CExt.IsDone() || !CInt.IsDone())
1898       StdFail_NotDone::Raise("Cannot build cylinders of thickness reduction");
1899     BRepAlgoAPI_Cut cut2 (CExt.Shape(), CInt.Shape());
1900     if (!cut2.IsDone())
1901       StdFail_NotDone::Raise("Coudn't build thin part of thickness reduction");
1902     aThinPart = cut2.Shape();
1903   }
1904
1905   // Join parts
1906   if (fuse) {
1907     if (isThinPart) {
1908       BRepAlgoAPI_Fuse fuse1 (aReduction, aThinPart);
1909       if (!fuse1.IsDone())
1910         StdFail_NotDone::Raise("Cannot fuse parts of thickness reduction");
1911       aReduction = fuse1.Shape();
1912     }
1913   }
1914   else {
1915     // Partition the reduction on blocks
1916     gp_Ax3 anAxesPln1 (aPntCyl, theAxes.XDirection(), aNormal);
1917     gp_Ax3 anAxesPln2 (aPntCyl, theAxes.YDirection(), aNormal);
1918     gp_Pln aPln1 (anAxesPln1);
1919     gp_Pln aPln2 (anAxesPln2);
1920     double aSize = Ltrans + Lthin + R + Rthin + Wthin; // to guarantee enough size in all directions
1921     TopoDS_Shape aTool1 = BRepBuilderAPI_MakeFace(aPln1, -aSize, +aSize, -aSize, +aSize).Shape();
1922     TopoDS_Shape aTool2 = BRepBuilderAPI_MakeFace(aPln2, -aSize, +aSize, -aSize, +aSize).Shape();
1923
1924     GEOMAlgo_Splitter PS;
1925     PS.AddArgument(aReduction);
1926     if (isThinPart)
1927       PS.AddArgument(aThinPart);
1928     PS.AddTool(aTool1);
1929     PS.AddTool(aTool2);
1930     PS.SetLimit(TopAbs_SOLID);
1931     PS.Perform();
1932
1933     aReduction = PS.Shape();
1934   }
1935
1936   return aReduction;
1937 }
1938
1939 //=============================================================================
1940 /*!
1941  *  MakePipeTShape
1942  *  \brief Create a T-shape object with specified caracteristics for the main and
1943  *         the incident pipes (radius, width, half-length).
1944  *         Center of the shape is (0,0,0). The main plane of the T-shape is XOY.
1945  *  \param theR1 Internal radius of main pipe
1946  *  \param theW1 Width of main pipe
1947  *  \param theL1 Half-length of main pipe
1948  *  \param theR2 Internal radius of incident pipe (R2 < R1)
1949  *  \param theW2 Width of incident pipe (R2+W2 < R1+W1)
1950  *  \param theL2 Half-length of incident pipe
1951  *  \param theHexMesh Boolean indicating if shape is prepared for hex mesh
1952  *  \return List of GEOM_Objects, containing the created shape and propagation groups.
1953  */
1954 //=============================================================================
1955 Handle(TColStd_HSequenceOfTransient)
1956   AdvancedEngine_IOperations::MakePipeTShape(double theR1, double theW1, double theL1,
1957                                              double theR2, double theW2, double theL2,
1958                                              double theRL, double theWL, double theLtransL, double theLthinL,
1959                                              double theRR, double theWR, double theLtransR, double theLthinR,
1960                                              double theRI, double theWI, double theLtransI, double theLthinI,
1961                                              bool theHexMesh)
1962 {
1963   MESSAGE("AdvancedEngine_IOperations::MakePipeTShape");
1964   SetErrorCode(KO);
1965   //Add a new object
1966   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_TSHAPE);
1967
1968   //Add a new shape function with parameters
1969   Handle(GEOM_Function) aFunction = aShape->AddFunction(AdvancedEngine_PipeTShapeDriver::GetID(), TSHAPE_BASIC);
1970   if (aFunction.IsNull()) return NULL;
1971
1972   //Check if the function is set correctly
1973   if (aFunction->GetDriverGUID() != AdvancedEngine_PipeTShapeDriver::GetID()) return NULL;
1974
1975   AdvancedEngine_IPipeTShape aData (aFunction);
1976
1977   aData.SetR1(theR1);
1978   aData.SetW1(theW1);
1979   aData.SetL1(theL1);
1980   aData.SetR2(theR2);
1981   aData.SetW2(theW2);
1982   aData.SetL2(theL2);
1983   aData.SetHexMesh(theHexMesh);
1984
1985   bool isTRL = (theRL + theWL + theLtransL + theLthinL) > Precision::Confusion();
1986   bool isTRR = (theRR + theWR + theLtransR + theLthinR) > Precision::Confusion();
1987   bool isTRI = (theRI + theWI + theLtransI + theLthinI) > Precision::Confusion();
1988
1989   //Compute the resulting value
1990   try {
1991     OCC_CATCH_SIGNALS;
1992     if (!GetSolver()->ComputeFunction(aFunction)) {
1993       SetErrorCode("TShape driver failed");
1994       return NULL;
1995     }
1996
1997     if (theHexMesh) {
1998       if (!MakePipeTShapePartition(aShape, theR1, theW1, theL1, theR2, theW2, theL2))
1999         return NULL;
2000       if (!MakePipeTShapeMirrorAndGlue(aShape, theR1, theW1, theL1, theR2, theW2, theL2))
2001         return NULL;
2002     }
2003
2004     if (isTRL || isTRR || isTRI) {
2005       // Add thickness reduction elements
2006       // at the three extremities: Left, Right and Incident
2007       TopoDS_Shape aResShape =
2008         MakePipeTShapeThicknessReduction(aShape->GetValue(), theR1, theW1, theL1, theR2, theW2, theL2,
2009                                          theRL, theWL, theLtransL, theLthinL,
2010                                          theRR, theWR, theLtransR, theLthinR,
2011                                          theRI, theWI, theLtransI, theLthinI,
2012                                          !theHexMesh);
2013       aFunction->SetValue(aResShape);
2014     }
2015   }
2016   catch (Standard_Failure) {
2017     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2018     SetErrorCode(aFail->GetMessageString());
2019     return NULL;
2020   }
2021
2022   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
2023   aSeq->Append(aShape);
2024
2025   try {
2026     if (theHexMesh) {
2027       // Get the groups
2028       if (!MakeGroups(aShape, TSHAPE_BASIC, theR1, theW1, theL1, theR2, theW2, theL2,
2029                       0., 0., 0., aSeq, gp_Trsf()))
2030         return NULL;
2031     }
2032
2033     // Get internal group.
2034     if (!MakeInternalGroup(aShape, theR1, theL1, theR2, theL2, theRL, theLtransL,
2035                            theRR, theLtransR, theRI, theLtransI,
2036                            aSeq, gp_Trsf())) {
2037       return NULL;
2038     }
2039   }
2040   catch (Standard_Failure) {
2041     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2042     SetErrorCode(aFail->GetMessageString());
2043     return NULL;
2044   }
2045
2046   //Make a Python command
2047   TCollection_AsciiString anEntry, aListRes("[");
2048   // Iterate over the sequence aSeq
2049   Standard_Integer aNbGroups = aSeq->Length();
2050   Standard_Integer i = 1;
2051   for (; i <= aNbGroups; i++) {
2052     Handle(Standard_Transient) anItem = aSeq->Value(i);
2053     if (anItem.IsNull()) continue;
2054     Handle(GEOM_Object) aGroup = Handle(GEOM_Object)::DownCast(anItem);
2055     if (aGroup.IsNull()) continue;
2056     //Make a Python command
2057     TDF_Tool::Entry(aGroup->GetEntry(), anEntry);
2058     aListRes += anEntry + ", ";
2059   }
2060   aListRes.Trunc(aListRes.Length() - 2);
2061
2062   GEOM::TPythonDump pd (aFunction);
2063
2064   pd << aListRes.ToCString() << "] = geompy.MakePipeTShape("
2065      << theR1 << ", " << theW1 << ", " << theL1 << ", "
2066      << theR2 << ", " << theW2 << ", " << theL2 << ", "
2067      << theHexMesh;
2068
2069   // thickness reduction
2070   if (isTRL)
2071     pd << ", theRL=" << theRL << ", theWL=" << theWL
2072        << ", theLtransL=" << theLtransL << ", theLthinL=" << theLthinL;
2073   if (isTRR)
2074     pd << ", theRR=" << theRR << ", theWR=" << theWR
2075        << ", theLtransR=" << theLtransR << ", theLthinR=" << theLthinR;
2076   if (isTRI)
2077     pd << ", theRI=" << theRI << ", theWI=" << theWI
2078        << ", theLtransI=" << theLtransI << ", theLthinI=" << theLthinI;
2079
2080   pd << ")";
2081
2082   SetErrorCode(OK);
2083
2084   return aSeq;
2085 }
2086
2087 //=============================================================================
2088 /*!
2089  *  MakePipeTShapeWithPosition
2090  *  Create a T-shape object with specified caracteristics for the main and
2091  *  the incident pipes (radius, width, half-length).
2092  *  The extremities of the main pipe are located on junctions points P1 and P2.
2093  *  The extremity of the incident pipe is located on junction point P3.
2094  *  \param theR1 Internal radius of main pipe
2095  *  \param theW1 Width of main pipe
2096  *  \param theL1 Half-length of main pipe
2097  *  \param theR2 Internal radius of incident pipe (R2 < R1)
2098  *  \param theW2 Width of incident pipe (R2+W2 < R1+W1)
2099  *  \param theL2 Half-length of incident pipe
2100  *  \param theHexMesh Boolean indicating if shape is prepared for hex mesh
2101  *  \param theP1 1st junction point of main pipe
2102  *  \param theP2 2nd junction point of main pipe
2103  *  \param theP3 Junction point of incident pipe
2104  *  \return List of GEOM_Objects, containing the created shape and propagation groups..
2105  */
2106 //=============================================================================
2107 Handle(TColStd_HSequenceOfTransient)
2108 AdvancedEngine_IOperations::MakePipeTShapeWithPosition
2109                              (double theR1, double theW1, double theL1,
2110                               double theR2, double theW2, double theL2,
2111                               double theRL, double theWL, double theLtransL, double theLthinL,
2112                               double theRR, double theWR, double theLtransR, double theLthinR,
2113                               double theRI, double theWI, double theLtransI, double theLthinI,
2114                               bool theHexMesh,
2115                               Handle(GEOM_Object) theP1,
2116                               Handle(GEOM_Object) theP2,
2117                               Handle(GEOM_Object) theP3)
2118 {
2119   SetErrorCode(KO);
2120   //Add a new object
2121   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_TSHAPE);
2122   /////////////////
2123   // TSHAPE CODE
2124   /////////////////
2125   //Add a new shape function with parameters
2126   Handle(GEOM_Function) aFunction = aShape->AddFunction(AdvancedEngine_PipeTShapeDriver::GetID(), TSHAPE_BASIC);
2127   if (aFunction.IsNull()) return NULL;
2128
2129   //Check if the function is set correctly
2130   if (aFunction->GetDriverGUID() != AdvancedEngine_PipeTShapeDriver::GetID()) return NULL;
2131
2132   // Check new position
2133   if (!CheckCompatiblePosition(theL1, theL2, theP1, theP2, theP3, 0.01)) {
2134     return NULL;
2135   }
2136
2137   AdvancedEngine_IPipeTShape aData(aFunction);
2138
2139   aData.SetR1(theR1);
2140   aData.SetW1(theW1);
2141   aData.SetL1(theL1);
2142   aData.SetR2(theR2);
2143   aData.SetW2(theW2);
2144   aData.SetL2(theL2);
2145   aData.SetHexMesh(theHexMesh);
2146
2147   bool isTRL = (theRL + theWL + theLtransL + theLthinL) > Precision::Confusion();
2148   bool isTRR = (theRR + theWR + theLtransR + theLthinR) > Precision::Confusion();
2149   bool isTRI = (theRI + theWI + theLtransI + theLthinI) > Precision::Confusion();
2150
2151   //Compute the resulting value
2152   try {
2153     OCC_CATCH_SIGNALS;
2154     if (!GetSolver()->ComputeFunction(aFunction)) {
2155       SetErrorCode("TShape driver failed");
2156       return NULL;
2157     }
2158
2159     if (theHexMesh) {
2160       if (!MakePipeTShapePartition(aShape, theR1, theW1, theL1, theR2, theW2, theL2))
2161         return NULL;
2162       if (!MakePipeTShapeMirrorAndGlue(aShape, theR1, theW1, theL1, theR2, theW2, theL2))
2163         return NULL;
2164     }
2165
2166     if (isTRL || isTRR || isTRI) {
2167       // Add thickness reduction elements
2168       // at the three extremities: Left, Right and Incident
2169       TopoDS_Shape aResShape =
2170         MakePipeTShapeThicknessReduction(aShape->GetValue(), theR1, theW1, theL1, theR2, theW2, theL2,
2171                                          theRL, theWL, theLtransL, theLthinL,
2172                                          theRR, theWR, theLtransR, theLthinR,
2173                                          theRI, theWI, theLtransI, theLthinI,
2174                                          !theHexMesh);
2175       aFunction->SetValue(aResShape);
2176     }
2177   }
2178   catch (Standard_Failure) {
2179     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2180     SetErrorCode(aFail->GetMessageString());
2181     return NULL;
2182   }
2183
2184   TopoDS_Shape Te = aShape->GetValue();
2185
2186   // Set Position
2187   gp_Trsf aTrsf = GetPositionTrsf(theL1, theL2, theP1, theP2, theP3);
2188   BRepBuilderAPI_Transform aTransformation(Te, aTrsf, Standard_False);
2189   TopoDS_Shape aTrsf_Shape = aTransformation.Shape();
2190   aFunction->SetValue(aTrsf_Shape);
2191
2192   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
2193   aSeq->Append(aShape);
2194
2195   try {
2196     if (theHexMesh) {
2197       // Get the groups
2198       if (!MakeGroups(aShape,TSHAPE_BASIC, theR1, theW1, theL1, theR2, theW2, theL2,
2199                       0., 0., 0., aSeq, aTrsf)) {
2200         return NULL;
2201       }
2202     }
2203
2204     // Get internal group.
2205     if (!MakeInternalGroup(aShape, theR1, theL1, theR2, theL2, theRL, theLtransL,
2206                            theRR, theLtransR, theRI, theLtransI,
2207                            aSeq, aTrsf)) {
2208       return NULL;
2209     }
2210   }
2211   catch (Standard_Failure) {
2212     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2213     SetErrorCode(aFail->GetMessageString());
2214     return NULL;
2215   }
2216
2217   //Make a Python command
2218   TCollection_AsciiString anEntry, aListRes("[");
2219   // Iterate over the sequence aSeq
2220   Standard_Integer aNbGroups = aSeq->Length();
2221   Standard_Integer i = 1;
2222   for (; i <= aNbGroups; i++) {
2223     Handle(Standard_Transient) anItem = aSeq->Value(i);
2224     if (anItem.IsNull()) continue;
2225     Handle(GEOM_Object) aGroup = Handle(GEOM_Object)::DownCast(anItem);
2226     if (aGroup.IsNull()) continue;
2227     //Make a Python command
2228     TDF_Tool::Entry(aGroup->GetEntry(), anEntry);
2229     aListRes += anEntry + ", ";
2230   }
2231   aListRes.Trunc(aListRes.Length() - 2);
2232
2233   GEOM::TPythonDump pd (aFunction);
2234
2235   pd << aListRes.ToCString() << "] = geompy.MakePipeTShape("
2236      << theR1 << ", " << theW1 << ", " << theL1 << ", "
2237      << theR2 << ", " << theW2 << ", " << theL2 << ", "
2238      << theHexMesh << ", " << theP1 << ", " << theP2 << ", " << theP3;
2239
2240   // thickness reduction
2241   if (isTRL)
2242     pd << ", theRL=" << theRL << ", theWL=" << theWL
2243        << ", theLtransL=" << theLtransL << ", theLthinL=" << theLthinL;
2244   if (isTRR)
2245     pd << ", theRR=" << theRR << ", theWR=" << theWR
2246        << ", theLtransR=" << theLtransR << ", theLthinR=" << theLthinR;
2247   if (isTRI)
2248     pd << ", theRI=" << theRI << ", theWI=" << theWI
2249        << ", theLtransI=" << theLtransI << ", theLthinI=" << theLthinI;
2250
2251   pd << ")";
2252
2253   SetErrorCode(OK);
2254
2255   return aSeq;
2256 }
2257
2258 //=============================================================================
2259 /*!
2260  *  MakePipeTShapeChamfer
2261  *  Create a T-shape object with specified caracteristics for the main and
2262  *  the incident pipes (radius, width, half-length). A chamfer is created
2263  *  on the junction of the pipes.
2264  *  Center of the shape is (0,0,0). The main plane of the T-shape is XOY.
2265  *  \param theR1 Internal radius of main pipe
2266  *  \param theW1 Width of main pipe
2267  *  \param theL1 Half-length of main pipe
2268  *  \param theR2 Internal radius of incident pipe (R2 < R1)
2269  *  \param theW2 Width of incident pipe (R2+W2 < R1+W1)
2270  *  \param theL2 Half-length of incident pipe
2271  *  \param theH Height of chamfer.
2272  *  \param theW Width of chamfer.
2273  *  \param theHexMesh Boolean indicating if shape is prepared for hex mesh
2274  *  \return List of GEOM_Objects, containing the created shape and propagation groups.
2275  */
2276 //=============================================================================
2277 Handle(TColStd_HSequenceOfTransient)
2278 AdvancedEngine_IOperations::MakePipeTShapeChamfer
2279                              (double theR1, double theW1, double theL1,
2280                               double theR2, double theW2, double theL2,
2281                               double theRL, double theWL, double theLtransL, double theLthinL,
2282                               double theRR, double theWR, double theLtransR, double theLthinR,
2283                               double theRI, double theWI, double theLtransI, double theLthinI,
2284                               double theH, double theW,
2285                               bool theHexMesh)
2286 {
2287   SetErrorCode(KO);
2288   //Add a new object
2289   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_TSHAPE);
2290   //Add a new shape function with parameters
2291   Handle(GEOM_Function) aFunction = aShape->AddFunction(AdvancedEngine_PipeTShapeDriver::GetID(), TSHAPE_CHAMFER);
2292   if (aFunction.IsNull()) return NULL;
2293
2294   //Check if the function is set correctly
2295   if (aFunction->GetDriverGUID() != AdvancedEngine_PipeTShapeDriver::GetID()) return NULL;
2296
2297   AdvancedEngine_IPipeTShape aData(aFunction);
2298
2299   aData.SetR1(theR1);
2300   aData.SetW1(theW1);
2301   aData.SetL1(theL1);
2302   aData.SetR2(theR2);
2303   aData.SetW2(theW2);
2304   aData.SetL2(theL2);
2305   aData.SetH(theH);
2306   aData.SetW(theW);
2307   aData.SetHexMesh(theHexMesh);
2308
2309   bool isTRL = (theRL + theWL + theLtransL + theLthinL) > Precision::Confusion();
2310   bool isTRR = (theRR + theWR + theLtransR + theLthinR) > Precision::Confusion();
2311   bool isTRI = (theRI + theWI + theLtransI + theLthinI) > Precision::Confusion();
2312
2313   //Compute the resulting value
2314   try {
2315     OCC_CATCH_SIGNALS;
2316     if (!GetSolver()->ComputeFunction(aFunction)) {
2317       SetErrorCode("TShape driver failed");
2318       return NULL;
2319     }
2320   }
2321   catch (Standard_Failure) {
2322     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2323     SetErrorCode(aFail->GetMessageString());
2324     return NULL;
2325   }
2326
2327   // BEGIN of chamfer
2328   TopoDS_Shape aShapeShape = aShape->GetValue();
2329   TopTools_IndexedMapOfShape anEdgesIndices;
2330   TopExp::MapShapes(aShapeShape, anEdgesIndices);
2331   // Common edges on external cylinders
2332   Handle(GEOM_Object) box_e;
2333   if (theHexMesh) {
2334     box_e = my3DPrimOperations->MakeBoxDXDYDZ(theR2+theW2, theR2+theW2, theR1+theW1);
2335   }
2336   else {
2337     box_e = my3DPrimOperations->MakeBoxDXDYDZ(2*(theR2+theW2), 2*(theR2+theW2), theR1+theW1);
2338   }
2339   box_e->GetLastFunction()->SetDescription("");
2340   box_e = myTransformOperations->TranslateDXDYDZ(box_e, -(theR2+theW2), -(theR2+theW2), 0);
2341   box_e->GetLastFunction()->SetDescription("");
2342
2343   Handle(TColStd_HSequenceOfInteger) edges_e =
2344     myShapesOperations->GetShapesOnBoxIDs(box_e, aShape, TopAbs_EDGE, GEOMAlgo_ST_IN);
2345   box_e->GetLastFunction()->SetDescription("");
2346
2347   if (edges_e.IsNull() || edges_e->Length() == 0) {
2348     SetErrorCode("External edges not found");
2349     return NULL;
2350   }
2351   int nbEdgesInChamfer = 0;
2352   std::list<int> theEdges;
2353   for (int i=1; i<=edges_e->Length();i++) {
2354     int edgeID = edges_e->Value(i);
2355     TopoDS_Shape theEdge = anEdgesIndices.FindKey(edgeID);
2356     TopExp_Explorer Ex(theEdge,TopAbs_VERTEX);
2357     int iv=0;
2358     while (Ex.More()) {
2359       iv ++;
2360       gp_Pnt aPt = BRep_Tool::Pnt(TopoDS::Vertex(Ex.Current()));
2361       if (Abs(aPt.Z() - (theR1+theW1)) <= Precision::Confusion()) {
2362         nbEdgesInChamfer ++;
2363         theEdges.push_back(edgeID);
2364       }
2365       Ex.Next();
2366     }
2367     if (theHexMesh && nbEdgesInChamfer == 1)
2368       break;
2369   }
2370   Handle(GEOM_Object) aChamfer;
2371   try {
2372     aChamfer = myLocalOperations->MakeChamferEdges(aShape, theW, theH, theEdges);
2373   }
2374   catch (Standard_Failure) {
2375     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2376     SetErrorCode(aFail->GetMessageString());
2377     return NULL;
2378   }
2379   if (aChamfer.IsNull()) {
2380     SetErrorCode("Chamfer can not be computed on the given shape with the given parameters");
2381     return NULL;
2382   }
2383   aChamfer->GetLastFunction()->SetDescription("");
2384
2385   TopoDS_Shape aChamferShape = aChamfer->GetValue();
2386   aFunction->SetValue(aChamferShape);
2387   // END of chamfer
2388
2389   if (theHexMesh) {
2390     if (!MakePipeTShapePartition(aShape, theR1, theW1, theL1, theR2, theW2, theL2, theH, theW, 0, false))
2391       return NULL;
2392     if (!MakePipeTShapeMirrorAndGlue(aShape, theR1, theW1, theL1, theR2, theW2, theL2))
2393       return NULL;
2394   }
2395
2396   // Add thickness reduction elements
2397   // at the three extremities: Left, Right and Incident
2398   try {
2399     OCC_CATCH_SIGNALS;
2400     if (isTRL || isTRR || isTRI) {
2401       TopoDS_Shape aResShape =
2402         MakePipeTShapeThicknessReduction(aShape->GetValue(), theR1, theW1, theL1, theR2, theW2, theL2,
2403                                          theRL, theWL, theLtransL, theLthinL,
2404                                          theRR, theWR, theLtransR, theLthinR,
2405                                          theRI, theWI, theLtransI, theLthinI,
2406                                          !theHexMesh);
2407       aFunction->SetValue(aResShape);
2408     }
2409   }
2410   catch (Standard_Failure) {
2411     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2412     SetErrorCode(aFail->GetMessageString());
2413     return NULL;
2414   }
2415
2416   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
2417   aSeq->Append(aShape);
2418
2419   try {
2420     if (theHexMesh) {
2421       // Get the groups
2422       if (!MakeGroups(aShape, TSHAPE_CHAMFER, theR1, theW1, theL1, theR2, theW2, theL2,
2423                       theH, theW, 0., aSeq, gp_Trsf()))
2424         return NULL;
2425     }
2426
2427     // Get internal group.
2428     if (!MakeInternalGroup(aShape, theR1, theL1, theR2, theL2, theRL, theLtransL,
2429                            theRR, theLtransR, theRI, theLtransI,
2430                            aSeq, gp_Trsf())) {
2431       return NULL;
2432     }
2433   }
2434   catch (Standard_Failure) {
2435     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2436     SetErrorCode(aFail->GetMessageString());
2437     return NULL;
2438   }
2439
2440   //Make a Python command
2441   TCollection_AsciiString anEntry, aListRes("[");
2442   // Iterate over the sequence aSeq
2443   Standard_Integer aNbGroups = aSeq->Length();
2444   Standard_Integer i = 1;
2445   for (; i <= aNbGroups; i++) {
2446     Handle(Standard_Transient) anItem = aSeq->Value(i);
2447     if (anItem.IsNull()) continue;
2448     Handle(GEOM_Object) aGroup = Handle(GEOM_Object)::DownCast(anItem);
2449     if (aGroup.IsNull()) continue;
2450     //Make a Python command
2451     TDF_Tool::Entry(aGroup->GetEntry(), anEntry);
2452     aListRes += anEntry + ", ";
2453   }
2454   aListRes.Trunc(aListRes.Length() - 2);
2455
2456   GEOM::TPythonDump pd (aFunction);
2457
2458   pd << aListRes.ToCString() << "] = geompy.MakePipeTShapeChamfer("
2459      << theR1 << ", " << theW1 << ", " << theL1 << ", "
2460      << theR2 << ", " << theW2 << ", " << theL2 << ", "
2461      << theH << ", " << theW << ", " << theHexMesh;
2462
2463   // thickness reduction
2464   if (isTRL)
2465     pd << ", theRL=" << theRL << ", theWL=" << theWL
2466        << ", theLtransL=" << theLtransL << ", theLthinL=" << theLthinL;
2467   if (isTRR)
2468     pd << ", theRR=" << theRR << ", theWR=" << theWR
2469        << ", theLtransR=" << theLtransR << ", theLthinR=" << theLthinR;
2470   if (isTRI)
2471     pd << ", theRI=" << theRI << ", theWI=" << theWI
2472        << ", theLtransI=" << theLtransI << ", theLthinI=" << theLthinI;
2473
2474   pd << ")";
2475
2476   SetErrorCode(OK);
2477
2478   return aSeq;
2479 }
2480
2481 //=============================================================================
2482 /*!
2483  *  MakePipeTShapeChamferWithPosition
2484  *  Create a T-shape object with specified caracteristics for the main and
2485  *  the incident pipes (radius, width, half-length). A chamfer is created
2486  *  on the junction of the pipes.
2487  *  The extremities of the main pipe are located on junctions points P1 and P2.
2488  *  The extremity of the incident pipe is located on junction point P3.
2489  *  \param theR1 Internal radius of main pipe
2490  *  \param theW1 Width of main pipe
2491  *  \param theL1 Half-length of main pipe
2492  *  \param theR2 Internal radius of incident pipe (R2 < R1)
2493  *  \param theW2 Width of incident pipe (R2+W2 < R1+W1)
2494  *  \param theL2 Half-length of incident pipe
2495  *  \param theH Height of chamfer.
2496  *  \param theW Width of chamfer.
2497  *  \param theHexMesh Boolean indicating if shape is prepared for hex mesh
2498  *  \param theP1 1st junction point of main pipe
2499  *  \param theP2 2nd junction point of main pipe
2500  *  \param theP3 Junction point of incident pipe
2501  *  \return List of GEOM_Objects, containing the created shape and propagation groups.
2502  */
2503 //=============================================================================
2504 Handle(TColStd_HSequenceOfTransient)
2505 AdvancedEngine_IOperations::MakePipeTShapeChamferWithPosition
2506                              (double theR1, double theW1, double theL1,
2507                               double theR2, double theW2, double theL2,
2508                               double theRL, double theWL, double theLtransL, double theLthinL,
2509                               double theRR, double theWR, double theLtransR, double theLthinR,
2510                               double theRI, double theWI, double theLtransI, double theLthinI,
2511                               double theH, double theW,
2512                               bool theHexMesh,
2513                               Handle(GEOM_Object) theP1,
2514                               Handle(GEOM_Object) theP2,
2515                               Handle(GEOM_Object) theP3)
2516 {
2517   SetErrorCode(KO);
2518   //Add a new object
2519   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_TSHAPE);
2520   //Add a new shape function with parameters
2521   Handle(GEOM_Function) aFunction = aShape->AddFunction(AdvancedEngine_PipeTShapeDriver::GetID(), TSHAPE_CHAMFER);
2522   if (aFunction.IsNull()) return NULL;
2523
2524   //Check if the function is set correctly
2525   if (aFunction->GetDriverGUID() != AdvancedEngine_PipeTShapeDriver::GetID()) return NULL;
2526
2527   // Check new position
2528   if (!CheckCompatiblePosition(theL1, theL2, theP1, theP2, theP3, 0.01)) {
2529     return NULL;
2530   }
2531
2532   AdvancedEngine_IPipeTShape aData(aFunction);
2533
2534   aData.SetR1(theR1);
2535   aData.SetW1(theW1);
2536   aData.SetL1(theL1);
2537   aData.SetR2(theR2);
2538   aData.SetW2(theW2);
2539   aData.SetL2(theL2);
2540   aData.SetH(theH);
2541   aData.SetW(theW);
2542   aData.SetHexMesh(theHexMesh);
2543
2544   bool isTRL = (theRL + theWL + theLtransL + theLthinL) > Precision::Confusion();
2545   bool isTRR = (theRR + theWR + theLtransR + theLthinR) > Precision::Confusion();
2546   bool isTRI = (theRI + theWI + theLtransI + theLthinI) > Precision::Confusion();
2547
2548   //Compute the resulting value
2549   try {
2550     OCC_CATCH_SIGNALS;
2551     if (!GetSolver()->ComputeFunction(aFunction)) {
2552       SetErrorCode("TShape driver failed");
2553       return NULL;
2554     }
2555   }
2556   catch (Standard_Failure) {
2557     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2558     SetErrorCode(aFail->GetMessageString());
2559     return NULL;
2560   }
2561
2562   // BEGIN of chamfer
2563   TopoDS_Shape aShapeShape = aShape->GetValue();
2564   TopTools_IndexedMapOfShape anEdgesIndices;
2565   TopExp::MapShapes(aShapeShape, anEdgesIndices);
2566   // Common edges on external cylinders
2567   Handle(GEOM_Object) box_e;
2568   if (theHexMesh) {
2569     box_e = my3DPrimOperations->MakeBoxDXDYDZ(theR2+theW2, theR2+theW2, theR1+theW1);
2570   }
2571   else {
2572     box_e = my3DPrimOperations->MakeBoxDXDYDZ(2*(theR2+theW2), 2*(theR2+theW2), theR1+theW1);
2573   }
2574   box_e->GetLastFunction()->SetDescription("");
2575   box_e = myTransformOperations->TranslateDXDYDZ(box_e, -(theR2+theW2), -(theR2+theW2), 0);
2576   box_e->GetLastFunction()->SetDescription("");
2577
2578   Handle(TColStd_HSequenceOfInteger) edges_e =
2579     myShapesOperations->GetShapesOnBoxIDs(box_e, aShape, TopAbs_EDGE, GEOMAlgo_ST_IN);
2580   box_e->GetLastFunction()->SetDescription("");
2581
2582   if (edges_e.IsNull() || edges_e->Length() == 0) {
2583     SetErrorCode("External edges not found");
2584     return NULL;
2585   }
2586   int nbEdgesInChamfer = 0;
2587   std::list<int> theEdges;
2588   for (int i=1; i<=edges_e->Length();i++) {
2589     int edgeID = edges_e->Value(i);
2590     TopoDS_Shape theEdge = anEdgesIndices.FindKey(edgeID);
2591     TopExp_Explorer Ex(theEdge,TopAbs_VERTEX);
2592     while (Ex.More()) {
2593       gp_Pnt aPt = BRep_Tool::Pnt(TopoDS::Vertex(Ex.Current()));
2594       if (Abs(aPt.Z() - (theR1+theW1)) <= Precision::Confusion()) {
2595         nbEdgesInChamfer ++;
2596         theEdges.push_back(edgeID);
2597       }
2598       Ex.Next();
2599     }
2600     if (theHexMesh && nbEdgesInChamfer == 1)
2601       break;
2602   }
2603   Handle(GEOM_Object) aChamfer;
2604   try {
2605     aChamfer = myLocalOperations->MakeChamferEdges(aShape, theW, theH, theEdges);
2606   }
2607   catch (Standard_Failure) {
2608     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2609     SetErrorCode(aFail->GetMessageString());
2610     return NULL;
2611   }
2612   if (aChamfer.IsNull()) {
2613     SetErrorCode("Chamfer can not be computed on the given shape with the given parameters");
2614     return NULL;
2615   }
2616   aChamfer->GetLastFunction()->SetDescription("");
2617
2618   TopoDS_Shape aChamferShape = aChamfer->GetValue();
2619   aFunction->SetValue(aChamferShape);
2620   // END of chamfer
2621
2622   if (theHexMesh) {
2623     if (!MakePipeTShapePartition(aShape, theR1, theW1, theL1, theR2, theW2, theL2, theH, theW, 0, false))
2624       return NULL;
2625     if (!MakePipeTShapeMirrorAndGlue(aShape, theR1, theW1, theL1, theR2, theW2, theL2))
2626       return NULL;
2627   }
2628
2629   // Add thickness reduction elements
2630   // at the three extremities: Left, Right and Incident
2631   try {
2632     OCC_CATCH_SIGNALS;
2633     if (isTRL || isTRR || isTRI) {
2634       TopoDS_Shape aResShape =
2635         MakePipeTShapeThicknessReduction(aShape->GetValue(), theR1, theW1, theL1, theR2, theW2, theL2,
2636                                          theRL, theWL, theLtransL, theLthinL,
2637                                          theRR, theWR, theLtransR, theLthinR,
2638                                          theRI, theWI, theLtransI, theLthinI,
2639                                          !theHexMesh);
2640       aFunction->SetValue(aResShape);
2641     }
2642   }
2643   catch (Standard_Failure) {
2644     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2645     SetErrorCode(aFail->GetMessageString());
2646     return NULL;
2647   }
2648
2649   // Set Position
2650   gp_Trsf aTrsf = GetPositionTrsf(theL1, theL2, theP1, theP2, theP3);
2651   BRepBuilderAPI_Transform aTransformation (aShape->GetValue(), aTrsf, Standard_False);
2652   TopoDS_Shape aTrsf_Shape = aTransformation.Shape();
2653   aFunction->SetValue(aTrsf_Shape);
2654
2655   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
2656   aSeq->Append(aShape);
2657
2658   try {
2659     if (theHexMesh) {
2660       // Get the groups
2661       if (!MakeGroups(aShape, TSHAPE_CHAMFER, theR1, theW1, theL1, theR2, theW2, theL2,
2662                       theH, theW, 0., aSeq, aTrsf))
2663         return NULL;
2664     }
2665
2666     // Get internal group.
2667     if (!MakeInternalGroup(aShape, theR1, theL1, theR2, theL2, theRL, theLtransL,
2668                            theRR, theLtransR, theRI, theLtransI,
2669                            aSeq, aTrsf)) {
2670       return NULL;
2671     }
2672   }
2673   catch (Standard_Failure) {
2674     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2675     SetErrorCode(aFail->GetMessageString());
2676     return NULL;
2677   }
2678
2679   //Make a Python command
2680   TCollection_AsciiString anEntry, aListRes("[");
2681   // Iterate over the sequence aSeq
2682   Standard_Integer aNbGroups = aSeq->Length();
2683   Standard_Integer i = 1;
2684   for (; i <= aNbGroups; i++) {
2685     Handle(Standard_Transient) anItem = aSeq->Value(i);
2686     if (anItem.IsNull()) continue;
2687     Handle(GEOM_Object) aGroup = Handle(GEOM_Object)::DownCast(anItem);
2688     if (aGroup.IsNull()) continue;
2689     //Make a Python command
2690     TDF_Tool::Entry(aGroup->GetEntry(), anEntry);
2691     aListRes += anEntry + ", ";
2692   }
2693   aListRes.Trunc(aListRes.Length() - 2);
2694
2695   GEOM::TPythonDump pd (aFunction);
2696
2697   pd << aListRes.ToCString() << "] = geompy.MakePipeTShapeChamfer("
2698      << theR1 << ", " << theW1 << ", " << theL1 << ", "
2699      << theR2 << ", " << theW2 << ", " << theL2 << ", "
2700      << theH << ", " << theW << ", " << theHexMesh << ", "
2701      << theP1 << ", " << theP2 << ", " << theP3;
2702
2703   // thickness reduction
2704   if (isTRL)
2705     pd << ", theRL=" << theRL << ", theWL=" << theWL
2706        << ", theLtransL=" << theLtransL << ", theLthinL=" << theLthinL;
2707   if (isTRR)
2708     pd << ", theRR=" << theRR << ", theWR=" << theWR
2709        << ", theLtransR=" << theLtransR << ", theLthinR=" << theLthinR;
2710   if (isTRI)
2711     pd << ", theRI=" << theRI << ", theWI=" << theWI
2712        << ", theLtransI=" << theLtransI << ", theLthinI=" << theLthinI;
2713
2714   pd << ")";
2715
2716   SetErrorCode(OK);
2717
2718   return aSeq;
2719 }
2720
2721 //=============================================================================
2722 /*!
2723  *  MakePipeTShapeFillet
2724  *  Create a T-shape object with specified caracteristics for the main and
2725  *  the incident pipes (radius, width, half-length). A fillet is created
2726  *  on the junction of the pipes.
2727  *  Center of the shape is (0,0,0). The main plane of the T-shape is XOY.
2728  *  \param theR1 Internal radius of main pipe
2729  *  \param theW1 Width of main pipe
2730  *  \param theL1 Half-length of main pipe
2731  *  \param theR2 Internal radius of incident pipe (R2 < R1)
2732  *  \param theW2 Width of incident pipe (R2+W2 < R1+W1)
2733  *  \param theL2 Half-length of incident pipe
2734  *  \param theRF Radius of curvature of fillet.
2735  *  \param theHexMesh Boolean indicating if shape is prepared for hex mesh
2736  *  \return List of GEOM_Objects, containing the created shape and propagation groups.
2737  */
2738 //=============================================================================
2739 Handle(TColStd_HSequenceOfTransient)
2740 AdvancedEngine_IOperations::MakePipeTShapeFillet
2741                              (double theR1, double theW1, double theL1,
2742                               double theR2, double theW2, double theL2,
2743                               double theRL, double theWL, double theLtransL, double theLthinL,
2744                               double theRR, double theWR, double theLtransR, double theLthinR,
2745                               double theRI, double theWI, double theLtransI, double theLthinI,
2746                               double theRF, bool theHexMesh)
2747 {
2748   SetErrorCode(KO);
2749   //Add a new object
2750   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_TSHAPE);
2751   //Add a new shape function with parameters
2752   Handle(GEOM_Function) aFunction = aShape->AddFunction(AdvancedEngine_PipeTShapeDriver::GetID(), TSHAPE_FILLET);
2753   if (aFunction.IsNull()) return NULL;
2754
2755   //Check if the function is set correctly
2756   if (aFunction->GetDriverGUID() != AdvancedEngine_PipeTShapeDriver::GetID()) return NULL;
2757
2758   AdvancedEngine_IPipeTShape aData(aFunction);
2759
2760   aData.SetR1(theR1);
2761   aData.SetW1(theW1);
2762   aData.SetL1(theL1);
2763   aData.SetR2(theR2);
2764   aData.SetW2(theW2);
2765   aData.SetL2(theL2);
2766   aData.SetRF(theRF);
2767   aData.SetHexMesh(theHexMesh);
2768
2769   bool isTRL = (theRL + theWL + theLtransL + theLthinL) > Precision::Confusion();
2770   bool isTRR = (theRR + theWR + theLtransR + theLthinR) > Precision::Confusion();
2771   bool isTRI = (theRI + theWI + theLtransI + theLthinI) > Precision::Confusion();
2772
2773   //Compute the resulting value
2774   try {
2775     OCC_CATCH_SIGNALS;
2776     if (!GetSolver()->ComputeFunction(aFunction)) {
2777       SetErrorCode("TShape driver failed");
2778       return NULL;
2779     }
2780   }
2781   catch (Standard_Failure) {
2782     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2783     SetErrorCode(aFail->GetMessageString());
2784     return NULL;
2785   }
2786
2787   // BEGIN of fillet
2788   TopoDS_Shape aShapeShape = aShape->GetValue();
2789   TopTools_IndexedMapOfShape anEdgesIndices;
2790   TopExp::MapShapes(aShapeShape, anEdgesIndices);
2791   // Common edges on external cylinders
2792   Handle(GEOM_Object) box_e;
2793   if (theHexMesh) {
2794     box_e = my3DPrimOperations->MakeBoxDXDYDZ(theR2+theW2, theR2+theW2, theR1+theW1);
2795   }
2796   else {
2797     box_e = my3DPrimOperations->MakeBoxDXDYDZ(2*(theR2+theW2), 2*(theR2+theW2), theR1+theW1);
2798   }
2799   box_e->GetLastFunction()->SetDescription("");
2800   box_e = myTransformOperations->TranslateDXDYDZ(box_e, -(theR2+theW2), -(theR2+theW2), 0);
2801   box_e->GetLastFunction()->SetDescription("");
2802
2803   Handle(TColStd_HSequenceOfInteger) edges_e =
2804     myShapesOperations->GetShapesOnBoxIDs(box_e, aShape, TopAbs_EDGE, GEOMAlgo_ST_IN);
2805   box_e->GetLastFunction()->SetDescription("");
2806
2807   if (edges_e.IsNull() || edges_e->Length() == 0) {
2808     SetErrorCode("External edges not found");
2809     return NULL;
2810   }
2811   int nbEdgesInFillet = 0;
2812   std::list<int> theEdges;
2813   for (int i=1; i<=edges_e->Length();i++) {
2814     int edgeID = edges_e->Value(i);
2815     TopoDS_Shape theEdge = anEdgesIndices.FindKey(edgeID);
2816     TopExp_Explorer Ex(theEdge,TopAbs_VERTEX);
2817     while (Ex.More()) {
2818       gp_Pnt aPt = BRep_Tool::Pnt(TopoDS::Vertex(Ex.Current()));
2819       if (Abs(aPt.Z() - (theR1+theW1)) <= Precision::Confusion()) {
2820         nbEdgesInFillet ++;
2821         theEdges.push_back(edgeID);
2822       }
2823       Ex.Next();
2824     }
2825     if (theHexMesh && nbEdgesInFillet == 1)
2826       break;
2827   }
2828
2829   Handle(GEOM_Object) aFillet;
2830   try {
2831     aFillet = myLocalOperations->MakeFilletEdges(aShape, theRF, theEdges);
2832   }
2833   catch (Standard_Failure) {
2834     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2835     SetErrorCode(aFail->GetMessageString());
2836     return NULL;
2837   }
2838   if (aFillet.IsNull()) {
2839     //SetErrorCode("Fillet can not be computed on the given shape with the given parameters");
2840     SetErrorCode(myLocalOperations->GetErrorCode());
2841     return NULL;
2842   }
2843   aFillet->GetLastFunction()->SetDescription("");
2844
2845   TopoDS_Shape aFilletShape = aFillet->GetValue();
2846   aFunction->SetValue(aFilletShape);
2847   // END of fillet
2848
2849 // VSR: debug issues 0021568 and 0021550 (15/05/2012) - BEGIN (1)
2850 // the following block, when enabled, leads to partitioning problems
2851 #if 0
2852 // VSR: debug issues 0021568 and 0021550 (15/05/2012) - END (1)
2853   // BEGIN: Limit tolerances (debug)
2854   Handle(GEOM_Object) aCorr1 = myHealingOperations->LimitTolerance(aShape, 1e-07);
2855   TopoDS_Shape aCorr1Shape = aCorr1->GetValue();
2856   aShape->GetLastFunction()->SetValue(aCorr1Shape);
2857   aCorr1->GetLastFunction()->SetDescription("");
2858   // END: Limit tolerances (debug)
2859 // VSR: debug issues 0021568 and 0021550 (15/05/2012) - BEGIN (2)
2860 #endif
2861 // VSR: debug issues 0021568 and 0021550 (15/05/2012) - END (2)
2862
2863   if (theHexMesh) {
2864     if (!MakePipeTShapePartition(aShape, theR1, theW1, theL1, theR2, theW2, theL2, 0, 0, theRF, false))
2865       return NULL;
2866     if (!MakePipeTShapeMirrorAndGlue(aShape, theR1, theW1, theL1, theR2, theW2, theL2))
2867       return NULL;
2868   }
2869
2870   // Add thickness reduction elements
2871   // at the three extremities: Left, Right and Incident
2872   try {
2873     OCC_CATCH_SIGNALS;
2874     if (isTRL || isTRR || isTRI) {
2875       TopoDS_Shape aResShape =
2876         MakePipeTShapeThicknessReduction(aShape->GetValue(), theR1, theW1, theL1, theR2, theW2, theL2,
2877                                          theRL, theWL, theLtransL, theLthinL,
2878                                          theRR, theWR, theLtransR, theLthinR,
2879                                          theRI, theWI, theLtransI, theLthinI,
2880                                          !theHexMesh);
2881       aFunction->SetValue(aResShape);
2882     }
2883   }
2884   catch (Standard_Failure) {
2885     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2886     SetErrorCode(aFail->GetMessageString());
2887     return NULL;
2888   }
2889
2890   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
2891   aSeq->Append(aShape);
2892
2893   try {
2894     if (theHexMesh) {
2895       // Get the groups
2896       if (!MakeGroups(aShape, TSHAPE_FILLET, theR1, theW1, theL1, theR2, theW2, theL2,
2897                       0., 0., theRF, aSeq, gp_Trsf()))
2898         return NULL;
2899     }
2900
2901     // Get internal group.
2902     if (!MakeInternalGroup(aShape, theR1, theL1, theR2, theL2, theRL, theLtransL,
2903                            theRR, theLtransR, theRI, theLtransI,
2904                            aSeq, gp_Trsf())) {
2905       return NULL;
2906     }
2907   }
2908   catch (Standard_Failure) {
2909     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2910     SetErrorCode(aFail->GetMessageString());
2911     return NULL;
2912   }
2913
2914   //Make a Python command
2915   TCollection_AsciiString anEntry, aListRes("[");
2916   // Iterate over the sequence aSeq
2917   Standard_Integer aNbGroups = aSeq->Length();
2918   Standard_Integer i = 1;
2919   for (; i <= aNbGroups; i++) {
2920     Handle(Standard_Transient) anItem = aSeq->Value(i);
2921     if (anItem.IsNull()) continue;
2922     Handle(GEOM_Object) aGroup = Handle(GEOM_Object)::DownCast(anItem);
2923     if (aGroup.IsNull()) continue;
2924     //Make a Python command
2925     TDF_Tool::Entry(aGroup->GetEntry(), anEntry);
2926     aListRes += anEntry + ", ";
2927   }
2928   aListRes.Trunc(aListRes.Length() - 2);
2929
2930   GEOM::TPythonDump pd (aFunction);
2931
2932   pd << aListRes.ToCString() << "] = geompy.MakePipeTShapeFillet("
2933      << theR1 << ", " << theW1 << ", " << theL1 << ", "
2934      << theR2 << ", " << theW2 << ", " << theL2 << ", "
2935      << theRF << ", " << theHexMesh;
2936
2937   // thickness reduction
2938   if (isTRL)
2939     pd << ", theRL=" << theRL << ", theWL=" << theWL
2940        << ", theLtransL=" << theLtransL << ", theLthinL=" << theLthinL;
2941   if (isTRR)
2942     pd << ", theRR=" << theRR << ", theWR=" << theWR
2943        << ", theLtransR=" << theLtransR << ", theLthinR=" << theLthinR;
2944   if (isTRI)
2945     pd << ", theRI=" << theRI << ", theWI=" << theWI
2946        << ", theLtransI=" << theLtransI << ", theLthinI=" << theLthinI;
2947
2948   pd << ")";
2949
2950   SetErrorCode(OK);
2951
2952   return aSeq;
2953 }
2954
2955 //=============================================================================
2956 /*!
2957  *  MakePipeTShapeFilletWithPosition
2958  *  \brief Create a T-shape object with specified caracteristics for the main and
2959  *  the incident pipes (radius, width, half-length). A fillet is created
2960  *  on the junction of the pipes.
2961  *  The extremities of the main pipe are located on junctions points P1 and P2.
2962  *  The extremity of the incident pipe is located on junction point P3.
2963  *  \param theR1 Internal radius of main pipe
2964  *  \param theW1 Width of main pipe
2965  *  \param theL1 Half-length of main pipe
2966  *  \param theR2 Internal radius of incident pipe (R2 < R1)
2967  *  \param theW2 Width of incident pipe (R2+W2 < R1+W1)
2968  *  \param theL2 Half-length of incident pipe
2969  *  \param theRF Radius of curvature of fillet
2970  *  \param theHexMesh Boolean indicating if shape is prepared for hex mesh
2971  *  \param theP1 1st junction point of main pipe
2972  *  \param theP2 2nd junction point of main pipe
2973  *  \param theP3 Junction point of incident pipe
2974  *  \return List of GEOM_Objects, containing the created shape and propagation groups.
2975  */
2976 //=============================================================================
2977 Handle(TColStd_HSequenceOfTransient)
2978 AdvancedEngine_IOperations::MakePipeTShapeFilletWithPosition
2979                              (double theR1, double theW1, double theL1,
2980                               double theR2, double theW2, double theL2,
2981                               double theRL, double theWL, double theLtransL, double theLthinL,
2982                               double theRR, double theWR, double theLtransR, double theLthinR,
2983                               double theRI, double theWI, double theLtransI, double theLthinI,
2984                               double theRF, bool theHexMesh,
2985                               Handle(GEOM_Object) theP1,
2986                               Handle(GEOM_Object) theP2,
2987                               Handle(GEOM_Object) theP3)
2988 {
2989   SetErrorCode(KO);
2990   //Add a new object
2991   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_TSHAPE);
2992   //Add a new shape function with parameters
2993   Handle(GEOM_Function) aFunction = aShape->AddFunction(AdvancedEngine_PipeTShapeDriver::GetID(), TSHAPE_FILLET);
2994   if (aFunction.IsNull()) return NULL;
2995
2996   //Check if the function is set correctly
2997   if (aFunction->GetDriverGUID() != AdvancedEngine_PipeTShapeDriver::GetID()) return NULL;
2998
2999   // Check new position
3000   if (!CheckCompatiblePosition(theL1, theL2, theP1, theP2, theP3, 0.01)) {
3001     return NULL;
3002   }
3003
3004   AdvancedEngine_IPipeTShape aData(aFunction);
3005
3006   aData.SetR1(theR1);
3007   aData.SetW1(theW1);
3008   aData.SetL1(theL1);
3009   aData.SetR2(theR2);
3010   aData.SetW2(theW2);
3011   aData.SetL2(theL2);
3012   aData.SetRF(theRF);
3013   aData.SetHexMesh(theHexMesh);
3014
3015   bool isTRL = (theRL + theWL + theLtransL + theLthinL) > Precision::Confusion();
3016   bool isTRR = (theRR + theWR + theLtransR + theLthinR) > Precision::Confusion();
3017   bool isTRI = (theRI + theWI + theLtransI + theLthinI) > Precision::Confusion();
3018
3019   //Compute the resulting value
3020   try {
3021     OCC_CATCH_SIGNALS;
3022     if (!GetSolver()->ComputeFunction(aFunction)) {
3023       SetErrorCode("TShape driver failed");
3024       return NULL;
3025     }
3026   }
3027   catch (Standard_Failure) {
3028     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
3029     SetErrorCode(aFail->GetMessageString());
3030     return NULL;
3031   }
3032
3033   // BEGIN of fillet
3034   TopoDS_Shape aShapeShape = aShape->GetValue();
3035   TopTools_IndexedMapOfShape anEdgesIndices;
3036   TopExp::MapShapes(aShapeShape, anEdgesIndices);
3037   // Common edges on external cylinders
3038   Handle(GEOM_Object) box_e;
3039   if (theHexMesh) {
3040     box_e = my3DPrimOperations->MakeBoxDXDYDZ(theR2+theW2, theR2+theW2, theR1+theW1);
3041   }
3042   else {
3043     box_e = my3DPrimOperations->MakeBoxDXDYDZ(2*(theR2+theW2), 2*(theR2+theW2), theR1+theW1);
3044   }
3045   box_e->GetLastFunction()->SetDescription("");
3046   box_e = myTransformOperations->TranslateDXDYDZ(box_e, -(theR2+theW2), -(theR2+theW2), 0);
3047   box_e->GetLastFunction()->SetDescription("");
3048
3049   Handle(TColStd_HSequenceOfInteger) edges_e =
3050     myShapesOperations->GetShapesOnBoxIDs(box_e, aShape, TopAbs_EDGE, GEOMAlgo_ST_IN);
3051   box_e->GetLastFunction()->SetDescription("");
3052
3053   if (edges_e.IsNull() || edges_e->Length() == 0) {
3054     SetErrorCode("External edges not found");
3055     return NULL;
3056   }
3057   int nbEdgesInFillet = 0;
3058   std::list<int> theEdges;
3059   for (int i=1; i<=edges_e->Length();i++) {
3060     int edgeID = edges_e->Value(i);
3061     TopoDS_Shape theEdge = anEdgesIndices.FindKey(edgeID);
3062     TopExp_Explorer Ex(theEdge,TopAbs_VERTEX);
3063     while (Ex.More()) {
3064       gp_Pnt aPt = BRep_Tool::Pnt(TopoDS::Vertex(Ex.Current()));
3065       if (Abs(aPt.Z() - (theR1+theW1)) <= Precision::Confusion()) {
3066         nbEdgesInFillet ++;
3067         theEdges.push_back(edgeID);
3068       }
3069       Ex.Next();
3070     }
3071     if (theHexMesh && nbEdgesInFillet == 1)
3072       break;
3073   }
3074
3075   Handle(GEOM_Object) aFillet;
3076   try {
3077     aFillet = myLocalOperations->MakeFilletEdges(aShape, theRF, theEdges);
3078   }
3079   catch (Standard_Failure) {
3080     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
3081     SetErrorCode(aFail->GetMessageString());
3082     return NULL;
3083   }
3084   if (aFillet.IsNull()) {
3085     SetErrorCode("Fillet can not be computed on the given shape with the given parameters");
3086     return NULL;
3087   }
3088   aFillet->GetLastFunction()->SetDescription("");
3089
3090   TopoDS_Shape aFilletShape = aFillet->GetValue();
3091   aFunction->SetValue(aFilletShape);
3092   // END of fillet
3093
3094 // VSR: debug issues 0021568 and 0021550 (15/05/2012) - BEGIN (3)
3095 // the following block, when enabled, leads to partitioning problems
3096 #if 0
3097 // VSR: debug issues 0021568 and 0021550 (15/05/2012) - END (3)
3098   // BEGIN: Limit tolerances (debug)
3099   Handle(GEOM_Object) aCorr1 = myHealingOperations->LimitTolerance(aShape, 1e-07);
3100   TopoDS_Shape aCorr1Shape = aCorr1->GetValue();
3101   aShape->GetLastFunction()->SetValue(aCorr1Shape);
3102   aCorr1->GetLastFunction()->SetDescription("");
3103   // END: Limit tolerances (debug)
3104 // VSR: debug issues 0021568 and 0021550 (15/05/2012) - BEGIN (4)
3105 #endif
3106 // VSR: debug issues 0021568 and 0021550 (15/05/2012) - END (4)
3107
3108   if (theHexMesh) {
3109     if (!MakePipeTShapePartition(aShape, theR1, theW1, theL1, theR2, theW2, theL2, 0, 0, theRF, false))
3110       return NULL;
3111     if (!MakePipeTShapeMirrorAndGlue(aShape, theR1, theW1, theL1, theR2, theW2, theL2))
3112       return NULL;
3113   }
3114
3115   // Add thickness reduction elements
3116   // at the three extremities: Left, Right and Incident
3117   try {
3118     OCC_CATCH_SIGNALS;
3119     if (isTRL || isTRR || isTRI) {
3120       TopoDS_Shape aResShape =
3121         MakePipeTShapeThicknessReduction(aShape->GetValue(), theR1, theW1, theL1, theR2, theW2, theL2,
3122                                          theRL, theWL, theLtransL, theLthinL,
3123                                          theRR, theWR, theLtransR, theLthinR,
3124                                          theRI, theWI, theLtransI, theLthinI,
3125                                          !theHexMesh);
3126       aFunction->SetValue(aResShape);
3127     }
3128   }
3129   catch (Standard_Failure) {
3130     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
3131     SetErrorCode(aFail->GetMessageString());
3132     return NULL;
3133   }
3134
3135   // Set Position
3136   gp_Trsf aTrsf = GetPositionTrsf(theL1, theL2, theP1, theP2, theP3);
3137   BRepBuilderAPI_Transform aTransformation (aShape->GetValue(), aTrsf, Standard_False);
3138   TopoDS_Shape aTrsf_Shape = aTransformation.Shape();
3139   aFunction->SetValue(aTrsf_Shape);
3140
3141   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
3142   aSeq->Append(aShape);
3143
3144   try {
3145     if (theHexMesh) {
3146       // Get the groups
3147       if (!MakeGroups(aShape, TSHAPE_FILLET, theR1, theW1, theL1, theR2, theW2, theL2,
3148                       0., 0., theRF, aSeq, aTrsf))
3149         return NULL;
3150     }
3151
3152     // Get internal group.
3153     if (!MakeInternalGroup(aShape, theR1, theL1, theR2, theL2, theRL, theLtransL,
3154                            theRR, theLtransR, theRI, theLtransI,
3155                            aSeq, aTrsf)) {
3156       return NULL;
3157     }
3158   }
3159   catch (Standard_Failure) {
3160     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
3161     SetErrorCode(aFail->GetMessageString());
3162     return NULL;
3163   }
3164
3165   //Make a Python command
3166   TCollection_AsciiString anEntry, aListRes("[");
3167   // Iterate over the sequence aSeq
3168   Standard_Integer aNbGroups = aSeq->Length();
3169   Standard_Integer i = 1;
3170   for (; i <= aNbGroups; i++) {
3171     Handle(Standard_Transient) anItem = aSeq->Value(i);
3172     if (anItem.IsNull()) continue;
3173     Handle(GEOM_Object) aGroup = Handle(GEOM_Object)::DownCast(anItem);
3174     if (aGroup.IsNull()) continue;
3175     //Make a Python command
3176     TDF_Tool::Entry(aGroup->GetEntry(), anEntry);
3177     aListRes += anEntry + ", ";
3178   }
3179   aListRes.Trunc(aListRes.Length() - 2);
3180
3181   GEOM::TPythonDump pd (aFunction);
3182
3183   pd << aListRes.ToCString() << "] = geompy.MakePipeTShapeFillet("
3184      << theR1 << ", " << theW1 << ", " << theL1 << ", "
3185      << theR2  << ", " << theW2 << ", " << theL2 << ", "
3186      << theRF << ", " << theHexMesh << ", "
3187      << theP1 << ", " << theP2 << ", " << theP3;
3188
3189   // thickness reduction
3190   if (isTRL)
3191     pd << ", theRL=" << theRL << ", theWL=" << theWL
3192        << ", theLtransL=" << theLtransL << ", theLthinL=" << theLthinL;
3193   if (isTRR)
3194     pd << ", theRR=" << theRR << ", theWR=" << theWR
3195        << ", theLtransR=" << theLtransR << ", theLthinR=" << theLthinR;
3196   if (isTRI)
3197     pd << ", theRI=" << theRI << ", theWI=" << theWI
3198        << ", theLtransI=" << theLtransI << ", theLthinI=" << theLthinI;
3199
3200   pd << ")";
3201
3202   SetErrorCode(OK);
3203
3204   return aSeq;
3205 }
3206
3207 //=============================================================================
3208 /*!
3209  *  This function allows to create a disk already divided into blocks. It can be
3210  *  used to create divided pipes for later meshing in hexaedra.
3211  *  \param theR Radius of the disk
3212  *  \param theRatio Relative size of the central square diagonal against the disk diameter
3213  *  \param theOrientation Plane on which the disk will be built
3214  *  \param thePattern The division pattern of the disk (hexagon or square in the center)
3215  *  \return New GEOM_Object, containing the created shape.
3216  */
3217 //=============================================================================
3218 Handle(GEOM_Object) AdvancedEngine_IOperations::MakeDividedDisk (double theR, double theRatio, 
3219                                                                  int theOrientation, int thePattern)
3220 {
3221   SetErrorCode(KO);
3222   
3223   if (theOrientation != 1 &&
3224       theOrientation != 2 &&
3225       theOrientation != 3)
3226   {
3227     SetErrorCode("theOrientation must be 1(=OXY), 2(=OYZ) or 3(=OZX)");
3228     return NULL;
3229   }
3230   //Add a new object
3231   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_DIVIDEDDISK);
3232
3233   //Add a new shape function with parameters
3234   Handle(GEOM_Function) aFunction = aShape->AddFunction(AdvancedEngine_DividedDiskDriver::GetID(), DIVIDEDDISK_R_RATIO);
3235   if (aFunction.IsNull()) return NULL;
3236
3237   //Check if the function is set correctly
3238   if (aFunction->GetDriverGUID() != AdvancedEngine_DividedDiskDriver::GetID()) return NULL;
3239
3240   AdvancedEngine_IDividedDisk aData (aFunction);
3241
3242   aData.SetR(theR);
3243   aData.SetRatio(theRatio);
3244   aData.SetOrientation(theOrientation);
3245   aData.SetType(thePattern);
3246
3247   //Compute the resulting value
3248   try {
3249     OCC_CATCH_SIGNALS;
3250     if (!GetSolver()->ComputeFunction(aFunction)) {
3251       SetErrorCode("DividedDisk driver failed");
3252       return NULL;
3253     }
3254   }
3255   catch (Standard_Failure) {
3256     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
3257     SetErrorCode(aFail->GetMessageString());
3258     return NULL;
3259   }
3260   
3261   std::string aPatternStr;
3262   
3263   switch(thePattern)
3264   {
3265     case 0:
3266       aPatternStr = "GEOM.SQUARE";
3267       break;
3268     case 1:
3269       aPatternStr = "GEOM.HEXAGON";
3270       break;
3271   }
3272   
3273   //Make a Python command
3274   GEOM::TPythonDump(aFunction) << aShape << " = geompy.MakeDividedDisk(" << theR << ", " << theOrientation << ", " << aPatternStr.c_str() << ")";
3275
3276   SetErrorCode(OK);
3277
3278   return aShape;
3279 }
3280
3281 //=============================================================================
3282 /*!
3283  *  This function allows to create a disk already divided into blocks. It can be
3284  *  used to create divided pipes for later meshing in hexaedra.
3285  *  \param theR Radius of the disk
3286  *  \param theRatio Relative size of the central square diagonal against the disk diameter
3287  *  \return New GEOM_Object, containing the created shape.
3288  */
3289 //=============================================================================
3290 Handle(GEOM_Object) AdvancedEngine_IOperations::MakeDividedDiskPntVecR (Handle(GEOM_Object) thePnt, 
3291                                                                         Handle(GEOM_Object) theVec, 
3292                                                                         double theR, 
3293                                                                         double theRatio,
3294                                                                         int    thePattern)
3295 {
3296   SetErrorCode(KO);
3297
3298   //Add a new object
3299   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_DIVIDEDDISK);
3300
3301   //Add a new shape function with parameters
3302   Handle(GEOM_Function) aFunction = aShape->AddFunction(AdvancedEngine_DividedDiskDriver::GetID(), DIVIDEDDISK_R_VECTOR_PNT);
3303   if (aFunction.IsNull()) return NULL;
3304
3305   //Check if the function is set correctly
3306   if (aFunction->GetDriverGUID() != AdvancedEngine_DividedDiskDriver::GetID()) return NULL;
3307
3308   AdvancedEngine_IDividedDisk aData (aFunction);
3309   
3310   Handle(GEOM_Function) aRefPnt = thePnt->GetLastFunction();
3311   Handle(GEOM_Function) aRefVec = theVec->GetLastFunction();
3312
3313   if (aRefPnt.IsNull() || aRefVec.IsNull()) return NULL;
3314
3315   aData.SetCenter(aRefPnt);
3316   aData.SetVector(aRefVec);
3317
3318   aData.SetR(theR);
3319   aData.SetRatio(theRatio);
3320   aData.SetType(thePattern);
3321
3322   //Compute the resulting value
3323   try {
3324     OCC_CATCH_SIGNALS;
3325     if (!GetSolver()->ComputeFunction(aFunction)) {
3326       SetErrorCode("DividedDisk driver failed");
3327       return NULL;
3328     }
3329   }
3330   catch (Standard_Failure) {
3331     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
3332     SetErrorCode(aFail->GetMessageString());
3333     return NULL;
3334   }
3335   
3336   std::string aPatternStr;
3337   
3338   switch(thePattern)
3339   {
3340     case 0:
3341       aPatternStr = "GEOM.SQUARE";
3342       break;
3343     case 1:
3344       aPatternStr = "GEOM.HEXAGON";
3345       break;
3346   }
3347   
3348
3349   //Make a Python command
3350   GEOM::TPythonDump(aFunction) << aShape << " = geompy.MakeDividedDiskPntVecR(" << thePnt << ", " << theVec << ", " << theR << ", " << aPatternStr.c_str() << ")";
3351
3352   SetErrorCode(OK);
3353
3354   return aShape;
3355 }
3356
3357 //=============================================================================
3358 /*!
3359  *  Builds a cylinder prepared for hexa meshes
3360  *  \param theR Radius of the cylinder
3361  *  \param theH Height of the cylinder
3362  *  \return New GEOM_Object, containing the created shape.
3363  */
3364 //=============================================================================
3365 Handle(GEOM_Object) AdvancedEngine_IOperations::MakeDividedCylinder (double theR, 
3366                                                                      double theH,
3367                                                                      int    thePattern)
3368 {
3369   SetErrorCode(KO);
3370   
3371   //Add a new object
3372   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_DIVIDEDCYLINDER);
3373
3374   Handle(GEOM_Object) aBaseShape = MakeDividedDisk(theR, 67.0, 1, thePattern);
3375   aBaseShape->GetLastFunction()->SetDescription("");   // Erase dump of MakeDividedDisk
3376   
3377   aShape = my3DPrimOperations->MakePrismDXDYDZ(aBaseShape,0.0,0.0,theH, -1.0);
3378         
3379   Handle(GEOM_Function) aFunction =  aShape->GetLastFunction();
3380   aFunction->SetDescription("");   // Erase dump of MakePrismDXDYDZ
3381   aShape->SetType(GEOM_DIVIDEDCYLINDER);
3382   
3383   std::string aPatternStr;
3384   
3385   switch(thePattern)
3386   {
3387     case 0:
3388       aPatternStr = "GEOM.SQUARE";
3389       break;
3390     case 1:
3391       aPatternStr = "GEOM.HEXAGON";
3392       break;
3393   }
3394   
3395   //Make a Python command
3396   GEOM::TPythonDump(aFunction) << aShape << " = geompy.MakeDividedCylinder(" << theR << ", " << theH << ", " << aPatternStr.c_str() << ")";
3397
3398   SetErrorCode(OK);
3399
3400   return aShape;
3401 }
3402 //=============================================================================
3403 /*!
3404  *  Create a smoothing surface from a set of points
3405  *  \param thelPoints list of points or compounds of points
3406  *  \param theNbMax maximum number of Bezier pieces in the resulting surface.
3407  *  \param theDegMax maximum degree of the resulting BSpline surface
3408  *  \param theDMax specifies maximum value of the GeomPlate_PlateG0Criterion criterion.
3409  *  \return New GEOM_Object, containing the created shape.
3410  */
3411 //=============================================================================
3412 Handle(GEOM_Object) AdvancedEngine_IOperations::MakeSmoothingSurface (std::list<Handle(GEOM_Object)> thelPoints, 
3413                                                                       int                            theNbMax,
3414                                                                       int                            theDegMax,
3415                                                                       double                         theDMax)
3416 {
3417   SetErrorCode(KO);
3418
3419   //Add a new object
3420   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_SMOOTHINGSURFACE);
3421
3422   //Add a new shape function with parameters
3423   Handle(GEOM_Function) aFunction = aShape->AddFunction(AdvancedEngine_SmoothingSurfaceDriver::GetID(), SMOOTHINGSURFACE_LPOINTS);
3424   if (aFunction.IsNull()) return NULL;
3425
3426   //Check if the function is set correctly
3427   if (aFunction->GetDriverGUID() != AdvancedEngine_SmoothingSurfaceDriver::GetID()) return NULL;
3428
3429   AdvancedEngine_ISmoothingSurface aData (aFunction);
3430
3431   int aLen = thelPoints.size();
3432   aData.SetLength(aLen);
3433   int ind = 1;
3434   std::list<Handle(GEOM_Object)>::iterator it = thelPoints.begin();
3435   for (; it != thelPoints.end(); it++, ind++) {
3436     Handle(GEOM_Function) aRefObj = (*it)->GetLastFunction();
3437     if (aRefObj.IsNull()) {
3438       SetErrorCode("NULL point or compound for bSplineFaceShape");
3439       return NULL;
3440     }
3441     aData.SetPntOrComp(ind, aRefObj);
3442   }
3443
3444   aData.SetNbMax(theNbMax);
3445   aData.SetDegMax(theDegMax);
3446   aData.SetDMax(theDMax);
3447
3448   //Compute the resulting value
3449   try {
3450     OCC_CATCH_SIGNALS;
3451     if (!GetSolver()->ComputeFunction(aFunction)) {
3452       SetErrorCode("SmoothingSurface driver failed");
3453       return NULL;
3454     }
3455   }
3456   catch (Standard_Failure) {
3457     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
3458     SetErrorCode(aFail->GetMessageString());
3459     return NULL;
3460   }
3461
3462   //Make a Python command
3463   GEOM::TPythonDump pd (aFunction);
3464   pd << aShape << " = geompy.MakeSmoothingSurface([";
3465   it = thelPoints.begin();
3466   pd << (*it++);
3467   while (it != thelPoints.end()) {
3468     pd << ", " << (*it++);
3469   }
3470   pd << "], "
3471      << theNbMax << ", "
3472      << theDegMax << ", "
3473      << theDMax <<")";
3474
3475   SetErrorCode(OK);
3476
3477   return aShape;
3478 }