vtkScalarBarActor.cxx 49.8 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

17
18
#include "vtkCellArray.h"
#include "vtkCellData.h"
19
#include "vtkObjectFactory.h"
20
#include "vtkPolyData.h"
21
22
23
#include "vtkPolyDataMapper2D.h"
#include "vtkScalarsToColors.h"
#include "vtkTextMapper.h"
Sebastien Barre's avatar
Sebastien Barre committed
24
#include "vtkTextProperty.h"
25
26
#include "vtkViewport.h"
#include "vtkWindow.h"
27
#include "vtkLookupTable.h"
28
29
30
31
32
#include "vtkFloatArray.h"
#include "vtkPointData.h"
#include "vtkTexture.h"
#include "vtkImageData.h"
#include "vtkRenderer.h"
33
#include "vtkMathTextActor.h"
34
35
#include "vtkProperty2D.h"

36
37
38
#include <vector>
#include <set>

Brad King's avatar
Brad King committed
39
vtkStandardNewMacro(vtkScalarBarActor);
40

41
vtkCxxSetObjectMacro(vtkScalarBarActor,LookupTable,vtkScalarsToColors);
Sebastien Barre's avatar
Sebastien Barre committed
42
43
vtkCxxSetObjectMacro(vtkScalarBarActor,LabelTextProperty,vtkTextProperty);
vtkCxxSetObjectMacro(vtkScalarBarActor,TitleTextProperty,vtkTextProperty);
44
45
vtkCxxSetObjectMacro(vtkScalarBarActor,BackgroundProperty,vtkProperty2D);
vtkCxxSetObjectMacro(vtkScalarBarActor,FrameProperty,vtkProperty2D);
46

Sebastien Barre's avatar
Sebastien Barre committed
47
48
//----------------------------------------------------------------------------
// Instantiate object with 64 maximum colors; 5 labels; %%-#6.3g label
49
50
51
52
53
// format, no title, and vertical orientation. The initial scalar bar
// size is (0.05 x 0.8) of the viewport size.
vtkScalarBarActor::vtkScalarBarActor()
{
  this->LookupTable = NULL;
54
  this->Position2Coordinate->SetValue(0.17, 0.8);
55

56
57
  this->PositionCoordinate->SetCoordinateSystemToNormalizedViewport();
  this->PositionCoordinate->SetValue(0.82,0.1);
58

59
60
  this->MaximumNumberOfColors = 64;
  this->NumberOfLabels = 5;
61
  this->NumberOfLabelsBuilt = 0;
62
63
  this->Orientation = VTK_ORIENT_VERTICAL;
  this->Title = NULL;
64
  this->ComponentTitle = NULL;
65

Sebastien Barre's avatar
Sebastien Barre committed
66
67
68
69
70
71
72
73
74
75
  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);

76
  this->LabelFormat = new char[8];
77
78
79
80
81
  sprintf(this->LabelFormat,"%s","%-#6.3g");

  this->TitleMapper = vtkTextMapper::New();
  this->TitleActor = vtkActor2D::New();
  this->TitleActor->SetMapper(this->TitleMapper);
82
83
  this->TitleActor->GetPositionCoordinate()->
    SetReferenceCoordinate(this->PositionCoordinate);
84

85
86
87
88
89
  this->TextMappers = NULL;
  this->TextActors = NULL;

  this->ScalarBar = vtkPolyData::New();
  this->ScalarBarMapper = vtkPolyDataMapper2D::New();
90
  this->ScalarBarMapper->SetInputData(this->ScalarBar);
91
92
  this->ScalarBarActor = vtkActor2D::New();
  this->ScalarBarActor->SetMapper(this->ScalarBarMapper);
93
94
  this->ScalarBarActor->GetPositionCoordinate()->
    SetReferenceCoordinate(this->PositionCoordinate);
Ken Martin's avatar
Ken Martin committed
95
96
97
98
  this->LastOrigin[0] = 0;
  this->LastOrigin[1] = 0;
  this->LastSize[0] = 0;
  this->LastSize[1] = 0;
99

100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
  this->AnnotationBoxes = vtkPolyData::New();
  this->AnnotationBoxesMapper = vtkPolyDataMapper2D::New();
  this->AnnotationBoxesActor = vtkActor2D::New();
  this->AnnotationBoxesMapper->SetInputData( this->AnnotationBoxes );
  this->AnnotationBoxesActor->SetMapper( this->AnnotationBoxesMapper );
  this->AnnotationBoxesActor->GetPositionCoordinate()->
    SetReferenceCoordinate( this->PositionCoordinate );
  this->AnnotationLeaders = vtkPolyData::New();
  this->AnnotationLeadersMapper = vtkPolyDataMapper2D::New();
  this->AnnotationLeadersActor = vtkActor2D::New();
  this->AnnotationLeadersMapper->SetInputData( this->AnnotationLeaders );
  this->AnnotationLeadersActor->SetMapper( this->AnnotationLeadersMapper );
  this->AnnotationLeadersActor->GetPositionCoordinate()->
    SetReferenceCoordinate( this->PositionCoordinate );
  this->AnnotationLabels = 0; // Can't allocate until we have a lookup table.
  this->NumberOfAnnotationLabelsBuilt = 0;

117
118
119
120
  // If opacity is on, a jail like texture is displayed behind it..

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

122
123
  this->TexturePolyData = vtkPolyData::New();
  vtkPolyDataMapper2D * textureMapper = vtkPolyDataMapper2D::New();
124
  textureMapper->SetInputData(this->TexturePolyData);
125
126
127
128
129
130
131
132
  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);
133
  tc->InsertComponent(0,0, 0.0);
134
135
  tc->InsertComponent(0,1, 0.0);
  tc->InsertComponent(1,1, 0.0);
