vtkScalarBarActor.cxx 74 KB
Newer Older
1
2
3
4
5
/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkScalarBarActor.cxx

6
  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7
8
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
Will Schroeder's avatar
Will Schroeder committed
9

10
11
     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12
     PURPOSE.  See the above copyright notice for more information.
13
14
15

=========================================================================*/
#include "vtkScalarBarActor.h"
16
#include "vtkScalarBarActorInternal.h"
17

18
19
#include "vtkCellArray.h"
#include "vtkCellData.h"
20
#include "vtkColor.h"
21
#include "vtkCoordinate.h"
22
23
24
25
#include "vtkFloatArray.h"
#include "vtkPointData.h"
#include "vtkImageData.h"
#include "vtkMath.h"
26
#include "vtkObjectFactory.h"
27
#include "vtkPolyData.h"
28
#include "vtkPolyDataMapper2D.h"
29
30
#include "vtkProperty2D.h"
#include "vtkRenderer.h"
31
#include "vtkRenderWindow.h"
32
#include "vtkScalarsToColors.h"
33
34
#include "vtkSmartPointer.h"
#include "vtkTextActor.h"
Sebastien Barre's avatar
Sebastien Barre committed
35
#include "vtkTextProperty.h"
36
#include "vtkTexture.h"
37
38
#include "vtkViewport.h"
#include "vtkWindow.h"
39
#include "vtkMathTextUtilities.h"
40

41
42
#include <vector>
#include <set>
43
44
45
46
47
48
49
50
51
#include <map>

#include <stdio.h> // for snprintf

#if defined(_WIN32) && !defined(__CYGWIN__)
#  define SNPRINTF _snprintf
#else
#  define SNPRINTF snprintf
#endif
52

53
54
#undef VTK_DBG_LAYOUT

Brad King's avatar
Brad King committed
55
vtkStandardNewMacro(vtkScalarBarActor);
56

57
vtkCxxSetObjectMacro(vtkScalarBarActor,LookupTable,vtkScalarsToColors);
Sebastien Barre's avatar
Sebastien Barre committed
58
59
vtkCxxSetObjectMacro(vtkScalarBarActor,LabelTextProperty,vtkTextProperty);
vtkCxxSetObjectMacro(vtkScalarBarActor,TitleTextProperty,vtkTextProperty);
60
61
vtkCxxSetObjectMacro(vtkScalarBarActor,BackgroundProperty,vtkProperty2D);
vtkCxxSetObjectMacro(vtkScalarBarActor,FrameProperty,vtkProperty2D);
62

