vtkDynamic2DLabelMapper.cxx 22.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14
/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkDynamic2DLabelMapper.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

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

=========================================================================*/
15 16 17 18 19
/*-------------------------------------------------------------------------
  Copyright 2008 Sandia Corporation.
  Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
  the U.S. Government retains certain rights in this software.
-------------------------------------------------------------------------*/
20 21 22 23

#include "vtkDynamic2DLabelMapper.h"

#include "vtkActor2D.h"
24
#include "vtkCamera.h"
25 26 27 28
#include "vtkCommand.h"
#include "vtkDataArray.h"
#include "vtkDataSet.h"
#include "vtkExecutive.h"
29
#include "vtkGraph.h"
30 31
#include "vtkIdTypeArray.h"
#include "vtkInformation.h"
32
#include "vtkIntArray.h"
33
#include "vtkKdTree.h"
34
#include "vtkMath.h"
35 36 37
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkPoints.h"
38
#include "vtkRenderer.h"
39
#include "vtkSmartPointer.h"
40 41 42 43 44
#include "vtkSortDataArray.h"
#include "vtkStringArray.h"
#include "vtkTextMapper.h"
#include "vtkTextProperty.h"
#include "vtkTimerLog.h"
45
#include "vtkTypeTraits.h"
46
#include "vtkUnicodeStringArray.h"
47 48
#include "vtkViewport.h"

49
#include <fstream>
50
using std::ofstream;
51 52 53 54 55 56 57 58 59 60 61

vtkStandardNewMacro(vtkDynamic2DLabelMapper);

//----------------------------------------------------------------------------
// Creates a new label mapper

vtkDynamic2DLabelMapper::vtkDynamic2DLabelMapper()
{
  this->LabelWidth = NULL;
  this->LabelHeight = NULL;
  this->Cutoff = NULL;
62

63
  this->SetInputArrayToProcess(1, 0, 0, vtkDataObject::FIELD_ASSOCIATION_POINTS, "priority");
64 65 66
  this->ReversePriority = false;
  this->LabelHeightPadding = 50;
  this->LabelWidthPadding = 10;
67
  this->ReferenceScale = 1.0;
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85

  // Set new default property
  vtkTextProperty* prop = vtkTextProperty::New();
  prop->SetFontSize(12);
  prop->SetBold(1);
  prop->SetItalic(0);
  prop->SetShadow(1);
  prop->SetFontFamilyToArial();
  prop->SetJustificationToCentered();
  prop->SetVerticalJustificationToCentered();
  prop->SetColor(1, 1, 1);
  this->SetLabelTextProperty(prop);
  prop->Delete();
}

//----------------------------------------------------------------------------
vtkDynamic2DLabelMapper::~vtkDynamic2DLabelMapper()
{
86 87 88
  delete[] this->LabelWidth;
  delete[] this->LabelHeight;
  delete[] this->Cutoff;
89 90 91 92 93
}

//----------------------------------------------------------------------------
void vtkDynamic2DLabelMapper::SetPriorityArrayName(const char* name)
{
94
  this->SetInputArrayToProcess(1, 0, 0, vtkDataObject::FIELD_ASSOCIATION_POINTS, name);
95 96 97 98 99 100 101 102 103 104
}

//----------------------------------------------------------------------------
template<typename T>
void vtkDynamic2DLabelMapper_PrintComponent(char *output, const char *format, int index, const T *array)
{
  sprintf(output, format, array[index]);
}