136
  tc->InsertComponent(3,0, 0.0);
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
  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();

  vtkProperty2D *imageProperty = vtkProperty2D::New();
  imageProperty->SetOpacity(0.08);
  this->TextureActor->SetProperty(imageProperty);
  imageProperty->Delete();

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

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

161
162
  for (unsigned int y = 0; y < dim; y++)
    {
163
    unsigned char *ptr =
164
165
166
167
168
169
170
171
172
      static_cast< unsigned char * >(image->GetScalarPointer(0, y, 0));
    for (unsigned int x = 0; x < dim; x++)
      {
      *ptr = ((x == y) || (x == (dim-y-1))) ? 255 : 0;
      ++ptr;
      }
    }

  this->Texture = vtkTexture::New();
173
  this->Texture->SetInputData( image );
174
175
  this->Texture->RepeatOn();
  image->Delete();
176
177
178
179

  // Default text position : Above scalar bar if orientation is horizontal
  //                         Right of scalar bar if orientation is vertical
  this->TextPosition = SucceedScalarBar;
180
181
182

  this->MaximumWidthInPixels = VTK_INT_MAX;
  this->MaximumHeightInPixels = VTK_INT_MAX;
183
184
185
186
187
188
189

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

  this->DrawBackground = 0;
  this->Background = vtkPolyData::New();
  this->BackgroundMapper = vtkPolyDataMapper2D::New();
190
  this->BackgroundMapper->SetInputData(this->Background);
191
192
193
194
195
196
197
  this->BackgroundActor = vtkActor2D::New();
  this->BackgroundActor->SetMapper(this->BackgroundMapper);
  this->BackgroundActor->GetPositionCoordinate()->SetReferenceCoordinate(this->PositionCoordinate);

  this->DrawFrame = 0;
  this->Frame = vtkPolyData::New();
  this->FrameMapper = vtkPolyDataMapper2D::New();
198
  this->FrameMapper->SetInputData(this->Frame);
199
200
201
  this->FrameActor = vtkActor2D::New();
  this->FrameActor->SetMapper(this->FrameMapper);
  this->FrameActor->GetPositionCoordinate()->SetReferenceCoordinate(this->PositionCoordinate);
202
203
}

Sebastien Barre's avatar
Sebastien Barre committed
204
//----------------------------------------------------------------------------
Ken Martin's avatar
Ken Martin committed
205
206
207
208
209
210
211
212
213
214
215
216
217
// Release any graphics resources that are being consumed by this actor.
// The parameter window could be used to determine which graphic
// resources to release.
void vtkScalarBarActor::ReleaseGraphicsResources(vtkWindow *win)
{
  this->TitleActor->ReleaseGraphicsResources(win);
  if (this->TextMappers != NULL )
    {
    for (int i=0; i < this->NumberOfLabelsBuilt; i++)
      {
      this->TextActors[i]->ReleaseGraphicsResources(win);
      }
    }
218
219
220
221
222
223
224
  if ( this->AnnotationLabels != NULL )
    {
    for ( int i = 0; i < this->NumberOfAnnotationLabelsBuilt; ++ i )
      {
      this->AnnotationLabels[i]->ReleaseGraphicsResources(win);
      }
    }
Ken Martin's avatar
Ken Martin committed
225
  this->ScalarBarActor->ReleaseGraphicsResources(win);
226
227
  this->AnnotationBoxesActor->ReleaseGraphicsResources(win);
  this->AnnotationLeadersActor->ReleaseGraphicsResources(win);
228
229
  this->BackgroundActor->ReleaseGraphicsResources(win);
  this->FrameActor->ReleaseGraphicsResources(win);
Ken Martin's avatar
Ken Martin committed
230
231
}

Sebastien Barre's avatar
Sebastien Barre committed
232
//----------------------------------------------------------------------------
233
234
vtkScalarBarActor::~vtkScalarBarActor()
{
235
  if (this->LabelFormat)
Ken Martin's avatar
Ken Martin committed
236
237
238
239
    {
    delete [] this->LabelFormat;
    this->LabelFormat = NULL;
    }
240
241
242
243
244
245

  this->TitleMapper->Delete();
  this->TitleActor->Delete();

  if (this->TextMappers != NULL )
    {
246
    for (int i=0; i < this->NumberOfLabelsBuilt; i++)
247
248
249
250
251
252
253
254
      {
      this->TextMappers[i]->Delete();
      this->TextActors[i]->Delete();
      }
    delete [] this->TextMappers;
    delete [] this->TextActors;
    }

255
256
257
258
259
260
261
262
263
  if ( this->AnnotationLabels != NULL )
    {
    for ( int i = 0; i < this->NumberOfAnnotationLabelsBuilt; ++ i )
      {
      this->AnnotationLabels[i]->Delete();
      }
    delete [] this->AnnotationLabels;
    }

264
265
266
  this->ScalarBar->Delete();
  this->ScalarBarMapper->Delete();
  this->ScalarBarActor->Delete();
Ken Martin's avatar
Ken Martin committed
267

268
269
270
271
272
273
274
275
  this->AnnotationBoxes->Delete();
  this->AnnotationBoxesMapper->Delete();
  this->AnnotationBoxesActor->Delete();

  this->AnnotationLeaders->Delete();
  this->AnnotationLeadersMapper->Delete();
  this->AnnotationLeadersActor->Delete();

Ken Martin's avatar
Ken Martin committed
276
277
278
279
280
  if (this->Title)
    {
    delete [] this->Title;
    this->Title = NULL;
    }
281
282
283
284
285
286

  if ( this->ComponentTitle )
    {
    delete [] this->ComponentTitle;
    this->ComponentTitle = NULL;
    }
287

288
  this->SetLookupTable(NULL);
Sebastien Barre's avatar
Sebastien Barre committed
289
290
  this->SetLabelTextProperty(NULL);
  this->SetTitleTextProperty(NULL);
291
292
293
  this->Texture->Delete();
  this->TextureActor->Delete();
  this->TexturePolyData->Delete();
294
295
296
297
298
299
300
301
  this->Background->Delete();
  this->BackgroundMapper->Delete();
  this->BackgroundActor->Delete();
  this->Frame->Delete();
  this->FrameMapper->Delete();
  this->FrameActor->Delete();
  this->SetBackgroundProperty(NULL);
  this->SetFrameProperty(NULL);
302
303
}

