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