//----------------------------------------------------------------------------
105
void vtkDynamic2DLabelMapper::RenderOpaqueGeometry(vtkViewport *viewport,
106 107 108 109 110 111 112
                                                vtkActor2D *actor)
{
  int i, j, numComp = 0, pointIdLabels, activeComp = 0;
  double x[3];
  vtkAbstractArray *abstractData;
  vtkDataArray *numericData;
  vtkStringArray *stringData;
113
  vtkUnicodeStringArray* uStringData;
114
  vtkDataObject *input = this->GetExecutive()->GetInputData(0, 0);
115 116 117 118 119 120 121

  if ( ! input )
    {
    vtkErrorMacro(<<"Need input data to render labels (2)");
    return;
    }

122
  vtkTextProperty *tprop = this->GetLabelTextProperty();
123 124 125 126 127 128
  if (!tprop)
    {
    vtkErrorMacro(<<"Need text property to render labels");
    return;
    }

Berk Geveci's avatar
Berk Geveci committed
129
  this->GetInputAlgorithm()->Update();
130 131

  // Input might have changed
132
  input = this->GetExecutive()->GetInputData(0, 0);
133

134 135 136 137 138 139 140
  vtkDataSet *dsInput = vtkDataSet::SafeDownCast(input);
  vtkGraph *gInput = vtkGraph::SafeDownCast(input);
  if (!dsInput && !gInput)
    {
    vtkErrorMacro(<<"Input must be vtkDataSet or vtkGraph.");
    return;
    }
141
  vtkDataSetAttributes *pd =
142
    dsInput ? dsInput->GetPointData() : gInput->GetVertexData();
143

144 145 146 147 148 149 150
  // If no labels we are done
  vtkIdType numItems = dsInput ? dsInput->GetNumberOfPoints() : gInput->GetNumberOfVertices();
  if (numItems == 0)
    {
    return;
    }

151
  // Check to see whether we have to rebuild everything
152
  if ( this->GetMTime() > this->BuildTime ||
153
       input->GetMTime() > this->BuildTime)
154 155 156
    {
    vtkDebugMacro(<<"Rebuilding labels");

157
    vtkIntArray *typeArr = vtkArrayDownCast<vtkIntArray>(
158
      this->GetInputAbstractArrayToProcess(0, input));
159 160 161 162 163 164

    // figure out what to label, and if we can label it
    pointIdLabels = 0;
    abstractData = NULL;
    numericData = NULL;
    stringData = NULL;
165
    uStringData = NULL;
166 167 168 169 170 171 172 173 174 175 176
    switch (this->LabelMode)
      {
      case VTK_LABEL_IDS:
        pointIdLabels = 1;
        break;
      case VTK_LABEL_SCALARS:
        if ( pd->GetScalars() )
          {
          numericData = pd->GetScalars();
          }
        break;
177
      case VTK_LABEL_VECTORS:
178 179 180 181 182
        if ( pd->GetVectors() )
          {
          numericData = pd->GetVectors();
          }
        break;
183
      case VTK_LABEL_NORMALS:
184 185 186 187 188
        if ( pd->GetNormals() )
          {
          numericData = pd->GetNormals();
          }
        break;
189
      case VTK_LABEL_TCOORDS:
190 191 192 193 194
        if ( pd->GetTCoords() )
          {
          numericData = pd->GetTCoords();
          }
        break;
195
      case VTK_LABEL_TENSORS:
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
        if ( pd->GetTensors() )
          {
          numericData = pd->GetTensors();
          }
        break;
      case VTK_LABEL_FIELD_DATA:
      {
      int arrayNum;
      if (this->FieldDataName != NULL)
        {
        abstractData = pd->GetAbstractArray(this->FieldDataName, arrayNum);
        }
      else
        {
        arrayNum = (this->FieldDataArray < pd->GetNumberOfArrays() ?
                    this->FieldDataArray : pd->GetNumberOfArrays() - 1);
        abstractData = pd->GetAbstractArray(arrayNum);
        }
214 215 216
      numericData = vtkArrayDownCast<vtkDataArray>(abstractData);
      stringData = vtkArrayDownCast<vtkStringArray>(abstractData);
      uStringData = vtkArrayDownCast<vtkUnicodeStringArray>(abstractData);
217 218 219 220 221 222 223 224 225 226 227 228 229 230
      }; break;
      }

    // determine number of components and check input
    if ( pointIdLabels )
      {
      ;
      }
    else if ( numericData )
      {
      numComp = numericData->GetNumberOfComponents();
      activeComp = 0;
      if ( this->LabeledComponent >= 0 )
        {
231
        activeComp = (this->LabeledComponent < numComp ?
232 233 234 235
                      this->LabeledComponent : numComp - 1);
        numComp = 1;
        }
      }
236 237 238 239
    else if ( uStringData )
      {
      vtkWarningMacro( "Unicode string arrays are not adequately supported by the vtkDynamic2DLabelMapper.  Unicode strings will be converted to vtkStdStrings for rendering.");
      }
240 241
    else if ( !stringData )
      {
242 243 244 245 246 247
      if (this->FieldDataName)
        {
        vtkWarningMacro(<< "Could not find label array ("
                        << this->FieldDataName << ") "
                        << "in input.");
        }
248
      else
249 250 251 252 253 254
        {
        vtkWarningMacro(<< "Could not find label array ("
                        << "index " << this->FieldDataArray << ") "
                        << "in input.");
        }

255 256 257 258 259 260
      return;
      }

    vtkStdString FormatString;
    if (this->LabelFormat)
      {
261
      // The user has specified a format string.
262 263 264 265 266 267 268 269
      vtkDebugMacro(<<"Using user-specified format string " << this->LabelFormat);
      FormatString = this->LabelFormat;
      }
    else
      {
      // Try to come up with some sane default.
      if (pointIdLabels)
        {
270
        FormatString = "%d";
271 272 273 274 275 276 277
        }
      else if (numericData)
        {
        switch (numericData->GetDataType())
          {
          case VTK_VOID: FormatString = "0x%x"; break;

278 279
          // dont use vtkTypeTraits::ParseFormat for character types as parse formats
          // aren't the same as print formats for these types.
280 281 282 283 284 285 286 287 288 289 290 291 292
          case VTK_BIT:
          case VTK_SHORT:
          case VTK_UNSIGNED_SHORT:
          case VTK_INT:
          case VTK_UNSIGNED_INT:
            FormatString = "%d"; break;

          case VTK_CHAR:
          case VTK_SIGNED_CHAR:
          case VTK_UNSIGNED_CHAR:
            FormatString = "%c"; break;

          case VTK_LONG:
293
            FormatString = vtkTypeTraits<long>::ParseFormat(); break;
294
          case VTK_UNSIGNED_LONG:
295 296
            FormatString = vtkTypeTraits<unsigned long>::ParseFormat(); break;

297
          case VTK_ID_TYPE:
298
            FormatString = vtkTypeTraits<vtkIdType>::ParseFormat(); break;
299 300

          case VTK_LONG_LONG:
301
            FormatString = vtkTypeTraits<long long>::ParseFormat(); break;
302
          case VTK_UNSIGNED_LONG_LONG:
303 304
            FormatString = vtkTypeTraits<unsigned long long>::ParseFormat(); break;

305
          case VTK_FLOAT:
306
            FormatString = vtkTypeTraits<float>::ParseFormat(); break;
307 308

          case VTK_DOUBLE:
309
            FormatString = vtkTypeTraits<double>::ParseFormat(); break;
310 311 312 313 314 315 316 317 318

          default:
            FormatString = "BUG - UNKNOWN DATA FORMAT"; break;
          }
        }
      else if (stringData)
        {
        FormatString = ""; // we'll use vtkStdString::operator+ instead of sprintf
        }
319 320 321 322
      else if (uStringData)
        {
        FormatString = "unicode"; // we'll use vtkStdString::operator+ instead of sprintf
        }
323 324
      else
        {
325
        FormatString = "BUG - COULDN'T DETECT DATA TYPE";
326 327 328 329 330
        }

      vtkDebugMacro(<<"Using default format string " << FormatString.c_str());
      } // Done building default format string

331
    this->NumberOfLabels =
332
      dsInput ? dsInput->GetNumberOfPoints() : gInput->GetNumberOfVertices();
333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358
    if ( this->NumberOfLabels > this->NumberOfLabelsAllocated )
      {
      // delete old stuff
      for (i=0; i < this->NumberOfLabelsAllocated; i++)
        {
        this->TextMappers[i]->Delete();
        }
      delete [] this->TextMappers;

      this->NumberOfLabelsAllocated = this->NumberOfLabels;
      this->TextMappers = new vtkTextMapper * [this->NumberOfLabelsAllocated];
      for (i=0; i<this->NumberOfLabelsAllocated; i++)
        {
        this->TextMappers[i] = vtkTextMapper::New();
        }
      }//if we have to allocate new text mappers

    // ----------------------------------------
    // Now we actually construct the label strings
    //

    const char *LiveFormatString = FormatString.c_str();
    char TempString[1024];

    for (i=0; i < this->NumberOfLabels; i++)
      {
359
      vtkStdString ResultString;
360 361 362 363 364 365

      if ( pointIdLabels )
        {
        sprintf(TempString, LiveFormatString, i);
        ResultString = TempString;
        }
366
      else
367 368 369 370
        {
        if ( numericData )
          {
          void *rawData = numericData->GetVoidPointer(i);
371

372 373 374 375 376 377 378
          if ( numComp == 1 )
            {
            switch (numericData->GetDataType())
              {
              vtkTemplateMacro(vtkDynamic2DLabelMapper_PrintComponent(TempString, LiveFormatString, activeComp, static_cast<VTK_TT *>(rawData)));
              }
            ResultString = TempString;
379
            }
380 381 382
          else // numComp != 1
            {
            ResultString = "(";
383

384 385 386 387 388 389
            // Print each component in turn and add it to the string.
            for (j = 0; j < numComp; ++j)
              {
              switch (numericData->GetDataType())
                {
                vtkTemplateMacro(
390 391 392
                  vtkDynamic2DLabelMapper_PrintComponent(TempString,
                                                      LiveFormatString,
                                                      j,
393 394 395
                                                      static_cast<VTK_TT *>(rawData)));
                }
              ResultString += TempString;
396

397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413
              if (j < (numComp-1))
                {
                ResultString += ' ';
                }
              else
                {
                ResultString += ')';
                }
              }
            }
          }
        else // rendering string data
          {
          // If the user hasn't given us a custom format string then
          // we'll sidestep a lot of sprintf nonsense.
          if (this->LabelFormat == NULL)
            {
414 415 416 417 418 419 420 421
            if( uStringData )
              {
              ResultString = uStringData->GetValue(i).utf8_str();
              }
            else
              {
              ResultString = stringData->GetValue(i);
              }
422 423 424
            }
          else // the user specified a label format
            {
425
            snprintf(TempString, 1023, LiveFormatString,
426 427 428 429
                     stringData->GetValue(i).c_str());
              ResultString = TempString;
            } // done printing strings with label format
          } // done printing strings
430
        } // done creating string
431 432

      this->TextMappers[i]->SetInput(ResultString.c_str());
433 434 435 436 437 438 439 440 441 442 443 444 445

      // Find the correct property type
      int type = 0;
      if (typeArr)
        {
        type = typeArr->GetValue(i);
        }
      vtkTextProperty* prop = this->GetLabelTextProperty(type);
      if (!prop)
        {
        prop = this->GetLabelTextProperty(0);
        }
      this->TextMappers[i]->SetTextProperty(prop);
446 447 448 449 450 451 452
      }

    this->BuildTime.Modified();

    //
    // Perform the label layout preprocessing
    //
453

454 455 456 457 458 459 460 461 462 463 464
    // Calculate height and width padding
    float widthPadding=0, heightPadding = 0;
    if (this->NumberOfLabels > 0)
      {
      widthPadding = this->TextMappers[0]->GetHeight(viewport) *
              this->LabelWidthPadding/100.0;
      heightPadding = this->TextMappers[0]->GetHeight(viewport) *
               this->LabelHeightPadding/100.0;
      }

    // Calculate label widths / heights
465
    delete[] this->LabelWidth;
466 467 468 469 470 471 472
    this->LabelWidth = new float[this->NumberOfLabels];
    for (i = 0; i < this->NumberOfLabels; i++)
      {
      this->LabelWidth[i] = this->TextMappers[i]->GetWidth(viewport)+
                            widthPadding;
      }

473
    delete[] this->LabelHeight;
474 475 476 477 478 479 480 481
    this->LabelHeight = new float[this->NumberOfLabels];
    for (i = 0; i < this->NumberOfLabels; i++)
      {
      this->LabelHeight[i] = this->TextMappers[i]->GetHeight(viewport)+
                             heightPadding;
      }

    // Determine cutoff scales of each point
482
    delete[] this->Cutoff;
483 484
    this->Cutoff = new float[this->NumberOfLabels];

485 486
    vtkTimerLog* timer = vtkTimerLog::New();
    timer->StartTimer();
487 488 489 490 491 492 493 494

    vtkCoordinate* coord = vtkCoordinate::New();
    coord->SetViewport(viewport);
    vtkPoints* pts = vtkPoints::New();
    for (i = 0; i < this->NumberOfLabels; i++)
      {
      double* dc;
      double pti[3];
495 496 497 498 499 500 501 502
      if (dsInput)
        {
        dsInput->GetPoint(i, pti);
        }
      else
        {
        gInput->GetPoint(i, pti);
        }
503 504 505 506
      coord->SetValue(pti);
      dc = coord->GetComputedDoubleDisplayValue(0);
      pts->InsertNextPoint(dc[0], dc[1], 0);
      }
507
    coord->Delete();
508

509 510 511
    timer->StopTimer();
    vtkDebugMacro("vtkDynamic2DLabelMapper computed display coordinates for " << timer->GetElapsedTime() << "s");
    timer->StartTimer();
512 513 514 515 516 517 518 519 520 521 522 523 524 525

    // Announce progress
    double progress = 0;
    this->InvokeEvent(vtkCommand::ProgressEvent, static_cast<void*>(&progress));
    int current = 0;
    int total = this->NumberOfLabels*(this->NumberOfLabels - 1)/2;

    // Create an index array to store the offsets of the sorted elements.
    vtkIdTypeArray* index = vtkIdTypeArray::New();
    index->SetNumberOfValues(this->NumberOfLabels);
    for (i = 0; i < this->NumberOfLabels; i++)
      {
      index->SetValue(i, i);
      }
526

527
    // If the array is found, sort it and rearrange the corresponding index array.
528
    vtkAbstractArray* inputArr = this->GetInputAbstractArrayToProcess(1, input);
529
    if (inputArr)
530
      {
531 532 533
      // Don't sort the original array, instead make a copy.
      vtkAbstractArray* arr = vtkAbstractArray::CreateArray(inputArr->GetDataType());
      arr->DeepCopy(inputArr);
534
      vtkSortDataArray::Sort(arr, index);
535
      arr->Delete();
536
      }
537

538 539 540 541 542 543
    // We normally go from highest (at the end) to lowest (at the beginning).
    // If priorities are reversed, we go from lowest to highest.
    // If no sorted array was used, we just go from index 0 to index n-1.
    vtkIdType begin = this->NumberOfLabels - 1;
    vtkIdType end = -1;
    vtkIdType step = -1;
544
    if ((this->ReversePriority && inputArr) || (!this->ReversePriority && !inputArr))
545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560
      {
      begin = 0;
      end = this->NumberOfLabels;
      step = 1;
      }
    for (i = begin; i != end; i += step)
      {
      vtkIdType indexI = index->GetValue(i);
      float* pti = reinterpret_cast<float*>(pts->GetVoidPointer(3*indexI));
      this->Cutoff[indexI] = VTK_FLOAT_MAX;
      for (j = begin; j != i; j += step)
        {
        vtkIdType indexJ = index->GetValue(j);
        float* ptj = reinterpret_cast<float*>(pts->GetVoidPointer(3*indexJ));
        float absX = (pti[0] - ptj[0]) > 0 ? (pti[0] - ptj[0]) : -(pti[0] - ptj[0]);
        float absY = (pti[1] - ptj[1]) > 0 ? (pti[1] - ptj[1]) : -(pti[1] - ptj[1]);
561 562
        float xScale = 2*absX/(this->LabelWidth[indexI] + this->LabelWidth[indexJ]);
        float yScale = 2*absY/(this->LabelHeight[indexI] + this->LabelHeight[indexJ]);
563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582
        float maxScale = xScale < yScale ? yScale : xScale;
        if (maxScale < this->Cutoff[indexJ] && maxScale < this->Cutoff[indexI])
          {
          this->Cutoff[indexI] = maxScale;
          }
        if (current % 100000 == 0)
          {
          progress = static_cast<double>(current)/total;
          this->InvokeEvent(vtkCommand::ProgressEvent, static_cast<void*>(&progress));
          }
        current++;
        }
      }
    index->Delete();
    progress = 1.0;
    this->InvokeEvent(vtkCommand::ProgressEvent, static_cast<void*>(&progress));

    pts->Delete();

    // Determine the reference scale
583
    this->ReferenceScale = this->GetCurrentScale(viewport);
584

585 586 587
    timer->StopTimer();
    vtkDebugMacro("vtkDynamic2DLabelMapper computed label cutoffs for " << timer->GetElapsedTime() << "s");
    timer->Delete();
588 589 590 591 592 593 594
    }

  //
  // Draw labels visible in the current scale
  //

  // Determine the current scale
595 596 597
  double scale = 1.0;
  if (this->ReferenceScale != 0.0)
    {
598
    scale = this->GetCurrentScale(viewport) / this->ReferenceScale;
599
    }
600 601 602

  for (i = 0; i < this->NumberOfLabels; i++)
    {
603 604 605 606 607 608 609 610
    if (dsInput)
      {
      dsInput->GetPoint(i,x);
      }
    else
      {
      gInput->GetPoint(i,x);
      }
611 612 613 614 615 616 617 618 619
    if ((1.0 / scale) < this->Cutoff[i])
      {
      actor->GetPositionCoordinate()->SetCoordinateSystemToWorld();
      actor->GetPositionCoordinate()->SetValue(x);
      this->TextMappers[i]->RenderOpaqueGeometry(viewport, actor);
      }
    }
}

