Salome HOME
1f5b00b63a5ee13e16f5c72587cd3addce35024e
[modules/smesh.git] / src / OBJECT / SMESH_ScalarBarActor.cxx
1 // Copyright (C) 2007-2016  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 //  File   : SMESH_ScalarBarActor.cxx
23 //  Author : Roman NIKOLAEV
24 //  Module : SMESH
25 //
26
27 #include "SMESH_ScalarBarActor.h"
28
29 #include <vtkCellArray.h>
30 #include <vtkCellData.h>
31 #include <vtkObjectFactory.h>
32 #include <vtkPolyData.h>
33 #include <vtkPolyDataMapper2D.h>
34 #include <vtkScalarsToColors.h>
35 #include <vtkTextMapper.h>
36 #include <vtkTextProperty.h>
37 #include <vtkViewport.h>
38 #include <vtkWindow.h>
39 #include <vtkLookupTable.h>
40 #include <vtkProperty2D.h>
41
42 #define SHRINK_COEF 0.08;
43
44 vtkStandardNewMacro(SMESH_ScalarBarActor);
45
46 vtkCxxSetObjectMacro(SMESH_ScalarBarActor,LookupTable,vtkScalarsToColors);
47 vtkCxxSetObjectMacro(SMESH_ScalarBarActor,LabelTextProperty,vtkTextProperty);
48 vtkCxxSetObjectMacro(SMESH_ScalarBarActor,TitleTextProperty,vtkTextProperty);
49
50 //----------------------------------------------------------------------------
51 // Instantiate object with 64 maximum colors; 5 labels; %%-#6.3g label
52 // format, no title, and vertical orientation. The initial scalar bar
53 // size is (0.05 x 0.8) of the viewport size.
54 SMESH_ScalarBarActor::SMESH_ScalarBarActor() {
55   this->LookupTable = NULL;
56   this->Position2Coordinate->SetValue(0.17, 0.8);
57   
58   this->PositionCoordinate->SetCoordinateSystemToNormalizedViewport();
59   this->PositionCoordinate->SetValue(0.82,0.1);
60   
61   this->MaximumNumberOfColors = 64;
62   this->NumberOfLabels = 5;
63   this->NumberOfLabelsBuilt = 0;
64   this->Orientation = VTK_ORIENT_VERTICAL;
65   this->Title = NULL;
66
67   this->LabelTextProperty = vtkTextProperty::New();
68   this->LabelTextProperty->SetFontSize(12);
69   this->LabelTextProperty->SetBold(1);
70   this->LabelTextProperty->SetItalic(1);
71   this->LabelTextProperty->SetShadow(1);
72   this->LabelTextProperty->SetFontFamilyToArial();
73
74   this->TitleTextProperty = vtkTextProperty::New();
75   this->TitleTextProperty->ShallowCopy(this->LabelTextProperty);
76
77   this->LabelFormat = new char[8]; 
78   sprintf(this->LabelFormat,"%s","%-#6.3g");
79
80   this->TitleMapper = vtkTextMapper::New();
81   this->TitleActor = vtkActor2D::New();
82   this->TitleActor->SetMapper(this->TitleMapper);
83   this->TitleActor->GetPositionCoordinate()->
84     SetReferenceCoordinate(this->PositionCoordinate);
85   
86   this->TextMappers = NULL;
87   this->TextActors = NULL;
88
89   this->ScalarBar = vtkPolyData::New();
90   this->ScalarBarMapper = vtkPolyDataMapper2D::New();
91   this->ScalarBarMapper->SetInputData(this->ScalarBar);
92   this->ScalarBarActor = vtkActor2D::New();
93   this->ScalarBarActor->SetMapper(this->ScalarBarMapper);
94   this->ScalarBarActor->GetPositionCoordinate()->
95     SetReferenceCoordinate(this->PositionCoordinate);
96   this->LastOrigin[0] = 0;
97   this->LastOrigin[1] = 0;
98   this->LastSize[0] = 0;
99   this->LastSize[1] = 0;
100
101
102   // rnv begin
103   // Customization of the vtkScalarBarActor to show distribution histogram.
104   myDistribution = vtkPolyData::New();
105   myDistributionMapper = vtkPolyDataMapper2D::New();
106   myDistributionMapper->SetInputData(this->myDistribution);
107   
108   myDistributionActor = vtkActor2D::New();
109   myDistributionActor->SetMapper(this->myDistributionMapper);
110   myDistributionActor->GetPositionCoordinate()->
111     SetReferenceCoordinate(this->PositionCoordinate);
112
113   // By default distribution histogram is invisible
114   myDistributionActor->SetVisibility(0);
115
116   // By default monocolor
117   myDistributionColoringType = SMESH_MONOCOLOR_TYPE;
118
119   // By default scalar map is shown
120   myTitleOnlyVisibility = false;
121   // rnv end
122 }
123
124 //----------------------------------------------------------------------------
125 // Release any graphics resources that are being consumed by this actor.
126 // The parameter window could be used to determine which graphic
127 // resources to release.
128 void SMESH_ScalarBarActor::ReleaseGraphicsResources(vtkWindow *win)
129 {
130   this->TitleActor->ReleaseGraphicsResources(win);
131   if (this->TextMappers != NULL )
132     {
133     for (int i=0; i < this->NumberOfLabelsBuilt; i++)
134       {
135       this->TextActors[i]->ReleaseGraphicsResources(win);
136       }
137     }
138   this->ScalarBarActor->ReleaseGraphicsResources(win);
139   // rnv begin
140   // Customization of the vtkScalarBarActor to show distribution histogram.
141   myDistributionActor->ReleaseGraphicsResources(win);
142 }
143
144
145 /*--------------------------------------------------------------------------*/
146 SMESH_ScalarBarActor::~SMESH_ScalarBarActor() {
147   if (this->LabelFormat) 
148     {
149     delete [] this->LabelFormat;
150     this->LabelFormat = NULL;
151     }
152
153   this->TitleMapper->Delete();
154   this->TitleActor->Delete();
155
156   if (this->TextMappers != NULL )
157     {
158     for (int i=0; i < this->NumberOfLabelsBuilt; i++)
159       {
160       this->TextMappers[i]->Delete();
161       this->TextActors[i]->Delete();
162       }
163     delete [] this->TextMappers;
164     delete [] this->TextActors;
165     }
166
167   this->ScalarBar->Delete();
168   this->ScalarBarMapper->Delete();
169   this->ScalarBarActor->Delete();
170
171   if (this->Title)
172     {
173     delete [] this->Title;
174     this->Title = NULL;
175     }
176   
177   this->SetLookupTable(NULL);
178   this->SetLabelTextProperty(NULL);
179   this->SetTitleTextProperty(NULL);
180   
181   // rnv begin
182   // Customization of the vtkScalarBarActor to show distribution histogram:
183   myDistribution->Delete();
184   myDistributionMapper->Delete();
185   myDistributionActor->Delete();
186   // rnv end
187 }
188
189 //----------------------------------------------------------------------------
190 int SMESH_ScalarBarActor::RenderOverlay(vtkViewport *viewport)
191 {
192   int renderedSomething = 0;
193   int i;
194   
195   // Everything is built, just have to render
196   if (this->Title != NULL)
197     {
198     renderedSomething += this->TitleActor->RenderOverlay(viewport);
199     }
200   if (!myTitleOnlyVisibility) {
201     this->ScalarBarActor->RenderOverlay(viewport);
202     this->myDistributionActor->RenderOverlay(viewport);
203     if( this->TextActors == NULL)
204       {
205        vtkWarningMacro(<<"Need a mapper to render a scalar bar");
206        return renderedSomething;
207       }
208   
209     for (i=0; i<this->NumberOfLabels; i++)
210       {
211       renderedSomething += this->TextActors[i]->RenderOverlay(viewport);
212       }
213   }  
214   renderedSomething = (renderedSomething > 0)?(1):(0);
215
216   return renderedSomething;
217 }
218
219
220 //----------------------------------------------------------------------------
221 int SMESH_ScalarBarActor::RenderOpaqueGeometry(vtkViewport *viewport)
222 {
223   int renderedSomething = 0;
224   int i;
225   int size[2];
226   
227   if (!this->LookupTable)
228     {
229     vtkWarningMacro(<<"Need a mapper to render a scalar bar");
230     return 0;
231     }
232
233   if (!this->TitleTextProperty)
234     {
235     vtkErrorMacro(<<"Need title text property to render a scalar bar");
236     return 0;
237     }
238
239   if (!this->LabelTextProperty)
240     {
241     vtkErrorMacro(<<"Need label text property to render a scalar bar");
242     return 0;
243     }
244
245   // Check to see whether we have to rebuild everything
246   int positionsHaveChanged = 0;
247   if (viewport->GetMTime() > this->BuildTime || 
248       (viewport->GetVTKWindow() && 
249        viewport->GetVTKWindow()->GetMTime() > this->BuildTime))
250     {
251     // if the viewport has changed we may - or may not need
252     // to rebuild, it depends on if the projected coords chage
253     int *barOrigin;
254     barOrigin = this->PositionCoordinate->GetComputedViewportValue(viewport);
255     size[0] = 
256       this->Position2Coordinate->GetComputedViewportValue(viewport)[0] -
257       barOrigin[0];
258     size[1] = 
259       this->Position2Coordinate->GetComputedViewportValue(viewport)[1] -
260       barOrigin[1];
261     if (this->LastSize[0] != size[0] || 
262         this->LastSize[1] != size[1] ||
263         this->LastOrigin[0] != barOrigin[0] || 
264         this->LastOrigin[1] != barOrigin[1])
265       {
266       positionsHaveChanged = 1;
267       }
268     }
269   
270   // Check to see whether we have to rebuild everything
271   if (positionsHaveChanged ||
272       this->GetMTime() > this->BuildTime || 
273       this->LookupTable->GetMTime() > this->BuildTime ||
274       this->LabelTextProperty->GetMTime() > this->BuildTime ||
275       this->TitleTextProperty->GetMTime() > this->BuildTime)
276     {
277     vtkDebugMacro(<<"Rebuilding subobjects");
278
279     // Delete previously constructed objects
280     //
281     if (this->TextMappers != NULL )
282       {
283       for (i=0; i < this->NumberOfLabelsBuilt; i++)
284         {
285         this->TextMappers[i]->Delete();
286         this->TextActors[i]->Delete();
287         }
288       delete [] this->TextMappers;
289       delete [] this->TextActors;
290       }
291
292     // Build scalar bar object; determine its type
293     //
294     // is this a vtkLookupTable or a subclass of vtkLookupTable 
295     // with its scale set to log
296     // NOTE: it's possible we could to without the 'lut' variable
297     // later in the code, but if the vtkLookupTableSafeDownCast operation
298     // fails for some reason, this code will break in new ways. So, the 'LUT'
299     // variable is used for this operation only
300     vtkLookupTable *LUT = vtkLookupTable::SafeDownCast( this->LookupTable );
301     int isLogTable = 0;
302     if ( LUT )
303       {
304       if ( LUT->GetScale() == VTK_SCALE_LOG10 )
305         {
306         isLogTable = 1; 
307         }
308       }
309     
310     // we hard code how many steps to display
311     vtkScalarsToColors *lut = this->LookupTable;
312     int numColors = this->MaximumNumberOfColors;
313     double *range = lut->GetRange();
314
315     int numPts = 2*(numColors + 1);
316     vtkPoints *pts = vtkPoints::New();
317     pts->SetNumberOfPoints(numPts);
318     vtkCellArray *polys = vtkCellArray::New();
319     polys->Allocate(polys->EstimateSize(numColors,4));
320     vtkUnsignedCharArray *colors = vtkUnsignedCharArray::New();
321     colors->SetNumberOfComponents(3);
322     colors->SetNumberOfTuples(numColors);
323
324
325     // rnv begin
326     // Customization of the vtkScalarBarActor to show distribution histogram.
327     bool distrVisibility =  (numColors == (int)this->myNbValues.size());
328     vtkPoints *distrPts = 0;
329     vtkCellArray *distrPolys = 0;
330     vtkUnsignedCharArray *distColors = 0;
331     int numDistrPts = 0, numPositiveVal=0, maxValue=0;
332     if(!distrVisibility)
333       vtkDebugMacro(<<" Distribution invisible, because numColors == this->myNbValues.size()");
334
335     if ( distrVisibility && GetDistributionVisibility() ) {
336       for ( i = 0 ; i < (int)myNbValues.size(); i++ ) {
337         if ( myNbValues[i] ) {
338           numPositiveVal++;
339           maxValue = std::max(maxValue,myNbValues[i]);
340         }
341       }
342       numDistrPts = 4*(numPositiveVal);
343       distrPts = vtkPoints::New();
344       distrPolys = vtkCellArray::New();
345       distrPts->SetNumberOfPoints(numDistrPts);
346       distrPolys->Allocate(distrPolys->EstimateSize(numPositiveVal,4));
347       this->myDistribution->Initialize();
348       this->myDistribution->SetPoints(distrPts);
349       this->myDistribution->SetPolys(distrPolys);
350       distrPts->Delete();
351       distrPolys->Delete();
352       if ( myDistributionColoringType == SMESH_MULTICOLOR_TYPE ) {
353         distColors = vtkUnsignedCharArray::New();
354         distColors->SetNumberOfComponents(3);
355         distColors->SetNumberOfTuples(numPositiveVal);
356         this->myDistribution->GetCellData()->SetScalars(distColors);
357         distColors->Delete();
358       } else if( myDistributionColoringType == SMESH_MONOCOLOR_TYPE ){
359         this->myDistribution->GetCellData()->SetScalars(NULL);
360       }
361     } else {
362       myDistribution->Reset();
363     }
364     // rnv end
365
366     this->ScalarBarActor->SetProperty(this->GetProperty());
367     this->ScalarBar->Initialize();
368     this->ScalarBar->SetPoints(pts);
369     this->ScalarBar->SetPolys(polys);
370     this->ScalarBar->GetCellData()->SetScalars(colors);
371     pts->Delete(); polys->Delete(); colors->Delete();
372
373     // get the viewport size in display coordinates
374     int *barOrigin, barWidth, barHeight, distrHeight;
375     barOrigin = this->PositionCoordinate->GetComputedViewportValue(viewport);
376     size[0] = 
377       this->Position2Coordinate->GetComputedViewportValue(viewport)[0] -
378       barOrigin[0];
379     size[1] = 
380       this->Position2Coordinate->GetComputedViewportValue(viewport)[1] -
381       barOrigin[1];
382     this->LastOrigin[0] = barOrigin[0];
383     this->LastOrigin[1] = barOrigin[1];
384     this->LastSize[0] = size[0];
385     this->LastSize[1] = size[1];
386     
387     // Update all the composing objects
388     this->TitleActor->SetProperty(this->GetProperty());
389     this->TitleMapper->SetInput(this->Title);
390     if (this->TitleTextProperty->GetMTime() > this->BuildTime)
391       {
392       // Shallow copy here so that the size of the title prop is not affected
393       // by the automatic adjustment of its text mapper's size (i.e. its
394       // mapper's text property is identical except for the font size
395       // which will be modified later). This allows text actors to
396       // share the same text property, and in that case specifically allows
397       // the title and label text prop to be the same.
398       this->TitleMapper->GetTextProperty()->ShallowCopy(this->TitleTextProperty);
399       this->TitleMapper->GetTextProperty()->SetJustificationToCentered();
400       }
401     
402     // find the best size for the title font
403     int titleSize[2];
404     this->SizeTitle(titleSize, size, viewport);
405     
406     // find the best size for the ticks
407     int labelSize[2];
408     this->AllocateAndSizeLabels(labelSize, size, viewport,range);
409     this->NumberOfLabelsBuilt = this->NumberOfLabels;
410     
411     // generate points
412     double x[3]; x[2] = 0.0;
413     double delta, itemH, shrink;
414     if ( this->Orientation == VTK_ORIENT_VERTICAL ) {
415       // rnv begin
416       // Customization of the vtkScalarBarActor to show distribution histogram.
417       double delimeter=0.0;
418       if(GetDistributionVisibility() && distrVisibility) {
419         delimeter=0.01*size[0]; //1 % from horizontal size of the full presentation size.
420         barWidth = size[0] - 4 - labelSize[0];
421         distrHeight = barWidth/2;
422       } else {
423         barWidth = size[0] - 4 - labelSize[0];
424         distrHeight = 0;
425       }
426
427       barHeight = (int)(0.86*size[1]);
428       delta=(double)barHeight/numColors;
429       
430       for ( i=0; i<numPts/2; i++ ) {
431         x[0] = distrHeight+delimeter/2.0;
432         x[1] = i*delta;
433         pts->SetPoint(2*i,x);
434         x[0] = barWidth;
435         pts->SetPoint(2*i+1,x);
436       }
437
438       if(GetDistributionVisibility() && distrVisibility) {
439         // Distribution points 
440         shrink = delta*SHRINK_COEF;
441         vtkIdType distPtsId=0;
442         vtkIdType distPtsIds[4];
443         for(i=0; i<numColors; i++) {
444           if(myNbValues[i]) {
445             itemH = distrHeight*((double)myNbValues[i]/maxValue);
446             
447             if(distrHeight == itemH) 
448               itemH = itemH - delimeter/2;
449
450             x[1] = i*delta+shrink;
451
452             // first point of polygon (quadrangle)
453             x[0] = 0; 
454             distPtsIds[0] = distPtsId;
455             distrPts->SetPoint(distPtsId++,x);
456
457             // second point of polygon (quadrangle)
458             x[0] = itemH;
459             distPtsIds[1] = distPtsId;
460             distrPts->SetPoint(distPtsId++,x);
461
462             x[1] = i*delta+delta-shrink;
463
464             // third point of polygon (quadrangle)
465             x[0] = 0; 
466             distPtsIds[3] = distPtsId;
467             distrPts->SetPoint(distPtsId++,x);
468
469             // fourth point of polygon (quadrangle)
470             x[0] = itemH;
471             distPtsIds[2] = distPtsId;
472             distrPts->SetPoint(distPtsId++,x);
473
474             //Inser Quadrangle
475             distrPolys->InsertNextCell(4,distPtsIds);
476           }
477         }
478       }    
479     }
480     // rnv end
481     else {
482       barWidth = size[0];
483       
484       // rnv begin
485       // Customization of the vtkScalarBarActor to show distribution histogram.
486       double coef1, delimeter=0.0;
487       if(GetDistributionVisibility() && distrVisibility) {
488         coef1=0.62;
489         distrHeight = (int)((coef1/2)*size[1]);
490         //delimeter between distribution diagram and scalar bar 
491         delimeter=0.02*size[1];
492       }
493       else {
494         coef1=0.4;
495         barHeight = (int)(coef1*size[1]);
496         distrHeight = 0;
497       }
498       
499       barHeight = (int)(coef1*size[1]);
500       
501       delta=(double)barWidth/numColors;
502       for (i=0; i<numPts/2; i++) {
503         x[0] = i*delta;
504         x[1] = barHeight;
505         pts->SetPoint(2*i,x);                        
506         x[1] = distrHeight + delimeter;
507         pts->SetPoint(2*i+1,x);
508       }
509       
510       if(GetDistributionVisibility() && distrVisibility) {
511         // Distribution points 
512         shrink = delta*SHRINK_COEF;
513         vtkIdType distPtsId=0;
514         vtkIdType distPtsIds[4];
515         for(i=0; i<numColors; i++) {
516           if(myNbValues[i]) {
517             itemH = distrHeight*((double)myNbValues[i]/maxValue);
518             
519             // first point of polygon (quadrangle)
520             x[0] = i*delta+shrink; 
521             x[1] = 0;
522             distPtsIds[0] = distPtsId;
523             distrPts->SetPoint(distPtsId++,x);
524             
525             // second point of polygon (quadrangle)
526             x[0] = i*delta+shrink; 
527             x[1] = itemH;
528             distPtsIds[3] = distPtsId;
529             distrPts->SetPoint(distPtsId++,x);
530             
531             // third point of polygon (quadrangle)
532             x[0] = i*delta+delta-shrink; 
533             x[1] = 0;
534             distPtsIds[1] = distPtsId;
535             distrPts->SetPoint(distPtsId++,x);
536             
537             // fourth point of polygon (quadrangle)
538             x[0] = i*delta+delta-shrink; 
539             x[1] = itemH;
540             distPtsIds[2] = distPtsId;
541             distrPts->SetPoint(distPtsId++,x);
542             
543             // Add polygon into poly data
544             distrPolys->InsertNextCell(4,distPtsIds);
545           }
546         } 
547       }
548       // rnv end
549     }
550     
551     //polygons & cell colors
552     unsigned char *rgba, *rgb;
553     vtkIdType ptIds[4], dcCount=0;
554     for (i=0; i<numColors; i++)
555       {
556       ptIds[0] = 2*i;
557       ptIds[1] = ptIds[0] + 1;
558       ptIds[2] = ptIds[1] + 2;
559       ptIds[3] = ptIds[0] + 2;
560       polys->InsertNextCell(4,ptIds);
561
562       if ( isLogTable )
563         {
564         double rgbval = log10(range[0]) + 
565           i*(log10(range[1])-log10(range[0]))/(numColors -1);
566         rgba = lut->MapValue(pow(10.0,rgbval));
567         }
568       else
569         {
570         rgba = lut->MapValue(range[0] + (range[1] - range[0])*
571                              ((double)i /(numColors-1.0)));
572         }
573
574       rgb = colors->GetPointer(3*i); //write into array directly
575       rgb[0] = rgba[0];
576       rgb[1] = rgba[1];
577       rgb[2] = rgba[2];
578       
579       // rnv begin
580       // Customization of the vtkScalarBarActor to show distribution histogram.
581       if(myDistributionColoringType == SMESH_MULTICOLOR_TYPE && GetDistributionVisibility() && distrVisibility)
582         {
583           rgb = distColors->GetPointer(3*dcCount); //write into array directly
584           rgb[0] = rgba[0];
585           rgb[1] = rgba[1];
586           rgb[2] = rgba[2];
587           dcCount++;
588         }
589       }
590
591     // Now position everything properly
592     //
593     double val;
594     if (this->Orientation == VTK_ORIENT_VERTICAL)
595       {
596       int sizeTextData[2];
597       
598       // center the title
599       this->TitleActor->SetPosition(size[0]/2, 0.9*size[1]);
600       
601       for (i=0; i < this->NumberOfLabels; i++)
602         {
603         if (this->NumberOfLabels > 1)
604           {
605           val = (double)i/(this->NumberOfLabels-1) *barHeight;
606           }
607         else 
608           {
609           val = 0.5*barHeight;
610           }
611         this->TextMappers[i]->GetSize(viewport,sizeTextData);
612         this->TextMappers[i]->GetTextProperty()->SetJustificationToLeft();
613         this->TextActors[i]->SetPosition(barWidth+3,
614                                          val - sizeTextData[1]/2);
615         }
616       }
617     else
618       {
619       this->TitleActor->SetPosition(size[0]/2, 
620                                     barHeight + labelSize[1] + 0.1*size[1]);
621       for (i=0; i < this->NumberOfLabels; i++)
622         {
623         this->TextMappers[i]->GetTextProperty()->SetJustificationToCentered();
624         if (this->NumberOfLabels > 1)
625           {
626           val = (double)i/(this->NumberOfLabels-1) * barWidth;
627           }
628         else
629           {
630           val = 0.5*barWidth;
631           }
632         this->TextActors[i]->SetPosition(val, barHeight + 0.05*size[1]);
633         }
634       }
635
636     this->BuildTime.Modified();
637     }
638
639   // Everything is built, just have to render
640   if (this->Title != NULL)
641     {
642     renderedSomething += this->TitleActor->RenderOpaqueGeometry(viewport);
643     }
644   this->ScalarBarActor->RenderOpaqueGeometry(viewport);
645   this->myDistributionActor->RenderOpaqueGeometry(viewport);
646   for (i=0; i<this->NumberOfLabels; i++)
647     {
648     renderedSomething += this->TextActors[i]->RenderOpaqueGeometry(viewport);
649     }
650
651   renderedSomething = (renderedSomething > 0)?(1):(0);
652
653   return renderedSomething;
654 }
655
656 //----------------------------------------------------------------------------
657 void SMESH_ScalarBarActor::PrintSelf(ostream& os, vtkIndent indent)
658 {
659   this->Superclass::PrintSelf(os,indent);
660
661   if ( this->LookupTable )
662     {
663     os << indent << "Lookup Table:\n";
664     this->LookupTable->PrintSelf(os,indent.GetNextIndent());
665     }
666   else
667     {
668     os << indent << "Lookup Table: (none)\n";
669     }
670
671   if (this->TitleTextProperty)
672     {
673     os << indent << "Title Text Property:\n";
674     this->TitleTextProperty->PrintSelf(os,indent.GetNextIndent());
675     }
676   else
677     {
678     os << indent << "Title Text Property: (none)\n";
679     }
680
681   if (this->LabelTextProperty)
682     {
683     os << indent << "Label Text Property:\n";
684     this->LabelTextProperty->PrintSelf(os,indent.GetNextIndent());
685     }
686   else
687     {
688     os << indent << "Label Text Property: (none)\n";
689     }
690
691   os << indent << "Title: " << (this->Title ? this->Title : "(none)") << "\n";
692   os << indent << "Maximum Number Of Colors: " 
693      << this->MaximumNumberOfColors << "\n";
694   os << indent << "Number Of Labels: " << this->NumberOfLabels << "\n";
695   os << indent << "Number Of Labels Built: " << this->NumberOfLabelsBuilt << "\n";
696
697   os << indent << "Orientation: ";
698   if ( this->Orientation == VTK_ORIENT_HORIZONTAL )
699     {
700     os << "Horizontal\n";
701     }
702   else
703     {
704     os << "Vertical\n";
705     }
706
707   os << indent << "Label Format: " << this->LabelFormat << "\n";
708 }
709
710 //----------------------------------------------------------------------------
711 void SMESH_ScalarBarActor::ShallowCopy(vtkProp *prop)
712 {
713   SMESH_ScalarBarActor *a = SMESH_ScalarBarActor::SafeDownCast(prop);
714   if ( a != NULL )
715     {
716     this->SetPosition2(a->GetPosition2());
717     this->SetLookupTable(a->GetLookupTable());
718     this->SetMaximumNumberOfColors(a->GetMaximumNumberOfColors());
719     this->SetOrientation(a->GetOrientation());
720     this->SetLabelTextProperty(a->GetLabelTextProperty());
721     this->SetTitleTextProperty(a->GetTitleTextProperty());
722     this->SetLabelFormat(a->GetLabelFormat());
723     this->SetTitle(a->GetTitle());
724     this->GetPositionCoordinate()->SetCoordinateSystem(
725       a->GetPositionCoordinate()->GetCoordinateSystem());    
726     this->GetPositionCoordinate()->SetValue(
727       a->GetPositionCoordinate()->GetValue());
728     this->GetPosition2Coordinate()->SetCoordinateSystem(
729       a->GetPosition2Coordinate()->GetCoordinateSystem());    
730     this->GetPosition2Coordinate()->SetValue(
731       a->GetPosition2Coordinate()->GetValue());
732     }
733
734   // Now do superclass
735   this->vtkActor2D::ShallowCopy(prop);
736 }
737
738 //----------------------------------------------------------------------------
739 void SMESH_ScalarBarActor::AllocateAndSizeLabels(int *labelSize, 
740                                               int *size,
741                                               vtkViewport *viewport,
742                                               double *range)
743 {
744   labelSize[0] = labelSize[1] = 0;
745
746   this->TextMappers = new vtkTextMapper * [this->NumberOfLabels];
747   this->TextActors = new vtkActor2D * [this->NumberOfLabels];
748
749   char string[512];
750
751   double val;
752   int i;
753   
754   // TODO: this should be optimized, maybe by keeping a list of
755   // allocated mappers, in order to avoid creation/destruction of
756   // their underlying text properties (i.e. each time a mapper is
757   // created, text properties are created and shallow-assigned a font size
758   // which value might be "far" from the target font size).
759
760   // is this a vtkLookupTable or a subclass of vtkLookupTable 
761   // with its scale set to log
762   vtkLookupTable *LUT = vtkLookupTable::SafeDownCast( this->LookupTable );
763   int isLogTable = 0;
764   if ( LUT )
765     {
766     if ( LUT->GetScale() == VTK_SCALE_LOG10 )
767       {
768       isLogTable = 1; 
769       }
770     }
771
772   for (i=0; i < this->NumberOfLabels; i++)
773     {
774     this->TextMappers[i] = vtkTextMapper::New();
775
776     if ( isLogTable )
777       {
778       double lval;
779       if (this->NumberOfLabels > 1)
780         {
781         lval = log10(range[0]) + (double)i/(this->NumberOfLabels-1) *
782           (log10(range[1])-log10(range[0]));
783         }
784       else
785         {
786         lval = log10(range[0]) + 0.5*(log10(range[1])-log10(range[0]));
787         }
788       val = pow(10.0,lval);
789       }
790     else
791       {
792       if (this->NumberOfLabels > 1)
793         {
794         val = range[0] + 
795           (double)i/(this->NumberOfLabels-1) * (range[1]-range[0]);
796         }
797       else
798         {
799         val = range[0] + 0.5*(range[1]-range[0]);
800         }
801       }
802
803     sprintf(string, this->LabelFormat, val);
804     this->TextMappers[i]->SetInput(string);
805
806     // Shallow copy here so that the size of the label prop is not affected
807     // by the automatic adjustment of its text mapper's size (i.e. its
808     // mapper's text property is identical except for the font size
809     // which will be modified later). This allows text actors to
810     // share the same text property, and in that case specifically allows
811     // the title and label text prop to be the same.
812     this->TextMappers[i]->GetTextProperty()->ShallowCopy(
813       this->LabelTextProperty);
814
815     this->TextActors[i] = vtkActor2D::New();
816     this->TextActors[i]->SetMapper(this->TextMappers[i]);
817     this->TextActors[i]->SetProperty(this->GetProperty());
818     this->TextActors[i]->GetPositionCoordinate()->
819       SetReferenceCoordinate(this->PositionCoordinate);
820     }
821
822   if (this->NumberOfLabels)
823     {
824     int targetWidth, targetHeight;
825     // rnv begin
826     // Customization of the vtkScalarBarActor to show distribution histogram.
827     bool distrVisibility = ( this->MaximumNumberOfColors == (int) this->myNbValues.size() );
828     double coef;
829     if( GetDistributionVisibility() && distrVisibility )
830       if(this->Orientation == VTK_ORIENT_VERTICAL)
831         coef = 0.4;
832       else 
833         coef = 0.18;
834     else 
835       if(this->Orientation == VTK_ORIENT_VERTICAL)
836         coef = 0.6;
837       else 
838         coef=0.25;
839
840
841     if ( this->Orientation == VTK_ORIENT_VERTICAL )
842       {
843       targetWidth = (int)(coef*size[0]);
844       targetHeight = (int)(0.86*size[1]/this->NumberOfLabels);
845       }
846     else
847       {
848       targetWidth = (int)(size[0]*0.8/this->NumberOfLabels);
849       targetHeight = (int)(coef*size[1]);
850       }
851     // rnv end
852     
853     vtkTextMapper::SetMultipleConstrainedFontSize(viewport, 
854                                                   targetWidth, 
855                                                   targetHeight,
856                                                   this->TextMappers,
857                                                   this->NumberOfLabels,
858                                                   labelSize);
859     }
860 }
861
862 //----------------------------------------------------------------------------
863 void SMESH_ScalarBarActor::SizeTitle(int *titleSize,
864                                      int *size,
865                                      vtkViewport *viewport)
866 {
867   titleSize[0] = titleSize[1] = 0;
868
869   if (this->Title == NULL || !strlen(this->Title))
870   {
871     return;
872   }
873
874   int targetWidth, targetHeight;
875
876   targetWidth = size[0];
877   // rnv begin
878   // Customization of the vtkScalarBarActor to show distribution histogram.
879   bool distrVisibility = ( this->MaximumNumberOfColors == (int) this->myNbValues.size() );
880   double coef;
881   if ( GetDistributionVisibility() && distrVisibility )
882     coef=0.18;
883   else
884     coef=0.25;
885
886   if ( this->Orientation == VTK_ORIENT_VERTICAL )
887   {
888     targetHeight = (int)(0.1*size[1]);
889   }
890   else
891   {
892     targetHeight = (int)(coef*size[1]);
893   }
894
895   this->TitleMapper->SetConstrainedFontSize(viewport, targetWidth, targetHeight);
896
897   this->TitleMapper->GetSize(viewport, titleSize);
898 }
899
900
901 /*--------------------------------------------------------------------------*/
902 void SMESH_ScalarBarActor::SetDistributionVisibility(int flag) {
903   myDistributionActor->SetVisibility(flag);
904   Modified();
905 }
906
907
908 /*--------------------------------------------------------------------------*/
909 int SMESH_ScalarBarActor::GetDistributionVisibility() {
910   return myDistributionActor->GetVisibility();
911 }
912
913
914 void SMESH_ScalarBarActor::SetDistribution(std::vector<int> theNbValues) {
915   myNbValues = theNbValues;
916
917
918
919 void SMESH_ScalarBarActor::SetDistributionColor (double rgb[3]) {
920   myDistributionActor->GetProperty()->SetColor(rgb);
921   Modified();
922 }
923
924 void SMESH_ScalarBarActor::GetDistributionColor (double rgb[3]) {
925   myDistributionActor->GetProperty()->GetColor(rgb);
926 }
927
928 void SMESH_ScalarBarActor::SetTitleOnlyVisibility( bool theTitleOnlyVisibility) {
929   myTitleOnlyVisibility = theTitleOnlyVisibility;
930 }
931
932 bool SMESH_ScalarBarActor::GetTitleOnlyVisibility() {
933   return myTitleOnlyVisibility;
934 }