Salome HOME
Merge branch 'V8_3_BR' into ngr/python3_dev
[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 &&
582            GetDistributionVisibility() &&
583            distrVisibility &&
584            myNbValues[i] > 0 )
585       {
586         rgb = distColors->GetPointer(3*dcCount); //write into array directly
587         rgb[0] = rgba[0];
588         rgb[1] = rgba[1];
589         rgb[2] = rgba[2];
590         dcCount++;
591       }
592     }
593
594     // Now position everything properly
595     //
596     double val;
597     if (this->Orientation == VTK_ORIENT_VERTICAL)
598       {
599       int sizeTextData[2];
600       
601       // center the title
602       this->TitleActor->SetPosition(size[0]/2, 0.9*size[1]);
603       
604       for (i=0; i < this->NumberOfLabels; i++)
605         {
606         if (this->NumberOfLabels > 1)
607           {
608           val = (double)i/(this->NumberOfLabels-1) *barHeight;
609           }
610         else 
611           {
612           val = 0.5*barHeight;
613           }
614         this->TextMappers[i]->GetSize(viewport,sizeTextData);
615         this->TextMappers[i]->GetTextProperty()->SetJustificationToLeft();
616         this->TextActors[i]->SetPosition(barWidth+3,
617                                          val - sizeTextData[1]/2);
618         }
619       }
620     else
621       {
622       this->TitleActor->SetPosition(size[0]/2, 
623                                     barHeight + labelSize[1] + 0.1*size[1]);
624       for (i=0; i < this->NumberOfLabels; i++)
625         {
626         this->TextMappers[i]->GetTextProperty()->SetJustificationToCentered();
627         if (this->NumberOfLabels > 1)
628           {
629           val = (double)i/(this->NumberOfLabels-1) * barWidth;
630           }
631         else
632           {
633           val = 0.5*barWidth;
634           }
635         this->TextActors[i]->SetPosition(val, barHeight + 0.05*size[1]);
636         }
637       }
638
639     this->BuildTime.Modified();
640     }
641
642   // Everything is built, just have to render
643   if (this->Title != NULL)
644     {
645     renderedSomething += this->TitleActor->RenderOpaqueGeometry(viewport);
646     }
647   this->ScalarBarActor->RenderOpaqueGeometry(viewport);
648   this->myDistributionActor->RenderOpaqueGeometry(viewport);
649   for (i=0; i<this->NumberOfLabels; i++)
650     {
651     renderedSomething += this->TextActors[i]->RenderOpaqueGeometry(viewport);
652     }
653
654   renderedSomething = (renderedSomething > 0)?(1):(0);
655
656   return renderedSomething;
657 }
658
659 //----------------------------------------------------------------------------
660 void SMESH_ScalarBarActor::PrintSelf(ostream& os, vtkIndent indent)
661 {
662   this->Superclass::PrintSelf(os,indent);
663
664   if ( this->LookupTable )
665     {
666     os << indent << "Lookup Table:\n";
667     this->LookupTable->PrintSelf(os,indent.GetNextIndent());
668     }
669   else
670     {
671     os << indent << "Lookup Table: (none)\n";
672     }
673
674   if (this->TitleTextProperty)
675     {
676     os << indent << "Title Text Property:\n";
677     this->TitleTextProperty->PrintSelf(os,indent.GetNextIndent());
678     }
679   else
680     {
681     os << indent << "Title Text Property: (none)\n";
682     }
683
684   if (this->LabelTextProperty)
685     {
686     os << indent << "Label Text Property:\n";
687     this->LabelTextProperty->PrintSelf(os,indent.GetNextIndent());
688     }
689   else
690     {
691     os << indent << "Label Text Property: (none)\n";
692     }
693
694   os << indent << "Title: " << (this->Title ? this->Title : "(none)") << "\n";
695   os << indent << "Maximum Number Of Colors: " 
696      << this->MaximumNumberOfColors << "\n";
697   os << indent << "Number Of Labels: " << this->NumberOfLabels << "\n";
698   os << indent << "Number Of Labels Built: " << this->NumberOfLabelsBuilt << "\n";
699
700   os << indent << "Orientation: ";
701   if ( this->Orientation == VTK_ORIENT_HORIZONTAL )
702     {
703     os << "Horizontal\n";
704     }
705   else
706     {
707     os << "Vertical\n";
708     }
709
710   os << indent << "Label Format: " << this->LabelFormat << "\n";
711 }
712
713 //----------------------------------------------------------------------------
714 void SMESH_ScalarBarActor::ShallowCopy(vtkProp *prop)
715 {
716   SMESH_ScalarBarActor *a = SMESH_ScalarBarActor::SafeDownCast(prop);
717   if ( a != NULL )
718     {
719     this->SetPosition2(a->GetPosition2());
720     this->SetLookupTable(a->GetLookupTable());
721     this->SetMaximumNumberOfColors(a->GetMaximumNumberOfColors());
722     this->SetOrientation(a->GetOrientation());
723     this->SetLabelTextProperty(a->GetLabelTextProperty());
724     this->SetTitleTextProperty(a->GetTitleTextProperty());
725     this->SetLabelFormat(a->GetLabelFormat());
726     this->SetTitle(a->GetTitle());
727     this->GetPositionCoordinate()->SetCoordinateSystem(
728       a->GetPositionCoordinate()->GetCoordinateSystem());    
729     this->GetPositionCoordinate()->SetValue(
730       a->GetPositionCoordinate()->GetValue());
731     this->GetPosition2Coordinate()->SetCoordinateSystem(
732       a->GetPosition2Coordinate()->GetCoordinateSystem());    
733     this->GetPosition2Coordinate()->SetValue(
734       a->GetPosition2Coordinate()->GetValue());
735     }
736
737   // Now do superclass
738   this->vtkActor2D::ShallowCopy(prop);
739 }
740
741 //----------------------------------------------------------------------------
742 void SMESH_ScalarBarActor::AllocateAndSizeLabels(int *labelSize, 
743                                               int *size,
744                                               vtkViewport *viewport,
745                                               double *range)
746 {
747   labelSize[0] = labelSize[1] = 0;
748
749   this->TextMappers = new vtkTextMapper * [this->NumberOfLabels];
750   this->TextActors = new vtkActor2D * [this->NumberOfLabels];
751
752   char string[512];
753
754   double val;
755   int i;
756   
757   // TODO: this should be optimized, maybe by keeping a list of
758   // allocated mappers, in order to avoid creation/destruction of
759   // their underlying text properties (i.e. each time a mapper is
760   // created, text properties are created and shallow-assigned a font size
761   // which value might be "far" from the target font size).
762
763   // is this a vtkLookupTable or a subclass of vtkLookupTable 
764   // with its scale set to log
765   vtkLookupTable *LUT = vtkLookupTable::SafeDownCast( this->LookupTable );
766   int isLogTable = 0;
767   if ( LUT )
768     {
769     if ( LUT->GetScale() == VTK_SCALE_LOG10 )
770       {
771       isLogTable = 1; 
772       }
773     }
774
775   for (i=0; i < this->NumberOfLabels; i++)
776     {
777     this->TextMappers[i] = vtkTextMapper::New();
778
779     if ( isLogTable )
780       {
781       double lval;
782       if (this->NumberOfLabels > 1)
783         {
784         lval = log10(range[0]) + (double)i/(this->NumberOfLabels-1) *
785           (log10(range[1])-log10(range[0]));
786         }
787       else
788         {
789         lval = log10(range[0]) + 0.5*(log10(range[1])-log10(range[0]));
790         }
791       val = pow(10.0,lval);
792       }
793     else
794       {
795       if (this->NumberOfLabels > 1)
796         {
797         val = range[0] + 
798           (double)i/(this->NumberOfLabels-1) * (range[1]-range[0]);
799         }
800       else
801         {
802         val = range[0] + 0.5*(range[1]-range[0]);
803         }
804       }
805
806     sprintf(string, this->LabelFormat, val);
807     this->TextMappers[i]->SetInput(string);
808
809     // Shallow copy here so that the size of the label prop is not affected
810     // by the automatic adjustment of its text mapper's size (i.e. its
811     // mapper's text property is identical except for the font size
812     // which will be modified later). This allows text actors to
813     // share the same text property, and in that case specifically allows
814     // the title and label text prop to be the same.
815     this->TextMappers[i]->GetTextProperty()->ShallowCopy(
816       this->LabelTextProperty);
817
818     this->TextActors[i] = vtkActor2D::New();
819     this->TextActors[i]->SetMapper(this->TextMappers[i]);
820     this->TextActors[i]->SetProperty(this->GetProperty());
821     this->TextActors[i]->GetPositionCoordinate()->
822       SetReferenceCoordinate(this->PositionCoordinate);
823     }
824
825   if (this->NumberOfLabels)
826     {
827     int targetWidth, targetHeight;
828     // rnv begin
829     // Customization of the vtkScalarBarActor to show distribution histogram.
830     bool distrVisibility = ( this->MaximumNumberOfColors == (int) this->myNbValues.size() );
831     double coef;
832     if( GetDistributionVisibility() && distrVisibility )
833       if(this->Orientation == VTK_ORIENT_VERTICAL)
834         coef = 0.4;
835       else 
836         coef = 0.18;
837     else 
838       if(this->Orientation == VTK_ORIENT_VERTICAL)
839         coef = 0.6;
840       else 
841         coef=0.25;
842
843
844     if ( this->Orientation == VTK_ORIENT_VERTICAL )
845       {
846       targetWidth = (int)(coef*size[0]);
847       targetHeight = (int)(0.86*size[1]/this->NumberOfLabels);
848       }
849     else
850       {
851       targetWidth = (int)(size[0]*0.8/this->NumberOfLabels);
852       targetHeight = (int)(coef*size[1]);
853       }
854     // rnv end
855     
856     vtkTextMapper::SetMultipleConstrainedFontSize(viewport, 
857                                                   targetWidth, 
858                                                   targetHeight,
859                                                   this->TextMappers,
860                                                   this->NumberOfLabels,
861                                                   labelSize);
862     }
863 }
864
865 //----------------------------------------------------------------------------
866 void SMESH_ScalarBarActor::SizeTitle(int *titleSize,
867                                      int *size,
868                                      vtkViewport *viewport)
869 {
870   titleSize[0] = titleSize[1] = 0;
871
872   if (this->Title == NULL || !strlen(this->Title))
873   {
874     return;
875   }
876
877   int targetWidth, targetHeight;
878
879   targetWidth = size[0];
880   // rnv begin
881   // Customization of the vtkScalarBarActor to show distribution histogram.
882   bool distrVisibility = ( this->MaximumNumberOfColors == (int) this->myNbValues.size() );
883   double coef;
884   if ( GetDistributionVisibility() && distrVisibility )
885     coef=0.18;
886   else
887     coef=0.25;
888
889   if ( this->Orientation == VTK_ORIENT_VERTICAL )
890   {
891     targetHeight = (int)(0.1*size[1]);
892   }
893   else
894   {
895     targetHeight = (int)(coef*size[1]);
896   }
897
898   this->TitleMapper->SetConstrainedFontSize(viewport, targetWidth, targetHeight);
899
900   this->TitleMapper->GetSize(viewport, titleSize);
901 }
902
903
904 /*--------------------------------------------------------------------------*/
905 void SMESH_ScalarBarActor::SetDistributionVisibility(int flag) {
906   myDistributionActor->SetVisibility(flag);
907   Modified();
908 }
909
910
911 /*--------------------------------------------------------------------------*/
912 int SMESH_ScalarBarActor::GetDistributionVisibility() {
913   return myDistributionActor->GetVisibility();
914 }
915
916
917 void SMESH_ScalarBarActor::SetDistribution(std::vector<int> theNbValues) {
918   myNbValues = theNbValues;
919
920
921
922 void SMESH_ScalarBarActor::SetDistributionColor (double rgb[3]) {
923   myDistributionActor->GetProperty()->SetColor(rgb);
924   Modified();
925 }
926
927 void SMESH_ScalarBarActor::GetDistributionColor (double rgb[3]) {
928   myDistributionActor->GetProperty()->GetColor(rgb);
929 }
930
931 void SMESH_ScalarBarActor::SetTitleOnlyVisibility( bool theTitleOnlyVisibility) {
932   myTitleOnlyVisibility = theTitleOnlyVisibility;
933 }
934
935 bool SMESH_ScalarBarActor::GetTitleOnlyVisibility() {
936   return myTitleOnlyVisibility;
937 }