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