Sebastien Barre's avatar
Sebastien Barre committed
63
64
//----------------------------------------------------------------------------
// Instantiate object with 64 maximum colors; 5 labels; %%-#6.3g label
65
66
67
68
// format, no title, and vertical orientation. The initial scalar bar
// size is (0.05 x 0.8) of the viewport size.
vtkScalarBarActor::vtkScalarBarActor()
{
69
  this->P = new vtkScalarBarActorInternal;
70
  this->LookupTable = NULL;
71
  this->Position2Coordinate->SetValue(0.17, 0.8);
72

73
74
  this->PositionCoordinate->SetCoordinateSystemToNormalizedViewport();
  this->PositionCoordinate->SetValue(0.82,0.1);
75

76
77
78
  this->TextPad = 1;
  this->TitleRatio = 0.5;
  this->BarRatio = 0.375;
79
80
  this->MaximumNumberOfColors = 64;
  this->NumberOfLabels = 5;
81
  this->NumberOfLabelsBuilt = 0;
82
83
  this->Orientation = VTK_ORIENT_VERTICAL;
  this->Title = NULL;
84
  this->ComponentTitle = NULL;
85

Sebastien Barre's avatar
Sebastien Barre committed
86
87
88
89
90
91
92
93
94
95
  this->LabelTextProperty = vtkTextProperty::New();
  this->LabelTextProperty->SetFontSize(12);
  this->LabelTextProperty->SetBold(1);
  this->LabelTextProperty->SetItalic(1);
  this->LabelTextProperty->SetShadow(1);
  this->LabelTextProperty->SetFontFamilyToArial();

  this->TitleTextProperty = vtkTextProperty::New();
  this->TitleTextProperty->ShallowCopy(this->LabelTextProperty);

96
  this->LabelFormat = new char[8];
97
98
  sprintf(this->LabelFormat,"%s","%-#6.3g");

99
  this->TitleActor = vtkTextActor::New();
100
101
  this->TitleActor->GetPositionCoordinate()->
    SetReferenceCoordinate(this->PositionCoordinate);
102

103
104
  this->ScalarBar = vtkPolyData::New();
  this->ScalarBarMapper = vtkPolyDataMapper2D::New();
105
  this->ScalarBarMapper->SetInputData(this->ScalarBar);
106
107
  this->ScalarBarActor = vtkActor2D::New();
  this->ScalarBarActor->SetMapper(this->ScalarBarMapper);
108
109
  this->ScalarBarActor->GetPositionCoordinate()->
    SetReferenceCoordinate(this->PositionCoordinate);
Ken Martin's avatar
Ken Martin committed
110
111
112
113
  this->LastOrigin[0] = 0;
  this->LastOrigin[1] = 0;
  this->LastSize[0] = 0;
  this->LastSize[1] = 0;
114

David Thompson's avatar
David Thompson committed
115
  this->DrawAnnotations = 1;
116
  this->DrawNanAnnotation = 0;
117
  this->AnnotationTextScaling = 0;
118
119
120
121
122
123
124
125
126
127
128
  this->FixedAnnotationLeaderLineColor = 0;
  this->NanAnnotation = 0;
  this->SetNanAnnotation("NaN");
  this->P->NanSwatch = vtkPolyData::New();
  this->P->NanSwatchMapper = vtkPolyDataMapper2D::New();
  this->P->NanSwatchActor = vtkActor2D::New();
  this->P->NanSwatchMapper->SetInputData(this->P->NanSwatch);
  this->P->NanSwatchActor->SetMapper(this->P->NanSwatchMapper);
  this->P->NanSwatchActor->GetPositionCoordinate()->
    SetReferenceCoordinate(this->PositionCoordinate);

David Thompson's avatar
David Thompson committed
129
  this->AnnotationLeaderPadding = 8.;
130
131
132
133
134
135
136
137
138
139
140
141
142
143
  this->P->AnnotationBoxes = vtkPolyData::New();
  this->P->AnnotationBoxesMapper = vtkPolyDataMapper2D::New();
  this->P->AnnotationBoxesActor = vtkActor2D::New();
  this->P->AnnotationBoxesMapper->SetInputData(this->P->AnnotationBoxes);
  this->P->AnnotationBoxesActor->SetMapper(this->P->AnnotationBoxesMapper);
  this->P->AnnotationBoxesActor->GetPositionCoordinate()->
    SetReferenceCoordinate(this->PositionCoordinate);
  this->P->AnnotationLeaders = vtkPolyData::New();
  this->P->AnnotationLeadersMapper = vtkPolyDataMapper2D::New();
  this->P->AnnotationLeadersActor = vtkActor2D::New();
  this->P->AnnotationLeadersMapper->SetInputData(this->P->AnnotationLeaders);
  this->P->AnnotationLeadersActor->SetMapper(this->P->AnnotationLeadersMapper);
  this->P->AnnotationLeadersActor->GetPositionCoordinate()->
    SetReferenceCoordinate(this->PositionCoordinate);
144

145
146
147
148
  // If opacity is on, a jail like texture is displayed behind it..

  this->UseOpacity       = 0;
  this->TextureGridWidth = 10.0;
149

150
  this->TexturePolyData = vtkPolyData::New();
151
  vtkPolyDataMapper2D* textureMapper = vtkPolyDataMapper2D::New();
152
  textureMapper->SetInputData(this->TexturePolyData);
153
154
155
156
157
158
159
160
  this->TextureActor = vtkActor2D::New();
  this->TextureActor->SetMapper(textureMapper);
  textureMapper->Delete();
  this->TextureActor->GetPositionCoordinate()->
    SetReferenceCoordinate(this->PositionCoordinate);
  vtkFloatArray* tc = vtkFloatArray::New();
  tc->SetNumberOfComponents(2);
  tc->SetNumberOfTuples(4);
161
  tc->InsertComponent(0,0, 0.0);
162
163
  tc->InsertComponent(0,1, 0.0);
  tc->InsertComponent(1,1, 0.0);
164
  tc->InsertComponent(3,0, 0.0);
165
166
167
168
169
170
171
172
173
174
175
176
  this->TexturePolyData->GetPointData()->SetTCoords(tc);
  tc->Delete();

  vtkCellArray* polys2 = vtkCellArray::New();
  polys2->InsertNextCell(4);
  polys2->InsertCellPoint(0);
  polys2->InsertCellPoint(1);
  polys2->InsertCellPoint(2);
  polys2->InsertCellPoint(3);
  this->TexturePolyData->SetPolys(polys2);
  polys2->Delete();

177
  vtkProperty2D* imageProperty = vtkProperty2D::New();
178
179
180
181
182
183
184
  imageProperty->SetOpacity(0.08);
  this->TextureActor->SetProperty(imageProperty);
  imageProperty->Delete();

  // Create the default texture. Just a "Jail" like grid

  const unsigned int dim = 128;
185
  vtkImageData* image = vtkImageData::New();
186
  image->SetDimensions(dim, dim, 1);
Berk Geveci's avatar
Berk Geveci committed
187
  image->AllocateScalars(VTK_UNSIGNED_CHAR, 1);
188

189
190
  for (unsigned int y = 0; y < dim; y++)
    {
191
192
    unsigned char* ptr =
      static_cast<unsigned char*>(image->GetScalarPointer(0, y, 0));
193
194
195
196
197
198
199
200
    for (unsigned int x = 0; x < dim; x++)
      {
      *ptr = ((x == y) || (x == (dim-y-1))) ? 255 : 0;
      ++ptr;
      }
    }

  this->Texture = vtkTexture::New();
201
  this->Texture->SetInputData( image );
202
203
  this->Texture->RepeatOn();
  image->Delete();
204
205
206
207

  // Default text position : Above scalar bar if orientation is horizontal
  //                         Right of scalar bar if orientation is vertical
  this->TextPosition = SucceedScalarBar;
208
209
210

  this->MaximumWidthInPixels = VTK_INT_MAX;
  this->MaximumHeightInPixels = VTK_INT_MAX;
211
212
213
214
215
216
217

  this->BackgroundProperty = vtkProperty2D::New();
  this->FrameProperty = vtkProperty2D::New();

  this->DrawBackground = 0;
  this->Background = vtkPolyData::New();
  this->BackgroundMapper = vtkPolyDataMapper2D::New();
218
  this->BackgroundMapper->SetInputData(this->Background);
219
220
  this->BackgroundActor = vtkActor2D::New();
  this->BackgroundActor->SetMapper(this->BackgroundMapper);
221
222
  this->BackgroundActor->GetPositionCoordinate()
    ->SetReferenceCoordinate(this->PositionCoordinate);
223

224
225
226
#ifdef VTK_DBG_LAYOUT
  this->DrawFrame = 1;
#else // VTK_DBG_LAYOUT
227
  this->DrawFrame = 0;
228
#endif // VTK_DBG_LAYOUT
229
230
  this->Frame = vtkPolyData::New();
  this->FrameMapper = vtkPolyDataMapper2D::New();
231
  this->FrameMapper->SetInputData(this->Frame);
232
233
  this->FrameActor = vtkActor2D::New();
  this->FrameActor->SetMapper(this->FrameMapper);
234
235
  this->FrameActor->GetPositionCoordinate()
    ->SetReferenceCoordinate(this->PositionCoordinate);
236
237

  this->DrawColorBar = true;
238
  this->DrawTickLabels = true;
239
240
}

