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