1 // VISU OBJECT : interactive object for VISU entities implementation
3 // Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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.
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.
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
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // File: VISU_PipeLine.hxx
24 // Author: Alexey PETROV
27 #include "VISU_ScalarBarActor.hxx"
29 #include <vtkPolyDataMapper2D.h>
30 #include <vtkCellArray.h>
31 #include <vtkCellData.h>
32 #include <vtkObjectFactory.h>
33 #include <vtkPolyData.h>
34 #include <vtkPolyDataMapper2D.h>
35 #include <vtkScalarsToColors.h>
36 #include <vtkTextMapper.h>
37 #include <vtkTextProperty.h>
38 #include <vtkViewport.h>
39 #include <vtkWindow.h>
40 #include <vtkLogLookupTable.h>
44 vtkCxxRevisionMacro(VISU_ScalarBarActor, "$Revision$");
46 vtkCxxSetObjectMacro(VISU_ScalarBarActor,LookupTable,VISU_LookupTable);
47 vtkCxxSetObjectMacro(VISU_ScalarBarActor,LabelTextProperty,vtkTextProperty);
48 vtkCxxSetObjectMacro(VISU_ScalarBarActor,TitleTextProperty,vtkTextProperty);
50 //------------------------------------------------------------------------------
51 VISU_ScalarBarActor* VISU_ScalarBarActor::New(){
52 vtkObject* ret = vtkObjectFactory::CreateInstance("VISU_ScalarBarActor");
54 return (VISU_ScalarBarActor*)ret;
55 return new VISU_ScalarBarActor;
58 VISU_ScalarBarActor::VISU_ScalarBarActor()
60 this->LookupTable = NULL;
61 this->Position2Coordinate->SetValue(0.17, 0.8);
63 this->PositionCoordinate->SetCoordinateSystemToNormalizedViewport();
64 this->PositionCoordinate->SetValue(0.82,0.1);
66 this->MaximumNumberOfColors = 64;
67 this->NumberOfLabels = 5;
68 this->NumberOfLabelsBuilt = 0;
69 this->Orientation = VTK_ORIENT_VERTICAL;
72 this->LabelTextProperty = vtkTextProperty::New();
73 this->LabelTextProperty->SetFontSize(12);
74 this->LabelTextProperty->SetBold(1);
75 this->LabelTextProperty->SetItalic(1);
76 this->LabelTextProperty->SetShadow(1);
77 this->LabelTextProperty->SetFontFamilyToArial();
79 this->TitleTextProperty = vtkTextProperty::New();
80 this->TitleTextProperty->ShallowCopy(this->LabelTextProperty);
82 this->LabelFormat = new char[8];
83 sprintf(this->LabelFormat,"%s","%-#6.3g");
85 this->TitleMapper = vtkTextMapper::New();
86 this->TitleActor = vtkActor2D::New();
87 this->TitleActor->SetMapper(this->TitleMapper);
88 this->TitleActor->GetPositionCoordinate()->
89 SetReferenceCoordinate(this->PositionCoordinate);
91 this->TextMappers = NULL;
92 this->TextActors = NULL;
94 this->ScalarBar = vtkPolyData::New();
95 this->ScalarBarMapper = vtkPolyDataMapper2D::New();
96 this->ScalarBarMapper->SetInput(this->ScalarBar);
97 this->ScalarBarActor = vtkActor2D::New();
98 this->ScalarBarActor->SetMapper(this->ScalarBarMapper);
99 this->ScalarBarActor->GetPositionCoordinate()->
100 SetReferenceCoordinate(this->PositionCoordinate);
101 this->LastOrigin[0] = 0;
102 this->LastOrigin[1] = 0;
103 this->LastSize[0] = 0;
104 this->LastSize[1] = 0;
106 this->TitleRatioWidth = 0;
107 this->LabelRatioWidth = 0;
108 this->BarRatioWidth = 0;
109 this->TitleRatioHeight = 0;
110 this->LabelRatioHeight = 0;
111 this->BarRatioHeight = 0;
114 void VISU_ScalarBarActor::ReleaseGraphicsResources(vtkWindow *win)
116 this->TitleActor->ReleaseGraphicsResources(win);
117 if (this->TextMappers != NULL )
119 for (int i=0; i < this->NumberOfLabelsBuilt; i++)
121 this->TextActors[i]->ReleaseGraphicsResources(win);
124 this->ScalarBarActor->ReleaseGraphicsResources(win);
127 VISU_ScalarBarActor::~VISU_ScalarBarActor()
129 if (this->LabelFormat)
131 delete [] this->LabelFormat;
132 this->LabelFormat = NULL;
135 this->TitleMapper->Delete();
136 this->TitleActor->Delete();
138 if (this->TextMappers != NULL )
140 for (int i=0; i < this->NumberOfLabelsBuilt; i++)
142 this->TextMappers[i]->Delete();
143 this->TextActors[i]->Delete();
145 delete [] this->TextMappers;
146 delete [] this->TextActors;
149 this->ScalarBar->Delete();
150 this->ScalarBarMapper->Delete();
151 this->ScalarBarActor->Delete();
155 delete [] this->Title;
159 this->SetLookupTable(NULL);
160 this->SetLabelTextProperty(NULL);
161 this->SetTitleTextProperty(NULL);
164 int VISU_ScalarBarActor::RenderOverlay(vtkViewport *viewport)
166 int renderedSomething = 0;
169 // Everything is built, just have to render
170 if (this->Title != NULL)
172 renderedSomething += this->TitleActor->RenderOverlay(viewport);
174 this->ScalarBarActor->RenderOverlay(viewport);
175 if( this->TextActors == NULL)
177 vtkWarningMacro(<<"Need a mapper to render a scalar bar");
178 return renderedSomething;
181 for (i=0; i<this->NumberOfLabels; i++)
183 renderedSomething += this->TextActors[i]->RenderOverlay(viewport);
186 renderedSomething = (renderedSomething > 0)?(1):(0);
188 return renderedSomething;
191 int VISU_ScalarBarActor::RenderOpaqueGeometry(vtkViewport *viewport)
193 int renderedSomething = 0;
197 if (!this->LookupTable)
199 vtkWarningMacro(<<"Need a mapper to render a scalar bar");
203 if (!this->TitleTextProperty)
205 vtkErrorMacro(<<"Need title text property to render a scalar bar");
209 if (!this->LabelTextProperty)
211 vtkErrorMacro(<<"Need label text property to render a scalar bar");
215 // Check to see whether we have to rebuild everything
216 int positionsHaveChanged = 0;
217 if (viewport->GetMTime() > this->BuildTime ||
218 (viewport->GetVTKWindow() &&
219 viewport->GetVTKWindow()->GetMTime() > this->BuildTime))
221 // if the viewport has changed we may - or may not need
222 // to rebuild, it depends on if the projected coords chage
224 barOrigin = this->PositionCoordinate->GetComputedViewportValue(viewport);
226 this->Position2Coordinate->GetComputedViewportValue(viewport)[0] -
229 this->Position2Coordinate->GetComputedViewportValue(viewport)[1] -
231 if (this->LastSize[0] != size[0] ||
232 this->LastSize[1] != size[1] ||
233 this->LastOrigin[0] != barOrigin[0] ||
234 this->LastOrigin[1] != barOrigin[1])
236 positionsHaveChanged = 1;
240 // Check to see whether we have to rebuild everything
241 if (positionsHaveChanged ||
242 this->GetMTime() > this->BuildTime ||
243 this->LookupTable->GetMTime() > this->BuildTime ||
244 this->LabelTextProperty->GetMTime() > this->BuildTime ||
245 this->TitleTextProperty->GetMTime() > this->BuildTime)
248 // Delete previously constructed objects
250 if (this->TextMappers != NULL )
252 for (i=0; i < this->NumberOfLabelsBuilt; i++)
254 this->TextMappers[i]->Delete();
255 this->TextActors[i]->Delete();
257 delete [] this->TextMappers;
258 delete [] this->TextActors;
261 // Build scalar bar object; determine its type
263 VISU_LookupTable *lut = this->LookupTable; //SALOME specific
264 int isLogTable = lut->GetScale() == VTK_SCALE_LOG10;
266 // we hard code how many steps to display
267 int numColors = this->MaximumNumberOfColors;
268 vtkFloatingPointType *range = lut->GetRange();
270 int numPts = 2*(numColors + 1);
271 vtkPoints *pts = vtkPoints::New();
272 pts->SetNumberOfPoints(numPts);
273 vtkCellArray *polys = vtkCellArray::New();
274 polys->Allocate(polys->EstimateSize(numColors,4));
275 vtkUnsignedCharArray *colors = vtkUnsignedCharArray::New();
276 colors->SetNumberOfComponents(3);
277 colors->SetNumberOfTuples(numColors);
279 this->ScalarBarActor->SetProperty(this->GetProperty());
280 this->ScalarBar->Initialize();
281 this->ScalarBar->SetPoints(pts);
282 this->ScalarBar->SetPolys(polys);
283 this->ScalarBar->GetCellData()->SetScalars(colors);
284 pts->Delete(); polys->Delete(); colors->Delete();
286 // get the viewport size in display coordinates
287 int *barOrigin, barWidth, barHeight;
288 barOrigin = this->PositionCoordinate->GetComputedViewportValue(viewport);
290 this->Position2Coordinate->GetComputedViewportValue(viewport)[0] -
293 this->Position2Coordinate->GetComputedViewportValue(viewport)[1] -
295 this->LastOrigin[0] = barOrigin[0];
296 this->LastOrigin[1] = barOrigin[1];
297 this->LastSize[0] = size[0];
298 this->LastSize[1] = size[1];
300 // Update all the composing objects
301 this->TitleActor->SetProperty(this->GetProperty());
302 this->TitleMapper->SetInput(this->Title);
303 if (this->TitleTextProperty->GetMTime() > this->BuildTime)
305 // Shallow copy here so that the size of the title prop is not affected
306 // by the automatic adjustment of its text mapper's size (i.e. its
307 // mapper's text property is identical except for the font size
308 // which will be modified later). This allows text actors to
309 // share the same text property, and in that case specifically allows
310 // the title and label text prop to be the same.
311 this->TitleMapper->GetTextProperty()->ShallowCopy(this->TitleTextProperty);
312 this->TitleMapper->GetTextProperty()->SetJustificationToCentered();
315 // find the best size for the title font
317 this->SizeTitle(titleSize, size, viewport);
319 // find the best size for the ticks
321 this->AllocateAndSizeLabels(labelSize, size, viewport, range);
322 this->NumberOfLabelsBuilt = this->NumberOfLabels;
324 this->SizeBar(barWidth, barHeight, size, viewport, range);
327 vtkFloatingPointType x[3]; x[2] = 0.0;
328 vtkFloatingPointType delta, val;
329 if ( this->Orientation == VTK_ORIENT_VERTICAL )
331 delta=(vtkFloatingPointType)barHeight/numColors;
332 for (i=0; i<numPts/2; i++)
336 pts->SetPoint(2*i,x);
338 pts->SetPoint(2*i+1,x);
343 delta=(vtkFloatingPointType)barWidth/numColors;
344 for (i=0; i<numPts/2; i++)
348 pts->SetPoint(2*i,x);
350 pts->SetPoint(2*i+1,x);
354 //polygons & cell colors
355 unsigned char *rgba, *rgb;
357 for (i=0; i<numColors; i++)
360 ptIds[1] = ptIds[0] + 1;
361 ptIds[2] = ptIds[1] + 2;
362 ptIds[3] = ptIds[0] + 2;
363 polys->InsertNextCell(4,ptIds);
365 if ( isLogTable ){ //SALOME specific
366 vtkFloatingPointType rgbval = log10(range[0]) +
367 i*(log10(range[1])-log10(range[0]))/(numColors -1);
368 rgba = lut->MapValue(rgbval);
370 rgba = lut->MapValue(range[0] + (range[1] - range[0])*
371 ((vtkFloatingPointType)i /(numColors-1.0)));
374 rgb = colors->GetPointer(3*i); //write into array directly
380 // Now position everything properly
382 if (this->Orientation == VTK_ORIENT_VERTICAL)
387 this->TitleActor->SetPosition(size[0]/2, 0.9*size[1]);
389 for (i=0; i < this->NumberOfLabels; i++)
391 val = (vtkFloatingPointType)i/(this->NumberOfLabels-1) *barHeight;
392 this->TextMappers[i]->GetSize(viewport,sizeTextData);
393 this->TextMappers[i]->GetTextProperty()->SetJustificationToLeft();
394 this->TextActors[i]->SetPosition(barWidth+3,
395 val - sizeTextData[1]/2);
400 this->TitleActor->SetPosition(size[0]/2,
401 barHeight + labelSize[1] + 0.1*size[1]);
402 for (i=0; i < this->NumberOfLabels; i++)
404 this->TextMappers[i]->GetTextProperty()->SetJustificationToCentered();
405 val = (vtkFloatingPointType)i/(this->NumberOfLabels-1) * barWidth;
406 this->TextActors[i]->SetPosition(val, barHeight + 0.05*size[1]);
410 this->BuildTime.Modified();
413 // Everything is built, just have to render
414 if (this->Title != NULL)
416 renderedSomething += this->TitleActor->RenderOpaqueGeometry(viewport);
418 this->ScalarBarActor->RenderOpaqueGeometry(viewport);
419 for (i=0; i<this->NumberOfLabels; i++)
421 renderedSomething += this->TextActors[i]->RenderOpaqueGeometry(viewport);
424 renderedSomething = (renderedSomething > 0)?(1):(0);
426 return renderedSomething;
429 void VISU_ScalarBarActor::PrintSelf(ostream& os, vtkIndent indent)
431 this->Superclass::PrintSelf(os,indent);
433 if ( this->LookupTable )
435 os << indent << "Lookup Table:\n";
436 this->LookupTable->PrintSelf(os,indent.GetNextIndent());
440 os << indent << "Lookup Table: (none)\n";
443 if (this->TitleTextProperty)
445 os << indent << "Title Text Property:\n";
446 this->TitleTextProperty->PrintSelf(os,indent.GetNextIndent());
450 os << indent << "Title Text Property: (none)\n";
453 if (this->LabelTextProperty)
455 os << indent << "Label Text Property:\n";
456 this->LabelTextProperty->PrintSelf(os,indent.GetNextIndent());
460 os << indent << "Label Text Property: (none)\n";
463 os << indent << "Title: " << (this->Title ? this->Title : "(none)") << "\n";
464 os << indent << "Maximum Number Of Colors: "
465 << this->MaximumNumberOfColors << "\n";
466 os << indent << "Number Of Labels: " << this->NumberOfLabels << "\n";
467 os << indent << "Number Of Labels Built: " << this->NumberOfLabelsBuilt << "\n";
469 os << indent << "Orientation: ";
470 if ( this->Orientation == VTK_ORIENT_HORIZONTAL )
472 os << "Horizontal\n";
479 os << indent << "Label Format: " << this->LabelFormat << "\n";
482 void VISU_ScalarBarActor::ShallowCopy(vtkProp *prop)
484 VISU_ScalarBarActor *a = VISU_ScalarBarActor::SafeDownCast(prop);
487 this->SetPosition2(a->GetPosition2());
488 this->SetLookupTable(a->GetLookupTable());
489 this->SetMaximumNumberOfColors(a->GetMaximumNumberOfColors());
490 this->SetOrientation(a->GetOrientation());
491 this->SetLabelTextProperty(a->GetLabelTextProperty());
492 this->SetTitleTextProperty(a->GetTitleTextProperty());
493 this->SetLabelFormat(a->GetLabelFormat());
494 this->SetTitle(a->GetTitle());
495 this->GetPositionCoordinate()->SetCoordinateSystem(
496 a->GetPositionCoordinate()->GetCoordinateSystem());
497 this->GetPositionCoordinate()->SetValue(
498 a->GetPositionCoordinate()->GetValue());
499 this->GetPosition2Coordinate()->SetCoordinateSystem(
500 a->GetPosition2Coordinate()->GetCoordinateSystem());
501 this->GetPosition2Coordinate()->SetValue(
502 a->GetPosition2Coordinate()->GetValue());
506 this->vtkActor2D::ShallowCopy(prop);
509 void VISU_ScalarBarActor::AllocateAndSizeLabels(int *labelSize, int *size,
510 vtkViewport *viewport,
511 vtkFloatingPointType *range)
513 labelSize[0] = labelSize[1] = 0;
515 this->TextMappers = new vtkTextMapper * [this->NumberOfLabels];
516 this->TextActors = new vtkActor2D * [this->NumberOfLabels];
520 vtkFloatingPointType val;
523 // TODO: this should be optimized, maybe by keeping a list of
524 // allocated mappers, in order to avoid creation/destruction of
525 // their underlying text properties (i.e. each time a mapper is
526 // created, text properties are created and shallow-assigned a font size
527 // which value might be "far" from the target font size).
529 VISU_LookupTable *lut = this->LookupTable; //SALOME specific
530 int isLogTable = lut->GetScale() == VTK_SCALE_LOG10;
532 for (i=0; i < this->NumberOfLabels; i++)
534 this->TextMappers[i] = vtkTextMapper::New();
536 if(isLogTable && 0 < i && i < this->NumberOfLabels - 1){ // SALOME specific
537 vtkFloatingPointType lval = log10(range[0]) + (vtkFloatingPointType)i/(this->NumberOfLabels-1) *
538 (log10(range[1])-log10(range[0]));
539 val = pow((double)10,(double)lval);
541 val = range[0] + (vtkFloatingPointType)i/(this->NumberOfLabels-1) * (range[1]-range[0]);
543 sprintf(string, this->LabelFormat, val);
544 this->TextMappers[i]->SetInput(string);
546 // Shallow copy here so that the size of the label prop is not affected
547 // by the automatic adjustment of its text mapper's size (i.e. its
548 // mapper's text property is identical except for the font size
549 // which will be modified later). This allows text actors to
550 // share the same text property, and in that case specifically allows
551 // the title and label text prop to be the same.
552 this->TextMappers[i]->GetTextProperty()->ShallowCopy(
553 this->LabelTextProperty);
555 this->TextActors[i] = vtkActor2D::New();
556 this->TextActors[i]->SetMapper(this->TextMappers[i]);
557 this->TextActors[i]->SetProperty(this->GetProperty());
558 this->TextActors[i]->GetPositionCoordinate()->
559 SetReferenceCoordinate(this->PositionCoordinate);
562 if (this->NumberOfLabels)
564 int targetWidth, targetHeight;
566 if(LabelRatioWidth == 0)
567 if ( this->Orientation == VTK_ORIENT_VERTICAL )
568 targetWidth = (int)(0.6*size[0]);
570 targetWidth = (int)(size[0]*0.8/this->NumberOfLabels);
572 targetWidth = (int)(0.01*LabelRatioWidth*size[0]);
574 if(LabelRatioHeight == 0)
575 if ( this->Orientation == VTK_ORIENT_VERTICAL )
576 targetHeight = (int)(0.86*size[1]/this->NumberOfLabels);
578 targetHeight = (int)(0.25*size[1]);
580 targetHeight = (int)(0.01*LabelRatioHeight*size[1]);
582 vtkTextMapper::SetMultipleConstrainedFontSize(viewport,
586 this->NumberOfLabels,
591 void VISU_ScalarBarActor::SizeTitle(int *titleSize, int *size,
592 vtkViewport *viewport)
594 titleSize[0] = titleSize[1] = 0;
596 if (this->Title == NULL || !strlen(this->Title))
601 int targetWidth, targetHeight;
603 if(TitleRatioWidth == 0)
604 targetWidth = size[0];
606 targetWidth = (int)(0.01*TitleRatioWidth*size[0]);
608 if(TitleRatioHeight == 0)
609 if ( this->Orientation == VTK_ORIENT_VERTICAL )
610 targetHeight = (int)(0.1*size[1]);
612 targetHeight = (int)(0.25*size[1]);
614 targetHeight = (int)(0.01*TitleRatioHeight*size[1]);
616 this->TitleMapper->SetConstrainedFontSize(
617 viewport, targetWidth, targetHeight);
619 this->TitleMapper->GetSize(viewport, titleSize);
622 void VISU_ScalarBarActor::SetRatios(int titleRatioWidth, int titleRatioHeight,
623 int labelRatioWidth, int labelRatioHeight,
624 int barRatioWidth, int barRatioHeight)
626 TitleRatioWidth=titleRatioWidth;
627 if(TitleRatioWidth>100)
629 else if(TitleRatioWidth<0)
632 TitleRatioHeight=titleRatioHeight;
633 if(TitleRatioHeight>100)
634 TitleRatioHeight=100;
635 else if(TitleRatioHeight<0)
638 LabelRatioWidth=labelRatioWidth;
639 if(LabelRatioWidth>100)
641 else if(LabelRatioWidth<0)
644 LabelRatioHeight=labelRatioHeight;
645 if(LabelRatioHeight>100)
646 LabelRatioHeight=100;
647 else if(LabelRatioHeight<0)
650 BarRatioWidth=barRatioWidth;
651 if(BarRatioWidth>100)
653 else if(BarRatioWidth<0)
656 BarRatioHeight=barRatioHeight;
657 if(BarRatioHeight>100)
659 else if(BarRatioHeight<0)
663 void VISU_ScalarBarActor::GetRatios(int& titleRatioWidth, int& titleRatioHeight,
664 int& labelRatioWidth, int& labelRatioHeight,
665 int& barRatioWidth, int& barRatioHeight)
667 titleRatioWidth=TitleRatioWidth;
668 titleRatioHeight=TitleRatioHeight;
669 labelRatioWidth=LabelRatioWidth;
670 labelRatioHeight=LabelRatioHeight;
671 barRatioWidth=BarRatioWidth;
672 barRatioHeight=BarRatioHeight;
675 void VISU_ScalarBarActor::SizeBar(int& barSizeWidth, int& barSizeHeight, int *size,
676 vtkViewport *viewport, vtkFloatingPointType *range)
678 if(BarRatioWidth == 0)
679 if ( this->Orientation == VTK_ORIENT_VERTICAL )
682 this->AllocateAndSizeLabels(labelSize, size, viewport,range);
683 barSizeWidth = size[0] - 4 - labelSize[0];
685 barSizeWidth = size[0];
687 barSizeWidth = (int)(0.01*BarRatioWidth*size[0]);
689 if(BarRatioHeight == 0)
690 if ( this->Orientation == VTK_ORIENT_VERTICAL )
691 barSizeHeight = (int)(0.86*size[1]);
693 barSizeHeight = (int)(0.4*size[1]);
695 barSizeHeight = (int)(0.01*BarRatioHeight*size[1]);