Sebastien Barre's avatar
Sebastien Barre committed
241
//----------------------------------------------------------------------------
Ken Martin's avatar
Ken Martin committed
242
243
244
// Release any graphics resources that are being consumed by this actor.
// The parameter window could be used to determine which graphic
// resources to release.
245
void vtkScalarBarActor::ReleaseGraphicsResources(vtkWindow* win)
Ken Martin's avatar
Ken Martin committed
246
247
{
  this->TitleActor->ReleaseGraphicsResources(win);
248
  if (!this->P->TextActors.empty())
Ken Martin's avatar
Ken Martin committed
249
    {
250
251
252
253
254
    vtkScalarBarActorInternal::ActorVec::iterator it;
    for (
      it = this->P->TextActors.begin();
      it != this->P->TextActors.end();
      ++it)
Ken Martin's avatar
Ken Martin committed
255
      {
256
      (*it)->ReleaseGraphicsResources(win);
Ken Martin's avatar
Ken Martin committed
257
258
      }
    }
259
  for (vtkScalarBarActorInternal::ActorVec::size_type i = 0; i < this->P->AnnotationLabels.size(); ++ i )
260
    {
261
    this->P->AnnotationLabels[i]->ReleaseGraphicsResources(win);
262
    }
Ken Martin's avatar
Ken Martin committed
263
  this->ScalarBarActor->ReleaseGraphicsResources(win);
264
265
266
  this->P->NanSwatchActor->ReleaseGraphicsResources(win);
  this->P->AnnotationBoxesActor->ReleaseGraphicsResources(win);
  this->P->AnnotationLeadersActor->ReleaseGraphicsResources(win);
267
268
  this->BackgroundActor->ReleaseGraphicsResources(win);
  this->FrameActor->ReleaseGraphicsResources(win);
269
  this->Texture->ReleaseGraphicsResources(win);
Ken Martin's avatar
Ken Martin committed
270
271
}

272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
//----------------------------------------------------------------------------
void vtkScalarBarActor::GetScalarBarRect(int rect[4], vtkViewport* viewport)
{
  vtkCoordinate *origin = this->ScalarBarActor->GetPositionCoordinate();
  int * vpPos = origin->GetComputedViewportValue(viewport);
  rect[0] = vpPos[0];
  rect[1] = vpPos[1];

  double *bounds = this->ScalarBar->GetBounds();
  rect[0] += static_cast<int>(bounds[0] + 0.5);
  rect[1] += static_cast<int>(bounds[2] + 0.5);
  rect[2] = static_cast<int>(bounds[1] - bounds[0] + 0.5);
  rect[3] = static_cast<int>(bounds[3] - bounds[2] + 0.5);
}

Sebastien Barre's avatar
Sebastien Barre committed
287
//----------------------------------------------------------------------------
288
289
vtkScalarBarActor::~vtkScalarBarActor()
{
290
291
  delete [] this->LabelFormat;
  this->LabelFormat = NULL;
292
293

  this->TitleActor->Delete();
294
  this->SetNanAnnotation(NULL);
295

296
297
298
  this->ScalarBar->Delete();
  this->ScalarBarMapper->Delete();
  this->ScalarBarActor->Delete();
Ken Martin's avatar
Ken Martin committed
299

300
301
302
303
304
305
306
  this->P->NanSwatch->Delete();
  this->P->NanSwatchMapper->Delete();
  this->P->NanSwatchActor->Delete();

  this->P->AnnotationBoxes->Delete();
  this->P->AnnotationBoxesMapper->Delete();
  this->P->AnnotationBoxesActor->Delete();
307

308
309
310
  this->P->AnnotationLeaders->Delete();
  this->P->AnnotationLeadersMapper->Delete();
  this->P->AnnotationLeadersActor->Delete();
311

312
313
  delete [] this->Title;
  this->Title = NULL;
314

315
316
  delete [] this->ComponentTitle;
  this->ComponentTitle = NULL;
317

318
  this->SetLookupTable(NULL);
Sebastien Barre's avatar
Sebastien Barre committed
319
320
  this->SetLabelTextProperty(NULL);
  this->SetTitleTextProperty(NULL);
321
322
323
  this->Texture->Delete();
  this->TextureActor->Delete();
  this->TexturePolyData->Delete();
324
325
326
327
328
329
330
331
  this->Background->Delete();
  this->BackgroundMapper->Delete();
  this->BackgroundActor->Delete();
  this->Frame->Delete();
  this->FrameMapper->Delete();
  this->FrameActor->Delete();
  this->SetBackgroundProperty(NULL);
  this->SetFrameProperty(NULL);
332
  delete this->P;
333
334
}

Sebastien Barre's avatar
Sebastien Barre committed
335
//----------------------------------------------------------------------------
336
int vtkScalarBarActor::RenderOverlay(vtkViewport* viewport)
Ken Martin's avatar
Ken Martin committed
337
{
338
  int renderedSomething = 0;
339

340
341
342
343
344
345
346
347
348
349
350
351
352
  // Is the viewport's RenderWindow capturing GL2PS-special props? We'll need
  // to handle this specially to get the texture to show up right.
  if (vtkRenderer *renderer = vtkRenderer::SafeDownCast(viewport))
    {
    if (vtkRenderWindow *renderWindow = renderer->GetRenderWindow())
      {
      if (renderWindow->GetCapturingGL2PSSpecialProps())
        {
        renderer->CaptureGL2PSSpecialProp(this);
        }
      }
    }

353
  // Everything is built, just have to render
354
355
356
357
  if (this->DrawBackground)
    {
    renderedSomething += this->BackgroundActor->RenderOverlay(viewport);
    }
358

359
  if (this->UseOpacity && this->DrawColorBar)
360
361
362
363
364
    {
    this->Texture->Render(vtkRenderer::SafeDownCast(viewport));
    renderedSomething += this->TextureActor->RenderOverlay(viewport);
    }

365
366
367
  // Draw either the scalar bar (non-indexed mode) or
  // the annotated value boxes (indexed mode).
  if (!this->LookupTable->GetIndexedLookup())
368
    {
369
370
    if (this->DrawColorBar)
      {
371
      renderedSomething += this->ScalarBarActor->RenderOverlay(viewport);
372
      }
373

374
    if (this->DrawTickLabels)
375
      {
376
377
378
379
380
381
382
383
      vtkScalarBarActorInternal::ActorVec::iterator it;
      for (
           it = this->P->TextActors.begin();
           it != this->P->TextActors.end();
           ++it)
        {
        renderedSomething += (*it)->RenderOverlay(viewport);
        }
384
385
      }
    }
386
  else if (this->DrawColorBar)
387
    {
388
389
390
391
392
393
394
395
396
397
398
399
400
    renderedSomething +=
      this->P->AnnotationBoxesActor->RenderOverlay(viewport);
    }

  if (this->DrawNanAnnotation)
    {
    renderedSomething +=
      this->P->NanSwatchActor->RenderOverlay(viewport);
    }

  if (this->DrawFrame)
    {
    renderedSomething += this->FrameActor->RenderOverlay(viewport);
401
    }
402

403
404
405
406
407
  if (this->Title != NULL)
    {
    renderedSomething += this->TitleActor->RenderOverlay(viewport);
    }

408
  if (this->DrawAnnotations)
409
    {
410
    if (!this->P->AnnotationLabels.empty())
411
412
413
      {
      renderedSomething +=
        this->P->AnnotationLeadersActor->RenderOverlay( viewport );
414
415
416
417
418
      for (vtkScalarBarActorInternal::ActorVec::size_type i = 0; i < this->P->AnnotationLabels.size(); ++ i )
        {
        renderedSomething +=
          this->P->AnnotationLabels[i]->RenderOverlay( viewport );
        }
David Thompson's avatar
David Thompson committed
419
      }
420
    }
421

422
  renderedSomething = (renderedSomething > 0)?(1):(0);
423
  return renderedSomething;
Ken Martin's avatar
Ken Martin committed
424
425
}