Sebastien Barre's avatar
Sebastien Barre committed
304
//----------------------------------------------------------------------------
305
int vtkScalarBarActor::RenderOverlay(vtkViewport *viewport)
Ken Martin's avatar
Ken Martin committed
306
{
307
  int renderedSomething = 0;
Ken Martin's avatar
Ken Martin committed
308
  int i;
309

310
311
312
313
  if (this->DrawBackground)
    {
    renderedSomething += this->BackgroundActor->RenderOverlay(viewport);
    }
314

315
316
317
318
  if (this->DrawFrame)
    {
    renderedSomething += this->FrameActor->RenderOverlay(viewport);
    }
319

320
321
322
323
324
325
  if (this->UseOpacity)
    {
    this->Texture->Render(vtkRenderer::SafeDownCast(viewport));
    renderedSomething += this->TextureActor->RenderOverlay(viewport);
    }

Ken Martin's avatar
Ken Martin committed
326
327
328
  // Everything is built, just have to render
  if (this->Title != NULL)
    {
329
    renderedSomething += this->TitleActor->RenderOverlay(viewport);
Ken Martin's avatar
Ken Martin committed
330
    }
331
332
333
334

  // Draw either the scalar bar (non-indexed mode) or the annotated value boxes (indexed mode).
  vtkLookupTable* lkup = vtkLookupTable::SafeDownCast( this->LookupTable );
  if ( ! lkup || ( lkup && ! lkup->GetIndexedLookup() ) )
335
    {
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
    this->ScalarBarActor->RenderOverlay(viewport);

    if( this->TextActors == NULL)
      {
      vtkWarningMacro(<<"Need a mapper to render a scalar bar");
      return renderedSomething;
      }

    for (i=0; i<this->NumberOfLabels; i++)
      {
      renderedSomething += this->TextActors[i]->RenderOverlay(viewport);
      }
    }
  else
    {
    this->AnnotationBoxesActor->RenderOverlay(viewport);
352
    }
353

354
  if ( this->AnnotationLabels == NULL && this->NumberOfAnnotationLabelsBuilt )
Ken Martin's avatar
Ken Martin committed
355
    {
356
357
    vtkWarningMacro(<<"Need a mapper to render the scalar bar");
    return renderedSomething;
Ken Martin's avatar
Ken Martin committed
358
    }
359

360
361
362
363
  for ( i = 0; i < this->NumberOfAnnotationLabelsBuilt; ++ i )
    {
    renderedSomething += this->AnnotationLabels[i]->RenderOverlay( viewport );
    }
364

365
  renderedSomething = (renderedSomething > 0)?(1):(0);
366
  return renderedSomething;
Ken Martin's avatar
Ken Martin committed
367
368
}

