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