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