Salome HOME
NRI : Remove dependence with KERNEL.
[modules/visu.git] / src / VISU_I / VISU_ScalarBarActor.cxx
1 using namespace std;
2 // File:        VISU_ScalarBarActor.cxx
3 // Created:     Wed Feb 26 10:34:56 2003
4 // Author:      Alexey PETROV
5 //              <apo@ivanox.nnov.matra-dtv.fr>
6
7
8 #include "VISU_ScalarBarActor.hxx"
9 #include "VISU_LookupTable.hxx"
10 #include <vtkObjectFactory.h>
11
12 //------------------------------------------------------------------------------
13 VISU_ScalarBarActor* VISU_ScalarBarActor::New(){
14   vtkObject* ret = vtkObjectFactory::CreateInstance("VISU_ScalarBarActor");
15   if(ret)
16     return (VISU_ScalarBarActor*)ret;
17   return new VISU_ScalarBarActor;
18 }
19
20 VISU_ScalarBarActor::VISU_ScalarBarActor()
21 {
22   this->myLookupTable = NULL;
23   this->Position2Coordinate->SetValue(0.17, 0.8);
24   
25   this->PositionCoordinate->SetCoordinateSystemToNormalizedViewport();
26   this->PositionCoordinate->SetValue(0.82,0.1);
27   
28   this->MaximumNumberOfColors = 64;
29   this->NumberOfLabels = 5;
30   this->NumberOfLabelsBuilt = 0;
31   this->Orientation = VTK_ORIENT_VERTICAL;
32   this->Title = NULL;
33
34   this->Bold = 1;
35   this->Italic = 1;
36   this->Shadow = 1;
37   this->FontFamily = VTK_ARIAL;
38   this->LabelFormat = new char[8]; 
39   sprintf(this->LabelFormat,"%s","%-#6.3g");
40
41   this->TitleMapper = vtkTextMapper::New();
42   this->TitleMapper->SetJustificationToCentered();
43   this->TitleActor = vtkActor2D::New();
44   this->TitleActor->SetMapper(this->TitleMapper);
45   this->TitleActor->GetPositionCoordinate()->
46     SetReferenceCoordinate(this->PositionCoordinate);
47   
48   this->TextMappers = NULL;
49   this->TextActors = NULL;
50
51   this->ScalarBar = vtkPolyData::New();
52   this->ScalarBarMapper = vtkPolyDataMapper2D::New();
53   this->ScalarBarMapper->SetInput(this->ScalarBar);
54   this->ScalarBarActor = vtkActor2D::New();
55   this->ScalarBarActor->SetMapper(this->ScalarBarMapper);
56   this->ScalarBarActor->GetPositionCoordinate()->
57     SetReferenceCoordinate(this->PositionCoordinate);
58   this->LastOrigin[0] = 0;
59   this->LastOrigin[1] = 0;
60   this->LastSize[0] = 0;
61   this->LastSize[1] = 0;
62 }
63
64 void VISU_ScalarBarActor::ReleaseGraphicsResources(vtkWindow *win)
65 {
66   this->TitleActor->ReleaseGraphicsResources(win);
67   if (this->TextMappers != NULL )
68     {
69     for (int i=0; i < this->NumberOfLabelsBuilt; i++)
70       {
71       this->TextActors[i]->ReleaseGraphicsResources(win);
72       }
73     }
74   this->ScalarBarActor->ReleaseGraphicsResources(win);
75 }
76
77 VISU_ScalarBarActor::~VISU_ScalarBarActor()
78 {
79   if (this->LabelFormat) 
80     {
81     delete [] this->LabelFormat;
82     this->LabelFormat = NULL;
83     }
84
85   this->TitleMapper->Delete();
86   this->TitleActor->Delete();
87
88   if (this->TextMappers != NULL )
89     {
90     for (int i=0; i < this->NumberOfLabelsBuilt; i++)
91       {
92       this->TextMappers[i]->Delete();
93       this->TextActors[i]->Delete();
94       }
95     delete [] this->TextMappers;
96     delete [] this->TextActors;
97     }
98
99   this->ScalarBar->Delete();
100   this->ScalarBarMapper->Delete();
101   this->ScalarBarActor->Delete();
102
103   if (this->Title)
104     {
105     delete [] this->Title;
106     this->Title = NULL;
107     }
108   
109   this->SetLookupTable(NULL);
110 }
111
112 void VISU_ScalarBarActor::SetLookupTable(vtkScalarsToColors* theLookupTable){
113   //this->myLookupTable = dynamic_cast<VISU_LookupTable*>(theLookupTable);
114   if(this->myLookupTable != NULL) this->myLookupTable->UnRegister(this);
115   this->myLookupTable = VISU_LookupTable::SafeDownCast(theLookupTable);
116   this->myLookupTable->Register(this);
117 }
118
119 vtkScalarsToColors* VISU_ScalarBarActor::GetLookupTable(){
120   cout<<"VISU_ScalarBarActor::GetLookupTable = "<<this->myLookupTable;
121   return this->myLookupTable;
122 }
123
124 int VISU_ScalarBarActor::RenderOverlay(vtkViewport *viewport)
125 {
126   int renderedSomething = 0;
127   int i;
128   
129   // Everything is built, just have to render
130   if (this->Title != NULL)
131     {
132     renderedSomething += this->TitleActor->RenderOverlay(viewport);
133     }
134   this->ScalarBarActor->RenderOverlay(viewport);
135   if( this->TextActors == NULL)
136     {
137      vtkWarningMacro(<<"Need a mapper to render a scalar bar");
138      return renderedSomething;
139     }
140   
141   for (i=0; i<this->NumberOfLabels; i++)
142     {
143     renderedSomething += this->TextActors[i]->RenderOverlay(viewport);
144     }
145
146   renderedSomething = (renderedSomething > 0)?(1):(0);
147
148   return renderedSomething;
149 }
150
151 int VISU_ScalarBarActor::RenderOpaqueGeometry(vtkViewport *viewport)
152 {
153   int renderedSomething = 0;
154   int i;
155   int size[2];
156   
157   if ( ! this->myLookupTable )
158     {
159     vtkWarningMacro(<<"Need a mapper to render a scalar bar");
160     return 0;
161     }
162
163   // Check to see whether we have to rebuild everything
164   if ( viewport->GetMTime() > this->BuildTime || 
165        ( viewport->GetVTKWindow() && 
166          viewport->GetVTKWindow()->GetMTime() > this->BuildTime ) )
167     {
168     // if the viewport has changed we may - or may not need
169     // to rebuild, it depends on if the projected coords chage
170     int *barOrigin;
171     barOrigin = this->PositionCoordinate->GetComputedViewportValue(viewport);
172     size[0] = 
173       this->Position2Coordinate->GetComputedViewportValue(viewport)[0] -
174       barOrigin[0];
175     size[1] = 
176       this->Position2Coordinate->GetComputedViewportValue(viewport)[1] -
177       barOrigin[1];
178     if (this->LastSize[0] != size[0] || this->LastSize[1] != size[1] ||
179         this->LastOrigin[0] != barOrigin[0] || 
180         this->LastOrigin[1] != barOrigin[1])
181       {
182       this->Modified();
183       }
184     }
185   
186   // Check to see whether we have to rebuild everything
187   if ( this->GetMTime() > this->BuildTime || 
188        this->myLookupTable->GetMTime() > this->BuildTime )
189     {
190     vtkDebugMacro(<<"Rebuilding subobjects");
191
192     // Delete previously constructed objects
193     //
194     if (this->TextMappers != NULL )
195       {
196       for (i=0; i < this->NumberOfLabelsBuilt; i++)
197         {
198         this->TextMappers[i]->Delete();
199         this->TextActors[i]->Delete();
200         }
201       delete [] this->TextMappers;
202       delete [] this->TextActors;
203       }
204
205     // Build scalar bar object
206     //
207     VISU_LookupTable *lut = this->myLookupTable;  //VISU specific
208     // we hard code how many steps to display
209     int numColors = this->MaximumNumberOfColors;
210     float *range = lut->GetRange();
211
212     int numPts = 2*(numColors + 1);
213     vtkPoints *pts = vtkPoints::New();
214     pts->SetNumberOfPoints(numPts);
215     vtkCellArray *polys = vtkCellArray::New();
216     polys->Allocate(polys->EstimateSize(numColors,4));
217     vtkScalars *colors = vtkScalars::New(VTK_UNSIGNED_CHAR,3);
218     colors->SetNumberOfScalars(numColors);
219     vtkUnsignedCharArray *colorData = (vtkUnsignedCharArray *)colors->GetData();
220
221     this->ScalarBarActor->SetProperty(this->GetProperty());
222     this->ScalarBar->Initialize();
223     this->ScalarBar->SetPoints(pts);
224     this->ScalarBar->SetPolys(polys);
225     this->ScalarBar->GetCellData()->SetScalars(colors);
226     pts->Delete(); polys->Delete(); colors->Delete();
227
228     // get the viewport size in display coordinates
229     int *barOrigin, barWidth, barHeight;
230     barOrigin = this->PositionCoordinate->GetComputedViewportValue(viewport);
231     size[0] = 
232       this->Position2Coordinate->GetComputedViewportValue(viewport)[0] -
233       barOrigin[0];
234     size[1] = 
235       this->Position2Coordinate->GetComputedViewportValue(viewport)[1] -
236       barOrigin[1];
237     this->LastOrigin[0] = barOrigin[0];
238     this->LastOrigin[1] = barOrigin[1];
239     this->LastSize[0] = size[0];
240     this->LastSize[1] = size[1];
241     
242     // Update all the composing objects
243     //
244     if (this->Title == NULL )
245       {
246       this->TitleActor->VisibilityOff();
247       }
248     this->TitleActor->VisibilityOn();
249     this->TitleActor->SetProperty(this->GetProperty());
250     this->TitleMapper->SetInput(this->Title);
251     this->TitleMapper->SetBold(this->Bold);
252     this->TitleMapper->SetItalic(this->Italic);
253     this->TitleMapper->SetShadow(this->Shadow);
254     this->TitleMapper->SetFontFamily(this->FontFamily);
255
256     
257     // find the best size for the title font
258     int titleSize[2];
259     this->SizeTitle(titleSize, size, viewport);
260     
261     // find the best size for the ticks
262     int labelSize[2];
263     this->AllocateAndSizeLabels(labelSize, size, viewport,range);
264     this->NumberOfLabelsBuilt = this->NumberOfLabels;
265     
266     // generate points
267     float x[3]; x[2] = 0.0;
268     float delta;
269     if ( this->Orientation == VTK_ORIENT_VERTICAL )
270       {
271       barWidth = size[0] - 4 - labelSize[0];
272       barHeight = (int)(0.86*size[1]);
273       delta=(float)barHeight/numColors;
274       for (i=0; i<numPts/2; i++)
275         {
276         x[0] = 0;
277         x[1] = i*delta;
278         pts->SetPoint(2*i,x);
279         x[0] = barWidth;
280         pts->SetPoint(2*i+1,x);
281         }
282       }
283     else
284       {
285       barWidth = size[0];
286       barHeight = (int)(0.4*size[1]);
287       delta=(float)barWidth/numColors;
288       for (i=0; i<numPts/2; i++)
289         {
290         x[0] = i*delta;
291         x[1] = barHeight;
292         pts->SetPoint(2*i,x);
293         x[1] = 0;
294         pts->SetPoint(2*i+1,x);
295         }
296       }
297
298     //polygons & cell colors
299     unsigned char *rgba, *rgb;
300     int ptIds[4];
301     float val, *aLogRange = this->myLookupTable->GetLogRange();
302     for (i=0; i<numColors; i++)
303       {
304       ptIds[0] = 2*i;
305       ptIds[1] = ptIds[0] + 1;
306       ptIds[2] = ptIds[1] + 2;
307       ptIds[3] = ptIds[0] + 2;
308       polys->InsertNextCell(4,ptIds);
309       rgba = lut->MapValue(range[0] + (range[1] - range[0])*((float)i /(numColors-1.0)));
310       if(this->myLookupTable->IsLog()){ // SALOME specific
311         val = aLogRange[0] + (float)i/(numColors-1.0) * (aLogRange[1]-aLogRange[0]);
312         rgba = lut->MapValue(val);
313       }
314       rgb = colorData->GetPointer(3*i); //write into array directly
315       rgb[0] = rgba[0];
316       rgb[1] = rgba[1];
317       rgb[2] = rgba[2];
318       }
319
320     // Now position everything properly
321     //
322     if (this->Orientation == VTK_ORIENT_VERTICAL)
323       {
324       int sizeTextData[2];
325       
326       // center the title
327       this->TitleActor->SetPosition(size[0]/2, 0.9*size[1]);
328       
329       for (i=0; i < this->NumberOfLabels; i++)
330         {
331         val = (float)i/(this->NumberOfLabels-1) *barHeight;
332         this->TextMappers[i]->SetJustificationToLeft();
333         this->TextMappers[i]->GetSize(viewport,sizeTextData);
334         this->TextActors[i]->SetPosition(barWidth+3,
335                                          val - sizeTextData[1]/2);
336         }
337       }
338     else
339       {
340       this->TitleActor->SetPosition(size[0]/2, 
341                                     barHeight + labelSize[1] + 0.1*size[1]);
342       for (i=0; i < this->NumberOfLabels; i++)
343         {
344         val = (float)i/(this->NumberOfLabels-1) * barWidth;
345         this->TextMappers[i]->SetJustificationToCentered();
346         this->TextActors[i]->SetPosition(val, barHeight + 0.05*size[1]);
347         }
348       }
349
350     this->BuildTime.Modified();
351     }
352
353   // Everything is built, just have to render
354   if (this->Title != NULL)
355     {
356     renderedSomething += this->TitleActor->RenderOpaqueGeometry(viewport);
357     }
358   this->ScalarBarActor->RenderOpaqueGeometry(viewport);
359   for (i=0; i<this->NumberOfLabels; i++)
360     {
361     renderedSomething += this->TextActors[i]->RenderOpaqueGeometry(viewport);
362     }
363
364   renderedSomething = (renderedSomething > 0)?(1):(0);
365
366   return renderedSomething;
367 }
368
369 void VISU_ScalarBarActor::PrintSelf(ostream& os, vtkIndent indent)
370 {
371   vtkActor2D::PrintSelf(os,indent);
372
373   if ( this->myLookupTable )
374     {
375     os << indent << "Lookup Table:\n";
376     this->myLookupTable->PrintSelf(os,indent.GetNextIndent());
377     }
378   else
379     {
380     os << indent << "Lookup Table: (none)\n";
381     }
382
383   os << indent << "Title: " << (this->Title ? this->Title : "(none)") << "\n";
384   os << indent << "Maximum Number Of Colors: " 
385      << this->MaximumNumberOfColors << "\n";
386   os << indent << "Number Of Labels: " << this->NumberOfLabels << "\n";
387   os << indent << "Number Of Labels Built: " << this->NumberOfLabelsBuilt << "\n";
388
389   os << indent << "Orientation: ";
390   if ( this->Orientation == VTK_ORIENT_HORIZONTAL )
391     {
392     os << "Horizontal\n";
393     }
394   else
395     {
396     os << "Vertical\n";
397     }
398
399   os << indent << "Font Family: ";
400   if ( this->FontFamily == VTK_ARIAL )
401     {
402     os << "Arial\n";
403     }
404   else if ( this->FontFamily == VTK_COURIER )
405     {
406     os << "Courier\n";
407     }
408   else
409     {
410     os << "Times\n";
411     }
412
413   os << indent << "Bold: " << (this->Bold ? "On\n" : "Off\n");
414   os << indent << "Italic: " << (this->Italic ? "On\n" : "Off\n");
415   os << indent << "Shadow: " << (this->Shadow ? "On\n" : "Off\n");
416   os << indent << "Label Format: " << this->LabelFormat << "\n";
417 }
418
419 void VISU_ScalarBarActor::ShallowCopy(vtkProp *prop)
420 {
421   VISU_ScalarBarActor *a = VISU_ScalarBarActor::SafeDownCast(prop);
422   if ( a != NULL )
423     {
424     this->SetPosition2(a->GetPosition2());
425     this->SetLookupTable(a->GetLookupTable());
426     this->SetMaximumNumberOfColors(a->GetMaximumNumberOfColors());
427     this->SetOrientation(a->GetOrientation());
428     this->SetBold(a->GetBold());
429     this->SetItalic(a->GetItalic());
430     this->SetShadow(a->GetShadow());
431     this->SetFontFamily(a->GetFontFamily());
432     this->SetLabelFormat(a->GetLabelFormat());
433     this->SetTitle(a->GetTitle());
434
435     this->GetPositionCoordinate()->SetCoordinateSystem(
436       a->GetPositionCoordinate()->GetCoordinateSystem());    
437     this->GetPositionCoordinate()->SetValue(
438       a->GetPositionCoordinate()->GetValue());
439     this->GetPosition2Coordinate()->SetCoordinateSystem(
440       a->GetPosition2Coordinate()->GetCoordinateSystem());    
441     this->GetPosition2Coordinate()->SetValue(
442       a->GetPosition2Coordinate()->GetValue());
443     }
444
445   // Now do superclass
446   this->vtkActor2D::ShallowCopy(prop);
447 }
448
449 void VISU_ScalarBarActor::AllocateAndSizeLabels(int *labelSize, int *size,
450                                               vtkViewport *viewport,
451                                               float *range)
452 {
453   labelSize[0] = 0;
454   labelSize[1] = 0;
455   int fontSize;
456   int tempi[2];
457   
458   this->TextMappers = new vtkTextMapper * [this->NumberOfLabels];
459   this->TextActors = new vtkActor2D * [this->NumberOfLabels];
460   char string[512];
461   float val, *aLogRange = this->myLookupTable->GetLogRange();
462   int targetWidth, targetHeight;
463   int i;
464   
465   for (i=0; i < this->NumberOfLabels; i++)
466     {
467     this->TextMappers[i] = vtkTextMapper::New();
468     val = range[0] + (float)i/(this->NumberOfLabels-1) * (range[1]-range[0]);
469     if(0 < i && i < this->NumberOfLabels - 1)  // SALOME specific
470        if(this->myLookupTable->IsLog()){
471          val = aLogRange[0] + (float)i/(this->NumberOfLabels-1) * (aLogRange[1]-aLogRange[0]);
472          val = pow((float)10.0,val);
473        }
474     sprintf(string, this->LabelFormat, val);
475     this->TextMappers[i]->SetInput(string);
476     this->TextMappers[i]->SetBold(this->Bold);
477     this->TextMappers[i]->SetItalic(this->Italic);
478     this->TextMappers[i]->SetShadow(this->Shadow);
479     this->TextMappers[i]->SetFontFamily(this->FontFamily);
480     this->TextActors[i] = vtkActor2D::New();
481     this->TextActors[i]->SetMapper(this->TextMappers[i]);
482     this->TextActors[i]->SetProperty(this->GetProperty());
483     this->TextActors[i]->GetPositionCoordinate()->
484       SetReferenceCoordinate(this->PositionCoordinate);
485     }
486   if (this->NumberOfLabels)
487     {
488     if ( this->Orientation == VTK_ORIENT_VERTICAL )
489       {
490       targetWidth = (int)(0.6*size[0]);
491       targetHeight = (int)(0.86*size[1]/this->NumberOfLabels);
492       }
493     else
494       {
495       targetWidth = (int)(size[0]*0.8/this->NumberOfLabels);
496       targetHeight = (int)(0.25*size[1]);
497       }
498     fontSize = targetWidth;
499     for (i=0; i < this->NumberOfLabels; i++)
500       {
501       this->TextMappers[i]->SetFontSize(fontSize);
502       this->TextMappers[i]->GetSize(viewport,tempi);
503       if (labelSize[0] < tempi[0])
504         {
505         labelSize[0] = tempi[0];
506         }
507       if (labelSize[1] < tempi[1])
508         {
509         labelSize[1] = tempi[1];
510         }
511       }
512     
513     while (labelSize[0] < targetWidth && labelSize[1] < targetHeight && 
514            fontSize < 100 ) 
515       {
516       fontSize++;
517       labelSize[0] = 0;
518       labelSize[1] = 0;
519       for (i=0; i < this->NumberOfLabels; i++)
520         {
521         this->TextMappers[i]->SetFontSize(fontSize);
522         this->TextMappers[i]->GetSize(viewport,tempi);
523         if (labelSize[0] < tempi[0])
524           {
525           labelSize[0] = tempi[0];
526           }
527         if (labelSize[1] < tempi[1])
528           {
529           labelSize[1] = tempi[1];
530           }
531         }
532       }
533     
534     while ((labelSize[0] > targetWidth || 
535             labelSize[1] > targetHeight) && fontSize > 0 )
536       {
537       fontSize--;
538       labelSize[0] = 0;
539       labelSize[1] = 0;
540       for (i=0; i < this->NumberOfLabels; i++)
541         {
542         this->TextMappers[i]->SetFontSize(fontSize);
543         this->TextMappers[i]->GetSize(viewport,tempi);
544         if (labelSize[0] < tempi[0])
545           {
546           labelSize[0] = tempi[0];
547           }
548         if (labelSize[1] < tempi[1])
549           {
550           labelSize[1] = tempi[1];
551           }
552         }
553       }
554     }
555 }
556
557 void VISU_ScalarBarActor::SizeTitle(int *titleSize, int *size, 
558                                   vtkViewport *viewport)
559 {
560   int targetWidth, targetHeight;
561   titleSize[0] = 0;    
562   titleSize[1] = 0;
563   int fontSize;
564   int tempi[2];
565   
566   if (this->Title != NULL && (strlen(this->Title) != 0))
567     {
568     if ( this->Orientation == VTK_ORIENT_VERTICAL )
569       {
570       targetWidth = size[0];
571       targetHeight = (int)(0.1*size[1]);
572       }
573     else
574       {
575       targetWidth = size[0];
576       targetHeight = (int)(0.25*size[1]);
577       }
578     fontSize = targetWidth;
579     this->TitleMapper->SetFontSize(fontSize);
580     this->TitleMapper->GetSize(viewport,tempi);
581     
582     while (tempi[1] < targetHeight && tempi[0] < targetWidth 
583            && fontSize < 100 ) 
584       {
585       fontSize++;
586       this->TitleMapper->SetFontSize(fontSize);
587       this->TitleMapper->GetSize(viewport,tempi);
588       }
589     
590     while ((tempi[1] > targetHeight || tempi[0] > targetWidth )
591            && fontSize > 0 )
592       {
593       fontSize--;
594       this->TitleMapper->SetFontSize(fontSize);
595       this->TitleMapper->GetSize(viewport,tempi);
596       }
597     titleSize[0] = tempi[0];
598     titleSize[1] = tempi[1];
599     }
600 }