Salome HOME
0022616: [CEA 1038] Improve the quality of stl and vtk exports
[modules/geom.git] / src / AdvancedEngine / AdvancedEngine_DividedDiskDriver.cxx
1 // Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 #include <Standard_Stream.hxx>
24
25 #include "AdvancedEngine_DividedDiskDriver.hxx"
26 #include "AdvancedEngine_IDividedDisk.hxx"
27 #include "AdvancedEngine_Types.hxx"
28
29 #include "GEOM_Function.hxx"
30
31 // OCCT includes
32 #include <gp_Pnt.hxx>
33 #include <gp_Dir.hxx>
34 #include <gp_Lin.hxx>
35 #include <gp_Circ.hxx>
36 #include <gp_Ax1.hxx>
37 #include <gp_Ax2.hxx>
38
39 #include <BRep_Builder.hxx>
40 #include <BRepBuilderAPI_MakeFace.hxx>
41 #include <BRepBuilderAPI_MakeEdge.hxx>
42 #include <BRepBuilderAPI_MakeVertex.hxx>
43 #include <BRepBuilderAPI_MakeWire.hxx>
44 #include <BRepBuilderAPI_Transform.hxx>
45
46 #include <Geom_Plane.hxx>
47
48 #include <TopoDS.hxx>
49 #include <TopoDS_Shape.hxx>
50 #include <TopoDS_Edge.hxx>
51
52 #include <TFunction_Logbook.hxx>
53 #include <StdFail_NotDone.hxx>
54
55 #include <TopExp.hxx>
56
57 #include <utilities.h>
58
59 enum
60 {
61   SQUARE,
62   HEXAGON
63 };
64
65 //=======================================================================
66 //function : GetID
67 //purpose  :
68 //=======================================================================
69 const Standard_GUID& AdvancedEngine_DividedDiskDriver::GetID()
70 {
71   static Standard_GUID aGUID("0b01da9a-c5da-11e1-8d80-78e7d1879630");
72   return aGUID;
73 }
74
75 //=======================================================================
76 //function : AdvancedEngine_DividedDiskDriver
77 //purpose  :
78 //=======================================================================
79 AdvancedEngine_DividedDiskDriver::AdvancedEngine_DividedDiskDriver()
80 {
81 }
82
83 //=======================================================================
84 //function : Execute
85 //purpose  :
86 //=======================================================================
87 Standard_Integer AdvancedEngine_DividedDiskDriver::Execute(TFunction_Logbook& log) const
88 {
89   if (Label().IsNull()) return 0;
90   Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
91
92   AdvancedEngine_IDividedDisk aData (aFunction);
93   Standard_Integer aType = aFunction->GetType();
94
95   TopoDS_Shape aShape;
96
97   // Getting data
98   double R       = aData.GetR();
99   double Ratio   = aData.GetRatio();
100   int    Pattern = aData.GetType();
101   
102   // Build reference disk (in the global coordinate system)
103   TopoDS_Shape aDisk;
104   
105   if (Pattern == SQUARE)
106     aDisk = MakeDiskSquare( R, Ratio );
107   else if (Pattern == HEXAGON)
108     aDisk = MakeDiskHexagon( R, Ratio );
109   
110   if (aType == DIVIDEDDISK_R_RATIO) 
111   { 
112     int theOrientation = aData.GetOrientation();        
113     aShape = TransformShape(aDisk, theOrientation);   
114   }
115   else if (aType == DIVIDEDDISK_R_VECTOR_PNT)
116   {
117     Handle(GEOM_Function) aRefPoint  = aData.GetCenter();
118     Handle(GEOM_Function) aRefVector = aData.GetVector();
119     TopoDS_Shape aShapePnt = aRefPoint->GetValue();
120     TopoDS_Shape aShapeVec = aRefVector->GetValue();
121     
122     if (aShapePnt.ShapeType() == TopAbs_VERTEX &&
123         aShapeVec.ShapeType() == TopAbs_EDGE) 
124     {
125       gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aShapePnt));
126       TopoDS_Edge anE = TopoDS::Edge(aShapeVec);
127       TopoDS_Vertex V1, V2;
128       TopExp::Vertices(anE, V1, V2, Standard_True);
129       if (!V1.IsNull() && !V2.IsNull()) 
130       {
131         gp_Vec aVec (BRep_Tool::Pnt(V1), BRep_Tool::Pnt(V2));
132         gp_Dir aDir(aVec);
133         aShape = TransformShape(aDisk, aPnt, aDir); 
134       }
135     }   
136   }
137
138   if (aShape.IsNull()) return 0;
139
140   aFunction->SetValue(aShape);
141
142   log.SetTouched(Label());
143
144   return 1;
145 }
146
147
148 //=======================================================================
149 //function : MakeDiskHexagon
150 //purpose  :
151 //=======================================================================
152 TopoDS_Shell AdvancedEngine_DividedDiskDriver::MakeDiskHexagon(double R, double Ratio) const
153 {
154   // Geometry
155   gp_Dir ZDir(0,0,1);
156   gp_Dir XDir(1,0,0);
157   gp_Pnt Orig(0,0,0);
158   
159   // Circle
160   gp_Ax1 Ax1(Orig,ZDir);
161   gp_Ax2 Ax(Orig,ZDir,XDir);
162   gp_Circ aCircle(Ax, R);
163   
164   // Points
165 //   gp_Pnt P4(0.01*Ratio*R,0,0); 
166 //   gp_Pnt P3(R,0,0);
167 //   gp_Pnt P2 = P3.Rotated(Ax1,-M_PI/6.0);
168 //   gp_Pnt P1(P4.X(), 
169 //             P4.X()/sqrt(3.0),0);
170   gp_Pnt P1(0.01*Ratio*R*sqrt(3.0)/2,0,0);
171   gp_Pnt P2(R,0,0);
172   gp_Pnt P3 = P2.Rotated(Ax1,M_PI/6.0);
173   gp_Pnt P4(P1.X(), 
174             P1.X()/sqrt(3.0),0);
175
176   
177   //surfaces
178   gp_Ax2 anAx (gp::XOY());
179   Handle(Geom_Plane) aPlane = new Geom_Plane (anAx);
180   
181   // Topology
182   
183   // Vertices
184   TopoDS_Vertex O  = BRepBuilderAPI_MakeVertex(Orig);
185   TopoDS_Vertex V1_init = BRepBuilderAPI_MakeVertex(P1);
186   TopoDS_Vertex V2_init = BRepBuilderAPI_MakeVertex(P2);
187   TopoDS_Vertex V3 = BRepBuilderAPI_MakeVertex(P3);
188   TopoDS_Vertex V4 = BRepBuilderAPI_MakeVertex(P4);
189   
190   TopoDS_Vertex V1 = V1_init;
191   TopoDS_Vertex V2 = V2_init;
192   
193   //Rotation
194   gp_Trsf myTrsf;
195   myTrsf.SetRotation(Ax1, M_PI/3.0);
196   
197   BRepBuilderAPI_Transform xform(myTrsf);
198   xform.Perform(V1,Standard_True);
199   TopoDS_Vertex V1_60 = TopoDS::Vertex(xform.Shape()); 
200   xform.Perform(V2,Standard_True);
201   TopoDS_Vertex V2_60 = TopoDS::Vertex(xform.Shape());
202   
203   // Declaration of shapes (used in the loop) 
204   TopoDS_Edge E1, E2, E3, E4, E5, E6, E7, E8, E9;
205   TopoDS_Wire W1, W2, W3;
206   TopoDS_Face F1, F2, F3;   
207   TopoDS_Shell S;
208   
209   BRep_Builder aBuilder;
210   aBuilder.MakeShell(S);
211   
212   // Initialisation of edges
213   TopoDS_Edge E1_init = BRepBuilderAPI_MakeEdge(V1,TopoDS::Vertex(V2.Reversed()));
214   E1 = E1_init;
215   TopoDS_Edge E8_init = BRepBuilderAPI_MakeEdge(O,TopoDS::Vertex(V1.Reversed()));
216   E8 = E8_init;
217   
218   for (int i=1;i<=6;i++)
219   { 
220     // Edges
221     
222     // for Face1
223     E2 = BRepBuilderAPI_MakeEdge(aCircle, V2, TopoDS::Vertex(V3.Reversed())); 
224     E3 = BRepBuilderAPI_MakeEdge(V3,TopoDS::Vertex(V4.Reversed()));
225     E4 = BRepBuilderAPI_MakeEdge(V4,TopoDS::Vertex(V1.Reversed()));
226       
227     // for Face2
228     if (i==6)
229     {
230       E5 = BRepBuilderAPI_MakeEdge(aCircle, V3, TopoDS::Vertex(V2_init.Reversed()));
231       E7 = BRepBuilderAPI_MakeEdge(V1_init,TopoDS::Vertex(V4.Reversed()));
232     }
233     else
234     {
235       E5 = BRepBuilderAPI_MakeEdge(aCircle, V3, TopoDS::Vertex(V2_60.Reversed()));
236       E7 = BRepBuilderAPI_MakeEdge(V1_60,TopoDS::Vertex(V4.Reversed()));
237     }    
238     E6 = BRepBuilderAPI_MakeEdge(V2_60,TopoDS::Vertex(V1_60.Reversed()));
239     
240     // for Face3
241     E9 = BRepBuilderAPI_MakeEdge(V1_60,TopoDS::Vertex(O.Reversed()));
242     
243     
244     // Wires
245     
246     //Wire1
247     aBuilder.MakeWire(W1);
248     if (i==1)
249       aBuilder.Add(W1,E1);
250     else
251       aBuilder.Add(W1,TopoDS::Edge(E1.Reversed()));
252     aBuilder.Add(W1,E2);
253     aBuilder.Add(W1,E3);
254     aBuilder.Add(W1,E4);
255     
256     // Wire 2
257     aBuilder.MakeWire(W2);
258     aBuilder.Add(W2,TopoDS::Edge(E3.Reversed()));
259     aBuilder.Add(W2,E5);
260     if (i==6)
261       aBuilder.Add(W2,TopoDS::Edge(E1_init.Reversed()));
262     else
263       aBuilder.Add(W2,E6);
264     aBuilder.Add(W2,E7);
265     
266     // Wire3
267     aBuilder.MakeWire(W3);
268     if (i==1)
269       aBuilder.Add(W3,E8);
270     else 
271       aBuilder.Add(W3,TopoDS::Edge(E8.Reversed()));    
272     aBuilder.Add(W3,TopoDS::Edge(E4.Reversed()));
273     aBuilder.Add(W3,TopoDS::Edge(E7.Reversed()));
274     if (i==6)
275       aBuilder.Add(W3,TopoDS::Edge(E8_init.Reversed()));
276     else
277       aBuilder.Add(W3,E9);
278       
279     // Faces creation
280     F1 = BRepBuilderAPI_MakeFace(aPlane,W1);
281     F2 = BRepBuilderAPI_MakeFace(aPlane,W2);
282     F3 = BRepBuilderAPI_MakeFace(aPlane,W3);
283     
284     //Shell
285     aBuilder.Add(S, F1);
286     aBuilder.Add(S, F2);
287     aBuilder.Add(S, F3);
288           
289     // rotation
290     V1=V1_60;
291     V2=V2_60;
292     
293     xform.Perform(V1_60,Standard_True);
294     V1_60 = TopoDS::Vertex(xform.Shape());
295     xform.Perform(V2_60,Standard_True);
296     V2_60 = TopoDS::Vertex(xform.Shape());
297     xform.Perform(V3,Standard_True);
298     V3    = TopoDS::Vertex(xform.Shape());
299     xform.Perform(V4,Standard_True);
300     V4    = TopoDS::Vertex(xform.Shape());
301     
302     // "Increment" of edges
303     E1=E6;
304     E8=E9;         
305   }
306   
307   return S;
308 }
309
310 //=======================================================================
311 //function : MakeDiskSquare
312 //purpose  :
313 //=======================================================================
314 TopoDS_Shape AdvancedEngine_DividedDiskDriver::MakeDiskSquare(double R, double Ratio) const
315 {
316   // Geometry
317   gp_Dir ZDir(0,0,1);
318   gp_Dir XDir(1,0,0);
319   gp_Pnt Orig(0,0,0);
320   
321   // Circle
322   gp_Ax1 Ax1(Orig,ZDir);
323   gp_Ax2 Ax(Orig,ZDir,XDir);
324   gp_Circ aCircle(Ax, R);
325   
326   // Points
327   gp_Pnt P1(0.01*Ratio*R,0,0);
328   gp_Pnt P2(R,0,0);
329   
330   //surfaces
331   gp_Ax2 anAx (gp::XOY());
332   Handle(Geom_Plane) aPlane = new Geom_Plane (anAx);
333   
334   // Topology
335   
336   // Vertices
337   TopoDS_Vertex V1_init = BRepBuilderAPI_MakeVertex(P1);
338   TopoDS_Vertex V2_init = BRepBuilderAPI_MakeVertex(P2);
339   
340   TopoDS_Vertex V1 = V1_init;
341   TopoDS_Vertex V2 = V2_init;
342   
343   //Rotation
344   gp_Trsf myTrsf;
345   myTrsf.SetRotation(Ax1, M_PI/2);
346   
347   BRepBuilderAPI_Transform xform(myTrsf);
348   xform.Perform(V1,Standard_True);
349   TopoDS_Vertex V1_rotated = TopoDS::Vertex(xform.Shape()); 
350   xform.Perform(V2,Standard_True);
351   TopoDS_Vertex V2_rotated = TopoDS::Vertex(xform.Shape());
352   
353   // Declaration of shapes (used in the loop) 
354   TopoDS_Edge E1, E2, E3, E4;
355   TopoDS_Wire W1, W2;
356   TopoDS_Face F1, F2;   
357   TopoDS_Shell S;
358   
359   BRep_Builder aBuilder;
360   aBuilder.MakeWire(W2);  // Central Wire
361   aBuilder.MakeShell(S);  // Shell
362   
363   // Initialisation of edges
364   TopoDS_Edge E1_init = BRepBuilderAPI_MakeEdge(V1,TopoDS::Vertex(V2.Reversed()));
365   E1 = E1_init;
366   
367   for (int i=1;i<=4;i++)
368   { 
369     // Edges
370     // for Face1
371    
372     E3 = BRepBuilderAPI_MakeEdge(V2_rotated,TopoDS::Vertex(V1_rotated.Reversed()));
373     if (i == 4)
374     {
375       E2 = BRepBuilderAPI_MakeEdge(aCircle, V2, TopoDS::Vertex(V2_init.Reversed())); 
376       E4 = BRepBuilderAPI_MakeEdge(V1_init,TopoDS::Vertex(V1.Reversed()));
377     }
378     else
379     {
380       E2 = BRepBuilderAPI_MakeEdge(aCircle, V2, TopoDS::Vertex(V2_rotated.Reversed())); 
381       E4 = BRepBuilderAPI_MakeEdge(V1_rotated,TopoDS::Vertex(V1.Reversed()));
382     }
383     
384     // Wires
385     //Wire1
386     aBuilder.MakeWire(W1);
387     if (i==1)
388       aBuilder.Add(W1,E1);
389     else
390       aBuilder.Add(W1,TopoDS::Edge(E1.Reversed()));
391     aBuilder.Add(W1,E2);
392     if (i==4)
393       aBuilder.Add(W1,TopoDS::Edge(E1_init.Reversed()));
394     else
395       aBuilder.Add(W1,E3);
396     aBuilder.Add(W1,E4);
397     
398     // Wire central
399     aBuilder.Add(W2,TopoDS::Edge(E4.Reversed()));
400     
401     // Faces creation
402     F1 = BRepBuilderAPI_MakeFace(aPlane,W1);
403     
404     //Shell
405     aBuilder.Add(S, F1);
406     
407     // rotation
408     V1=V1_rotated;
409     V2=V2_rotated;
410     
411     xform.Perform(V1_rotated,Standard_True);
412     V1_rotated = TopoDS::Vertex(xform.Shape());
413     xform.Perform(V2_rotated,Standard_True);
414     V2_rotated = TopoDS::Vertex(xform.Shape());
415     
416     // "Increment" of edges
417     E1=E3;        
418   }
419   // Central square Face 
420   F2 = BRepBuilderAPI_MakeFace(aPlane,W2);
421   aBuilder.Add(S, F2);
422   
423   return S;
424 }
425
426
427 //=======================================================================
428 //function :  TrasformShape(TopoDS_Shape aShape,int theOrientation)
429 //purpose  :  Perform shape transformation accordingly with specified
430 //            orientation
431 //=======================================================================
432 TopoDS_Shape AdvancedEngine_DividedDiskDriver::TransformShape(TopoDS_Shape theShape, int theOrientation) const
433 {
434   gp_Dir N, Vx;
435   gp_Pnt theOrigin = gp::Origin();
436   
437   switch(theOrientation)
438   {
439     case 1:
440     {
441       N = gp::DZ();
442       Vx = gp::DX();
443       break;
444     }
445     case 2:
446     {
447       N = gp::DX();
448       Vx = gp::DY();
449       break;
450     }
451     case 3:
452     {
453       N = gp::DY();
454       Vx = gp::DZ();
455       break;
456     }
457   }
458     
459   gp_Ax3 aWPlane = gp_Ax3(theOrigin, N, Vx);
460   
461   return WPlaneTransform(theShape, aWPlane);
462 }
463
464 //=======================================================================
465 //function :  TrasformShape(TopoDS_Shape aShape, gp_Dir V, gp_Pnt P)
466 //purpose  :  Perform shape transformation accordingly with specified
467 //            pnt and direction
468 //=======================================================================
469 TopoDS_Shape AdvancedEngine_DividedDiskDriver::TransformShape(TopoDS_Shape theShape, gp_Pnt P, gp_Dir V) const
470 {
471   gp_Ax3 aWPlane( P, V );
472   return WPlaneTransform(theShape, aWPlane);
473 }
474
475 //=======================================================================
476 //function :  WPlaneTransform
477 //purpose  :  Perform shape transformation accordingly with the given 
478 //            Working Plane  
479 //=======================================================================
480 TopoDS_Shape AdvancedEngine_DividedDiskDriver::WPlaneTransform(TopoDS_Shape theShape, gp_Ax3 theWPlane) const
481 {
482   gp_Trsf aTrans;
483   aTrans.SetTransformation(theWPlane);
484   aTrans.Invert();
485   BRepBuilderAPI_Transform aTransformation (theShape, aTrans, Standard_False);
486   return aTransformation.Shape();
487 }
488
489 //================================================================================
490 /*!
491  * \brief Returns a name of creation operation and names and values of creation parameters
492  */
493 //================================================================================
494
495 bool AdvancedEngine_DividedDiskDriver::
496 GetCreationInformation(std::string&             theOperationName,
497                        std::vector<GEOM_Param>& theParams)
498 {
499   if (Label().IsNull()) return 0;
500   Handle(GEOM_Function) function = GEOM_Function::GetFunction(Label());
501
502   AdvancedEngine_IDividedDisk aCI( function );
503   Standard_Integer aType = function->GetType();
504
505   theOperationName = "DIVIDEDDISK";
506
507   switch ( aType ) {
508   case DIVIDEDDISK_R_RATIO:
509     AddParam( theParams, "Radius", aCI.GetR() );
510     AddParam( theParams, "Ratio", aCI.GetRatio() );
511     AddParam( theParams, "Orientation", aCI.GetOrientation() );
512     AddParam( theParams, "Division pattern", aCI.GetType() );
513     break;
514   case DIVIDEDDISK_R_VECTOR_PNT:
515     AddParam( theParams, "Center Point", aCI.GetCenter() );
516     AddParam( theParams, "Vector", aCI.GetVector() );
517     AddParam( theParams, "Radius", aCI.GetR() );
518     AddParam( theParams, "Division pattern", aCI.GetType() );
519     break;
520   default:
521     return false;
522   }
523   
524   return true;
525 }
526
527 IMPLEMENT_STANDARD_HANDLE (AdvancedEngine_DividedDiskDriver,GEOM_BaseDriver);
528 IMPLEMENT_STANDARD_RTTIEXT (AdvancedEngine_DividedDiskDriver,GEOM_BaseDriver);