Salome HOME
0022616: [CEA 1038] Improve the quality of stl and vtk exports
[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 #if OCC_VERSION_LARGE > 0x06010000
1153     OCC_CATCH_SIGNALS;
1154 #endif
1155     Handle(GEOM_Object) Vector_Z = myBasicOperations->MakeVectorDXDYDZ(0, 0, 1);
1156     Vector_Z->GetLastFunction()->SetDescription("");
1157
1158     // Useful values
1159     double aSize = 2*(theL1 + theL2);
1160     double aR1Ext = theR1 + theW1;
1161     double aR2Ext = theR2 + theW2;
1162     double theVertCylinderRadius = aR2Ext + theW + theRF;
1163     double theHoriCylinderRadius = aR1Ext + theH + theRF;
1164
1165     // Common edges on internal cylinder
1166     Handle(GEOM_Object) box_i = my3DPrimOperations->MakeBoxDXDYDZ(theR2, theR2, theR1);
1167     box_i->GetLastFunction()->SetDescription("");
1168     box_i = myTransformOperations->TranslateDXDYDZ(box_i, -theR2, -theR2, 0);
1169     box_i->GetLastFunction()->SetDescription("");
1170
1171     Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
1172     TCollection_AsciiString theDesc = aFunction->GetDescription();
1173     Handle(TColStd_HSequenceOfTransient) edges_i =
1174       myShapesOperations->GetShapesOnBox(box_i, theShape, TopAbs_EDGE, GEOMAlgo_ST_IN);
1175     // Recover previous description to get rid of Propagate dump
1176     aFunction->SetDescription(theDesc);
1177     if (edges_i.IsNull() || edges_i->Length() == 0) {
1178       SetErrorCode("Internal edges not found");
1179       return false;
1180     }
1181     for (int i=1; i<=edges_i->Length();i++) {
1182       Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(edges_i->Value(i));
1183       anObj->GetLastFunction()->SetDescription("");
1184     }
1185     arete_intersect_int = Handle(GEOM_Object)::DownCast(edges_i->Value(1));
1186
1187     // search for vertices located on both internal pipes
1188     aFunction = theShape->GetLastFunction();
1189     theDesc = aFunction->GetDescription();
1190     Handle(TColStd_HSequenceOfTransient) vertices_i =
1191       myShapesOperations->GetShapesOnBox(box_i, theShape, TopAbs_VERTEX, GEOMAlgo_ST_ONIN);
1192     // Recover previous description to get rid of Propagate dump
1193     aFunction->SetDescription(theDesc);
1194     if (vertices_i.IsNull() || vertices_i->Length() == 0) {
1195       SetErrorCode("Internal vertices not found");
1196       return false;
1197     }
1198
1199     double d1min = theR2+theW2, d2min=theR2+theW2;
1200     for (int i = 1; i <= vertices_i->Length(); i++) {
1201       Handle(GEOM_Object) v = Handle(GEOM_Object)::DownCast(vertices_i->Value(i));
1202       v->GetLastFunction()->SetDescription("");
1203       TopoDS_Vertex aVertex = TopoDS::Vertex(v->GetValue());
1204       gp_Pnt aP = BRep_Tool::Pnt(aVertex);
1205       if (Abs(aP.X()) <= Precision::Confusion()) {
1206         if (Abs(aP.Y()) < d1min) {
1207           vi1 = v;
1208           d1min = Abs(aP.Y());
1209         }
1210       } else if (Abs(aP.Y()) <= Precision::Confusion()) {
1211         if (Abs(aP.X()) < d2min) {
1212           vi2 = v;
1213           d2min = Abs(aP.X());
1214         }
1215       }
1216     }
1217     if (vi1.IsNull() || vi2.IsNull()) {
1218       SetErrorCode("Cannot find internal intersection vertices");
1219       return false;
1220     }
1221
1222     std::list<Handle(GEOM_Object)> theShapes;
1223
1224     if (isNormal) {
1225       Handle(GEOM_Object) ve1, ve2;
1226       TopoDS_Vertex vertex1, vertex2;
1227
1228       Handle(GEOM_Object) box_e = my3DPrimOperations->MakeBoxDXDYDZ(aR2Ext, aR2Ext, aR1Ext);
1229       box_e->GetLastFunction()->SetDescription("");
1230       box_e = myTransformOperations->TranslateDXDYDZ(box_e, -aR2Ext, -aR2Ext, 0);
1231       box_e->GetLastFunction()->SetDescription("");
1232
1233       // search for vertices located on both external pipes
1234       aFunction = theShape->GetLastFunction();
1235       theDesc = aFunction->GetDescription();
1236       Handle(TColStd_HSequenceOfTransient) vertices_e =
1237         myShapesOperations->GetShapesOnBox(box_e, theShape, TopAbs_VERTEX, GEOMAlgo_ST_ONIN);
1238       // Recover previous description to get rid of Propagate dump
1239       aFunction->SetDescription(theDesc);
1240       if (vertices_e.IsNull() || vertices_e->Length() == 0) {
1241         SetErrorCode("External vertices not found");
1242         return false;
1243       }
1244
1245       double d1max = 0, d2max = 0;
1246       for (int i = 1; i <= vertices_e->Length(); i++) {
1247         Handle(GEOM_Object) v = Handle(GEOM_Object)::DownCast(vertices_e->Value(i));
1248         v->GetLastFunction()->SetDescription("");
1249         TopoDS_Vertex aVertex = TopoDS::Vertex(v->GetValue());
1250         gp_Pnt aP = BRep_Tool::Pnt(aVertex);
1251         if (Abs(aP.X()) <= Precision::Confusion()) {
1252           if (Abs(aP.Y()) > d1max) {
1253             ve1 = v;
1254             vertex1 = aVertex;
1255             d1max = Abs(aP.Y());
1256           }
1257         } else if (Abs(aP.Y()) <= Precision::Confusion()) {
1258           if (Abs(aP.X()) > d2max) {
1259             ve2 = v;
1260             vertex2 = aVertex;
1261             d2max = Abs(aP.X());
1262           }
1263         }
1264       }
1265       if (ve1.IsNull() || ve2.IsNull()) {
1266         SetErrorCode("Cannot find external intersection vertices");
1267         return false;
1268       }
1269       Handle(GEOM_Object) edge_e1, edge_e2;
1270
1271       // Common edges on external cylinder
1272       aFunction = theShape->GetLastFunction();
1273       theDesc = aFunction->GetDescription();
1274       Handle(TColStd_HSequenceOfTransient) edges_e =
1275         myShapesOperations->GetShapesOnBox(box_e, theShape, TopAbs_EDGE, GEOMAlgo_ST_IN);
1276       // Recover previous description to get rid of Propagate dump
1277       aFunction->SetDescription(theDesc);
1278       if (edges_e.IsNull() || edges_e->Length() == 0) {
1279         SetErrorCode("External edges not found");
1280         return false;
1281       }
1282       ShapeAnalysis_Edge sae;
1283       for (int i=1; i<=edges_e->Length();i++) {
1284         Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(edges_e->Value(i));
1285         anObj->GetLastFunction()->SetDescription("");
1286         TopoDS_Edge anEdge = TopoDS::Edge(anObj->GetValue());
1287         if ( !anEdge.IsNull() && 
1288              (sae.FirstVertex(anEdge).IsSame(vertex1) || sae.LastVertex(anEdge).IsSame(vertex1)) && 
1289              (sae.FirstVertex(anEdge).IsSame(vertex2) || sae.LastVertex(anEdge).IsSame(vertex2))) {
1290           arete_intersect_ext = anObj;
1291         }
1292       }
1293
1294       edge_e1 = myBasicOperations->MakeLineTwoPnt(ve1, vi1);
1295       if (edge_e1.IsNull()) {
1296         SetErrorCode("Edge 1 could not be built");
1297         return false;
1298       }
1299
1300       edge_e2 = myBasicOperations->MakeLineTwoPnt(ve2, vi2);
1301       if (edge_e2.IsNull()) {
1302         SetErrorCode("Edge 2 could not be built");
1303         return false;
1304       }
1305
1306       edge_e1->GetLastFunction()->SetDescription("");
1307       edge_e2->GetLastFunction()->SetDescription("");
1308
1309       std::list<Handle(GEOM_Object)> edge_e_elist;
1310       edge_e_elist.push_back(arete_intersect_int);
1311       edge_e_elist.push_back(edge_e1);
1312       edge_e_elist.push_back(arete_intersect_ext);
1313       edge_e_elist.push_back(edge_e2);
1314       wire_t = myShapesOperations->MakeWire(edge_e_elist, 1e-7);
1315       if (wire_t.IsNull()) {
1316         SetErrorCode("Impossible to build wire");
1317         return false;
1318       }
1319       wire_t->GetLastFunction()->SetDescription("");
1320       face_t = myShapesOperations->MakeFace(wire_t, false);
1321       if (face_t.IsNull()) {
1322         SetErrorCode("Impossible to build face");
1323         return false;
1324       }
1325       face_t->GetLastFunction()->SetDescription("");
1326
1327       theShapes.push_back(theShape);
1328       theShapes.push_back(vi1);
1329       theShapes.push_back(vi2);
1330       theShapes.push_back(ve1);
1331       theShapes.push_back(ve2);
1332       theShapes.push_back(edge_e1);
1333       theShapes.push_back(edge_e2);
1334       theShapes.push_back(wire_t);
1335       theShapes.push_back(face_t);
1336     }
1337     else {
1338       Handle(GEOM_Object) P1, P2, P3, P4, P5, P6;
1339       int idP1, idP2, idP3, idP4;
1340       int PZX, PZY;
1341       double ZX=0, ZY=0;
1342       std::vector<int> LX;
1343       std::vector<int> LY;
1344       Handle(GEOM_Object) box_e = my3DPrimOperations->MakeBoxDXDYDZ
1345         (theVertCylinderRadius, theVertCylinderRadius, theHoriCylinderRadius);
1346       box_e->GetLastFunction()->SetDescription("");
1347       box_e = myTransformOperations->TranslateDXDYDZ
1348         (box_e, -theVertCylinderRadius, -theVertCylinderRadius, 0);
1349       box_e->GetLastFunction()->SetDescription("");
1350
1351       aFunction = theShape->GetLastFunction();
1352       theDesc = aFunction->GetDescription();
1353       Handle(TColStd_HSequenceOfTransient) extremVertices =
1354         myShapesOperations->GetShapesOnBox(box_e, theShape, TopAbs_VERTEX, GEOMAlgo_ST_ONIN);
1355       // Recover previous description to get rid of Propagate dump
1356       aFunction->SetDescription(theDesc);
1357
1358       if (extremVertices.IsNull() || extremVertices->Length() == 0) {
1359         if (theRF == 0)
1360           SetErrorCode("Vertices on chamfer not found");
1361         else
1362           SetErrorCode("Vertices on fillet not found");
1363         return false;
1364       }
1365
1366       theShapes.push_back(theShape);
1367       theShapes.push_back(box_e);
1368       if (extremVertices->Length() != 6) {
1369         //           for (int i=1; i<=extremVertices->Length(); i++){
1370         //             theShapes.push_back(Handle(GEOM_Object)::DownCast(extremVertices->Value(i)));
1371         //           }
1372         //           Handle(GEOM_Object) aCompound = myShapesOperations->MakeCompound(theShapes);
1373         //           TopoDS_Shape aCompoundShape = aCompound->GetValue();
1374         //           theShape->GetLastFunction()->SetValue(aCompoundShape);
1375         SetErrorCode("Bad number of vertices on chamfer found");
1376         return false;
1377       }
1378
1379       for (int i=1; i<=extremVertices->Length(); i++){
1380         Handle(GEOM_Object) aV = Handle(GEOM_Object)::DownCast(extremVertices->Value(i));
1381         aV->GetLastFunction()->SetDescription("");
1382         gp_Pnt aP = BRep_Tool::Pnt(TopoDS::Vertex(aV->GetValue()));
1383
1384         if (Abs(aP.X()) <= Precision::Confusion()) {
1385           if (Abs(aP.Y()) - theR2 > Precision::Confusion()) {
1386             LX.push_back(i);
1387             if  (aP.Z()-ZX > Precision::Confusion()) {
1388               ZX = aP.Z();
1389               PZX = i;
1390             }
1391           }
1392         }
1393         else {
1394           if (Abs(aP.X()) - theR2 > Precision::Confusion()) {
1395             LY.push_back(i);
1396             if (aP.Z() - ZY > Precision::Confusion()) {
1397               ZY = aP.Z();
1398               PZY = i;
1399             }
1400           }
1401         }
1402       }
1403
1404       idP2 = PZX;
1405       idP4 = PZY;
1406       idP1 = LX.at(0);
1407       if (LX.at(0) == PZX)
1408         idP1 = LX.at(1);
1409       idP3 = LY.at(0);
1410       if (LY.at(0) == PZY)
1411         idP3 = LY.at(1);
1412
1413       P1 = Handle(GEOM_Object)::DownCast(extremVertices->Value(idP1));
1414       P2 = Handle(GEOM_Object)::DownCast(extremVertices->Value(idP2));
1415       P3 = Handle(GEOM_Object)::DownCast(extremVertices->Value(idP3));
1416       P4 = Handle(GEOM_Object)::DownCast(extremVertices->Value(idP4));
1417
1418       Handle(GEOM_Object) Cote_1 = myBasicOperations->MakeLineTwoPnt(P1, vi1);
1419       if (Cote_1.IsNull()) {
1420         SetErrorCode("Impossible to build edge in thickness");
1421         return false;
1422       }
1423       Cote_1->GetLastFunction()->SetDescription("");
1424
1425       Handle(GEOM_Object) Cote_2 = myBasicOperations->MakeLineTwoPnt(vi2, P3);
1426       if (Cote_2.IsNull()) {
1427         SetErrorCode("Impossible to build edge in thickness");
1428         return false;
1429       }
1430       Cote_2->GetLastFunction()->SetDescription("");
1431
1432       // edge_chan_princ = arete du chanfrein (ou raccord) sur le tuyau principal
1433       // edge_chan_inc = arete du chanfrein (ou raccord) sur le tuyau incident
1434       //         std::cerr << "Getting chamfer edge on main pipe" << std::endl;
1435       Handle(GEOM_Object) edge_chan_princ = myBlocksOperations->GetEdge(theShape, P1, P3);
1436       if (edge_chan_princ.IsNull()) {
1437         SetErrorCode("Impossible to find edge on main pipe");
1438         return false;
1439       }
1440       edge_chan_princ->GetLastFunction()->SetDescription("");
1441
1442       Handle(GEOM_Object) edge_chan_inc = myBlocksOperations->GetEdge(theShape, P2, P4);
1443       if (edge_chan_inc.IsNull()) {
1444         SetErrorCode("Impossible to find edge on incident pipe");
1445         return false;
1446       }
1447       edge_chan_inc->GetLastFunction()->SetDescription("");
1448
1449       std::list<Handle(GEOM_Object)> edgeList1;
1450       edgeList1.push_back(edge_chan_princ);
1451       edgeList1.push_back(Cote_1);
1452       edgeList1.push_back(arete_intersect_int);
1453       edgeList1.push_back(Cote_2);
1454
1455       //         std::cerr << "Creating wire 1" << std::endl;
1456       wire_t = myShapesOperations->MakeWire(edgeList1, 1e-7);
1457       if (wire_t.IsNull()) {
1458         SetErrorCode("Impossible to build wire");
1459         return false;
1460       }
1461       wire_t->GetLastFunction()->SetDescription("");
1462
1463       //         std::cerr << "Creating face 1" << std::endl;
1464       face_t = myShapesOperations->MakeFace(wire_t, false);
1465       if (face_t.IsNull()) {
1466         SetErrorCode("Impossible to build face");
1467         return false;
1468       }
1469       face_t->GetLastFunction()->SetDescription("");
1470       theShapes.push_back(face_t);
1471
1472       gp_Pnt aP2 = BRep_Tool::Pnt(TopoDS::Vertex(P2->GetValue()));
1473       gp_Pnt aP5 = BRep_Tool::Pnt(TopoDS::Vertex(vi1->GetValue()));
1474       double deltaZ = aP2.Z() - aP5.Z();
1475       //         std::cerr << "Creating new point from vi1 with deltaZ = " << deltaZ << std::endl;
1476       Handle(GEOM_Object) P5bis = myTransformOperations->TranslateDXDYDZCopy(vi1, 0, 0, deltaZ);
1477       if (P5bis.IsNull()) {
1478         SetErrorCode("Impossible to translate vertex");
1479         return false;
1480       }
1481       P5bis->GetLastFunction()->SetDescription("");
1482
1483       gp_Pnt aP4 = BRep_Tool::Pnt(TopoDS::Vertex(P4->GetValue()));
1484       gp_Pnt aP6 = BRep_Tool::Pnt(TopoDS::Vertex(vi2->GetValue()));
1485       deltaZ = aP4.Z() - aP6.Z();
1486       //         std::cerr << "Creating new point from vi2 with deltaZ = " << deltaZ << std::endl;
1487       Handle(GEOM_Object) P6bis = myTransformOperations->TranslateDXDYDZCopy(vi2, 0, 0, deltaZ);
1488       if (P6bis.IsNull()) {
1489         SetErrorCode("Impossible to translate vertex");
1490         return false;
1491       }
1492       P6bis->GetLastFunction()->SetDescription("");
1493
1494       //         std::cerr << "Creating new line 1 from 2 previous points" << std::endl;
1495       Handle(GEOM_Object) Cote_3 = myBasicOperations->MakeLineTwoPnt(P5bis, P2);
1496       if (Cote_3.IsNull()) {
1497         SetErrorCode("Impossible to build edge in thickness");
1498         return false;
1499       }
1500       Cote_3->GetLastFunction()->SetDescription("");
1501
1502       //         std::cerr << "Creating new line 2 from 2 previous points" << std::endl;
1503       Handle(GEOM_Object) Cote_4 = myBasicOperations->MakeLineTwoPnt(P6bis, P4);
1504       if (Cote_4.IsNull()) {
1505         SetErrorCode("Impossible to build edge in thickness");
1506         return false;
1507       }
1508       Cote_4->GetLastFunction()->SetDescription("");
1509
1510       //         std::cerr << "Creating new line 3 from 2 previous points" << std::endl;
1511       Handle(GEOM_Object) Cote_5 = myBasicOperations->MakeLineTwoPnt(P5bis, P6bis);
1512       if (Cote_4.IsNull()) {
1513         SetErrorCode("Impossible to build edge in thickness");
1514         return false;
1515       }
1516       Cote_5->GetLastFunction()->SetDescription("");
1517
1518       //std::list<Handle(GEOM_Object)> edgeList2;
1519       //edgeList2.push_back(edge_chan_inc);
1520       //edgeList2.push_back(Cote_3);
1521       //edgeList2.push_back(Cote_5);
1522       //edgeList2.push_back(Cote_4);
1523       //         std::cerr << "Creating wire 2" << std::endl;
1524       //wire_t2 = myShapesOperations->MakeWire(edgeList2, 1e-7);
1525       //if (wire_t2.IsNull()) {
1526       //  SetErrorCode("Impossible to build wire");
1527       //  return false;
1528       //}
1529       //wire_t2->GetLastFunction()->SetDescription("");
1530       //         std::cerr << "Creating face 2" << std::endl;
1531       //face_t2 = myShapesOperations->MakeFace(wire_t2, false);
1532
1533       // Mantis issue 0021682
1534       face_t2 = my3DPrimOperations->MakePrismVecH(edge_chan_inc, Cote_4, - (theR2 + theW2));
1535       //face_t2 = my3DPrimOperations->MakePrismVecH(edge_chan_inc, Cote_4, - 2.0*theR2);
1536       if (face_t2.IsNull()) {
1537         SetErrorCode("Impossible to build face");
1538         return false;
1539       }
1540       face_t2->GetLastFunction()->SetDescription("");
1541       theShapes.push_back(face_t2);
1542     }
1543
1544     // Planes
1545     Handle(GEOM_Object) aP0 = myBasicOperations->MakePointXYZ(0, 0, 0);
1546     Handle(GEOM_Object) aVZ = myBasicOperations->MakeVectorDXDYDZ(0, 0, 1);
1547     Handle(GEOM_Object) aVXZ = myBasicOperations->MakeVectorDXDYDZ(aR1Ext, 0, 0.5*(theL1+theVertCylinderRadius));
1548     Handle(GEOM_Object) aPlnOZ = myBasicOperations->MakePlanePntVec(aP0, aVZ, aSize);
1549     Handle(GEOM_Object) aPlnOXZ = myBasicOperations->MakePlanePntVec(aP0, aVXZ, aSize);
1550     aP0->GetLastFunction()->SetDescription("");
1551     aVZ->GetLastFunction()->SetDescription("");
1552     aVXZ->GetLastFunction()->SetDescription("");
1553     aPlnOZ->GetLastFunction()->SetDescription("");
1554     aPlnOXZ->GetLastFunction()->SetDescription("");
1555     theShapes.push_back(aPlnOZ);
1556     theShapes.push_back(aPlnOXZ);
1557
1558     // Partition
1559     Handle(TColStd_HSequenceOfTransient) partitionShapes = new TColStd_HSequenceOfTransient;
1560     Handle(TColStd_HSequenceOfTransient) theTools = new TColStd_HSequenceOfTransient;
1561     Handle(TColStd_HSequenceOfTransient) theKeepInside = new TColStd_HSequenceOfTransient;
1562     Handle(TColStd_HSequenceOfTransient) theRemoveInside = new TColStd_HSequenceOfTransient;
1563     Handle(TColStd_HArray1OfInteger) theMaterials;
1564
1565     partitionShapes->Append(theShape);
1566     theTools->Append(aPlnOZ);
1567     if (Abs(aR1Ext - aR2Ext) > Precision::Confusion())
1568       theTools->Append(aPlnOXZ);
1569     theTools->Append(face_t);
1570     if (!isNormal)
1571       theTools->Append(face_t2);
1572
1573     Te3 = myBooleanOperations->MakePartition
1574               (partitionShapes, theTools, theKeepInside, theRemoveInside,
1575               TopAbs_SOLID, false, theMaterials, 0, false, Standard_False);
1576     if (Te3.IsNull()) {
1577       SetErrorCode("Impossible to build partition of TShape");
1578       return false;
1579     }
1580     Te3->GetLastFunction()->SetDescription("");
1581
1582     // Last verification: result should be a block
1583     std::list<GEOMImpl_IBlocksOperations::BCError> errList;
1584     if (!myBlocksOperations->CheckCompoundOfBlocks(Te3,errList)) {
1585       SetErrorCode("TShape is not a compound of block");
1586       return false;
1587     }
1588
1589 //     // BEGIN Compound of created shapes - Only for debug purpose
1590 //     theShapes.clear();
1591 //     theShapes.push_back(theShape);
1592 //     theShapes.push_back(aPlnOZ);
1593 //     if (Abs(aR1Ext - aR2Ext) > Precision::Confusion() )
1594 //       theShapes.push_back(aPlnOXZ);
1595 //     theShapes.push_back(face_t);
1596 //     if (!isNormal)
1597 //       theShapes.push_back(face_t2);
1598 //
1599 //     Handle(GEOM_Object) aCompound = myShapesOperations->MakeCompound(theShapes);
1600 //     TopoDS_Shape aCompoundShape = aCompound->GetValue();
1601 //     theShape->GetLastFunction()->SetValue(aCompoundShape);
1602 //     // END Compound of created shapes - Only for debug purpose
1603
1604     TopoDS_Shape aShape = Te3->GetValue();
1605     theShape->GetLastFunction()->SetValue(aShape);
1606   }
1607   catch (Standard_Failure) {
1608     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1609     SetErrorCode(aFail->GetMessageString());
1610     return false;
1611   }
1612
1613   SetErrorCode(OK);
1614   return true;
1615 }
1616
1617 // Mirror and glue faces
1618 bool AdvancedEngine_IOperations::MakePipeTShapeMirrorAndGlue(Handle(GEOM_Object) theShape,
1619                                                              double theR1, double theW1, double theL1,
1620                                                              double theR2, double theW2, double theL2)
1621 {
1622   SetErrorCode(KO);
1623
1624   // Useful values
1625   double aSize = 2*(theL1 + theL2);
1626   double aR1Ext = theR1 + theW1;
1627
1628   // Planes
1629   Handle(GEOM_Object) aP0 = myBasicOperations->MakePointXYZ(0, 0, 0);
1630   aP0->GetLastFunction()->SetDescription("");
1631   Handle(GEOM_Object) aVX = myBasicOperations->MakeVectorDXDYDZ(1, 0, 0);
1632   Handle(GEOM_Object) aVY = myBasicOperations->MakeVectorDXDYDZ(0, 1, 0);
1633   aVX->GetLastFunction()->SetDescription("");
1634   aVY->GetLastFunction()->SetDescription("");
1635   Handle(GEOM_Object) aPlane_OX = myBasicOperations->MakePlanePntVec(aP0, aVX, 2*(aR1Ext + theL2));
1636   Handle(GEOM_Object) aPlane_OY = myBasicOperations->MakePlanePntVec(aP0, aVY, aSize);
1637   aPlane_OX->GetLastFunction()->SetDescription("");
1638   aPlane_OY->GetLastFunction()->SetDescription("");
1639
1640   Handle(GEOM_Object) Te4 = myTransformOperations->MirrorPlaneCopy(theShape, aPlane_OX);
1641   if (Te4.IsNull()) {
1642     SetErrorCode("Impossible to build mirror of quarter TShape");
1643     return false;
1644   }
1645
1646   Handle(GEOM_Object) Te5 = myTransformOperations->MirrorPlaneCopy(theShape, aPlane_OY);
1647   if (Te5.IsNull()) {
1648     SetErrorCode("Impossible to build mirror of half TShape");
1649     return false;
1650   }
1651
1652   Handle(GEOM_Object) Te6 = myTransformOperations->MirrorPlaneCopy(Te4, aPlane_OY);
1653   if (Te6.IsNull()) {
1654     SetErrorCode("Impossible to build mirror of half TShape");
1655     return false;
1656   }
1657
1658   std::list<Handle(GEOM_Object)> aShapesList;
1659   aShapesList.push_back(theShape);
1660   aShapesList.push_back(Te4);
1661   aShapesList.push_back(Te5);
1662   aShapesList.push_back(Te6);
1663   Handle(GEOM_Object) Te7 = myShapesOperations->MakeCompound(aShapesList);
1664   if (Te7.IsNull()) {
1665     SetErrorCode("Impossible to build compound");
1666     return false;
1667   }
1668
1669   // Copy source shape
1670   TopoDS_Shape aShapeCopy;
1671   TColStd_IndexedDataMapOfTransientTransient aMapTShapes;
1672   TNaming_CopyShape::CopyTool(Te7->GetValue(), aMapTShapes, aShapeCopy);
1673
1674   Handle(GEOM_Object) Te8 = myShapesOperations->MakeGlueFaces(Te7, 1e-7, true);
1675   if (Te8.IsNull()) {
1676     SetErrorCode("Impossible to glue faces of TShape");
1677     return false;
1678   }
1679
1680   TopoDS_Shape aShape = Te8->GetValue();
1681   BRepCheck_Analyzer anAna (aShape, Standard_True);
1682
1683   if (!anAna.IsValid()) {
1684     // Try to do gluing with the tolerance equal to maximal
1685     // tolerance of vertices of the source shape.
1686     Standard_Real aTolMax = -RealLast();
1687
1688     for (TopExp_Explorer ExV (aShapeCopy, TopAbs_VERTEX); ExV.More(); ExV.Next()) {
1689       TopoDS_Vertex aVertex = TopoDS::Vertex(ExV.Current());
1690       Standard_Real aTol = BRep_Tool::Tolerance(aVertex);
1691
1692       if (aTol > aTolMax) {
1693         aTolMax = aTol;
1694       }
1695     }
1696
1697     // Perform gluing
1698     Te7->GetLastFunction()->SetValue(aShapeCopy);
1699     Te8 = myShapesOperations->MakeGlueFaces(Te7, aTolMax, true);
1700
1701     if (Te8.IsNull()) {
1702       SetErrorCode("Impossible to glue faces of TShape");
1703       return false;
1704     }
1705
1706     aShape = Te8->GetValue();
1707   }
1708
1709
1710   theShape->GetLastFunction()->SetValue(aShape);
1711
1712   Te4->GetLastFunction()->SetDescription("");
1713   Te5->GetLastFunction()->SetDescription("");
1714   Te6->GetLastFunction()->SetDescription("");
1715   Te7->GetLastFunction()->SetDescription("");
1716   Te8->GetLastFunction()->SetDescription("");
1717
1718   SetErrorCode(OK);
1719   return true;
1720 }
1721
1722 //=======================================================================
1723 //function : MakePipeTShapeThicknessReduction
1724 //purpose  : Static method. Add thiskness reduction elements at the three
1725 //                          open ends of the T-Shape.
1726 //=======================================================================
1727 TopoDS_Shape AdvancedEngine_IOperations::MakePipeTShapeThicknessReduction
1728                                   (TopoDS_Shape theShape,
1729                                    double r1, double w1, double l1,
1730                                    double r2, double w2, double l2,
1731                                    double rL, double wL, double ltransL, double lthinL,
1732                                    double rR, double wR, double ltransR, double lthinR,
1733                                    double rI, double wI, double ltransI, double lthinI,
1734                                    bool fuseReductions)
1735 {
1736   // Add thickness reduction elements
1737   // at the three extremities: Left, Right and Incident
1738   //
1739   // ---------------------.
1740   //   W                   \
1741   // ---------------------. \
1742   //   ^                   \ '-----------------.
1743   //   |R                   \        Wthin     |
1744   //   |                     '-----------------'
1745   //   v                             Rthin
1746   // --.--.--.--.--.--.--.--.--.--.--.--.--.--.--
1747   //                     Ltrans    Lthin
1748
1749   TopoDS_Shape aResult = theShape;
1750   double aTol = Precision::Confusion();
1751
1752   gp_Vec aVX = gp::DX(), aVZ = gp::DZ();
1753
1754   // Left reduction (rL, wL, ltransL, lthinL)
1755   if (rL > aTol && wL > aTol && ltransL > aTol) {
1756     gp_Pnt aPLeft (-l1, 0, 0);
1757     gp_Ax2 anAxesLeft (aPLeft, -aVX, aVZ);
1758     TopoDS_Shape aReductionLeft = AdvancedEngine_IOperations::MakeThicknessReduction
1759       (anAxesLeft, r1, w1, rL, wL, ltransL, lthinL, fuseReductions);
1760
1761     if (fuseReductions) {
1762       BRepAlgoAPI_Fuse fuseL (aResult, aReductionLeft);
1763       if (!fuseL.IsDone())
1764         StdFail_NotDone::Raise("Cannot fuse Te with left reduction");
1765       aResult = fuseL.Shape();
1766     }
1767     else {
1768       BRep_Builder B;
1769       TopoDS_Compound C;
1770       B.MakeCompound(C);
1771       B.Add(C, aResult);
1772       B.Add(C, aReductionLeft);
1773       aResult = C;
1774     }
1775   }
1776
1777   // Right reduction
1778   if (rR > aTol && wR > aTol && ltransR > aTol) {
1779     gp_Pnt aPRight (l1, 0, 0);
1780     gp_Ax2 anAxesRight (aPRight, aVX, aVZ);
1781     TopoDS_Shape aReductionRight = AdvancedEngine_IOperations::MakeThicknessReduction
1782       (anAxesRight, r1, w1, rR, wR, ltransR, lthinR, fuseReductions);
1783
1784     if (fuseReductions) {
1785       BRepAlgoAPI_Fuse fuseR (aResult, aReductionRight);
1786       if (!fuseR.IsDone())
1787         StdFail_NotDone::Raise("Cannot fuse Te with right reduction");
1788       aResult = fuseR.Shape();
1789     }
1790     else {
1791       BRep_Builder B;
1792       TopoDS_Compound C;
1793       B.MakeCompound(C);
1794       B.Add(C, aResult);
1795       B.Add(C, aReductionRight);
1796       aResult = C;
1797     }
1798   }
1799
1800   // Incident reduction
1801   if (rI > aTol && wI > aTol && ltransI > aTol) {
1802     gp_Pnt aPInci (0, 0, l2);
1803     gp_Ax2 anAxesInci (aPInci, aVZ, aVX);
1804     TopoDS_Shape aReductionInci = AdvancedEngine_IOperations::MakeThicknessReduction
1805       (anAxesInci, r2, w2, rI, wI, ltransI, lthinI, fuseReductions);
1806
1807     if (fuseReductions) {
1808       BRepAlgoAPI_Fuse fuseInci (aResult, aReductionInci);
1809       if (!fuseInci.IsDone())
1810         StdFail_NotDone::Raise("Cannot fuse Te with incident reduction");
1811       aResult = fuseInci.Shape();
1812     }
1813     else {
1814       BRep_Builder B;
1815       TopoDS_Compound C;
1816       B.MakeCompound(C);
1817       B.Add(C, aResult);
1818       B.Add(C, aReductionInci);
1819       aResult = C;
1820     }
1821   }
1822
1823   // Get rid of extra compounds
1824   TopTools_ListOfShape listShapeRes;
1825   GEOMUtils::AddSimpleShapes(aResult, listShapeRes);
1826   aResult = listShapeRes.First(); // useful for the case "fuseReductions == true"
1827
1828   if (!fuseReductions && listShapeRes.Extent() > 1) {
1829     // Simplify T-Shape compound (get rid of sub-compounds) and glue duplicated faces
1830     BRep_Builder B;
1831     TopoDS_Compound C;
1832     B.MakeCompound(C);
1833
1834     TopTools_ListIteratorOfListOfShape itSub (listShapeRes);
1835     for (; itSub.More(); itSub.Next())
1836       B.Add(C, itSub.Value());
1837
1838     // GlueFaces
1839     aResult = GEOMImpl_GlueDriver::GlueFaces(C, Precision::Confusion(), Standard_True);
1840   }
1841
1842   return aResult;
1843 }
1844
1845 //=======================================================================
1846 //function : MakeThicknessReduction
1847 //purpose  : Static method. Create one thickness reduction element.
1848 //=======================================================================
1849 TopoDS_Shape AdvancedEngine_IOperations::MakeThicknessReduction (gp_Ax2 theAxes,
1850                                                                  const double R, const double W,
1851                                                                  const double Rthin, const double Wthin,
1852                                                                  const double Ltrans, const double Lthin,
1853                                                                  bool fuse)
1854 {
1855   double aTol = Precision::Confusion();
1856   if (Rthin < aTol || Wthin < aTol || Ltrans < aTol) {
1857     StdFail_NotDone::Raise("Cannot build thickness reduction: too small values");
1858   }
1859   bool isThinPart = (Lthin > aTol);
1860
1861   //     .
1862   //   W |\
1863   //     . \
1864   //   ^  \ '-----------------.
1865   //   |R  \|                 | Wthin
1866   //   |    '-----------------'
1867   //   v                        Rthin
1868   // --.--.--.--.--.--.--.--.--.--.--.--.--> theAxes.Direction()
1869   //     Ltrans     Lthin
1870
1871   double RExt = R + W;
1872   double RthinExt = Rthin + Wthin;
1873
1874   gp_Dir aNormal = theAxes.Direction();
1875   gp_Dir anXDir  = theAxes.XDirection();
1876   gp_Pnt aPntCyl (theAxes.Location().XYZ() + aNormal.XYZ()*Ltrans);
1877   gp_Ax2 anAxesCyl (aPntCyl, aNormal, anXDir);
1878
1879   // Build the transition part
1880   BRepPrimAPI_MakeCone ConeExt (theAxes, RExt, RthinExt, Ltrans);
1881   BRepPrimAPI_MakeCone ConeInt (theAxes, R, Rthin, Ltrans);
1882   ConeExt.Build();
1883   ConeInt.Build();
1884   if (!ConeExt.IsDone() || !ConeInt.IsDone())
1885     StdFail_NotDone::Raise("Cannot build cones of thickness reduction");
1886   BRepAlgoAPI_Cut cut1 (ConeExt.Shape(), ConeInt.Shape());
1887   if (!cut1.IsDone())
1888     StdFail_NotDone::Raise("Coudn't build transition part of thickness reduction");
1889   TopoDS_Shape aReduction = cut1.Shape();
1890
1891   // Build the thin part, if required
1892   TopoDS_Shape aThinPart;
1893   if (isThinPart) {
1894     BRepPrimAPI_MakeCylinder CExt (anAxesCyl, RthinExt, Lthin);
1895     BRepPrimAPI_MakeCylinder CInt (anAxesCyl, Rthin, Lthin);
1896     CExt.Build();
1897     CInt.Build();
1898     if (!CExt.IsDone() || !CInt.IsDone())
1899       StdFail_NotDone::Raise("Cannot build cylinders of thickness reduction");
1900     BRepAlgoAPI_Cut cut2 (CExt.Shape(), CInt.Shape());
1901     if (!cut2.IsDone())
1902       StdFail_NotDone::Raise("Coudn't build thin part of thickness reduction");
1903     aThinPart = cut2.Shape();
1904   }
1905
1906   // Join parts
1907   if (fuse) {
1908     if (isThinPart) {
1909       BRepAlgoAPI_Fuse fuse1 (aReduction, aThinPart);
1910       if (!fuse1.IsDone())
1911         StdFail_NotDone::Raise("Cannot fuse parts of thickness reduction");
1912       aReduction = fuse1.Shape();
1913     }
1914   }
1915   else {
1916     // Partition the reduction on blocks
1917     gp_Ax3 anAxesPln1 (aPntCyl, theAxes.XDirection(), aNormal);
1918     gp_Ax3 anAxesPln2 (aPntCyl, theAxes.YDirection(), aNormal);
1919     gp_Pln aPln1 (anAxesPln1);
1920     gp_Pln aPln2 (anAxesPln2);
1921     double aSize = Ltrans + Lthin + R + Rthin + Wthin; // to guarantee enough size in all directions
1922     TopoDS_Shape aTool1 = BRepBuilderAPI_MakeFace(aPln1, -aSize, +aSize, -aSize, +aSize).Shape();
1923     TopoDS_Shape aTool2 = BRepBuilderAPI_MakeFace(aPln2, -aSize, +aSize, -aSize, +aSize).Shape();
1924
1925     GEOMAlgo_Splitter PS;
1926     PS.AddArgument(aReduction);
1927     if (isThinPart)
1928       PS.AddArgument(aThinPart);
1929     PS.AddTool(aTool1);
1930     PS.AddTool(aTool2);
1931     PS.SetLimit(TopAbs_SOLID);
1932     PS.Perform();
1933
1934     aReduction = PS.Shape();
1935   }
1936
1937   return aReduction;
1938 }
1939
1940 //=============================================================================
1941 /*!
1942  *  MakePipeTShape
1943  *  \brief Create a T-shape object with specified caracteristics for the main and
1944  *         the incident pipes (radius, width, half-length).
1945  *         Center of the shape is (0,0,0). The main plane of the T-shape is XOY.
1946  *  \param theR1 Internal radius of main pipe
1947  *  \param theW1 Width of main pipe
1948  *  \param theL1 Half-length of main pipe
1949  *  \param theR2 Internal radius of incident pipe (R2 < R1)
1950  *  \param theW2 Width of incident pipe (R2+W2 < R1+W1)
1951  *  \param theL2 Half-length of incident pipe
1952  *  \param theHexMesh Boolean indicating if shape is prepared for hex mesh
1953  *  \return List of GEOM_Objects, containing the created shape and propagation groups.
1954  */
1955 //=============================================================================
1956 Handle(TColStd_HSequenceOfTransient)
1957   AdvancedEngine_IOperations::MakePipeTShape(double theR1, double theW1, double theL1,
1958                                              double theR2, double theW2, double theL2,
1959                                              double theRL, double theWL, double theLtransL, double theLthinL,
1960                                              double theRR, double theWR, double theLtransR, double theLthinR,
1961                                              double theRI, double theWI, double theLtransI, double theLthinI,
1962                                              bool theHexMesh)
1963 {
1964   MESSAGE("AdvancedEngine_IOperations::MakePipeTShape");
1965   SetErrorCode(KO);
1966   //Add a new object
1967   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_TSHAPE);
1968
1969   //Add a new shape function with parameters
1970   Handle(GEOM_Function) aFunction = aShape->AddFunction(AdvancedEngine_PipeTShapeDriver::GetID(), TSHAPE_BASIC);
1971   if (aFunction.IsNull()) return NULL;
1972
1973   //Check if the function is set correctly
1974   if (aFunction->GetDriverGUID() != AdvancedEngine_PipeTShapeDriver::GetID()) return NULL;
1975
1976   AdvancedEngine_IPipeTShape aData (aFunction);
1977
1978   aData.SetR1(theR1);
1979   aData.SetW1(theW1);
1980   aData.SetL1(theL1);
1981   aData.SetR2(theR2);
1982   aData.SetW2(theW2);
1983   aData.SetL2(theL2);
1984   aData.SetHexMesh(theHexMesh);
1985
1986   bool isTRL = (theRL + theWL + theLtransL + theLthinL) > Precision::Confusion();
1987   bool isTRR = (theRR + theWR + theLtransR + theLthinR) > Precision::Confusion();
1988   bool isTRI = (theRI + theWI + theLtransI + theLthinI) > Precision::Confusion();
1989
1990   //Compute the resulting value
1991   try {
1992 #if OCC_VERSION_LARGE > 0x06010000
1993     OCC_CATCH_SIGNALS;
1994 #endif
1995     if (!GetSolver()->ComputeFunction(aFunction)) {
1996       SetErrorCode("TShape driver failed");
1997       return NULL;
1998     }
1999
2000     if (theHexMesh) {
2001       if (!MakePipeTShapePartition(aShape, theR1, theW1, theL1, theR2, theW2, theL2))
2002         return NULL;
2003       if (!MakePipeTShapeMirrorAndGlue(aShape, theR1, theW1, theL1, theR2, theW2, theL2))
2004         return NULL;
2005     }
2006
2007     if (isTRL || isTRR || isTRI) {
2008       // Add thickness reduction elements
2009       // at the three extremities: Left, Right and Incident
2010       TopoDS_Shape aResShape =
2011         MakePipeTShapeThicknessReduction(aShape->GetValue(), theR1, theW1, theL1, theR2, theW2, theL2,
2012                                          theRL, theWL, theLtransL, theLthinL,
2013                                          theRR, theWR, theLtransR, theLthinR,
2014                                          theRI, theWI, theLtransI, theLthinI,
2015                                          !theHexMesh);
2016       aFunction->SetValue(aResShape);
2017     }
2018   }
2019   catch (Standard_Failure) {
2020     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2021     SetErrorCode(aFail->GetMessageString());
2022     return NULL;
2023   }
2024
2025   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
2026   aSeq->Append(aShape);
2027
2028   try {
2029     if (theHexMesh) {
2030       // Get the groups
2031       if (!MakeGroups(aShape, TSHAPE_BASIC, theR1, theW1, theL1, theR2, theW2, theL2,
2032                       0., 0., 0., aSeq, gp_Trsf()))
2033         return NULL;
2034     }
2035
2036     // Get internal group.
2037     if (!MakeInternalGroup(aShape, theR1, theL1, theR2, theL2, theRL, theLtransL,
2038                            theRR, theLtransR, theRI, theLtransI,
2039                            aSeq, gp_Trsf())) {
2040       return NULL;
2041     }
2042   }
2043   catch (Standard_Failure) {
2044     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2045     SetErrorCode(aFail->GetMessageString());
2046     return NULL;
2047   }
2048
2049   //Make a Python command
2050   TCollection_AsciiString anEntry, aListRes("[");
2051   // Iterate over the sequence aSeq
2052   Standard_Integer aNbGroups = aSeq->Length();
2053   Standard_Integer i = 1;
2054   for (; i <= aNbGroups; i++) {
2055     Handle(Standard_Transient) anItem = aSeq->Value(i);
2056     if (anItem.IsNull()) continue;
2057     Handle(GEOM_Object) aGroup = Handle(GEOM_Object)::DownCast(anItem);
2058     if (aGroup.IsNull()) continue;
2059     //Make a Python command
2060     TDF_Tool::Entry(aGroup->GetEntry(), anEntry);
2061     aListRes += anEntry + ", ";
2062   }
2063   aListRes.Trunc(aListRes.Length() - 2);
2064
2065   GEOM::TPythonDump pd (aFunction);
2066
2067   pd << aListRes.ToCString() << "] = geompy.MakePipeTShape("
2068      << theR1 << ", " << theW1 << ", " << theL1 << ", "
2069      << theR2 << ", " << theW2 << ", " << theL2 << ", "
2070      << theHexMesh;
2071
2072   // thickness reduction
2073   if (isTRL)
2074     pd << ", theRL=" << theRL << ", theWL=" << theWL
2075        << ", theLtransL=" << theLtransL << ", theLthinL=" << theLthinL;
2076   if (isTRR)
2077     pd << ", theRR=" << theRR << ", theWR=" << theWR
2078        << ", theLtransR=" << theLtransR << ", theLthinR=" << theLthinR;
2079   if (isTRI)
2080     pd << ", theRI=" << theRI << ", theWI=" << theWI
2081        << ", theLtransI=" << theLtransI << ", theLthinI=" << theLthinI;
2082
2083   pd << ")";
2084
2085   SetErrorCode(OK);
2086
2087   return aSeq;
2088 }
2089
2090 //=============================================================================
2091 /*!
2092  *  MakePipeTShapeWithPosition
2093  *  Create a T-shape object with specified caracteristics for the main and
2094  *  the incident pipes (radius, width, half-length).
2095  *  The extremities of the main pipe are located on junctions points P1 and P2.
2096  *  The extremity of the incident pipe is located on junction point P3.
2097  *  \param theR1 Internal radius of main pipe
2098  *  \param theW1 Width of main pipe
2099  *  \param theL1 Half-length of main pipe
2100  *  \param theR2 Internal radius of incident pipe (R2 < R1)
2101  *  \param theW2 Width of incident pipe (R2+W2 < R1+W1)
2102  *  \param theL2 Half-length of incident pipe
2103  *  \param theHexMesh Boolean indicating if shape is prepared for hex mesh
2104  *  \param theP1 1st junction point of main pipe
2105  *  \param theP2 2nd junction point of main pipe
2106  *  \param theP3 Junction point of incident pipe
2107  *  \return List of GEOM_Objects, containing the created shape and propagation groups..
2108  */
2109 //=============================================================================
2110 Handle(TColStd_HSequenceOfTransient)
2111 AdvancedEngine_IOperations::MakePipeTShapeWithPosition
2112                              (double theR1, double theW1, double theL1,
2113                               double theR2, double theW2, double theL2,
2114                               double theRL, double theWL, double theLtransL, double theLthinL,
2115                               double theRR, double theWR, double theLtransR, double theLthinR,
2116                               double theRI, double theWI, double theLtransI, double theLthinI,
2117                               bool theHexMesh,
2118                               Handle(GEOM_Object) theP1,
2119                               Handle(GEOM_Object) theP2,
2120                               Handle(GEOM_Object) theP3)
2121 {
2122   SetErrorCode(KO);
2123   //Add a new object
2124   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_TSHAPE);
2125   /////////////////
2126   // TSHAPE CODE
2127   /////////////////
2128   //Add a new shape function with parameters
2129   Handle(GEOM_Function) aFunction = aShape->AddFunction(AdvancedEngine_PipeTShapeDriver::GetID(), TSHAPE_BASIC);
2130   if (aFunction.IsNull()) return NULL;
2131
2132   //Check if the function is set correctly
2133   if (aFunction->GetDriverGUID() != AdvancedEngine_PipeTShapeDriver::GetID()) return NULL;
2134
2135   // Check new position
2136   if (!CheckCompatiblePosition(theL1, theL2, theP1, theP2, theP3, 0.01)) {
2137     return NULL;
2138   }
2139
2140   AdvancedEngine_IPipeTShape aData(aFunction);
2141
2142   aData.SetR1(theR1);
2143   aData.SetW1(theW1);
2144   aData.SetL1(theL1);
2145   aData.SetR2(theR2);
2146   aData.SetW2(theW2);
2147   aData.SetL2(theL2);
2148   aData.SetHexMesh(theHexMesh);
2149
2150   bool isTRL = (theRL + theWL + theLtransL + theLthinL) > Precision::Confusion();
2151   bool isTRR = (theRR + theWR + theLtransR + theLthinR) > Precision::Confusion();
2152   bool isTRI = (theRI + theWI + theLtransI + theLthinI) > Precision::Confusion();
2153
2154   //Compute the resulting value
2155   try {
2156 #if OCC_VERSION_LARGE > 0x06010000
2157     OCC_CATCH_SIGNALS;
2158 #endif
2159     if (!GetSolver()->ComputeFunction(aFunction)) {
2160       SetErrorCode("TShape driver failed");
2161       return NULL;
2162     }
2163
2164     if (theHexMesh) {
2165       if (!MakePipeTShapePartition(aShape, theR1, theW1, theL1, theR2, theW2, theL2))
2166         return NULL;
2167       if (!MakePipeTShapeMirrorAndGlue(aShape, theR1, theW1, theL1, theR2, theW2, theL2))
2168         return NULL;
2169     }
2170
2171     if (isTRL || isTRR || isTRI) {
2172       // Add thickness reduction elements
2173       // at the three extremities: Left, Right and Incident
2174       TopoDS_Shape aResShape =
2175         MakePipeTShapeThicknessReduction(aShape->GetValue(), theR1, theW1, theL1, theR2, theW2, theL2,
2176                                          theRL, theWL, theLtransL, theLthinL,
2177                                          theRR, theWR, theLtransR, theLthinR,
2178                                          theRI, theWI, theLtransI, theLthinI,
2179                                          !theHexMesh);
2180       aFunction->SetValue(aResShape);
2181     }
2182   }
2183   catch (Standard_Failure) {
2184     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2185     SetErrorCode(aFail->GetMessageString());
2186     return NULL;
2187   }
2188
2189   TopoDS_Shape Te = aShape->GetValue();
2190
2191   // Set Position
2192   gp_Trsf aTrsf = GetPositionTrsf(theL1, theL2, theP1, theP2, theP3);
2193   BRepBuilderAPI_Transform aTransformation(Te, aTrsf, Standard_False);
2194   TopoDS_Shape aTrsf_Shape = aTransformation.Shape();
2195   aFunction->SetValue(aTrsf_Shape);
2196
2197   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
2198   aSeq->Append(aShape);
2199
2200   try {
2201     if (theHexMesh) {
2202       // Get the groups
2203       if (!MakeGroups(aShape,TSHAPE_BASIC, theR1, theW1, theL1, theR2, theW2, theL2,
2204                       0., 0., 0., aSeq, aTrsf)) {
2205         return NULL;
2206       }
2207     }
2208
2209     // Get internal group.
2210     if (!MakeInternalGroup(aShape, theR1, theL1, theR2, theL2, theRL, theLtransL,
2211                            theRR, theLtransR, theRI, theLtransI,
2212                            aSeq, aTrsf)) {
2213       return NULL;
2214     }
2215   }
2216   catch (Standard_Failure) {
2217     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2218     SetErrorCode(aFail->GetMessageString());
2219     return NULL;
2220   }
2221
2222   //Make a Python command
2223   TCollection_AsciiString anEntry, aListRes("[");
2224   // Iterate over the sequence aSeq
2225   Standard_Integer aNbGroups = aSeq->Length();
2226   Standard_Integer i = 1;
2227   for (; i <= aNbGroups; i++) {
2228     Handle(Standard_Transient) anItem = aSeq->Value(i);
2229     if (anItem.IsNull()) continue;
2230     Handle(GEOM_Object) aGroup = Handle(GEOM_Object)::DownCast(anItem);
2231     if (aGroup.IsNull()) continue;
2232     //Make a Python command
2233     TDF_Tool::Entry(aGroup->GetEntry(), anEntry);
2234     aListRes += anEntry + ", ";
2235   }
2236   aListRes.Trunc(aListRes.Length() - 2);
2237
2238   GEOM::TPythonDump pd (aFunction);
2239
2240   pd << aListRes.ToCString() << "] = geompy.MakePipeTShape("
2241      << theR1 << ", " << theW1 << ", " << theL1 << ", "
2242      << theR2 << ", " << theW2 << ", " << theL2 << ", "
2243      << theHexMesh << ", " << theP1 << ", " << theP2 << ", " << theP3;
2244
2245   // thickness reduction
2246   if (isTRL)
2247     pd << ", theRL=" << theRL << ", theWL=" << theWL
2248        << ", theLtransL=" << theLtransL << ", theLthinL=" << theLthinL;
2249   if (isTRR)
2250     pd << ", theRR=" << theRR << ", theWR=" << theWR
2251        << ", theLtransR=" << theLtransR << ", theLthinR=" << theLthinR;
2252   if (isTRI)
2253     pd << ", theRI=" << theRI << ", theWI=" << theWI
2254        << ", theLtransI=" << theLtransI << ", theLthinI=" << theLthinI;
2255
2256   pd << ")";
2257
2258   SetErrorCode(OK);
2259
2260   return aSeq;
2261 }
2262
2263 //=============================================================================
2264 /*!
2265  *  MakePipeTShapeChamfer
2266  *  Create a T-shape object with specified caracteristics for the main and
2267  *  the incident pipes (radius, width, half-length). A chamfer is created
2268  *  on the junction of the pipes.
2269  *  Center of the shape is (0,0,0). The main plane of the T-shape is XOY.
2270  *  \param theR1 Internal radius of main pipe
2271  *  \param theW1 Width of main pipe
2272  *  \param theL1 Half-length of main pipe
2273  *  \param theR2 Internal radius of incident pipe (R2 < R1)
2274  *  \param theW2 Width of incident pipe (R2+W2 < R1+W1)
2275  *  \param theL2 Half-length of incident pipe
2276  *  \param theH Height of chamfer.
2277  *  \param theW Width of chamfer.
2278  *  \param theHexMesh Boolean indicating if shape is prepared for hex mesh
2279  *  \return List of GEOM_Objects, containing the created shape and propagation groups.
2280  */
2281 //=============================================================================
2282 Handle(TColStd_HSequenceOfTransient)
2283 AdvancedEngine_IOperations::MakePipeTShapeChamfer
2284                              (double theR1, double theW1, double theL1,
2285                               double theR2, double theW2, double theL2,
2286                               double theRL, double theWL, double theLtransL, double theLthinL,
2287                               double theRR, double theWR, double theLtransR, double theLthinR,
2288                               double theRI, double theWI, double theLtransI, double theLthinI,
2289                               double theH, double theW,
2290                               bool theHexMesh)
2291 {
2292   SetErrorCode(KO);
2293   //Add a new object
2294   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_TSHAPE);
2295   //Add a new shape function with parameters
2296   Handle(GEOM_Function) aFunction = aShape->AddFunction(AdvancedEngine_PipeTShapeDriver::GetID(), TSHAPE_CHAMFER);
2297   if (aFunction.IsNull()) return NULL;
2298
2299   //Check if the function is set correctly
2300   if (aFunction->GetDriverGUID() != AdvancedEngine_PipeTShapeDriver::GetID()) return NULL;
2301
2302   AdvancedEngine_IPipeTShape aData(aFunction);
2303
2304   aData.SetR1(theR1);
2305   aData.SetW1(theW1);
2306   aData.SetL1(theL1);
2307   aData.SetR2(theR2);
2308   aData.SetW2(theW2);
2309   aData.SetL2(theL2);
2310   aData.SetH(theH);
2311   aData.SetW(theW);
2312   aData.SetHexMesh(theHexMesh);
2313
2314   bool isTRL = (theRL + theWL + theLtransL + theLthinL) > Precision::Confusion();
2315   bool isTRR = (theRR + theWR + theLtransR + theLthinR) > Precision::Confusion();
2316   bool isTRI = (theRI + theWI + theLtransI + theLthinI) > Precision::Confusion();
2317
2318   //Compute the resulting value
2319   try {
2320 #if OCC_VERSION_LARGE > 0x06010000
2321     OCC_CATCH_SIGNALS;
2322 #endif
2323     if (!GetSolver()->ComputeFunction(aFunction)) {
2324       SetErrorCode("TShape driver failed");
2325       return NULL;
2326     }
2327   }
2328   catch (Standard_Failure) {
2329     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2330     SetErrorCode(aFail->GetMessageString());
2331     return NULL;
2332   }
2333
2334   // BEGIN of chamfer
2335   TopoDS_Shape aShapeShape = aShape->GetValue();
2336   TopTools_IndexedMapOfShape anEdgesIndices;
2337   TopExp::MapShapes(aShapeShape, anEdgesIndices);
2338   // Common edges on external cylinders
2339   Handle(GEOM_Object) box_e;
2340   if (theHexMesh) {
2341     box_e = my3DPrimOperations->MakeBoxDXDYDZ(theR2+theW2, theR2+theW2, theR1+theW1);
2342   }
2343   else {
2344     box_e = my3DPrimOperations->MakeBoxDXDYDZ(2*(theR2+theW2), 2*(theR2+theW2), theR1+theW1);
2345   }
2346   box_e->GetLastFunction()->SetDescription("");
2347   box_e = myTransformOperations->TranslateDXDYDZ(box_e, -(theR2+theW2), -(theR2+theW2), 0);
2348   box_e->GetLastFunction()->SetDescription("");
2349
2350   Handle(TColStd_HSequenceOfInteger) edges_e =
2351     myShapesOperations->GetShapesOnBoxIDs(box_e, aShape, TopAbs_EDGE, GEOMAlgo_ST_IN);
2352   box_e->GetLastFunction()->SetDescription("");
2353
2354   if (edges_e.IsNull() || edges_e->Length() == 0) {
2355     SetErrorCode("External edges not found");
2356     return NULL;
2357   }
2358   int nbEdgesInChamfer = 0;
2359   std::list<int> theEdges;
2360   for (int i=1; i<=edges_e->Length();i++) {
2361     int edgeID = edges_e->Value(i);
2362     TopoDS_Shape theEdge = anEdgesIndices.FindKey(edgeID);
2363     TopExp_Explorer Ex(theEdge,TopAbs_VERTEX);
2364     int iv=0;
2365     while (Ex.More()) {
2366       iv ++;
2367       gp_Pnt aPt = BRep_Tool::Pnt(TopoDS::Vertex(Ex.Current()));
2368       if (Abs(aPt.Z() - (theR1+theW1)) <= Precision::Confusion()) {
2369         nbEdgesInChamfer ++;
2370         theEdges.push_back(edgeID);
2371       }
2372       Ex.Next();
2373     }
2374     if (theHexMesh && nbEdgesInChamfer == 1)
2375       break;
2376   }
2377   Handle(GEOM_Object) aChamfer;
2378   try {
2379     aChamfer = myLocalOperations->MakeChamferEdges(aShape, theW, theH, theEdges);
2380   }
2381   catch (Standard_Failure) {
2382     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2383     SetErrorCode(aFail->GetMessageString());
2384     return NULL;
2385   }
2386   if (aChamfer.IsNull()) {
2387     SetErrorCode("Chamfer can not be computed on the given shape with the given parameters");
2388     return NULL;
2389   }
2390   aChamfer->GetLastFunction()->SetDescription("");
2391
2392   TopoDS_Shape aChamferShape = aChamfer->GetValue();
2393   aFunction->SetValue(aChamferShape);
2394   // END of chamfer
2395
2396   if (theHexMesh) {
2397     if (!MakePipeTShapePartition(aShape, theR1, theW1, theL1, theR2, theW2, theL2, theH, theW, 0, false))
2398       return NULL;
2399     if (!MakePipeTShapeMirrorAndGlue(aShape, theR1, theW1, theL1, theR2, theW2, theL2))
2400       return NULL;
2401   }
2402
2403   // Add thickness reduction elements
2404   // at the three extremities: Left, Right and Incident
2405   try {
2406 #if OCC_VERSION_LARGE > 0x06010000
2407     OCC_CATCH_SIGNALS;
2408 #endif
2409     if (isTRL || isTRR || isTRI) {
2410       TopoDS_Shape aResShape =
2411         MakePipeTShapeThicknessReduction(aShape->GetValue(), theR1, theW1, theL1, theR2, theW2, theL2,
2412                                          theRL, theWL, theLtransL, theLthinL,
2413                                          theRR, theWR, theLtransR, theLthinR,
2414                                          theRI, theWI, theLtransI, theLthinI,
2415                                          !theHexMesh);
2416       aFunction->SetValue(aResShape);
2417     }
2418   }
2419   catch (Standard_Failure) {
2420     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2421     SetErrorCode(aFail->GetMessageString());
2422     return NULL;
2423   }
2424
2425   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
2426   aSeq->Append(aShape);
2427
2428   try {
2429     if (theHexMesh) {
2430       // Get the groups
2431       if (!MakeGroups(aShape, TSHAPE_CHAMFER, theR1, theW1, theL1, theR2, theW2, theL2,
2432                       theH, theW, 0., aSeq, gp_Trsf()))
2433         return NULL;
2434     }
2435
2436     // Get internal group.
2437     if (!MakeInternalGroup(aShape, theR1, theL1, theR2, theL2, theRL, theLtransL,
2438                            theRR, theLtransR, theRI, theLtransI,
2439                            aSeq, gp_Trsf())) {
2440       return NULL;
2441     }
2442   }
2443   catch (Standard_Failure) {
2444     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2445     SetErrorCode(aFail->GetMessageString());
2446     return NULL;
2447   }
2448
2449   //Make a Python command
2450   TCollection_AsciiString anEntry, aListRes("[");
2451   // Iterate over the sequence aSeq
2452   Standard_Integer aNbGroups = aSeq->Length();
2453   Standard_Integer i = 1;
2454   for (; i <= aNbGroups; i++) {
2455     Handle(Standard_Transient) anItem = aSeq->Value(i);
2456     if (anItem.IsNull()) continue;
2457     Handle(GEOM_Object) aGroup = Handle(GEOM_Object)::DownCast(anItem);
2458     if (aGroup.IsNull()) continue;
2459     //Make a Python command
2460     TDF_Tool::Entry(aGroup->GetEntry(), anEntry);
2461     aListRes += anEntry + ", ";
2462   }
2463   aListRes.Trunc(aListRes.Length() - 2);
2464
2465   GEOM::TPythonDump pd (aFunction);
2466
2467   pd << aListRes.ToCString() << "] = geompy.MakePipeTShapeChamfer("
2468      << theR1 << ", " << theW1 << ", " << theL1 << ", "
2469      << theR2 << ", " << theW2 << ", " << theL2 << ", "
2470      << theH << ", " << theW << ", " << theHexMesh;
2471
2472   // thickness reduction
2473   if (isTRL)
2474     pd << ", theRL=" << theRL << ", theWL=" << theWL
2475        << ", theLtransL=" << theLtransL << ", theLthinL=" << theLthinL;
2476   if (isTRR)
2477     pd << ", theRR=" << theRR << ", theWR=" << theWR
2478        << ", theLtransR=" << theLtransR << ", theLthinR=" << theLthinR;
2479   if (isTRI)
2480     pd << ", theRI=" << theRI << ", theWI=" << theWI
2481        << ", theLtransI=" << theLtransI << ", theLthinI=" << theLthinI;
2482
2483   pd << ")";
2484
2485   SetErrorCode(OK);
2486
2487   return aSeq;
2488 }
2489
2490 //=============================================================================
2491 /*!
2492  *  MakePipeTShapeChamferWithPosition
2493  *  Create a T-shape object with specified caracteristics for the main and
2494  *  the incident pipes (radius, width, half-length). A chamfer is created
2495  *  on the junction of the pipes.
2496  *  The extremities of the main pipe are located on junctions points P1 and P2.
2497  *  The extremity of the incident pipe is located on junction point P3.
2498  *  \param theR1 Internal radius of main pipe
2499  *  \param theW1 Width of main pipe
2500  *  \param theL1 Half-length of main pipe
2501  *  \param theR2 Internal radius of incident pipe (R2 < R1)
2502  *  \param theW2 Width of incident pipe (R2+W2 < R1+W1)
2503  *  \param theL2 Half-length of incident pipe
2504  *  \param theH Height of chamfer.
2505  *  \param theW Width of chamfer.
2506  *  \param theHexMesh Boolean indicating if shape is prepared for hex mesh
2507  *  \param theP1 1st junction point of main pipe
2508  *  \param theP2 2nd junction point of main pipe
2509  *  \param theP3 Junction point of incident pipe
2510  *  \return List of GEOM_Objects, containing the created shape and propagation groups.
2511  */
2512 //=============================================================================
2513 Handle(TColStd_HSequenceOfTransient)
2514 AdvancedEngine_IOperations::MakePipeTShapeChamferWithPosition
2515                              (double theR1, double theW1, double theL1,
2516                               double theR2, double theW2, double theL2,
2517                               double theRL, double theWL, double theLtransL, double theLthinL,
2518                               double theRR, double theWR, double theLtransR, double theLthinR,
2519                               double theRI, double theWI, double theLtransI, double theLthinI,
2520                               double theH, double theW,
2521                               bool theHexMesh,
2522                               Handle(GEOM_Object) theP1,
2523                               Handle(GEOM_Object) theP2,
2524                               Handle(GEOM_Object) theP3)
2525 {
2526   SetErrorCode(KO);
2527   //Add a new object
2528   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_TSHAPE);
2529   //Add a new shape function with parameters
2530   Handle(GEOM_Function) aFunction = aShape->AddFunction(AdvancedEngine_PipeTShapeDriver::GetID(), TSHAPE_CHAMFER);
2531   if (aFunction.IsNull()) return NULL;
2532
2533   //Check if the function is set correctly
2534   if (aFunction->GetDriverGUID() != AdvancedEngine_PipeTShapeDriver::GetID()) return NULL;
2535
2536   // Check new position
2537   if (!CheckCompatiblePosition(theL1, theL2, theP1, theP2, theP3, 0.01)) {
2538     return NULL;
2539   }
2540
2541   AdvancedEngine_IPipeTShape aData(aFunction);
2542
2543   aData.SetR1(theR1);
2544   aData.SetW1(theW1);
2545   aData.SetL1(theL1);
2546   aData.SetR2(theR2);
2547   aData.SetW2(theW2);
2548   aData.SetL2(theL2);
2549   aData.SetH(theH);
2550   aData.SetW(theW);
2551   aData.SetHexMesh(theHexMesh);
2552
2553   bool isTRL = (theRL + theWL + theLtransL + theLthinL) > Precision::Confusion();
2554   bool isTRR = (theRR + theWR + theLtransR + theLthinR) > Precision::Confusion();
2555   bool isTRI = (theRI + theWI + theLtransI + theLthinI) > Precision::Confusion();
2556
2557   //Compute the resulting value
2558   try {
2559 #if OCC_VERSION_LARGE > 0x06010000
2560     OCC_CATCH_SIGNALS;
2561 #endif
2562     if (!GetSolver()->ComputeFunction(aFunction)) {
2563       SetErrorCode("TShape driver failed");
2564       return NULL;
2565     }
2566   }
2567   catch (Standard_Failure) {
2568     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2569     SetErrorCode(aFail->GetMessageString());
2570     return NULL;
2571   }
2572
2573   // BEGIN of chamfer
2574   TopoDS_Shape aShapeShape = aShape->GetValue();
2575   TopTools_IndexedMapOfShape anEdgesIndices;
2576   TopExp::MapShapes(aShapeShape, anEdgesIndices);
2577   // Common edges on external cylinders
2578   Handle(GEOM_Object) box_e;
2579   if (theHexMesh) {
2580     box_e = my3DPrimOperations->MakeBoxDXDYDZ(theR2+theW2, theR2+theW2, theR1+theW1);
2581   }
2582   else {
2583     box_e = my3DPrimOperations->MakeBoxDXDYDZ(2*(theR2+theW2), 2*(theR2+theW2), theR1+theW1);
2584   }
2585   box_e->GetLastFunction()->SetDescription("");
2586   box_e = myTransformOperations->TranslateDXDYDZ(box_e, -(theR2+theW2), -(theR2+theW2), 0);
2587   box_e->GetLastFunction()->SetDescription("");
2588
2589   Handle(TColStd_HSequenceOfInteger) edges_e =
2590     myShapesOperations->GetShapesOnBoxIDs(box_e, aShape, TopAbs_EDGE, GEOMAlgo_ST_IN);
2591   box_e->GetLastFunction()->SetDescription("");
2592
2593   if (edges_e.IsNull() || edges_e->Length() == 0) {
2594     SetErrorCode("External edges not found");
2595     return NULL;
2596   }
2597   int nbEdgesInChamfer = 0;
2598   std::list<int> theEdges;
2599   for (int i=1; i<=edges_e->Length();i++) {
2600     int edgeID = edges_e->Value(i);
2601     TopoDS_Shape theEdge = anEdgesIndices.FindKey(edgeID);
2602     TopExp_Explorer Ex(theEdge,TopAbs_VERTEX);
2603     while (Ex.More()) {
2604       gp_Pnt aPt = BRep_Tool::Pnt(TopoDS::Vertex(Ex.Current()));
2605       if (Abs(aPt.Z() - (theR1+theW1)) <= Precision::Confusion()) {
2606         nbEdgesInChamfer ++;
2607         theEdges.push_back(edgeID);
2608       }
2609       Ex.Next();
2610     }
2611     if (theHexMesh && nbEdgesInChamfer == 1)
2612       break;
2613   }
2614   Handle(GEOM_Object) aChamfer;
2615   try {
2616     aChamfer = myLocalOperations->MakeChamferEdges(aShape, theW, theH, theEdges);
2617   }
2618   catch (Standard_Failure) {
2619     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2620     SetErrorCode(aFail->GetMessageString());
2621     return NULL;
2622   }
2623   if (aChamfer.IsNull()) {
2624     SetErrorCode("Chamfer can not be computed on the given shape with the given parameters");
2625     return NULL;
2626   }
2627   aChamfer->GetLastFunction()->SetDescription("");
2628
2629   TopoDS_Shape aChamferShape = aChamfer->GetValue();
2630   aFunction->SetValue(aChamferShape);
2631   // END of chamfer
2632
2633   if (theHexMesh) {
2634     if (!MakePipeTShapePartition(aShape, theR1, theW1, theL1, theR2, theW2, theL2, theH, theW, 0, false))
2635       return NULL;
2636     if (!MakePipeTShapeMirrorAndGlue(aShape, theR1, theW1, theL1, theR2, theW2, theL2))
2637       return NULL;
2638   }
2639
2640   // Add thickness reduction elements
2641   // at the three extremities: Left, Right and Incident
2642   try {
2643 #if OCC_VERSION_LARGE > 0x06010000
2644     OCC_CATCH_SIGNALS;
2645 #endif
2646     if (isTRL || isTRR || isTRI) {
2647       TopoDS_Shape aResShape =
2648         MakePipeTShapeThicknessReduction(aShape->GetValue(), theR1, theW1, theL1, theR2, theW2, theL2,
2649                                          theRL, theWL, theLtransL, theLthinL,
2650                                          theRR, theWR, theLtransR, theLthinR,
2651                                          theRI, theWI, theLtransI, theLthinI,
2652                                          !theHexMesh);
2653       aFunction->SetValue(aResShape);
2654     }
2655   }
2656   catch (Standard_Failure) {
2657     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2658     SetErrorCode(aFail->GetMessageString());
2659     return NULL;
2660   }
2661
2662   // Set Position
2663   gp_Trsf aTrsf = GetPositionTrsf(theL1, theL2, theP1, theP2, theP3);
2664   BRepBuilderAPI_Transform aTransformation (aShape->GetValue(), aTrsf, Standard_False);
2665   TopoDS_Shape aTrsf_Shape = aTransformation.Shape();
2666   aFunction->SetValue(aTrsf_Shape);
2667
2668   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
2669   aSeq->Append(aShape);
2670
2671   try {
2672     if (theHexMesh) {
2673       // Get the groups
2674       if (!MakeGroups(aShape, TSHAPE_CHAMFER, theR1, theW1, theL1, theR2, theW2, theL2,
2675                       theH, theW, 0., aSeq, aTrsf))
2676         return NULL;
2677     }
2678
2679     // Get internal group.
2680     if (!MakeInternalGroup(aShape, theR1, theL1, theR2, theL2, theRL, theLtransL,
2681                            theRR, theLtransR, theRI, theLtransI,
2682                            aSeq, aTrsf)) {
2683       return NULL;
2684     }
2685   }
2686   catch (Standard_Failure) {
2687     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2688     SetErrorCode(aFail->GetMessageString());
2689     return NULL;
2690   }
2691
2692   //Make a Python command
2693   TCollection_AsciiString anEntry, aListRes("[");
2694   // Iterate over the sequence aSeq
2695   Standard_Integer aNbGroups = aSeq->Length();
2696   Standard_Integer i = 1;
2697   for (; i <= aNbGroups; i++) {
2698     Handle(Standard_Transient) anItem = aSeq->Value(i);
2699     if (anItem.IsNull()) continue;
2700     Handle(GEOM_Object) aGroup = Handle(GEOM_Object)::DownCast(anItem);
2701     if (aGroup.IsNull()) continue;
2702     //Make a Python command
2703     TDF_Tool::Entry(aGroup->GetEntry(), anEntry);
2704     aListRes += anEntry + ", ";
2705   }
2706   aListRes.Trunc(aListRes.Length() - 2);
2707
2708   GEOM::TPythonDump pd (aFunction);
2709
2710   pd << aListRes.ToCString() << "] = geompy.MakePipeTShapeChamfer("
2711      << theR1 << ", " << theW1 << ", " << theL1 << ", "
2712      << theR2 << ", " << theW2 << ", " << theL2 << ", "
2713      << theH << ", " << theW << ", " << theHexMesh << ", "
2714      << theP1 << ", " << theP2 << ", " << theP3;
2715
2716   // thickness reduction
2717   if (isTRL)
2718     pd << ", theRL=" << theRL << ", theWL=" << theWL
2719        << ", theLtransL=" << theLtransL << ", theLthinL=" << theLthinL;
2720   if (isTRR)
2721     pd << ", theRR=" << theRR << ", theWR=" << theWR
2722        << ", theLtransR=" << theLtransR << ", theLthinR=" << theLthinR;
2723   if (isTRI)
2724     pd << ", theRI=" << theRI << ", theWI=" << theWI
2725        << ", theLtransI=" << theLtransI << ", theLthinI=" << theLthinI;
2726
2727   pd << ")";
2728
2729   SetErrorCode(OK);
2730
2731   return aSeq;
2732 }
2733
2734 //=============================================================================
2735 /*!
2736  *  MakePipeTShapeFillet
2737  *  Create a T-shape object with specified caracteristics for the main and
2738  *  the incident pipes (radius, width, half-length). A fillet is created
2739  *  on the junction of the pipes.
2740  *  Center of the shape is (0,0,0). The main plane of the T-shape is XOY.
2741  *  \param theR1 Internal radius of main pipe
2742  *  \param theW1 Width of main pipe
2743  *  \param theL1 Half-length of main pipe
2744  *  \param theR2 Internal radius of incident pipe (R2 < R1)
2745  *  \param theW2 Width of incident pipe (R2+W2 < R1+W1)
2746  *  \param theL2 Half-length of incident pipe
2747  *  \param theRF Radius of curvature of fillet.
2748  *  \param theHexMesh Boolean indicating if shape is prepared for hex mesh
2749  *  \return List of GEOM_Objects, containing the created shape and propagation groups.
2750  */
2751 //=============================================================================
2752 Handle(TColStd_HSequenceOfTransient)
2753 AdvancedEngine_IOperations::MakePipeTShapeFillet
2754                              (double theR1, double theW1, double theL1,
2755                               double theR2, double theW2, double theL2,
2756                               double theRL, double theWL, double theLtransL, double theLthinL,
2757                               double theRR, double theWR, double theLtransR, double theLthinR,
2758                               double theRI, double theWI, double theLtransI, double theLthinI,
2759                               double theRF, bool theHexMesh)
2760 {
2761   SetErrorCode(KO);
2762   //Add a new object
2763   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_TSHAPE);
2764   //Add a new shape function with parameters
2765   Handle(GEOM_Function) aFunction = aShape->AddFunction(AdvancedEngine_PipeTShapeDriver::GetID(), TSHAPE_FILLET);
2766   if (aFunction.IsNull()) return NULL;
2767
2768   //Check if the function is set correctly
2769   if (aFunction->GetDriverGUID() != AdvancedEngine_PipeTShapeDriver::GetID()) return NULL;
2770
2771   AdvancedEngine_IPipeTShape aData(aFunction);
2772
2773   aData.SetR1(theR1);
2774   aData.SetW1(theW1);
2775   aData.SetL1(theL1);
2776   aData.SetR2(theR2);
2777   aData.SetW2(theW2);
2778   aData.SetL2(theL2);
2779   aData.SetRF(theRF);
2780   aData.SetHexMesh(theHexMesh);
2781
2782   bool isTRL = (theRL + theWL + theLtransL + theLthinL) > Precision::Confusion();
2783   bool isTRR = (theRR + theWR + theLtransR + theLthinR) > Precision::Confusion();
2784   bool isTRI = (theRI + theWI + theLtransI + theLthinI) > Precision::Confusion();
2785
2786   //Compute the resulting value
2787   try {
2788 #if OCC_VERSION_LARGE > 0x06010000
2789     OCC_CATCH_SIGNALS;
2790 #endif
2791     if (!GetSolver()->ComputeFunction(aFunction)) {
2792       SetErrorCode("TShape driver failed");
2793       return NULL;
2794     }
2795   }
2796   catch (Standard_Failure) {
2797     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2798     SetErrorCode(aFail->GetMessageString());
2799     return NULL;
2800   }
2801
2802   // BEGIN of fillet
2803   TopoDS_Shape aShapeShape = aShape->GetValue();
2804   TopTools_IndexedMapOfShape anEdgesIndices;
2805   TopExp::MapShapes(aShapeShape, anEdgesIndices);
2806   // Common edges on external cylinders
2807   Handle(GEOM_Object) box_e;
2808   if (theHexMesh) {
2809     box_e = my3DPrimOperations->MakeBoxDXDYDZ(theR2+theW2, theR2+theW2, theR1+theW1);
2810   }
2811   else {
2812     box_e = my3DPrimOperations->MakeBoxDXDYDZ(2*(theR2+theW2), 2*(theR2+theW2), theR1+theW1);
2813   }
2814   box_e->GetLastFunction()->SetDescription("");
2815   box_e = myTransformOperations->TranslateDXDYDZ(box_e, -(theR2+theW2), -(theR2+theW2), 0);
2816   box_e->GetLastFunction()->SetDescription("");
2817
2818   Handle(TColStd_HSequenceOfInteger) edges_e =
2819     myShapesOperations->GetShapesOnBoxIDs(box_e, aShape, TopAbs_EDGE, GEOMAlgo_ST_IN);
2820   box_e->GetLastFunction()->SetDescription("");
2821
2822   if (edges_e.IsNull() || edges_e->Length() == 0) {
2823     SetErrorCode("External edges not found");
2824     return NULL;
2825   }
2826   int nbEdgesInFillet = 0;
2827   std::list<int> theEdges;
2828   for (int i=1; i<=edges_e->Length();i++) {
2829     int edgeID = edges_e->Value(i);
2830     TopoDS_Shape theEdge = anEdgesIndices.FindKey(edgeID);
2831     TopExp_Explorer Ex(theEdge,TopAbs_VERTEX);
2832     while (Ex.More()) {
2833       gp_Pnt aPt = BRep_Tool::Pnt(TopoDS::Vertex(Ex.Current()));
2834       if (Abs(aPt.Z() - (theR1+theW1)) <= Precision::Confusion()) {
2835         nbEdgesInFillet ++;
2836         theEdges.push_back(edgeID);
2837       }
2838       Ex.Next();
2839     }
2840     if (theHexMesh && nbEdgesInFillet == 1)
2841       break;
2842   }
2843
2844   Handle(GEOM_Object) aFillet;
2845   try {
2846     aFillet = myLocalOperations->MakeFilletEdges(aShape, theRF, theEdges);
2847   }
2848   catch (Standard_Failure) {
2849     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2850     SetErrorCode(aFail->GetMessageString());
2851     return NULL;
2852   }
2853   if (aFillet.IsNull()) {
2854     //SetErrorCode("Fillet can not be computed on the given shape with the given parameters");
2855     SetErrorCode(myLocalOperations->GetErrorCode());
2856     return NULL;
2857   }
2858   aFillet->GetLastFunction()->SetDescription("");
2859
2860   TopoDS_Shape aFilletShape = aFillet->GetValue();
2861   aFunction->SetValue(aFilletShape);
2862   // END of fillet
2863
2864 // VSR: debug issues 0021568 and 0021550 (15/05/2012) - BEGIN (1)
2865 // the following block, when enabled, leads to partitioning problems
2866 #if 0
2867 // VSR: debug issues 0021568 and 0021550 (15/05/2012) - END (1)
2868   // BEGIN: Limit tolerances (debug)
2869   Handle(GEOM_Object) aCorr1 = myHealingOperations->LimitTolerance(aShape, 1e-07);
2870   TopoDS_Shape aCorr1Shape = aCorr1->GetValue();
2871   aShape->GetLastFunction()->SetValue(aCorr1Shape);
2872   aCorr1->GetLastFunction()->SetDescription("");
2873   // END: Limit tolerances (debug)
2874 // VSR: debug issues 0021568 and 0021550 (15/05/2012) - BEGIN (2)
2875 #endif
2876 // VSR: debug issues 0021568 and 0021550 (15/05/2012) - END (2)
2877
2878   if (theHexMesh) {
2879     if (!MakePipeTShapePartition(aShape, theR1, theW1, theL1, theR2, theW2, theL2, 0, 0, theRF, false))
2880       return NULL;
2881     if (!MakePipeTShapeMirrorAndGlue(aShape, theR1, theW1, theL1, theR2, theW2, theL2))
2882       return NULL;
2883   }
2884
2885   // Add thickness reduction elements
2886   // at the three extremities: Left, Right and Incident
2887   try {
2888 #if OCC_VERSION_LARGE > 0x06010000
2889     OCC_CATCH_SIGNALS;
2890 #endif
2891     if (isTRL || isTRR || isTRI) {
2892       TopoDS_Shape aResShape =
2893         MakePipeTShapeThicknessReduction(aShape->GetValue(), theR1, theW1, theL1, theR2, theW2, theL2,
2894                                          theRL, theWL, theLtransL, theLthinL,
2895                                          theRR, theWR, theLtransR, theLthinR,
2896                                          theRI, theWI, theLtransI, theLthinI,
2897                                          !theHexMesh);
2898       aFunction->SetValue(aResShape);
2899     }
2900   }
2901   catch (Standard_Failure) {
2902     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2903     SetErrorCode(aFail->GetMessageString());
2904     return NULL;
2905   }
2906
2907   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
2908   aSeq->Append(aShape);
2909
2910   try {
2911     if (theHexMesh) {
2912       // Get the groups
2913       if (!MakeGroups(aShape, TSHAPE_FILLET, theR1, theW1, theL1, theR2, theW2, theL2,
2914                       0., 0., theRF, aSeq, gp_Trsf()))
2915         return NULL;
2916     }
2917
2918     // Get internal group.
2919     if (!MakeInternalGroup(aShape, theR1, theL1, theR2, theL2, theRL, theLtransL,
2920                            theRR, theLtransR, theRI, theLtransI,
2921                            aSeq, gp_Trsf())) {
2922       return NULL;
2923     }
2924   }
2925   catch (Standard_Failure) {
2926     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
2927     SetErrorCode(aFail->GetMessageString());
2928     return NULL;
2929   }
2930
2931   //Make a Python command
2932   TCollection_AsciiString anEntry, aListRes("[");
2933   // Iterate over the sequence aSeq
2934   Standard_Integer aNbGroups = aSeq->Length();
2935   Standard_Integer i = 1;
2936   for (; i <= aNbGroups; i++) {
2937     Handle(Standard_Transient) anItem = aSeq->Value(i);
2938     if (anItem.IsNull()) continue;
2939     Handle(GEOM_Object) aGroup = Handle(GEOM_Object)::DownCast(anItem);
2940     if (aGroup.IsNull()) continue;
2941     //Make a Python command
2942     TDF_Tool::Entry(aGroup->GetEntry(), anEntry);
2943     aListRes += anEntry + ", ";
2944   }
2945   aListRes.Trunc(aListRes.Length() - 2);
2946
2947   GEOM::TPythonDump pd (aFunction);
2948
2949   pd << aListRes.ToCString() << "] = geompy.MakePipeTShapeFillet("
2950      << theR1 << ", " << theW1 << ", " << theL1 << ", "
2951      << theR2 << ", " << theW2 << ", " << theL2 << ", "
2952      << theRF << ", " << theHexMesh;
2953
2954   // thickness reduction
2955   if (isTRL)
2956     pd << ", theRL=" << theRL << ", theWL=" << theWL
2957        << ", theLtransL=" << theLtransL << ", theLthinL=" << theLthinL;
2958   if (isTRR)
2959     pd << ", theRR=" << theRR << ", theWR=" << theWR
2960        << ", theLtransR=" << theLtransR << ", theLthinR=" << theLthinR;
2961   if (isTRI)
2962     pd << ", theRI=" << theRI << ", theWI=" << theWI
2963        << ", theLtransI=" << theLtransI << ", theLthinI=" << theLthinI;
2964
2965   pd << ")";
2966
2967   SetErrorCode(OK);
2968
2969   return aSeq;
2970 }
2971
2972 //=============================================================================
2973 /*!
2974  *  MakePipeTShapeFilletWithPosition
2975  *  \brief Create a T-shape object with specified caracteristics for the main and
2976  *  the incident pipes (radius, width, half-length). A fillet is created
2977  *  on the junction of the pipes.
2978  *  The extremities of the main pipe are located on junctions points P1 and P2.
2979  *  The extremity of the incident pipe is located on junction point P3.
2980  *  \param theR1 Internal radius of main pipe
2981  *  \param theW1 Width of main pipe
2982  *  \param theL1 Half-length of main pipe
2983  *  \param theR2 Internal radius of incident pipe (R2 < R1)
2984  *  \param theW2 Width of incident pipe (R2+W2 < R1+W1)
2985  *  \param theL2 Half-length of incident pipe
2986  *  \param theRF Radius of curvature of fillet
2987  *  \param theHexMesh Boolean indicating if shape is prepared for hex mesh
2988  *  \param theP1 1st junction point of main pipe
2989  *  \param theP2 2nd junction point of main pipe
2990  *  \param theP3 Junction point of incident pipe
2991  *  \return List of GEOM_Objects, containing the created shape and propagation groups.
2992  */
2993 //=============================================================================
2994 Handle(TColStd_HSequenceOfTransient)
2995 AdvancedEngine_IOperations::MakePipeTShapeFilletWithPosition
2996                              (double theR1, double theW1, double theL1,
2997                               double theR2, double theW2, double theL2,
2998                               double theRL, double theWL, double theLtransL, double theLthinL,
2999                               double theRR, double theWR, double theLtransR, double theLthinR,
3000                               double theRI, double theWI, double theLtransI, double theLthinI,
3001                               double theRF, bool theHexMesh,
3002                               Handle(GEOM_Object) theP1,
3003                               Handle(GEOM_Object) theP2,
3004                               Handle(GEOM_Object) theP3)
3005 {
3006   SetErrorCode(KO);
3007   //Add a new object
3008   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_TSHAPE);
3009   //Add a new shape function with parameters
3010   Handle(GEOM_Function) aFunction = aShape->AddFunction(AdvancedEngine_PipeTShapeDriver::GetID(), TSHAPE_FILLET);
3011   if (aFunction.IsNull()) return NULL;
3012
3013   //Check if the function is set correctly
3014   if (aFunction->GetDriverGUID() != AdvancedEngine_PipeTShapeDriver::GetID()) return NULL;
3015
3016   // Check new position
3017   if (!CheckCompatiblePosition(theL1, theL2, theP1, theP2, theP3, 0.01)) {
3018     return NULL;
3019   }
3020
3021   AdvancedEngine_IPipeTShape aData(aFunction);
3022
3023   aData.SetR1(theR1);
3024   aData.SetW1(theW1);
3025   aData.SetL1(theL1);
3026   aData.SetR2(theR2);
3027   aData.SetW2(theW2);
3028   aData.SetL2(theL2);
3029   aData.SetRF(theRF);
3030   aData.SetHexMesh(theHexMesh);
3031
3032   bool isTRL = (theRL + theWL + theLtransL + theLthinL) > Precision::Confusion();
3033   bool isTRR = (theRR + theWR + theLtransR + theLthinR) > Precision::Confusion();
3034   bool isTRI = (theRI + theWI + theLtransI + theLthinI) > Precision::Confusion();
3035
3036   //Compute the resulting value
3037   try {
3038 #if OCC_VERSION_LARGE > 0x06010000
3039     OCC_CATCH_SIGNALS;
3040 #endif
3041     if (!GetSolver()->ComputeFunction(aFunction)) {
3042       SetErrorCode("TShape driver failed");
3043       return NULL;
3044     }
3045   }
3046   catch (Standard_Failure) {
3047     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
3048     SetErrorCode(aFail->GetMessageString());
3049     return NULL;
3050   }
3051
3052   // BEGIN of fillet
3053   TopoDS_Shape aShapeShape = aShape->GetValue();
3054   TopTools_IndexedMapOfShape anEdgesIndices;
3055   TopExp::MapShapes(aShapeShape, anEdgesIndices);
3056   // Common edges on external cylinders
3057   Handle(GEOM_Object) box_e;
3058   if (theHexMesh) {
3059     box_e = my3DPrimOperations->MakeBoxDXDYDZ(theR2+theW2, theR2+theW2, theR1+theW1);
3060   }
3061   else {
3062     box_e = my3DPrimOperations->MakeBoxDXDYDZ(2*(theR2+theW2), 2*(theR2+theW2), theR1+theW1);
3063   }
3064   box_e->GetLastFunction()->SetDescription("");
3065   box_e = myTransformOperations->TranslateDXDYDZ(box_e, -(theR2+theW2), -(theR2+theW2), 0);
3066   box_e->GetLastFunction()->SetDescription("");
3067
3068   Handle(TColStd_HSequenceOfInteger) edges_e =
3069     myShapesOperations->GetShapesOnBoxIDs(box_e, aShape, TopAbs_EDGE, GEOMAlgo_ST_IN);
3070   box_e->GetLastFunction()->SetDescription("");
3071
3072   if (edges_e.IsNull() || edges_e->Length() == 0) {
3073     SetErrorCode("External edges not found");
3074     return NULL;
3075   }
3076   int nbEdgesInFillet = 0;
3077   std::list<int> theEdges;
3078   for (int i=1; i<=edges_e->Length();i++) {
3079     int edgeID = edges_e->Value(i);
3080     TopoDS_Shape theEdge = anEdgesIndices.FindKey(edgeID);
3081     TopExp_Explorer Ex(theEdge,TopAbs_VERTEX);
3082     while (Ex.More()) {
3083       gp_Pnt aPt = BRep_Tool::Pnt(TopoDS::Vertex(Ex.Current()));
3084       if (Abs(aPt.Z() - (theR1+theW1)) <= Precision::Confusion()) {
3085         nbEdgesInFillet ++;
3086         theEdges.push_back(edgeID);
3087       }
3088       Ex.Next();
3089     }
3090     if (theHexMesh && nbEdgesInFillet == 1)
3091       break;
3092   }
3093
3094   Handle(GEOM_Object) aFillet;
3095   try {
3096     aFillet = myLocalOperations->MakeFilletEdges(aShape, theRF, theEdges);
3097   }
3098   catch (Standard_Failure) {
3099     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
3100     SetErrorCode(aFail->GetMessageString());
3101     return NULL;
3102   }
3103   if (aFillet.IsNull()) {
3104     SetErrorCode("Fillet can not be computed on the given shape with the given parameters");
3105     return NULL;
3106   }
3107   aFillet->GetLastFunction()->SetDescription("");
3108
3109   TopoDS_Shape aFilletShape = aFillet->GetValue();
3110   aFunction->SetValue(aFilletShape);
3111   // END of fillet
3112
3113 // VSR: debug issues 0021568 and 0021550 (15/05/2012) - BEGIN (3)
3114 // the following block, when enabled, leads to partitioning problems
3115 #if 0
3116 // VSR: debug issues 0021568 and 0021550 (15/05/2012) - END (3)
3117   // BEGIN: Limit tolerances (debug)
3118   Handle(GEOM_Object) aCorr1 = myHealingOperations->LimitTolerance(aShape, 1e-07);
3119   TopoDS_Shape aCorr1Shape = aCorr1->GetValue();
3120   aShape->GetLastFunction()->SetValue(aCorr1Shape);
3121   aCorr1->GetLastFunction()->SetDescription("");
3122   // END: Limit tolerances (debug)
3123 // VSR: debug issues 0021568 and 0021550 (15/05/2012) - BEGIN (4)
3124 #endif
3125 // VSR: debug issues 0021568 and 0021550 (15/05/2012) - END (4)
3126
3127   if (theHexMesh) {
3128     if (!MakePipeTShapePartition(aShape, theR1, theW1, theL1, theR2, theW2, theL2, 0, 0, theRF, false))
3129       return NULL;
3130     if (!MakePipeTShapeMirrorAndGlue(aShape, theR1, theW1, theL1, theR2, theW2, theL2))
3131       return NULL;
3132   }
3133
3134   // Add thickness reduction elements
3135   // at the three extremities: Left, Right and Incident
3136   try {
3137 #if OCC_VERSION_LARGE > 0x06010000
3138     OCC_CATCH_SIGNALS;
3139 #endif
3140     if (isTRL || isTRR || isTRI) {
3141       TopoDS_Shape aResShape =
3142         MakePipeTShapeThicknessReduction(aShape->GetValue(), theR1, theW1, theL1, theR2, theW2, theL2,
3143                                          theRL, theWL, theLtransL, theLthinL,
3144                                          theRR, theWR, theLtransR, theLthinR,
3145                                          theRI, theWI, theLtransI, theLthinI,
3146                                          !theHexMesh);
3147       aFunction->SetValue(aResShape);
3148     }
3149   }
3150   catch (Standard_Failure) {
3151     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
3152     SetErrorCode(aFail->GetMessageString());
3153     return NULL;
3154   }
3155
3156   // Set Position
3157   gp_Trsf aTrsf = GetPositionTrsf(theL1, theL2, theP1, theP2, theP3);
3158   BRepBuilderAPI_Transform aTransformation (aShape->GetValue(), aTrsf, Standard_False);
3159   TopoDS_Shape aTrsf_Shape = aTransformation.Shape();
3160   aFunction->SetValue(aTrsf_Shape);
3161
3162   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
3163   aSeq->Append(aShape);
3164
3165   try {
3166     if (theHexMesh) {
3167       // Get the groups
3168       if (!MakeGroups(aShape, TSHAPE_FILLET, theR1, theW1, theL1, theR2, theW2, theL2,
3169                       0., 0., theRF, aSeq, aTrsf))
3170         return NULL;
3171     }
3172
3173     // Get internal group.
3174     if (!MakeInternalGroup(aShape, theR1, theL1, theR2, theL2, theRL, theLtransL,
3175                            theRR, theLtransR, theRI, theLtransI,
3176                            aSeq, aTrsf)) {
3177       return NULL;
3178     }
3179   }
3180   catch (Standard_Failure) {
3181     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
3182     SetErrorCode(aFail->GetMessageString());
3183     return NULL;
3184   }
3185
3186   //Make a Python command
3187   TCollection_AsciiString anEntry, aListRes("[");
3188   // Iterate over the sequence aSeq
3189   Standard_Integer aNbGroups = aSeq->Length();
3190   Standard_Integer i = 1;
3191   for (; i <= aNbGroups; i++) {
3192     Handle(Standard_Transient) anItem = aSeq->Value(i);
3193     if (anItem.IsNull()) continue;
3194     Handle(GEOM_Object) aGroup = Handle(GEOM_Object)::DownCast(anItem);
3195     if (aGroup.IsNull()) continue;
3196     //Make a Python command
3197     TDF_Tool::Entry(aGroup->GetEntry(), anEntry);
3198     aListRes += anEntry + ", ";
3199   }
3200   aListRes.Trunc(aListRes.Length() - 2);
3201
3202   GEOM::TPythonDump pd (aFunction);
3203
3204   pd << aListRes.ToCString() << "] = geompy.MakePipeTShapeFillet("
3205      << theR1 << ", " << theW1 << ", " << theL1 << ", "
3206      << theR2  << ", " << theW2 << ", " << theL2 << ", "
3207      << theRF << ", " << theHexMesh << ", "
3208      << theP1 << ", " << theP2 << ", " << theP3;
3209
3210   // thickness reduction
3211   if (isTRL)
3212     pd << ", theRL=" << theRL << ", theWL=" << theWL
3213        << ", theLtransL=" << theLtransL << ", theLthinL=" << theLthinL;
3214   if (isTRR)
3215     pd << ", theRR=" << theRR << ", theWR=" << theWR
3216        << ", theLtransR=" << theLtransR << ", theLthinR=" << theLthinR;
3217   if (isTRI)
3218     pd << ", theRI=" << theRI << ", theWI=" << theWI
3219        << ", theLtransI=" << theLtransI << ", theLthinI=" << theLthinI;
3220
3221   pd << ")";
3222
3223   SetErrorCode(OK);
3224
3225   return aSeq;
3226 }
3227
3228 //=============================================================================
3229 /*!
3230  *  This function allows to create a disk already divided into blocks. It can be
3231  *  used to create divided pipes for later meshing in hexaedra.
3232  *  \param theR Radius of the disk
3233  *  \param theRatio Relative size of the central square diagonal against the disk diameter
3234  *  \param theOrientation Plane on which the disk will be built
3235  *  \param thePattern The division pattern of the disk (hexagon or square in the center)
3236  *  \return New GEOM_Object, containing the created shape.
3237  */
3238 //=============================================================================
3239 Handle(GEOM_Object) AdvancedEngine_IOperations::MakeDividedDisk (double theR, double theRatio, 
3240                                                                  int theOrientation, int thePattern)
3241 {
3242   SetErrorCode(KO);
3243   
3244   if (theOrientation != 1 &&
3245       theOrientation != 2 &&
3246       theOrientation != 3)
3247   {
3248     SetErrorCode("theOrientation must be 1(=OXY), 2(=OYZ) or 3(=OZX)");
3249     return NULL;
3250   }
3251   //Add a new object
3252   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_DIVIDEDDISK);
3253
3254   //Add a new shape function with parameters
3255   Handle(GEOM_Function) aFunction = aShape->AddFunction(AdvancedEngine_DividedDiskDriver::GetID(), DIVIDEDDISK_R_RATIO);
3256   if (aFunction.IsNull()) return NULL;
3257
3258   //Check if the function is set correctly
3259   if (aFunction->GetDriverGUID() != AdvancedEngine_DividedDiskDriver::GetID()) return NULL;
3260
3261   AdvancedEngine_IDividedDisk aData (aFunction);
3262
3263   aData.SetR(theR);
3264   aData.SetRatio(theRatio);
3265   aData.SetOrientation(theOrientation);
3266   aData.SetType(thePattern);
3267
3268   //Compute the resulting value
3269   try {
3270 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
3271     OCC_CATCH_SIGNALS;
3272 #endif
3273     if (!GetSolver()->ComputeFunction(aFunction)) {
3274       SetErrorCode("DividedDisk driver failed");
3275       return NULL;
3276     }
3277   }
3278   catch (Standard_Failure) {
3279     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
3280     SetErrorCode(aFail->GetMessageString());
3281     return NULL;
3282   }
3283   
3284   std::string aPatternStr;
3285   
3286   switch(thePattern)
3287   {
3288     case 0:
3289       aPatternStr = "GEOM.SQUARE";
3290       break;
3291     case 1:
3292       aPatternStr = "GEOM.HEXAGON";
3293       break;
3294   }
3295   
3296   //Make a Python command
3297   GEOM::TPythonDump(aFunction) << aShape << " = geompy.MakeDividedDisk(" << theR << ", " << theOrientation << ", " << aPatternStr.c_str() << ")";
3298
3299   SetErrorCode(OK);
3300
3301   return aShape;
3302 }
3303
3304 //=============================================================================
3305 /*!
3306  *  This function allows to create a disk already divided into blocks. It can be
3307  *  used to create divided pipes for later meshing in hexaedra.
3308  *  \param theR Radius of the disk
3309  *  \param theRatio Relative size of the central square diagonal against the disk diameter
3310  *  \return New GEOM_Object, containing the created shape.
3311  */
3312 //=============================================================================
3313 Handle(GEOM_Object) AdvancedEngine_IOperations::MakeDividedDiskPntVecR (Handle(GEOM_Object) thePnt, 
3314                                                                         Handle(GEOM_Object) theVec, 
3315                                                                         double theR, 
3316                                                                         double theRatio,
3317                                                                         int    thePattern)
3318 {
3319   SetErrorCode(KO);
3320
3321   //Add a new object
3322   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_DIVIDEDDISK);
3323
3324   //Add a new shape function with parameters
3325   Handle(GEOM_Function) aFunction = aShape->AddFunction(AdvancedEngine_DividedDiskDriver::GetID(), DIVIDEDDISK_R_VECTOR_PNT);
3326   if (aFunction.IsNull()) return NULL;
3327
3328   //Check if the function is set correctly
3329   if (aFunction->GetDriverGUID() != AdvancedEngine_DividedDiskDriver::GetID()) return NULL;
3330
3331   AdvancedEngine_IDividedDisk aData (aFunction);
3332   
3333   Handle(GEOM_Function) aRefPnt = thePnt->GetLastFunction();
3334   Handle(GEOM_Function) aRefVec = theVec->GetLastFunction();
3335
3336   if (aRefPnt.IsNull() || aRefVec.IsNull()) return NULL;
3337
3338   aData.SetCenter(aRefPnt);
3339   aData.SetVector(aRefVec);
3340
3341   aData.SetR(theR);
3342   aData.SetRatio(theRatio);
3343   aData.SetType(thePattern);
3344
3345   //Compute the resulting value
3346   try {
3347 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
3348     OCC_CATCH_SIGNALS;
3349 #endif
3350     if (!GetSolver()->ComputeFunction(aFunction)) {
3351       SetErrorCode("DividedDisk driver failed");
3352       return NULL;
3353     }
3354   }
3355   catch (Standard_Failure) {
3356     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
3357     SetErrorCode(aFail->GetMessageString());
3358     return NULL;
3359   }
3360   
3361   std::string aPatternStr;
3362   
3363   switch(thePattern)
3364   {
3365     case 0:
3366       aPatternStr = "GEOM.SQUARE";
3367       break;
3368     case 1:
3369       aPatternStr = "GEOM.HEXAGON";
3370       break;
3371   }
3372   
3373
3374   //Make a Python command
3375   GEOM::TPythonDump(aFunction) << aShape << " = geompy.MakeDividedDiskPntVecR(" << thePnt << ", " << theVec << ", " << theR << ", " << aPatternStr.c_str() << ")";
3376
3377   SetErrorCode(OK);
3378
3379   return aShape;
3380 }
3381
3382 //=============================================================================
3383 /*!
3384  *  Builds a cylinder prepared for hexa meshes
3385  *  \param theR Radius of the cylinder
3386  *  \param theH Height of the cylinder
3387  *  \return New GEOM_Object, containing the created shape.
3388  */
3389 //=============================================================================
3390 Handle(GEOM_Object) AdvancedEngine_IOperations::MakeDividedCylinder (double theR, 
3391                                                                      double theH,
3392                                                                      int    thePattern)
3393 {
3394   SetErrorCode(KO);
3395   
3396   //Add a new object
3397   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_DIVIDEDCYLINDER);
3398
3399   Handle(GEOM_Object) aBaseShape = MakeDividedDisk(theR, 67.0, 1, thePattern);
3400   aBaseShape->GetLastFunction()->SetDescription("");   // Erase dump of MakeDividedDisk
3401   
3402   aShape = my3DPrimOperations->MakePrismDXDYDZ(aBaseShape,0.0,0.0,theH, -1.0);
3403         
3404   Handle(GEOM_Function) aFunction =  aShape->GetLastFunction();
3405   aFunction->SetDescription("");   // Erase dump of MakePrismDXDYDZ
3406   aShape->SetType(GEOM_DIVIDEDCYLINDER);
3407   
3408   std::string aPatternStr;
3409   
3410   switch(thePattern)
3411   {
3412     case 0:
3413       aPatternStr = "GEOM.SQUARE";
3414       break;
3415     case 1:
3416       aPatternStr = "GEOM.HEXAGON";
3417       break;
3418   }
3419   
3420   //Make a Python command
3421   GEOM::TPythonDump(aFunction) << aShape << " = geompy.MakeDividedCylinder(" << theR << ", " << theH << ", " << aPatternStr.c_str() << ")";
3422
3423   SetErrorCode(OK);
3424
3425   return aShape;
3426 }
3427 //=============================================================================
3428 /*!
3429  *  Create a smoothing surface from a set of points
3430  *  \param thelPoints list of points or compounds of points
3431  *  \param theNbMax maximum number of Bezier pieces in the resulting surface.
3432  *  \param theDegMax maximum degree of the resulting BSpline surface
3433  *  \param theDMax specifies maximum value of the GeomPlate_PlateG0Criterion criterion.
3434  *  \return New GEOM_Object, containing the created shape.
3435  */
3436 //=============================================================================
3437 Handle(GEOM_Object) AdvancedEngine_IOperations::MakeSmoothingSurface (std::list<Handle(GEOM_Object)> thelPoints, 
3438                                                                       int                            theNbMax,
3439                                                                       int                            theDegMax,
3440                                                                       double                         theDMax)
3441 {
3442   SetErrorCode(KO);
3443
3444   //Add a new object
3445   Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_SMOOTHINGSURFACE);
3446
3447   //Add a new shape function with parameters
3448   Handle(GEOM_Function) aFunction = aShape->AddFunction(AdvancedEngine_SmoothingSurfaceDriver::GetID(), SMOOTHINGSURFACE_LPOINTS);
3449   if (aFunction.IsNull()) return NULL;
3450
3451   //Check if the function is set correctly
3452   if (aFunction->GetDriverGUID() != AdvancedEngine_SmoothingSurfaceDriver::GetID()) return NULL;
3453
3454   AdvancedEngine_ISmoothingSurface aData (aFunction);
3455
3456   int aLen = thelPoints.size();
3457   aData.SetLength(aLen);
3458   int ind = 1;
3459   std::list<Handle(GEOM_Object)>::iterator it = thelPoints.begin();
3460   for (; it != thelPoints.end(); it++, ind++) {
3461     Handle(GEOM_Function) aRefObj = (*it)->GetLastFunction();
3462     if (aRefObj.IsNull()) {
3463       SetErrorCode("NULL point or compound for bSplineFaceShape");
3464       return NULL;
3465     }
3466     aData.SetPntOrComp(ind, aRefObj);
3467   }
3468
3469   aData.SetNbMax(theNbMax);
3470   aData.SetDegMax(theDegMax);
3471   aData.SetDMax(theDMax);
3472
3473   //Compute the resulting value
3474   try {
3475 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
3476     OCC_CATCH_SIGNALS;
3477 #endif
3478     if (!GetSolver()->ComputeFunction(aFunction)) {
3479       SetErrorCode("SmoothingSurface driver failed");
3480       return NULL;
3481     }
3482   }
3483   catch (Standard_Failure) {
3484     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
3485     SetErrorCode(aFail->GetMessageString());
3486     return NULL;
3487   }
3488
3489   //Make a Python command
3490   GEOM::TPythonDump pd (aFunction);
3491   pd << aShape << " = geompy.MakeSmoothingSurface([";
3492   it = thelPoints.begin();
3493   pd << (*it++);
3494   while (it != thelPoints.end()) {
3495     pd << ", " << (*it++);
3496   }
3497   pd << "], "
3498      << theNbMax << ", "
3499      << theDegMax << ", "
3500      << theDMax <<")";
3501
3502   SetErrorCode(OK);
3503
3504   return aShape;
3505 }