Sebastien Barre's avatar
Sebastien Barre committed
426
//----------------------------------------------------------------------------
427
int vtkScalarBarActor::RenderOpaqueGeometry(vtkViewport* viewport)
428
{
429
  int renderedSomething = 0;
430

Sebastien Barre's avatar
Sebastien Barre committed
431
  if (!this->LookupTable)
432
433
    {
    vtkWarningMacro(<<"Need a mapper to render a scalar bar");
434
    return 0;
435
436
    }

Sebastien Barre's avatar
Sebastien Barre committed
437
438
439
440
441
442
443
444
445
446
447
448
  if (!this->TitleTextProperty)
    {
    vtkErrorMacro(<<"Need title text property to render a scalar bar");
    return 0;
    }

  if (!this->LabelTextProperty)
    {
    vtkErrorMacro(<<"Need label text property to render a scalar bar");
    return 0;
    }

Ken Martin's avatar
Ken Martin committed
449
  // Check to see whether we have to rebuild everything
450
  int positionsHaveChanged = 0;
451
452
  if (viewport->GetMTime() > this->BuildTime ||
      (viewport->GetVTKWindow() &&
Sebastien Barre's avatar
Sebastien Barre committed
453
       viewport->GetVTKWindow()->GetMTime() > this->BuildTime))
Ken Martin's avatar
Ken Martin committed
454
455
456
    {
    // if the viewport has changed we may - or may not need
    // to rebuild, it depends on if the projected coords chage
457
458
    int size[2];
    int* barOrigin;
Ken Martin's avatar
Ken Martin committed
459
    barOrigin = this->PositionCoordinate->GetComputedViewportValue(viewport);
460
    size[0] =
Ken Martin's avatar
Ken Martin committed
461
462
      this->Position2Coordinate->GetComputedViewportValue(viewport)[0] -
      barOrigin[0];
463
    size[1] =
Ken Martin's avatar
Ken Martin committed
464
465
      this->Position2Coordinate->GetComputedViewportValue(viewport)[1] -
      barOrigin[1];
466

467
468
    // Check if we have bounds on the maximum size
    size[0] = size[0] > this->MaximumWidthInPixels
469
            ? this->MaximumWidthInPixels : size[0];
470
    size[1] = size[1] > this->MaximumHeightInPixels
471
472
            ? this->MaximumHeightInPixels : size[1];

473
    if (this->LastSize[0] != size[0] ||
Sebastien Barre's avatar
Sebastien Barre committed
474
        this->LastSize[1] != size[1] ||
475
        this->LastOrigin[0] != barOrigin[0] ||
476
        this->LastOrigin[1] != barOrigin[1])
Ken Martin's avatar
Ken Martin committed
477
      {
478
      positionsHaveChanged = 1;
Ken Martin's avatar
Ken Martin committed
479
480
      }
    }
481

482
  // Check to see whether we have to rebuild everything
483
  if (positionsHaveChanged ||
484
      this->GetMTime() > this->BuildTime ||
Sebastien Barre's avatar
Sebastien Barre committed
485
486
      this->LookupTable->GetMTime() > this->BuildTime ||
      this->LabelTextProperty->GetMTime() > this->BuildTime ||
487
488
489
490
      this->TitleTextProperty->GetMTime() > this->BuildTime ||
      this->BackgroundProperty->GetMTime() > this->BuildTime ||
      this->FrameProperty->GetMTime() > this->BuildTime)

491
    {
492
    this->RebuildLayout(viewport);
493
494
495
    }

  // Everything is built, just have to render
Jim Miller's avatar
Style  
Jim Miller committed
496
497
  if (this->Title != NULL)
    {
498
499
    renderedSomething +=
      this->TitleActor->RenderOpaqueGeometry(viewport);
Jim Miller's avatar
Style  
Jim Miller committed
500
    }
501
502
  // Draw either the scalar bar (non-indexed mode) or
  // the annotated value boxes (indexed mode).
503
  if ( ! this->LookupTable->GetIndexedLookup() )
Jim Miller's avatar
Style  
Jim Miller committed
504
    {
505
506
    if (this->DrawColorBar)
      {
507
508
      renderedSomething +=
        this->ScalarBarActor->RenderOpaqueGeometry(viewport);
509
      }
510
511
512
513
514
    vtkScalarBarActorInternal::ActorVec::iterator ait;
    for (
      ait = this->P->TextActors.begin();
      ait != this->P->TextActors.end();
      ++ait)
David Thompson's avatar
David Thompson committed
515
      {
516
      renderedSomething += (*ait)->RenderOpaqueGeometry(viewport);
David Thompson's avatar
David Thompson committed
517
518
519
520
      }
    }
  else
    {
521
522
    if (this->DrawColorBar)
      {
523
524
525
526
527
528
529
530
531
532
533
534
535
536
      renderedSomething +=
        this->P->AnnotationBoxesActor->RenderOpaqueGeometry( viewport );
      }
    }

  if (this->DrawNanAnnotation)
    {
    renderedSomething +=
      this->P->NanSwatchActor->RenderOpaqueGeometry(viewport);
    }

  // Draw the annotation leaders and labels
  if ( this->DrawAnnotations )
    {
537
    if (!this->P->AnnotationLabels.empty())
538
539
540
      {
      renderedSomething +=
        this->P->AnnotationLeadersActor->RenderOpaqueGeometry( viewport );
541
542
543
544
545
      for (vtkScalarBarActorInternal::ActorVec::size_type i = 0; i < this->P->AnnotationLabels.size(); ++ i )
        {
        renderedSomething +=
          this->P->AnnotationLabels[i]->RenderOpaqueGeometry( viewport );
        }
David Thompson's avatar
David Thompson committed
546
      }
Jim Miller's avatar
Style  
Jim Miller committed
547
    }
548
549
550
551

  renderedSomething = (renderedSomething > 0)?(1):(0);

  return renderedSomething;
552
553
}