Sebastien Barre's avatar
Sebastien Barre committed
369
//----------------------------------------------------------------------------
370
int vtkScalarBarActor::RenderOpaqueGeometry(vtkViewport *viewport)
371
{
372
  int renderedSomething = 0;
373
  int i;
374
  int size[2];
375

Sebastien Barre's avatar
Sebastien Barre committed
376
  if (!this->LookupTable)
377
378
    {
    vtkWarningMacro(<<"Need a mapper to render a scalar bar");
379
    return 0;
380
381
    }

Sebastien Barre's avatar
Sebastien Barre committed
382
383
384
385
386
387
388
389
390
391
392
393
  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
394
  // Check to see whether we have to rebuild everything
395
  int positionsHaveChanged = 0;
396
397
  if (viewport->GetMTime() > this->BuildTime ||
      (viewport->GetVTKWindow() &&
Sebastien Barre's avatar
Sebastien Barre committed
398
       viewport->GetVTKWindow()->GetMTime() > this->BuildTime))
Ken Martin's avatar
Ken Martin committed
399
400
401
    {
    // if the viewport has changed we may - or may not need
    // to rebuild, it depends on if the projected coords chage
Bill Lorensen's avatar
Bill Lorensen committed
402
    int *barOrigin;
Ken Martin's avatar
Ken Martin committed
403
    barOrigin = this->PositionCoordinate->GetComputedViewportValue(viewport);
404
    size[0] =
Ken Martin's avatar
Ken Martin committed
405
406
      this->Position2Coordinate->GetComputedViewportValue(viewport)[0] -
      barOrigin[0];
407
    size[1] =
Ken Martin's avatar
Ken Martin committed
408
409
      this->Position2Coordinate->GetComputedViewportValue(viewport)[1] -
      barOrigin[1];
410

411
412
    // Check if we have bounds on the maximum size
    size[0] = size[0] > this->MaximumWidthInPixels
413
            ? this->MaximumWidthInPixels : size[0];
414
    size[1] = size[1] > this->MaximumHeightInPixels
415
416
            ? this->MaximumHeightInPixels : size[1];

417
    if (this->LastSize[0] != size[0] ||
Sebastien Barre's avatar
Sebastien Barre committed
418
        this->LastSize[1] != size[1] ||
419
        this->LastOrigin[0] != barOrigin[0] ||
420
        this->LastOrigin[1] != barOrigin[1])
Ken Martin's avatar
Ken Martin committed
421
      {
422
      positionsHaveChanged = 1;
Ken Martin's avatar
Ken Martin committed
423
424
      }
    }
425

426
  // Check to see whether we have to rebuild everything
427
  if (positionsHaveChanged ||
428
      this->GetMTime() > this->BuildTime ||
Sebastien Barre's avatar
Sebastien Barre committed
429
430
      this->LookupTable->GetMTime() > this->BuildTime ||
      this->LabelTextProperty->GetMTime() > this->BuildTime ||
431
432
433
434
      this->TitleTextProperty->GetMTime() > this->BuildTime ||
      this->BackgroundProperty->GetMTime() > this->BuildTime ||
      this->FrameProperty->GetMTime() > this->BuildTime)

435
436
437
438
439
440
441
    {
    vtkDebugMacro(<<"Rebuilding subobjects");

    // Delete previously constructed objects
    //
    if (this->TextMappers != NULL )
      {
442
      for (i=0; i < this->NumberOfLabelsBuilt; i++)
443
444
445
446
        {
        this->TextMappers[i]->Delete();
        this->TextActors[i]->Delete();
        }
447
448
449
450
      delete [] this->TextMappers;
      delete [] this->TextActors;
      }

451
452
453
454
455
456
457
458
459
460
    if ( this->AnnotationLabels != NULL )
      {
      for ( i = 0; i < this->NumberOfAnnotationLabelsBuilt; ++ i )
        {
        this->AnnotationLabels[i]->Delete();
        }
      delete [] this->AnnotationLabels;
      this->AnnotationLabels = 0;
      }

461
    // Build scalar bar object; determine its type
462
    // i.e. is scale set to log, is categorical or continuous?
463
    int isLogTable = this->LookupTable->UsingLogScale();
464
465
    vtkLookupTable* lkup = vtkLookupTable::SafeDownCast( this->LookupTable );
    int isCategorical = lkup && lkup->GetIndexedLookup();
466

Ken Martin's avatar
Ken Martin committed
467
    // we hard code how many steps to display
468
    vtkScalarsToColors *lut = this->LookupTable;
Ken Martin's avatar
Ken Martin committed
469
    int numColors = this->MaximumNumberOfColors;
Ken Martin's avatar
Ken Martin committed
470
    double *range = lut->GetRange();
471
472
473
474
475
476

    int numPts = 2*(numColors + 1);
    vtkPoints *pts = vtkPoints::New();
    pts->SetNumberOfPoints(numPts);
    vtkCellArray *polys = vtkCellArray::New();
    polys->Allocate(polys->EstimateSize(numColors,4));
477
    vtkUnsignedCharArray *colors = vtkUnsignedCharArray::New();
478
479
480

    unsigned int nComponents = ((this->UseOpacity) ? 4 : 3);
    colors->SetNumberOfComponents( nComponents );
481
    colors->SetNumberOfTuples(numColors);
482
483
484
485
486
487
488
489

    this->ScalarBarActor->SetProperty(this->GetProperty());
    this->ScalarBar->Initialize();
    this->ScalarBar->SetPoints(pts);
    this->ScalarBar->SetPolys(polys);
    this->ScalarBar->GetCellData()->SetScalars(colors);
    pts->Delete(); polys->Delete(); colors->Delete();

490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
    // set frame structure
    vtkPoints *frPts = vtkPoints::New();
    frPts->SetNumberOfPoints(5);
    vtkCellArray *frLines = vtkCellArray::New();
    frLines->Allocate(frLines->EstimateSize(1,5));

    this->FrameActor->SetProperty(this->FrameProperty);
    this->Frame->Initialize();
    this->Frame->SetPoints(frPts);
    this->Frame->SetLines(frLines);
    frPts->Delete(); frLines->Delete();

    // set background structure
    vtkPoints *bgPts = vtkPoints::New();
    bgPts->SetNumberOfPoints(4);
    vtkCellArray *bgPolys = vtkCellArray::New();
    bgPolys->Allocate(bgPolys->EstimateSize(1,4));

    this->BackgroundActor->SetProperty(this->BackgroundProperty);
    this->Background->Initialize();
    this->Background->SetPoints(bgPts);
    this->Background->SetPolys(bgPolys);
    bgPts->Delete(); bgPolys->Delete();

514
    // get the viewport size in display coordinates
515
516
    int *barOrigin, barWidth, barHeight;
    barOrigin = this->PositionCoordinate->GetComputedViewportValue(viewport);
517
    size[0] =
518
519
      this->Position2Coordinate->GetComputedViewportValue(viewport)[0] -
      barOrigin[0];
520
    size[1] =
521
522
      this->Position2Coordinate->GetComputedViewportValue(viewport)[1] -
      barOrigin[1];
523

524
525
    // Check if we have bounds on the maximum size
    size[0] = size[0] > this->MaximumWidthInPixels
526
            ? this->MaximumWidthInPixels : size[0];
527
    size[1] = size[1] > this->MaximumHeightInPixels
528
            ? this->MaximumHeightInPixels : size[1];
529

Ken Martin's avatar
Ken Martin committed
530
531
532
533
    this->LastOrigin[0] = barOrigin[0];
    this->LastOrigin[1] = barOrigin[1];
    this->LastSize[0] = size[0];
    this->LastSize[1] = size[1];
534

535
536
    // Update all the composing objects
    this->TitleActor->SetProperty(this->GetProperty());
537
538


539
540
541
    //update with the proper title
    if ( this->ComponentTitle && strlen(this->ComponentTitle) > 0 )
      {
542
      //need to account for a space between title & component and null term
543
      char *combinedTitle = new char[ ( strlen(this->Title) + strlen(this->ComponentTitle) + 2) ];
544
545
546
547
548
549
550
551
552
553
554
      strcpy(combinedTitle, this->Title );
      strcat( combinedTitle, " " );
      strcat( combinedTitle, this->ComponentTitle );
      this->TitleMapper->SetInput(combinedTitle);
      delete [] combinedTitle;
      }
    else
      {
      this->TitleMapper->SetInput(this->Title);
      }

Sebastien Barre's avatar
Sebastien Barre committed
555
556
557
558
559
560
561
562
563
564
565
    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->TitleMapper->GetTextProperty()->ShallowCopy(this->TitleTextProperty);
      this->TitleMapper->GetTextProperty()->SetJustificationToCentered();
      }
566

Ken Martin's avatar
Ken Martin committed
567
568
569
    // find the best size for the title font
    int titleSize[2];
    this->SizeTitle(titleSize, size, viewport);
570

Ken Martin's avatar
Ken Martin committed
571
572
573
    // find the best size for the ticks
    int labelSize[2];
    this->AllocateAndSizeLabels(labelSize, size, viewport,range);
574
    this->NumberOfLabelsBuilt = this->NumberOfLabels;
575

576
    // generate points
Ken Martin's avatar
Ken Martin committed
577
578
    double x[3]; x[2] = 0.0;
    double delta;
Philippe Pébay's avatar
Philippe Pébay committed
579
580
    int barX = 0;
    int barY = 0;
581
582
    if ( this->Orientation == VTK_ORIENT_VERTICAL )
      {
583
584
585
      // Adjust height and width only in enhanced more or if at least
      // one amongst the frame and the background was requested
      if ( this->DrawBackground ||
586
           this->DrawFrame )
587
588
589
590
        {
        barX = static_cast<int>(size[0] * 0.05);
        barY = static_cast<int>(size[1] * 0.05 + labelSize[1] / 2);
        }
591
592
593

      barWidth = size[0] - 4 - labelSize[0] - 2 * barX;
      barHeight = static_cast<int>(0.86*size[1]) - barY;
594
      delta=static_cast<double>(barHeight)/numColors;
595
      for (i=0; i<numPts/2; i++)
596
        {
597
        x[0] = (this->TextPosition == vtkScalarBarActor::PrecedeScalarBar)
598
599
          ? (size[0] - barWidth - barX) : barX;
        x[1] = barY + i*delta;
600
        pts->SetPoint(2*i,x);
601
        x[0] = (this->TextPosition == vtkScalarBarActor::PrecedeScalarBar)
602
          ? size[0] - barX: barX + barWidth;
603
        pts->SetPoint(2*i+1,x);
604
        }
605
606
607
      }
    else
      {
608
609
610
      // Adjust height and width only in enhanced more or if at least
      // one amongst the frame and the background was requested
      if ( this->DrawBackground ||
611
           this->DrawFrame )
612
        {
613
614
        barX = static_cast<int>(size[0] * 0.05) + labelSize[0] / 2;
        barY = static_cast<int>(size[1] * 0.05);
615
        }
616
617
      barWidth = size[0] - 2 * barX;
      barHeight = static_cast<int>(0.4*size[1]) - barY;
618
      delta=static_cast<double>(barWidth)/numColors;
619
      for (i=0; i<numPts/2; i++)
620
        {
621
        x[0] = barX + i*delta;
622
        x[1] = (this->TextPosition == vtkScalarBarActor::PrecedeScalarBar)
623
          ? size[1] - barY: barY + barHeight ;
624
        pts->SetPoint(2*i,x);
625
        x[1] = (this->TextPosition == vtkScalarBarActor::PrecedeScalarBar)
626
          ? (size[1]-barHeight - barY) : barY;
627
        pts->SetPoint(2*i+1,x);
628
        }
629
      }
630

631
632
    //polygons & cell colors
    unsigned char *rgba, *rgb;
633
    vtkIdType ptIds[4];
634
635
636
637
638
639
640
641
    for (i=0; i<numColors; i++)
      {
      ptIds[0] = 2*i;
      ptIds[1] = ptIds[0] + 1;
      ptIds[2] = ptIds[1] + 2;
      ptIds[3] = ptIds[0] + 2;
      polys->InsertNextCell(4,ptIds);

642
643
      if ( isLogTable )
        {
644
        double rgbval = log10(range[0]) +
645
          i*(log10(range[1])-log10(range[0]))/(numColors -1);
Ken Martin's avatar
Ken Martin committed
646
        rgba = lut->MapValue(pow(10.0,rgbval));
647
648
649
650
        }
      else
        {
        rgba = lut->MapValue(range[0] + (range[1] - range[0])*
651
                             (i /(numColors-1.0)));
652
653
        }

654
      rgb = colors->GetPointer( nComponents * i); //write into array directly
655
656
657
      rgb[0] = rgba[0];
      rgb[1] = rgba[1];
      rgb[2] = rgba[2];
658
659
660
661
      if (this->UseOpacity)
        {
        rgb[3] = rgba[3];
        }
662
663
      }

664
665
666
667
668
    // generate background and frame points and cell
    x[0]=0; x[1]=0;
    bgPts->SetPoint(0,x);
    frPts->SetPoint(0,x);
    frPts->SetPoint(4,x);
669

670
671
672
    x[0]=0; x[1]=size[1];
    bgPts->SetPoint(1,x);
    frPts->SetPoint(1,x);
673

674
675
676
    x[0]=size[0]; x[1]=size[1];
    bgPts->SetPoint(2,x);
    frPts->SetPoint(2,x);
677

678
679
680
681
682
683
684
685
    x[0]=size[0]; x[1]=0;
    bgPts->SetPoint(3,x);
    frPts->SetPoint(3,x);

    vtkIdType bgIds[5] = {0,1,2,3,4};
    bgPolys->InsertNextCell(4,bgIds);
    frLines->InsertNextCell(5,bgIds);

686
687
    // Now position everything properly
    //
Ken Martin's avatar
Ken Martin committed
688
    double val;
689
    int sizeTextData[2];
690
691
    if (this->Orientation == VTK_ORIENT_VERTICAL)
      {
692
      // center the title
Ken Martin's avatar
Ken Martin committed
693
      this->TitleActor->SetPosition(size[0]/2, 0.9*size[1]);
694

Jim Miller's avatar
Style    
Jim Miller committed
695
      for (i=0; i < this->NumberOfLabels; i++)
696
        {
Ken Martin's avatar
Ken Martin committed
697
698
        if (this->NumberOfLabels > 1)
          {
699
          val = static_cast<double>(i)/(this->NumberOfLabels-1) *barHeight + barY;
Ken Martin's avatar
Ken Martin committed
700
          }
701
        else
Ken Martin's avatar
Ken Martin committed
702
          {
703
          val = 0.5*(barHeight + barY);
Ken Martin's avatar
Ken Martin committed
704
          }
705
        this->TextMappers[i]->GetSize(viewport,sizeTextData);
Sebastien Barre's avatar
Sebastien Barre committed
706
        this->TextMappers[i]->GetTextProperty()->SetJustificationToLeft();
707
708
        if (this->TextPosition == vtkScalarBarActor::PrecedeScalarBar)
          {
709
          this->TextActors[i]->SetPosition(barX,
710
                                           val - 0.6*sizeTextData[1]);
711
712
713
          }
        else
          {
714
          this->TextActors[i]->SetPosition(barX + barWidth + 3,
715
                                           val - 0.6*sizeTextData[1]);
716
          }
717
        }
718
      }
719
    else // if (this->Orientation == VTK_ORIENT_VERTICAL)
720
      {
721
722
      if (this->TextPosition == vtkScalarBarActor::PrecedeScalarBar)
        {
723
        this->TitleActor->SetPosition(size[0]/2,
724
                                      barY + 0.1*titleSize[1]);
725
726
727
        }
      else
        {
728
        this->TitleActor->SetPosition(size[0]/2,
729
                                      barHeight + labelSize[1] + 0.1*size[1] + 0.15*titleSize[1]);
730
        }
Jim Miller's avatar
Style    
Jim Miller committed
731
      for (i=0; i < this->NumberOfLabels; i++)
732
        {
733
        this->TextMappers[i]->GetSize(viewport,sizeTextData);
Sebastien Barre's avatar
Sebastien Barre committed
734
        this->TextMappers[i]->GetTextProperty()->SetJustificationToCentered();
Ken Martin's avatar
Ken Martin committed
735
736
        if (this->NumberOfLabels > 1)
          {
737
          val = static_cast<double>(i)/(this->NumberOfLabels-1) * barWidth + barX;
Ken Martin's avatar
Ken Martin committed
738
739
740
          }
        else
          {
741
          val = 0.5*(barWidth+barY);
Ken Martin's avatar
Ken Martin committed
742
          }
743
744
745
746
747
748
        if (this->TextPosition == vtkScalarBarActor::PrecedeScalarBar)
          {
          this->TextActors[i]->SetPosition(val, size[1] * 0.3);
          }
        else
          {
749
          this->TextActors[i]->SetPosition(val, barY + barHeight + 0.05*size[1]);
750
          }
751
        }
752
753
      }

754
755
756
757
758
759
    // Set the texture points
    //
    vtkPoints *texturePoints = vtkPoints::New();
    texturePoints->SetNumberOfPoints(4);
    this->TexturePolyData->SetPoints(texturePoints);
    texturePoints->SetPoint(0, 0.0, 0.0, 0.0);
760
761
762
763

    double p1[2], p2[2];
    if (this->Orientation == VTK_ORIENT_VERTICAL)
      {
764
      p1[0] = (this->TextPosition == vtkScalarBarActor::PrecedeScalarBar)
765
766
        ? (size[0] - barWidth - barX) : barX;
      p1[1] = barY;
767
      p2[0] = p1[0] + barWidth;
768
      p2[1] = p1[1] + barHeight;
769
770
771
      }
    else
      {
772
      p1[0] = barX;
773
      p1[1] = (this->TextPosition == vtkScalarBarActor::PrecedeScalarBar)
774
        ? (size[1] - barHeight - barY) : barY;
775
776
777
778
779
780
781
782
      p2[0] = p1[0] + barWidth;
      p2[1] = p1[1] + barHeight;
      }

    texturePoints->SetPoint(0, p1[0], p1[1], 0.0);
    texturePoints->SetPoint(1, p2[0], p1[1], 0.0);
    texturePoints->SetPoint(2, p2[0], p2[1], 0.0);
    texturePoints->SetPoint(3, p1[0], p2[1], 0.0);
783
784
785
786
    texturePoints->Delete();

    vtkDataArray * tc = this->TexturePolyData->GetPointData()->GetTCoords();
    tc->SetTuple2(1, barWidth / this->TextureGridWidth, 0.0);
787
    tc->SetTuple2(2, barWidth / this->TextureGridWidth,
788
                  barHeight / this->TextureGridWidth);
789
790
    tc->SetTuple2(3, 0.0, barHeight / this->TextureGridWidth);

791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
    if ( isCategorical )
      {
      // this->ScalarBar will not be drawn; instead, draw padded boxes
      // and leaders to labels for each annotated value.
      // Since labels are user-provided, we render with vtkMathTextActor to allow fancy-ness.
      int numNotes = lkup->GetNumberOfAnnotatedValues();
      int numPts = 4 * numNotes; // 2 triangles per annotation: half-opaque, half-translucent.
      pts = vtkPoints::New();
      pts->SetNumberOfPoints( numPts );
      polys = vtkCellArray::New();
      polys->Allocate( polys->EstimateSize( 2 * numNotes, 3 ) );
      colors = vtkUnsignedCharArray::New();
      colors->SetNumberOfComponents( 4 ); // RGBA
      colors->SetNumberOfTuples( 2 * numNotes );

      this->AnnotationBoxes->Initialize();
      this->AnnotationBoxes->SetPoints(pts);
      this->AnnotationBoxes->SetPolys(polys);
      this->AnnotationBoxes->GetCellData()->SetScalars( colors );
      //this->AnnotationBoxes->SetProperty( this->GetProperty() );
      pts->Delete(); polys->Delete(); colors->Delete();

      // Use the nicely-provided scalar bar position to place
      // the annotated value swatches.
David Thompson's avatar
David Thompson committed
815
      double swatchPad;
816
817
818
819
820
      if ( this->Orientation == VTK_ORIENT_VERTICAL )
        {
        barWidth = size[0] - 4 - labelSize[0] - 2 * barX;
        barHeight = static_cast<int>(0.86*size[1]) - barY;
        delta = static_cast<double>(barHeight) / numNotes;
David Thompson's avatar
David Thompson committed
821
822
823
        swatchPad = delta > 16. ? 4. : ( delta / 4. );
        this->NumberOfAnnotationLabelsBuilt =
          this->LayoutAnnotationsVertically( barX, barY, barWidth, barHeight, delta, swatchPad );
824
825
826
        for ( i = 0; i < numNotes; ++ i )
          {
          x[0] = barX;
David Thompson's avatar
David Thompson committed
827
          x[1] = barY + i * delta + swatchPad;
828
829
830
          pts->SetPoint( 4 * i, x );
          x[0] = barX + barWidth;
          pts->SetPoint( 4 * i + 1, x );
David Thompson's avatar
David Thompson committed
831
          x[1] += delta - swatchPad * 2;
832
833
834
835
836
837
838
839
840
841
          pts->SetPoint( 4 * i + 2, x );
          x[0] = barX;
          pts->SetPoint( 4 * i + 3, x );
          }
        }
      else
        {
        barWidth = size[0] - 2 * barX;
        barHeight = static_cast<int>( 0.4 * size[1] ) - barY;
        delta = static_cast<double>(barWidth) / numNotes;
David Thompson's avatar
David Thompson committed
842
843
844
        swatchPad = delta > 16. ? 4. : ( delta / 4. );
        this->NumberOfAnnotationLabelsBuilt =
          this->LayoutAnnotationsHorizontally( barX, barY, barWidth, barHeight, delta, swatchPad );
845
846
        for ( i = 0; i < numNotes; ++ i )
          {
David Thompson's avatar
David Thompson committed
847
          x[0] = barX + i * delta + swatchPad;
848
849
          x[1] = barY;
          pts->SetPoint( 4 * i, x );
David Thompson's avatar
David Thompson committed
850
          x[0] += delta - swatchPad * 2;
851
852
853
          pts->SetPoint( 4 * i + 1, x );
          x[1] += barHeight;
          pts->SetPoint( 4 * i + 2, x );
David Thompson's avatar
David Thompson committed
854
          x[0] -= delta - swatchPad * 2;
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
          pts->SetPoint( 4 * i + 3, x );
          }
        }
      for ( i = 0; i < numNotes; ++ i )
        {
        ptIds[0] = 4 * i;
        ptIds[1] = ptIds[0] + 1;
        ptIds[2] = ptIds[0] + 2;
        polys->InsertNextCell( 3, ptIds );

        ptIds[1] = ptIds[2];
        ptIds[2] = ptIds[0] + 3;
        polys->InsertNextCell( 3, ptIds );

        // We could just call lkup->GetTableValue( i % lkup->GetNumberOfTableValues() ), but
        // that would draw colors even when an annotation did not have a valid conversion to/from a double...
        rgba = lkup->MapValue( lkup->GetAnnotatedValue( i ).ToDouble() );
        rgb = colors->GetPointer( /* numComponents */ 4 * /* numCells/swatch */ 2 * /* swatch */ i ); //write into array directly
        rgb[0] = rgba[0]; rgb[1] = rgba[1]; rgb[2] = rgba[2]; rgb[3] = rgba[3];
        rgb[4] = rgba[0]; rgb[5] = rgba[1]; rgb[6] = rgba[2]; rgb[7] = 255; // second triangle is always opaque
        }
      //vtkIndent foo;
      //pts->PrintSelf( cout, foo );
      //polys->PrintSelf( cout, foo );
      //colors->PrintSelf( cout, foo );
      }
881
882
883
884
    this->BuildTime.Modified();
    }

  // Everything is built, just have to render
