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