Salome HOME
Fix documentation problems (reported as doxygen warnings)
[modules/geom.git] / src / OBJECT / GEOM_WireframeFace.cxx
1 //  Copyright (C) 2007-2008  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.
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 #include "GEOM_WireframeFace.h" 
23  
24 #include <vtkObjectFactory.h> 
25  
26 #include <vtkPoints.h> 
27 #include <vtkCellArray.h> 
28
29 #include <vtkPolyDataMapper.h>  
30 #include <vtkPolyData.h>  
31  
32 #include <Precision.hxx>
33 #include <BRepTools.hxx>
34 #include <TopExp_Explorer.hxx>
35 #include <Geom2dHatch_Hatcher.hxx>
36 #include <Geom2dHatch_Intersector.hxx>
37 #include <TColStd_Array1OfReal.hxx>
38 #include <TColStd_Array1OfInteger.hxx>
39  
40 #include <TopoDS.hxx> 
41 #include <TopoDS_Edge.hxx> 
42 #include <BRep_Tool.hxx>
43 #include <Geom2d_TrimmedCurve.hxx>
44 #include <Geom2d_Line.hxx>
45 #include <gp_Dir2d.hxx>
46 #include <gp_Pnt2d.hxx>
47  
48 #include <Geom2dHatch_Hatcher.hxx>
49 #include <HatchGen_Domain.hxx>
50
51 #include <Adaptor3d_HCurve.hxx>
52
53 vtkStandardNewMacro(GEOM_WireframeFace);
54  
55 GEOM_WireframeFace::GEOM_WireframeFace(): 
56   Discret(15)
57
58   NbIso[0] = 1;
59   NbIso[1] = 1;
60
61  
62 GEOM_WireframeFace::~GEOM_WireframeFace() 
63
64
65  
66 void
67 GEOM_WireframeFace:: 
68 Execute()
69 {
70   vtkPolyData* aPolyData = GetOutput();
71   aPolyData->Allocate();
72   vtkPoints* aPts = vtkPoints::New();
73   aPolyData->SetPoints(aPts);
74   aPts->Delete();
75
76   TFaceSet::Iterator anIter(myFaceSet);
77   for(; anIter.More(); anIter.Next()){
78     const TopoDS_Face& aFace = anIter.Value();
79     OCC2VTK(aFace,aPolyData,aPts,NbIso,Discret);
80   }
81 }
82
83 void GEOM_WireframeFace::SetNbIso(const int theNb[2])
84 {
85   if ( theNb[0] == NbIso[0] && theNb[1] == NbIso[1])
86     return;
87
88   NbIso[0] = theNb[0];
89   NbIso[1] = theNb[1];
90
91   Modified();
92 }
93
94 void GEOM_WireframeFace::GetNbIso(int &theNbU,int &theNbV)
95 {
96   theNbU = NbIso[0];
97   theNbV = NbIso[1];
98 }
99
100 void  
101 GEOM_WireframeFace:: 
102 OCC2VTK(const TopoDS_Face& theFace,
103         vtkPolyData* thePolyData,
104                     vtkPoints* thePts,  
105         const int theNbIso[2], 
106         const int theDiscret) 
107
108   TopoDS_Face aFace = theFace; 
109   aFace.Orientation(TopAbs_FORWARD);
110   CreateIso(aFace,theNbIso,theDiscret,thePolyData,thePts);
111 }
112
113 void 
114 GEOM_WireframeFace:: 
115 CreateIso(const TopoDS_Face& theFace,
116           const int theNbIso[2], 
117           const int theDiscret, 
118           vtkPolyData* thePolyData,
119           vtkPoints* thePts)
120 {
121   // Constants for iso building
122   static Standard_Real INTERSECTOR_CONFUSION = 1.e-10 ; // -8 ;
123   static Standard_Real INTERSECTOR_TANGENCY  = 1.e-10 ; // -8 ;
124
125   static Standard_Real HATHCER_CONFUSION_2D = 1.e-8 ;
126   static Standard_Real HATHCER_CONFUSION_3D = 1.e-8 ;
127
128   Geom2dHatch_Hatcher 
129     aHatcher(Geom2dHatch_Intersector(INTERSECTOR_CONFUSION,
130                                      INTERSECTOR_TANGENCY),
131                          HATHCER_CONFUSION_2D,
132                          HATHCER_CONFUSION_3D,
133                                      Standard_True,
134                                      Standard_False);
135   
136   Standard_Real anUMin, anUMax, aVMin, aVMax;
137   TColStd_Array1OfReal anUPrm(1, theNbIso[0]), aVPrm(1, theNbIso[1]);
138   TColStd_Array1OfInteger anUInd(1, theNbIso[0]), aVInd(1, theNbIso[1]);
139
140   anUInd.Init(0);
141   aVInd.Init(0);
142
143   //-----------------------------------------------------------------------
144   // If the Min Max bounds are infinite, there are bounded to Infinite
145   // value.
146   //-----------------------------------------------------------------------
147   BRepTools::UVBounds(theFace, anUMin, anUMax, aVMin, aVMax) ;
148   Standard_Boolean InfiniteUMin = Precision::IsNegativeInfinite (anUMin) ;
149   Standard_Boolean InfiniteUMax = Precision::IsPositiveInfinite (anUMax) ;
150   Standard_Boolean InfiniteVMin = Precision::IsNegativeInfinite (aVMin) ;
151   Standard_Boolean InfiniteVMax = Precision::IsPositiveInfinite (aVMax) ;
152
153   static float VTKINFINITE = 1.0E38;
154   if(InfiniteUMin && InfiniteUMax){
155     anUMin = - VTKINFINITE ;
156     anUMax =   VTKINFINITE ;
157   }else if(InfiniteUMin){
158     anUMin = anUMax - VTKINFINITE ;
159   }else if(InfiniteUMax){
160     anUMax = anUMin + VTKINFINITE ;
161   }
162
163   if(InfiniteVMin && InfiniteVMax){
164     aVMin = - VTKINFINITE ;
165     aVMax =   VTKINFINITE ;
166   }else if(InfiniteVMin){
167     aVMin = aVMax - VTKINFINITE ;
168   }else if(InfiniteVMax){
169     aVMax = aVMin + VTKINFINITE ;
170   }
171
172   //-----------------------------------------------------------------------
173   // Retreiving the edges and loading them into the hatcher.
174   //-----------------------------------------------------------------------
175   TopExp_Explorer ExpEdges(theFace, TopAbs_EDGE);
176   for(; ExpEdges.More(); ExpEdges.Next()){
177     const TopoDS_Edge& anEdge = TopoDS::Edge(ExpEdges.Current());
178     Standard_Real U1, U2 ;
179     const Handle(Geom2d_Curve) PCurve = 
180       BRep_Tool::CurveOnSurface(anEdge, theFace, U1, U2) ;
181
182     if(PCurve.IsNull() || U1 == U2)
183       return;
184
185     //-- Test if a TrimmedCurve is necessary
186     if(Abs(PCurve->FirstParameter()-U1) <= Precision::PConfusion() &&
187              Abs(PCurve->LastParameter()-U2) <= Precision::PConfusion())
188     { 
189       aHatcher.AddElement(PCurve, anEdge.Orientation()) ;      
190     }else{ 
191       if(!PCurve->IsPeriodic()){
192               Handle(Geom2d_TrimmedCurve) TrimPCurve =
193           Handle(Geom2d_TrimmedCurve)::DownCast(PCurve);
194               if(!TrimPCurve.IsNull()){
195           Handle_Geom2d_Curve aBasisCurve = TrimPCurve->BasisCurve();
196                 if(aBasisCurve->FirstParameter()-U1 > Precision::PConfusion() ||
197                    U2-aBasisCurve->LastParameter() > Precision::PConfusion()) 
198           {
199                   aHatcher.AddElement(PCurve, anEdge.Orientation()) ;      
200                   return;
201                 }
202               }else{
203                 if(PCurve->FirstParameter()-U1 > Precision::PConfusion()){
204                   U1=PCurve->FirstParameter();
205                 }
206                 if(U2-PCurve->LastParameter()  > Precision::PConfusion()){
207                   U2=PCurve->LastParameter();
208                 }
209               }
210       }
211       Handle(Geom2d_TrimmedCurve) TrimPCurve = 
212         new Geom2d_TrimmedCurve(PCurve, U1, U2);
213       aHatcher.AddElement(TrimPCurve, anEdge.Orientation());
214     }
215   }
216
217
218   //-----------------------------------------------------------------------
219   // Loading and trimming the hatchings.
220   //-----------------------------------------------------------------------
221   Standard_Integer IIso;
222   Standard_Real DeltaU = Abs(anUMax - anUMin) ;
223   Standard_Real DeltaV = Abs(aVMax - aVMin) ;
224   Standard_Real confusion = Min(DeltaU, DeltaV) * HATHCER_CONFUSION_3D ;
225   aHatcher.Confusion3d (confusion) ;
226
227   Standard_Real StepU = DeltaU / (Standard_Real)theNbIso[0];
228   if(StepU > confusion){
229     Standard_Real UPrm = anUMin + StepU / 2.;
230     gp_Dir2d Dir(0., 1.) ;
231     for(IIso = 1 ; IIso <= theNbIso[0] ; IIso++) {
232       anUPrm(IIso) = UPrm ;
233       gp_Pnt2d Ori (UPrm, 0.) ;
234       Geom2dAdaptor_Curve HCur (new Geom2d_Line (Ori, Dir)) ;
235       anUInd(IIso) = aHatcher.AddHatching (HCur) ;
236       UPrm += StepU ;
237     }
238   }
239
240   Standard_Real StepV = DeltaV / (Standard_Real) theNbIso[1] ;
241   if(StepV > confusion){
242     Standard_Real VPrm = aVMin + StepV / 2.;
243     gp_Dir2d Dir(1., 0.);
244     for(IIso = 1 ; IIso <= theNbIso[1] ; IIso++){
245       aVPrm(IIso) = VPrm;
246       gp_Pnt2d Ori (0., VPrm);
247       Geom2dAdaptor_Curve HCur(new Geom2d_Line (Ori, Dir));
248       aVInd(IIso) = aHatcher.AddHatching (HCur) ;
249       VPrm += StepV ;
250     }
251   }
252
253   //-----------------------------------------------------------------------
254   // Computation.
255   //-----------------------------------------------------------------------
256   aHatcher.Trim() ;
257
258   Standard_Integer aNbDom = 0 ; // for debug purpose
259   Standard_Integer Index ;
260
261   for(IIso = 1 ; IIso <= theNbIso[0] ; IIso++){
262     Index = anUInd(IIso) ;
263     if(Index != 0){
264       if(aHatcher.TrimDone(Index) && !aHatcher.TrimFailed(Index)){
265               aHatcher.ComputeDomains(Index);
266               if(aHatcher.IsDone (Index)) 
267           aNbDom = aHatcher.NbDomains (Index);
268       }
269     }
270   }
271
272   for(IIso = 1 ; IIso <= theNbIso[1] ; IIso++){
273     Index = aVInd(IIso);
274     if(Index != 0){
275       if(aHatcher.TrimDone (Index) && !aHatcher.TrimFailed(Index)){
276               aHatcher.ComputeDomains (Index);
277               if(aHatcher.IsDone (Index)) 
278           aNbDom = aHatcher.NbDomains (Index);
279       }
280     }
281   }
282
283   //-----------------------------------------------------------------------
284   // Push iso lines in vtk kernel
285   //-----------------------------------------------------------------------
286   for(Standard_Integer UIso = anUPrm.Lower() ; UIso <= anUPrm.Upper(); UIso++){
287     Standard_Integer UInd = anUInd.Value(UIso);
288     if(UInd != 0){
289       Standard_Real UPrm = anUPrm.Value(UIso);
290       if(aHatcher.IsDone(UInd)){
291               Standard_Integer NbDom = aHatcher.NbDomains(UInd);
292               for(Standard_Integer IDom = 1 ; IDom <= NbDom ; IDom++){
293                 const HatchGen_Domain& Dom = aHatcher.Domain(UInd, IDom) ;
294                 Standard_Real V1 = Dom.HasFirstPoint()? Dom.FirstPoint().Parameter(): aVMin - VTKINFINITE;
295                 Standard_Real V2 = Dom.HasSecondPoint()? Dom.SecondPoint().Parameter(): aVMax + VTKINFINITE;
296                 CreateIso_(theFace, GeomAbs_IsoU, UPrm, V1, V2, theDiscret, thePolyData, thePts);
297         }
298             }
299     }
300   }
301
302   for(Standard_Integer VIso = aVPrm.Lower() ; VIso <= aVPrm.Upper(); VIso++){
303     Standard_Integer VInd = aVInd.Value(VIso);
304     if(VInd != 0){
305       Standard_Real VPrm = aVPrm.Value(VIso);
306       if(aHatcher.IsDone (VInd)){
307               Standard_Integer NbDom = aHatcher.NbDomains(VInd);
308               for (Standard_Integer IDom = 1 ; IDom <= NbDom ; IDom++){
309                 const HatchGen_Domain& Dom = aHatcher.Domain(VInd, IDom);
310                 Standard_Real U1 = Dom.HasFirstPoint()? Dom.FirstPoint().Parameter(): aVMin - VTKINFINITE;
311                 Standard_Real U2 = Dom.HasSecondPoint()? Dom.SecondPoint().Parameter(): aVMax + VTKINFINITE;
312             CreateIso_(theFace, GeomAbs_IsoV, VPrm, U1, U2, theDiscret, thePolyData, thePts);
313               }
314       }
315     }
316   }
317 }
318
319  
320
321 void 
322 GEOM_WireframeFace:: 
323 CreateIso_(const TopoDS_Face& theFace,
324            GeomAbs_IsoType theIsoType, 
325            Standard_Real Par, 
326            Standard_Real T1,
327            Standard_Real T2,
328            const int theDiscret, 
329            vtkPolyData* thePolyData,
330            vtkPoints* thePts)
331 {
332   Standard_Real U1, U2, V1, V2, stepU=0., stepV=0.;
333   Standard_Integer j;
334   gp_Pnt P;
335
336   TopLoc_Location aLoc;
337   const Handle(Geom_Surface)& S = BRep_Tool::Surface(theFace,aLoc);
338
339   if(!S.IsNull()){
340     BRepAdaptor_Surface S(theFace,Standard_False);
341       
342     GeomAbs_SurfaceType SurfType = S.GetType();
343
344     GeomAbs_CurveType CurvType = GeomAbs_OtherCurve;
345
346     Standard_Integer Intrv, nbIntv;
347     Standard_Integer nbUIntv = S.NbUIntervals(GeomAbs_CN);
348     Standard_Integer nbVIntv = S.NbVIntervals(GeomAbs_CN);
349     TColStd_Array1OfReal TI(1,Max(nbUIntv, nbVIntv)+1);
350
351     if(theIsoType == GeomAbs_IsoU){
352       S.VIntervals(TI, GeomAbs_CN);
353       V1 = Max(T1, TI(1));
354       V2 = Min(T2, TI(2));
355       U1 = Par;
356       U2 = Par;
357       stepU = 0;
358       nbIntv = nbVIntv;
359     }else{
360       S.UIntervals(TI, GeomAbs_CN);
361       U1 = Max(T1, TI(1));
362       U2 = Min(T2, TI(2));
363       V1 = Par;
364       V2 = Par;
365       stepV = 0;
366       nbIntv = nbUIntv;
367     }   
368         
369     S.D0(U1,V1,P);
370     MoveTo(P,thePts);
371
372     for(Intrv = 1; Intrv <= nbIntv; Intrv++){
373       if(TI(Intrv) <= T1 && TI(Intrv + 1) <= T1)
374         continue;
375       if(TI(Intrv) >= T2 && TI(Intrv + 1) >= T2)
376               continue;
377       if(theIsoType == GeomAbs_IsoU){
378               V1 = Max(T1, TI(Intrv));
379               V2 = Min(T2, TI(Intrv + 1));
380               stepV = (V2 - V1) / theDiscret;
381       }else{
382               U1 = Max(T1, TI(Intrv));
383               U2 = Min(T2, TI(Intrv + 1));
384               stepU = (U2 - U1) / theDiscret;
385       }
386
387       switch (SurfType) {
388       case GeomAbs_Plane :
389               break;
390       case GeomAbs_Cylinder :
391       case GeomAbs_Cone :
392         if(theIsoType == GeomAbs_IsoV){
393                 for(j = 1; j < theDiscret; j++){
394                   U1 += stepU;
395                   V1 += stepV;
396                   S.D0(U1,V1,P);
397                   DrawTo(P,thePolyData,thePts);
398                 }
399               }
400               break;
401       case GeomAbs_Sphere :
402       case GeomAbs_Torus :
403       case GeomAbs_OffsetSurface :
404       case GeomAbs_OtherSurface :
405         for(j = 1; j < theDiscret; j++){
406                 U1 += stepU;
407                 V1 += stepV;
408                 S.D0(U1,V1,P);
409                 DrawTo(P,thePolyData,thePts);
410               }
411               break;
412       case GeomAbs_BezierSurface :
413       case GeomAbs_BSplineSurface :
414         for(j = 1; j <= theDiscret/2; j++){
415           Standard_Real aStep = (theIsoType == GeomAbs_IsoV) ? stepU*2. : stepV*2.;
416                 CreateIso__(S, theIsoType, U1, V1, aStep, thePolyData, thePts);
417                 U1 += stepU*2.;
418                 V1 += stepV*2.;
419               }
420               break;
421       case GeomAbs_SurfaceOfExtrusion :
422       case GeomAbs_SurfaceOfRevolution :
423         if((theIsoType == GeomAbs_IsoV && SurfType == GeomAbs_SurfaceOfRevolution) ||
424                  (theIsoType == GeomAbs_IsoU && SurfType == GeomAbs_SurfaceOfExtrusion)) 
425         {
426                 if(SurfType == GeomAbs_SurfaceOfExtrusion) 
427             break;
428                 for(j = 1; j < theDiscret; j++){
429                   U1 += stepU;
430                   V1 += stepV;
431                   S.D0(U1,V1,P);
432                   DrawTo(P,thePolyData,thePts);
433                 }
434               }else{
435                 CurvType = (S.BasisCurve())->GetType();
436                 switch(CurvType){
437                 case GeomAbs_Line :
438                   break;
439                 case GeomAbs_Circle :
440                 case GeomAbs_Ellipse :
441                   for (j = 1; j < theDiscret; j++) {
442                     U1 += stepU;
443                     V1 += stepV;
444                     S.D0(U1,V1,P);
445                     DrawTo(P,thePolyData,thePts);
446                   }
447                   break;
448                 case GeomAbs_Parabola :
449                 case GeomAbs_Hyperbola :
450                 case GeomAbs_BezierCurve :
451                 case GeomAbs_BSplineCurve :
452                 case GeomAbs_OtherCurve :
453                   for(j = 1; j <= theDiscret/2; j++){
454               Standard_Real aStep = (theIsoType == GeomAbs_IsoV) ? stepU*2. : stepV*2.;
455                   CreateIso__(S, theIsoType, U1, V1, aStep, thePolyData, thePts);
456                     U1 += stepU*2.;
457                     V1 += stepV*2.;
458                   }
459                   break;
460                 }
461               }
462       }
463     }
464     S.D0(U2,V2,P);
465     DrawTo(P,thePolyData,thePts);
466   }  
467 }
468  
469  
470  
471  
472 void 
473 GEOM_WireframeFace:: 
474 CreateIso__(const BRepAdaptor_Surface& theSurface, 
475             GeomAbs_IsoType theIsoType,
476                                     Standard_Real& theU, 
477                                     Standard_Real& theV, 
478                                     Standard_Real theStep, 
479             vtkPolyData* thePolyData,
480             vtkPoints* thePts)
481 {
482   gp_Pnt Pl, Pr, Pm;
483   if (theIsoType == GeomAbs_IsoU) {
484     theSurface.D0(theU, theV, Pl);
485     theSurface.D0(theU, theV + theStep/2., Pm);
486     theSurface.D0(theU, theV + theStep, Pr);
487   } else {
488     theSurface.D0(theU, theV, Pl);
489     theSurface.D0(theU + theStep/2., theV, Pm);
490     theSurface.D0(theU + theStep, theV, Pr);
491   }
492
493   static Standard_Real ISO_RATIO = 1.001;
494   if (Pm.Distance(Pl) + Pm.Distance(Pr) <= ISO_RATIO*Pl.Distance(Pr)) {
495     DrawTo(Pr,thePolyData,thePts);
496   } else {
497     if (theIsoType == GeomAbs_IsoU) {
498       CreateIso__(theSurface, theIsoType, theU, theV, theStep/2, thePolyData, thePts);
499       Standard_Real aLocalV = theV + theStep/2 ;
500       CreateIso__(theSurface, theIsoType, theU, aLocalV , theStep/2, thePolyData, thePts);
501     } else {
502       CreateIso__(theSurface, theIsoType, theU, theV, theStep/2, thePolyData, thePts);
503       Standard_Real aLocalU = theU + theStep/2 ;
504       CreateIso__(theSurface, theIsoType, aLocalU , theV, theStep/2, thePolyData, thePts);
505     }
506   }
507 }