620 621 622 623 624 625
//----------------------------------------------------------------------------
double vtkDynamic2DLabelMapper::GetCurrentScale(vtkViewport *viewport)
{
  // The current scale is the size on the screen of 1 unit in the xy plane

  vtkRenderer* ren = vtkRenderer::SafeDownCast(viewport);
626
  if ( ! ren )
627 628 629 630 631
    {
    vtkErrorMacro("vtkDynamic2DLabelMapper only works in a vtkRenderer or subclass");
    return 1.0;
    }
  vtkCamera* camera = ren->GetActiveCamera();
632
  if ( camera->GetParallelProjection() )
633
    {
634
    // For parallel projection, the scale depends on the parallel scale
635
    double scale = ( ren->GetSize()[1] / 2.0 ) / camera->GetParallelScale();
636 637 638 639 640 641
    return scale;
    }
  else
    {
    // For perspective projection, the scale depends on the view angle
    double viewAngle = camera->GetViewAngle();
Jeff Baumes's avatar
Jeff Baumes committed
642
    double distZ = camera->GetPosition()[2] > 0 ? camera->GetPosition()[2] : -camera->GetPosition()[2];
643
    double unitAngle = vtkMath::DegreesFromRadians( atan2( 1.0, distZ ) );
644 645 646 647 648
    double scale = ren->GetSize()[1] * unitAngle / viewAngle;
    return scale;
    }
}

