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