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