Jim Miller's avatar
Style    
Jim Miller committed
885
886
  if (this->Title != NULL)
    {
887
    renderedSomething += this->TitleActor->RenderOpaqueGeometry(viewport);
Jim Miller's avatar
Style    
Jim Miller committed
888
    }
David Thompson's avatar
David Thompson committed
889
890
891
  // Draw either the scalar bar (non-indexed mode) or the annotated value boxes (indexed mode).
  vtkLookupTable* lkup = vtkLookupTable::SafeDownCast( this->LookupTable );
  if ( ! lkup || ( lkup && ! lkup->GetIndexedLookup() ) )
Jim Miller's avatar
Style    
Jim Miller committed
892
    {
David Thompson's avatar
David Thompson committed
893
894
895
896
897
898
899
900
901
902
903
904
905
    this->ScalarBarActor->RenderOpaqueGeometry(viewport);
    for (i=0; i<this->NumberOfLabels; i++)
      {
      renderedSomething += this->TextActors[i]->RenderOpaqueGeometry(viewport);
      }
    }
  else
    {
    this->AnnotationBoxesActor->RenderOpaqueGeometry( viewport );
    for ( i = 0; i < this->NumberOfAnnotationLabelsBuilt; ++ i )
      {
      renderedSomething += this->AnnotationLabels[i]->RenderOpaqueGeometry( viewport );
      }
Jim Miller's avatar
Style    
Jim Miller committed
906
    }