649
//----------------------------------------------------------------------------
650
void vtkDynamic2DLabelMapper::RenderOverlay(vtkViewport *viewport,
651
                                            vtkActor2D *actor)
652 653 654
{
  int i;
  double x[3];
655 656 657 658
  vtkDataObject *input = this->GetExecutive()->GetInputData(0, 0);
  vtkGraph *gInput = vtkGraph::SafeDownCast(input);
  vtkDataSet *dsInput = vtkDataSet::SafeDownCast(input);
  vtkIdType numPts = dsInput ? dsInput->GetNumberOfPoints() : gInput->GetNumberOfVertices();
659 660

  // Determine the current scale
661 662 663 664 665
  double scale = 1.0;
  if (this->ReferenceScale != 0.0)
    {
    scale = this->GetCurrentScale(viewport) / this->ReferenceScale;
    }
666

667 668 669 670 671
  if ( ! input )
    {
    vtkErrorMacro(<<"Need input data to render labels (1)");
    return;
    }
672

673 674
  vtkTimerLog* timer = vtkTimerLog::New();
  timer->StartTimer();
675

676 677
  for (i=0; i<this->NumberOfLabels && i<numPts; i++)
    {
678 679 680 681 682 683 684 685
    if (dsInput)
      {
      dsInput->GetPoint(i, x);
      }
    else
      {
      gInput->GetPoint(i, x);
      }
686 687 688 689
    actor->SetPosition(x);
    double* display = actor->GetPositionCoordinate()->GetComputedDoubleDisplayValue(viewport);
    double screenX = display[0];
    double screenY = display[1];
690

691
    bool inside =
692
      viewport->IsInViewport(
693
        static_cast<int>(screenX + this->LabelWidth[i]),
694 695
        static_cast<int>(screenY + this->LabelHeight[i]))
      || viewport->IsInViewport(
696
        static_cast<int>(screenX + this->LabelWidth[i]),
697 698
        static_cast<int>(screenY - this->LabelHeight[i]))
      || viewport->IsInViewport(
699
        static_cast<int>(screenX - this->LabelWidth[i]),
700 701
        static_cast<int>(screenY + this->LabelHeight[i]))
      || viewport->IsInViewport(
702
        static_cast<int>(screenX - this->LabelWidth[i]),
703 704 705 706 707 708 709
        static_cast<int>(screenY - this->LabelHeight[i]));
    if (inside && (1.0f / scale) < this->Cutoff[i])
      {
      this->TextMappers[i]->RenderOverlay(viewport, actor);
      }
    }

710 711 712
  timer->StopTimer();
  vtkDebugMacro("vtkDynamic2DLabelMapper interactive time: " << timer->GetElapsedTime() << "s");
  timer->Delete();
713 714 715 716 717 718 719 720
}

//----------------------------------------------------------------------------
void vtkDynamic2DLabelMapper::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);
  os << indent << "ReversePriority: " << (this->ReversePriority ? "on" : "off") << endl;
  os << indent << "LabelHeightPadding: " << (this->LabelHeightPadding ? "on" : "off") << endl;
721
  os << indent << "LabelWidthPadding: " << (this->LabelWidthPadding ? "on" : "off") << endl;
722
}