554
555
556
557
//-----------------------------------------------------------------------------
// Description:
// Does this prop have some translucent polygonal geometry?
int vtkScalarBarActor::HasTranslucentPolygonalGeometry()
558
559
560
561
{ // TODO: Handle case when IndexedLookup is true and any colors in the palette
  // have an alpha value, as the color swatches drawn by
  // this->P->AnnotationBoxesActor have 1 translucent triangle for each
  // alpha-swatch.
562
563
564
  return 0;
}

Sebastien Barre's avatar
Sebastien Barre committed
565
//----------------------------------------------------------------------------
566
void vtkScalarBarActor::PrintSelf(ostream& os, vtkIndent indent)
567
{
Brad King's avatar
Brad King committed
568
  this->Superclass::PrintSelf(os,indent);
569
570
571
572
573
574
575
576
577
578
579

  if ( this->LookupTable )
    {
    os << indent << "Lookup Table:\n";
    this->LookupTable->PrintSelf(os,indent.GetNextIndent());
    }
  else
    {
    os << indent << "Lookup Table: (none)\n";
    }

Sebastien Barre's avatar
Sebastien Barre committed
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
  if (this->TitleTextProperty)
    {
    os << indent << "Title Text Property:\n";
    this->TitleTextProperty->PrintSelf(os,indent.GetNextIndent());
    }
  else
    {
    os << indent << "Title Text Property: (none)\n";
    }

  if (this->LabelTextProperty)
    {
    os << indent << "Label Text Property:\n";
    this->LabelTextProperty->PrintSelf(os,indent.GetNextIndent());
    }
  else
    {
    os << indent << "Label Text Property: (none)\n";
    }

600
  os << indent << "Title: " << (this->Title ? this->Title : "(none)") << "\n";
601
602
  os << indent << "ComponentTitle: "
    << (this->ComponentTitle ? this->ComponentTitle : "(none)") << "\n";
603
  os << indent << "Maximum Number Of Colors: "
604
605
     << this->MaximumNumberOfColors << "\n";
  os << indent << "Number Of Labels: " << this->NumberOfLabels << "\n";
606
  os << indent << "Number Of Labels Built: " << this->NumberOfLabelsBuilt << "\n";
607
608

  os << indent << "Orientation: ";
Jim Miller's avatar
Style  
Jim Miller committed
609
610
611
612
613
614
615
616
  if ( this->Orientation == VTK_ORIENT_HORIZONTAL )
    {
    os << "Horizontal\n";
    }
  else
    {
    os << "Vertical\n";
    }
617
618

  os << indent << "Label Format: " << this->LabelFormat << "\n";
619
620
621
622
  os << indent << "UseOpacity: " << this->UseOpacity << "\n";
  if (this->UseOpacity)
    {
    os << indent << "TextureGridWidth: " << this->TextureGridWidth << "\n";
Karthik Krishnan's avatar
Karthik Krishnan committed
623
624
    os << indent << "TextureActor:\n";
    this->TextureActor->PrintSelf(os, indent.GetNextIndent());
625
    }
626
627
628
629
630
631
632
633
  if (this->TextPosition == vtkScalarBarActor::PrecedeScalarBar)
    {
    os << indent << "TextPosition: PrecedeScalarBar\n";
    }
  else
    {
    os << indent << "TextPosition: SucceedScalarBar\n";
    }
Karthik Krishnan's avatar
Karthik Krishnan committed
634

635
  os << indent << "MaximumWidthInPixels: "
Karthik Krishnan's avatar
Karthik Krishnan committed
636
     << this->MaximumWidthInPixels << endl;
637
  os << indent << "MaximumHeightInPixels: "
Karthik Krishnan's avatar
Karthik Krishnan committed
638
     << this->MaximumHeightInPixels << endl;
639

David Thompson's avatar
David Thompson committed
640
641
  os << indent << "DrawAnnotations: "
    << this->DrawAnnotations << endl;
642
643
644
645
  os << indent << "DrawNanAnnotation: "
    << this->DrawNanAnnotation << endl;
  os << indent << "NanAnnotation: "
    << (this->NanAnnotation ? this->NanAnnotation : "(none)") << endl;
David Thompson's avatar
David Thompson committed
646
647
  os << indent << "AnnotationLeaderPadding: "
    << this->AnnotationLeaderPadding << endl;
648
649
  os << indent << "AnnotationTextScaling: "
    << this->AnnotationTextScaling << endl;
David Thompson's avatar
David Thompson committed
650

651
652
653
654
655
656
  os << indent << "DrawBackground: " << this->DrawBackground << "\n";
  os << indent << "Background Property:\n";
  this->BackgroundProperty->PrintSelf(os,indent.GetNextIndent());
  os << indent << "DrawFrame: " << this->DrawFrame << "\n";
  os << indent << "Frame Property:\n";
  this->FrameProperty->PrintSelf(os,indent.GetNextIndent());
657
}
Ken Martin's avatar
Ken Martin committed
658