907
908
909
910

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

  return renderedSomething;
911
912
}

913
914
915
916
917
918
919
920
//-----------------------------------------------------------------------------
// Description:
// Does this prop have some translucent polygonal geometry?
int vtkScalarBarActor::HasTranslucentPolygonalGeometry()
{
  return 0;
}

Sebastien Barre's avatar
Sebastien Barre committed
921
//----------------------------------------------------------------------------
922
void vtkScalarBarActor::PrintSelf(ostream& os, vtkIndent indent)
923
{
Brad King's avatar
Brad King committed
924
  this->Superclass::PrintSelf(os,indent);
925
926
927
928
929
930
931
932
933
934
935

  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
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
  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";
    }

956
  os << indent << "Title: " << (this->Title ? this->Title : "(none)") << "\n";
957
  os << indent << "ComponentTitle: " << (this->ComponentTitle ? this->ComponentTitle : "(none)") << "\n";
958
  os << indent << "Maximum Number Of Colors: "
959
960
     << this->MaximumNumberOfColors << "\n";
  os << indent << "Number Of Labels: " << this->NumberOfLabels << "\n";
961
  os << indent << "Number Of Labels Built: " << this->NumberOfLabelsBuilt << "\n";
962
963

  os << indent << "Orientation: ";
Jim Miller's avatar
Style    
Jim Miller committed
964
965
966
967
968
969
970
971
  if ( this->Orientation == VTK_ORIENT_HORIZONTAL )
    {
    os << "Horizontal\n";
    }
  else
    {
    os << "Vertical\n";
    }
