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