Sebastien Barre's avatar
Sebastien Barre committed
659
//----------------------------------------------------------------------------
660
void vtkScalarBarActor::ShallowCopy(vtkProp* prop)
Will Schroeder's avatar
Will Schroeder committed
661
{
662
  vtkScalarBarActor* a = vtkScalarBarActor::SafeDownCast(prop);
Will Schroeder's avatar
Will Schroeder committed
663
664
665
666
667
668
  if ( a != NULL )
    {
    this->SetPosition2(a->GetPosition2());
    this->SetLookupTable(a->GetLookupTable());
    this->SetMaximumNumberOfColors(a->GetMaximumNumberOfColors());
    this->SetOrientation(a->GetOrientation());
Sebastien Barre's avatar
Sebastien Barre committed
669
670
    this->SetLabelTextProperty(a->GetLabelTextProperty());
    this->SetTitleTextProperty(a->GetTitleTextProperty());
Will Schroeder's avatar
Will Schroeder committed
671
672
673
    this->SetLabelFormat(a->GetLabelFormat());
    this->SetTitle(a->GetTitle());
    this->GetPositionCoordinate()->SetCoordinateSystem(
674
      a->GetPositionCoordinate()->GetCoordinateSystem());
Will Schroeder's avatar
Will Schroeder committed
675
676
677
    this->GetPositionCoordinate()->SetValue(
      a->GetPositionCoordinate()->GetValue());
    this->GetPosition2Coordinate()->SetCoordinateSystem(
678
      a->GetPosition2Coordinate()->GetCoordinateSystem());
Will Schroeder's avatar
Will Schroeder committed
679
680
    this->GetPosition2Coordinate()->SetValue(
      a->GetPosition2Coordinate()->GetValue());
681
682
683
684
    this->SetDrawBackground(a->GetDrawBackground());
    this->SetBackgroundProperty(a->GetBackgroundProperty());
    this->SetDrawFrame(a->GetDrawFrame());
    this->SetFrameProperty(a->GetFrameProperty());
Will Schroeder's avatar
Will Schroeder committed
685
686
687
688
689
    }

  // Now do superclass
  this->vtkActor2D::ShallowCopy(prop);
}
Ken Martin's avatar
Ken Martin committed
690

Sebastien Barre's avatar
Sebastien Barre committed
691
//----------------------------------------------------------------------------
692
void vtkScalarBarActor::RebuildLayout(vtkViewport* viewport)
Ken Martin's avatar
Ken Martin committed
693
{
694
  vtkDebugMacro(<<"Rebuilding subobjects");
Sebastien Barre's avatar
Sebastien Barre committed
695

696
697
  this->P->Viewport = viewport;
  this->FreeLayoutStorage();
Sebastien Barre's avatar
Sebastien Barre committed
698

699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
  // Permute indices used to measure width and height
  // so that thickness and length according to the orientation
  // of the scalar bar instead.
  if (this->Orientation == VTK_ORIENT_VERTICAL)
    {
    this->P->TL[0] = 0;
    this->P->TL[1] = 1;
    }
  else
    {
    this->P->TL[0] = 1;
    this->P->TL[1] = 0;
    }
  this->P->NumNotes = this->LookupTable->GetNumberOfAnnotatedValues();

  // Warning: The order of these calls is extremely important
  // as each updates members of this->P used by later methods!
  this->ComputeFrame();
  this->ComputeScalarBarThickness();
  this->LayoutNanSwatch();
  this->PrepareTitleText();
  this->LayoutTitle();
  this->ComputeScalarBarLength();
  this->LayoutTicks();
  this->LayoutAnnotations();

  // Now generate/configure the VTK datasets and actors that
  // illustrate the scalar bar when rendered using the
  // layout computed above.
  this->ConfigureAnnotations();
  this->ConfigureFrame();
  this->ConfigureScalarBar();
  this->ConfigureTitle();
  this->ConfigureTicks();
  this->ConfigureNanSwatch();
734
735
736
#ifdef VTK_DBG_LAYOUT
  this->DrawBoxes();
#endif // VTK_DBG_LAYOUT
737
  this->BuildTime.Modified();
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
}

namespace {

void AddBox(vtkPoints* pts, vtkCellArray* lines, vtkScalarBarBox& box, int tl[2])
{
  vtkIdType pid[5];

  pid[0] = pts->InsertNextPoint(box.Posn[0], box.Posn[1], 0.);
  pid[1] = pts->InsertNextPoint(box.Posn[0] + box.Size[tl[0]], box.Posn[1], 0.);
  pid[2] = pts->InsertNextPoint(box.Posn[0] + box.Size[tl[0]], box.Posn[1] + box.Size[tl[1]], 0.);
  pid[3] = pts->InsertNextPoint(box.Posn[0], box.Posn[1] + box.Size[tl[1]], 0.);

  pid[4] = pid[0];
  for (int i = 0; i < 4; ++i)
    {
    lines->InsertNextCell(2, pid + i);
    }
}

}

void vtkScalarBarActor::DrawBoxes()
{
  vtkPoints* pts = this->Frame->GetPoints();
  vtkCellArray* lines = this->Frame->GetLines();

  AddBox(pts, lines, this->P->ScalarBarBox, this->P->TL);
  AddBox(pts, lines, this->P->NanBox, this->P->TL);
  AddBox(pts, lines, this->P->TitleBox, this->P->TL);
  if (this->NumberOfLabels > 0)
    {
    AddBox(pts, lines, this->P->TickBox, this->P->TL);
    }
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
}

//----------------------------------------------------------------------------
void vtkScalarBarActor::ComputeFrame()
{
  // get the viewport size in display coordinates
  int* p0;
  int* p1;
  int size[2];
  p0 = this->PositionCoordinate->GetComputedViewportValue(this->P->Viewport);
  p1 = this->Position2Coordinate->GetComputedViewportValue(this->P->Viewport);
  for (int i = 0; i < 2; ++i)
    {
    //this->P->Frame.Posn[i] = p0[i];
    this->P->Frame.Posn[i] = 0; // Translate the frame's coordinate system to p0
    size[i] = p1[i] - p0[i];
    }

  // Check if we have bounds on the maximum size
  size[0] = size[0] > this->MaximumWidthInPixels
          ? this->MaximumWidthInPixels : size[0];
  size[1] = size[1] > this->MaximumHeightInPixels
          ? this->MaximumHeightInPixels : size[1];

  for (int i = 0; i < 2; ++i)
    {
    this->P->Frame.Size[i] = size[this->P->TL[i]];
    }

  this->LastOrigin[0] = p0[0];
  this->LastOrigin[1] = p0[1];
  this->LastSize[0] = size[0];
  this->LastSize[1] = size[1];
}