972
973

  os << indent << "Label Format: " << this->LabelFormat << "\n";
974
975
976
977
  os << indent << "UseOpacity: " << this->UseOpacity << "\n";
  if (this->UseOpacity)
    {
    os << indent << "TextureGridWidth: " << this->TextureGridWidth << "\n";
Karthik Krishnan's avatar
Karthik Krishnan committed
978
979
    os << indent << "TextureActor:\n";
    this->TextureActor->PrintSelf(os, indent.GetNextIndent());
980
    }
981
982
983
984
985
986
987
988
  if (this->TextPosition == vtkScalarBarActor::PrecedeScalarBar)
    {
    os << indent << "TextPosition: PrecedeScalarBar\n";
    }
  else
    {
    os << indent << "TextPosition: SucceedScalarBar\n";
    }
Karthik Krishnan's avatar
Karthik Krishnan committed
989

990
  os << indent << "MaximumWidthInPixels: "
Karthik Krishnan's avatar
Karthik Krishnan committed
991
     << this->MaximumWidthInPixels << endl;
992
  os << indent << "MaximumHeightInPixels: "
Karthik Krishnan's avatar
Karthik Krishnan committed
993
     << this->MaximumHeightInPixels << endl;
994
995
996
997
998
999
1000

  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());
1001
}
Ken Martin's avatar
Ken Martin committed
1002

