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