//----------------------------------------------------------------------------
void vtkScalarBarActor::ComputeScalarBarThickness()
{
  // We do not set Size[1] (length), since the title bounds may encroach
  // on it in the vertical orientation.
  this->P->ScalarBarBox.Size[0] =
813
    static_cast<int>(ceil(this->P->Frame.Size[0] * this->BarRatio));
814
815
816
817
818
819
820
821
822
823
824
825
826
827

  // The lower-left corner of the scalar bar may be estimated here
  // as identical to the Frame position in one or both coordinates,
  // depending on whether tick marks should precede the scalar bar or
  // not and on the orientation.
  //
  // It will be altered later in this->LayoutTicks to account
  // for the half-height/width of tick labels.
  this->P->ScalarBarBox.Posn = this->P->Frame.Posn;
  if (this->TextPosition == PrecedeScalarBar)
    {
    this->P->ScalarBarBox.Posn[this->P->TL[0]] +=
      this->P->Frame.Size[0] - this->P->ScalarBarBox.Size[0];
    }
828
829

  // Now knock the thickness down and nudge the bar so the bar doesn't hug the frame.
830
831
832
833
834
  double nudge = this->P->ScalarBarBox.Size[0] / 8.;
  if (nudge > this->TextPad)
    {
    nudge = this->TextPad;
    }
835
  this->P->ScalarBarBox.Size[0] -= nudge;
836
837
  this->P->ScalarBarBox.Posn[this->P->TL[0]] += nudge *
    (this->TextPosition == PrecedeScalarBar ? -1 : +1);
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
}

//----------------------------------------------------------------------------
void vtkScalarBarActor::LayoutNanSwatch()
{
  // We don't have ScalarBarBox.Size[1] set yet; use the frame width instead.
  this->P->NanSwatchSize = static_cast<double>(
    this->P->ScalarBarBox.Size[0] > this->P->Frame.Size[1] / 4 ?
    this->P->Frame.Size[1] / 4 : this->P->ScalarBarBox.Size[0]);
  if (this->P->NanSwatchSize < 4 && this->P->Frame.Size[1] > 16)
    this->P->NanSwatchSize = 4;
  if (!this->DrawNanAnnotation)
    this->P->NanSwatchSize = 0;
  if (this->P->NumNotes)
    {
    this->P->SwatchPad = this->P->Frame.Size[1] / this->P->NumNotes > 16. ?
      4. : ( this->P->Frame.Size[1] / this->P->NumNotes / 4. );
    }
  else
    {
    this->P->SwatchPad = 4.;
    }

  if (this->Orientation == VTK_ORIENT_VERTICAL)
    {
    this->P->NanBox.Posn[0] = this->P->ScalarBarBox.Posn[0];
864
    this->P->NanBox.Posn[1] = this->P->Frame.Posn[1] + this->TextPad;
865
866
867
868
869
870
871
872
873
874
875
    this->P->ScalarBarBox.Posn[1] +=
      this->P->NanSwatchSize + this->P->SwatchPad;
    }
  else // HORIZONTAL
    {
    this->P->NanBox.Posn = this->P->ScalarBarBox.Posn;
    this->P->NanBox.Posn[this->P->TL[1]] +=
      this->P->Frame.Size[1] - this->P->NanSwatchSize;
    }
  this->P->NanBox.Size[0] = this->P->ScalarBarBox.Size[0];
  this->P->NanBox.Size[1] = this->P->NanSwatchSize;
876
877
878
879
  if (this->P->NanBox.Size[1] > 2 * this->TextPad)
    {
    this->P->NanBox.Size[1] -= this->TextPad;
    }
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
}

//----------------------------------------------------------------------------
void vtkScalarBarActor::PrepareTitleText()
{
  // Update actor with the latest title/subtitle
  if (this->ComponentTitle && strlen(this->ComponentTitle) > 0)
    {
    //need to account for a space between title & component and null term
    char* combinedTitle =
      new char[strlen(this->Title) + strlen(this->ComponentTitle) + 2];
    strcpy(combinedTitle, this->Title );
    strcat(combinedTitle, " ");
    strcat(combinedTitle, this->ComponentTitle);
    this->TitleActor->SetInput(combinedTitle);
    delete [] combinedTitle;
    }
  else
    {
    this->TitleActor->SetInput(this->Title);
    }

  if (this->TitleTextProperty->GetMTime() > this->BuildTime)
    {
    // Shallow copy here so that the size of the title prop is not affected
    // by the automatic adjustment of its text mapper's size (i.e. its
    // mapper's text property is identical except for the font size
    // which will be modified later). This allows text actors to
    // share the same text property, and in that case specifically allows
    // the title and label text prop to be the same.
    this->TitleActor->GetTextProperty()->ShallowCopy(this->TitleTextProperty);
    this->TitleActor->GetTextProperty()->SetJustificationToCentered();
    this->TitleActor->GetTextProperty()->SetVerticalJustification(
      this->TextPosition == PrecedeScalarBar ? VTK_TEXT_BOTTOM : VTK_TEXT_TOP);
    }
}