Sebastien Barre's avatar
Sebastien Barre committed
1003
//----------------------------------------------------------------------------
Will Schroeder's avatar
Will Schroeder committed
1004
1005
1006
1007
1008
1009
1010
1011
1012
void vtkScalarBarActor::ShallowCopy(vtkProp *prop)
{
  vtkScalarBarActor *a = vtkScalarBarActor::SafeDownCast(prop);
  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
1013
1014
    this->SetLabelTextProperty(a->GetLabelTextProperty());
    this->SetTitleTextProperty(a->GetTitleTextProperty());
Will Schroeder's avatar
Will Schroeder committed
1015
1016
1017
    this->SetLabelFormat(a->GetLabelFormat());
    this->SetTitle(a->GetTitle());
    this->GetPositionCoordinate()->SetCoordinateSystem(
1018
      a->GetPositionCoordinate()->GetCoordinateSystem());
Will Schroeder's avatar
Will Schroeder committed
1019
1020
1021
    this->GetPositionCoordinate()->SetValue(
      a->GetPositionCoordinate()->GetValue());
    this->GetPosition2Coordinate()->SetCoordinateSystem(
1022
      a->GetPosition2Coordinate()->GetCoordinateSystem());
Will Schroeder's avatar
Will Schroeder committed
1023
1024
    this->GetPosition2Coordinate()->SetValue(
      a->GetPosition2Coordinate()->GetValue());
1025
1026
1027
1028
    this->SetDrawBackground(a->GetDrawBackground());
    this->SetBackgroundProperty(a->GetBackgroundProperty());
    this->SetDrawFrame(a->GetDrawFrame());
    this->SetFrameProperty(a->GetFrameProperty());
Will Schroeder's avatar
Will Schroeder committed
1029
1030
1031
1032
1033
    }

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

Sebastien Barre's avatar
Sebastien Barre committed
1035
//----------------------------------------------------------------------------
1036
void vtkScalarBarActor::AllocateAndSizeLabels(int *labelSize,
Sebastien Barre's avatar
Sebastien Barre committed
1037
                                              int *size,
Ken Martin's avatar
Ken Martin committed