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