//----------------------------------------------------------------------------
void vtkScalarBarActor::LayoutTitle()
{
  if (this->Title == NULL || !strlen(this->Title))
    {
    return;
    }

  int targetWidth, targetHeight;
  // Title spans entire width of frame at top, regardless of orientation.
927
  targetWidth = static_cast<int>(this->P->Frame.Size[this->P->TL[0]]) - 2 * this->TextPad;
928
929
930
931
932
933
934
935
936
  // Height is either: at most half the frame height or
  // a fixed portion of the frame remaining after subtracting the
  // scalar bar's thickness.
  //
  // When laid out horizontally, ticks share vertical space with title.
  // We want the title to be larger (18pt vs 14pt).
  targetHeight = static_cast<int>((
    this->Orientation == VTK_ORIENT_VERTICAL ||
    this->LookupTable->GetIndexedLookup()) ?
937
938
939
940
941
    ceil(this->P->Frame.Size[this->P->TL[1]] / 2. - this->TextPad) :
    (this->P->Frame.Size[0] - this->P->ScalarBarBox.Size[0] -
     (this->TextPosition == SucceedScalarBar ?
     this->P->ScalarBarBox.Posn[this->P->TL[0]] : 0) - this->TextPad) *
     this->TitleRatio);
942
943
944
945
946
947
948
949

  this->TitleActor->SetConstrainedFontSize(
    this->P->Viewport, targetWidth, targetHeight);

  // Now fetch the actual size from the actor and use it to
  // update the box size and position.
  double titleSize[2] = {0, 0};
  this->TitleActor->GetSize(this->P->Viewport, titleSize);
950
  this->TitleActor->GetTextProperty()->SetVerticalJustificationToTop();
951
952
953
954
955
  for (int i = 0; i < 2; ++i)
    {
    this->P->TitleBox.Size[this->P->TL[i]] =
      static_cast<int>(ceil(titleSize[i]));
    }
Sebastien Barre's avatar
Sebastien Barre committed
956

957
958
959
960
961
962
963
964
965
  this->P->TitleBox.Posn[0] =
    this->P->Frame.Posn[0] +
    (this->P->Frame.Size[this->P->TL[0]] - titleSize[0]) / 2;
  this->P->TitleBox.Posn[1] =
    this->P->Frame.Posn[1] + this->P->Frame.Size[this->P->TL[1]];
  if (
    this->Orientation == VTK_ORIENT_VERTICAL ||
    this->TextPosition == vtkScalarBarActor::SucceedScalarBar)
    {
966
    this->P->TitleBox.Posn[1] -= this->P->TitleBox.Size[this->P->TL[1]] + this->TextPad;
967
968
969
    }
  else
    {
970
    this->P->TitleBox.Posn[1] = this->P->Frame.Posn[1] + this->TextPad;
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
    }
}

//-----------------------------------------------------------------------------
void vtkScalarBarActor::ComputeScalarBarLength()
{
  this->P->ScalarBarBox.Size[1] =
    this->Orientation == VTK_ORIENT_VERTICAL ?
      this->P->Frame.Size[1] - this->P->TitleBox.Size[1] :
      this->P->Frame.Size[1];

  // The scalar bar does not include the Nan Swatch.
  this->P->ScalarBarBox.Size[1] -= this->P->NanSwatchSize + this->P->SwatchPad;
}

//-----------------------------------------------------------------------------
void vtkScalarBarActor::LayoutTicks()
{
  if (this->LookupTable->GetIndexedLookup())
    { // no tick marks in indexed lookup mode.
    this->NumberOfLabelsBuilt = 0;
    return;
    }
994

995
996
997
  // find the best size for the ticks
  double* range = this->LookupTable->GetRange();
  char string[512];
Ken Martin's avatar
Ken Martin committed
998
  double val;
Ken Martin's avatar
Ken Martin committed
999
  int i;
1000

Sebastien Barre's avatar
Sebastien Barre committed
1001
1002
1003
1004
1005
  // TODO: this should be optimized, maybe by keeping a list of
  // allocated mappers, in order to avoid creation/destruction of
  // their underlying text properties (i.e. each time a mapper is
  // created, text properties are created and shallow-assigned a font size
  // which value might be "far" from the target font size).
1006
  this->P->TextActors.resize(this->NumberOfLabels);
1007

1008
  // Does this map have its scale set to log?
1009
  int isLogTable = this->LookupTable->UsingLogScale();
1010

1011
  for (i = 0; i < this->NumberOfLabels; i++)
Ken Martin's avatar
Ken Martin committed
1012
    {
1013
    this->P->TextActors[i].TakeReference(vtkTextActor::New());
Sebastien Barre's avatar
Sebastien Barre committed
1014

1015
1016
    if ( isLogTable )
      {
Ken Martin's avatar
Ken Martin committed
1017
      double lval;
Ken Martin's avatar
Ken Martin committed
1018
1019
      if (this->NumberOfLabels > 1)
        {
1020
1021
        lval = log10(range[0]) +
          static_cast<double>(i)/(this->NumberOfLabels-1) *
Ken Martin's avatar
Ken Martin committed
1022
1023
1024
1025
1026
1027
          (log10(range[1])-log10(range[0]));
        }
      else
        {
        lval = log10(range[0]) + 0.5*(log10(range[1])-log10(range[0]));
        }
Ken Martin's avatar
Ken Martin committed
1028
      val = pow(10.0,lval);
1029
1030
1031
      }
    else
      {
Ken Martin's avatar
Ken Martin committed
1032
1033
      if (this->NumberOfLabels > 1)
        {
1034
        val = range[0] +
1035
          static_cast<double>(i)/(this->NumberOfLabels-1)
1036
          * (range[1]-range[0]);
Ken Martin's avatar
Ken Martin committed
1037
1038
1039
1040
1041
        }
      else
        {
        val = range[0] + 0.5*(range[1]-range[0]);
        }
1042
1043
      }

1044
1045
    SNPRINTF(string, 511, this->LabelFormat, val);
    this->P->TextActors[i]->SetInput(string);
Sebastien Barre's avatar
Sebastien Barre committed
1046
1047
1048
1049
1050
1051
1052

    // Shallow copy here so that the size of the label prop is not affected
    // by the automatic adjustment of its text mapper's size (i.e. its
    // mapper's text property is identical except for the font size
    // which will be modified later). This allows text actors to
    // share the same text property, and in that case specifically allows
    // the title and label text prop to be the same.
1053
    this->P->TextActors[i]->GetTextProperty()->ShallowCopy(
Sebastien Barre's avatar
Sebastien Barre committed
1054
1055
      this->LabelTextProperty);

1056
1057
    this->P->TextActors[i]->SetProperty(this->GetProperty());
    this->P->TextActors[i]->GetPositionCoordinate()->
Ken Martin's avatar
Ken Martin committed
1058
1059
      SetReferenceCoordinate(this->PositionCoordinate);
    }