vtkPlotPie.cxx 7.18 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkPlotPie.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.

=========================================================================*/

#include "vtkPlotPie.h"

#include "vtkContext2D.h"
19
#include "vtkPen.h"
20 21 22 23 24 25
#include "vtkBrush.h"
#include "vtkColorSeries.h"
#include "vtkPoints2D.h"
#include "vtkContextMapper2D.h"
#include "vtkTable.h"
#include "vtkMath.h"
26
#include "vtkRect.h"
27 28 29

#include "vtkObjectFactory.h"

30
#include <algorithm>
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86

namespace {

template<class A>
A SumData(A *a, int n)
{
  A sum = 0;
  for (int i = 0; i < n; ++i)
    {
    sum += a[i];
    }
  return sum;
}

template<class A>
void CopyToPoints(vtkPoints2D *points, A *a, int n)
{
  points->SetNumberOfPoints(n);

  A sum = SumData(a,n);
  float* data = static_cast<float*>(points->GetVoidPointer(0));
  float startAngle = 0.0;

  for (int i = 0; i < n; ++i)
    {
    data[2*i] = startAngle;
    data[2*i+1] = startAngle + ((static_cast<float>(a[i]) / sum) * 360.0);
    startAngle = data[2*i+1];
    }
}
}

class vtkPlotPiePrivate
{
  public:
    vtkPlotPiePrivate()
      {
      this->CenterX = 0;
      this->CenterY = 0;
      this->Radius  = 0;
      }

  float CenterX;
  float CenterY;
  float Radius;
};

//-----------------------------------------------------------------------------
vtkStandardNewMacro(vtkPlotPie);

//-----------------------------------------------------------------------------
vtkPlotPie::vtkPlotPie()
{
  this->ColorSeries = vtkSmartPointer<vtkColorSeries>::New();
  this->Points = 0;
  this->Private = new vtkPlotPiePrivate();
87 88
  this->Dimensions[0] = this->Dimensions[1] = this->Dimensions[2] =
    this->Dimensions[3] = 0;
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
}

//-----------------------------------------------------------------------------
vtkPlotPie::~vtkPlotPie()
{
  delete this->Private;
  if (this->Points)
    {
    this->Points->Delete();
    this->Points = 0;
    }
  this->Private = 0;
}

//-----------------------------------------------------------------------------
bool vtkPlotPie::Paint(vtkContext2D *painter)
{
  if (!this->Visible)
    {
    return false;
    }

  // First check if we have an input
  vtkTable *table = this->Data->GetInput();
  if (!table)
    {
    vtkDebugMacro(<< "Paint event called with no input table set.");
    return false;
    }
  else if(this->Data->GetMTime() > this->BuildTime ||
          table->GetMTime() > this->BuildTime ||
          this->MTime > this->BuildTime)
    {
    vtkDebugMacro(<< "Paint event called with outdated table cache. Updating.");
    this->UpdateTableCache(table);
    }

  float* data = static_cast<float*>(this->Points->GetVoidPointer(0));

  for (int i = 0; i < this->Points->GetNumberOfPoints(); ++i)
    {
130 131
    painter->GetBrush()
        ->SetColor(this->ColorSeries->GetColorRepeating(i).GetData());
132 133 134 135 136 137 138 139 140 141 142 143 144 145

    painter->DrawEllipseWedge(this->Private->CenterX, this->Private->CenterY,
                              this->Private->Radius, this->Private->Radius,
                              0.0, 0.0,
                              data[2*i], data[2*i+1]
                              );
    }

  this->PaintChildren(painter);
  return true;
}

//-----------------------------------------------------------------------------

146 147
bool vtkPlotPie::PaintLegend(vtkContext2D *painter, const vtkRectf& rect,
                             int legendIndex)
148 149
{
  if (this->ColorSeries)
150 151
    this->Brush
      ->SetColor(this->ColorSeries->GetColorRepeating(legendIndex).GetData());
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172

  painter->ApplyPen(this->Pen);
  painter->ApplyBrush(this->Brush);
  painter->DrawRect(rect[0], rect[1], rect[2], rect[3]);
  return true;
}

//-----------------------------------------------------------------------------

void vtkPlotPie::SetDimensions(int arg1, int arg2, int arg3, int arg4)
{
  if (arg1 != this->Dimensions[0] || arg2 != this->Dimensions[1] ||
      arg3 != this->Dimensions[2] || arg4 != this->Dimensions[3])
    {
    this->Dimensions[0] = arg1;
    this->Dimensions[1] = arg2;
    this->Dimensions[2] = arg3;
    this->Dimensions[3] = arg4;

    this->Private->CenterX = this->Dimensions[0] + 0.5 * this->Dimensions[2];
    this->Private->CenterY = this->Dimensions[1] + 0.5 * this->Dimensions[3];
173 174
    this->Private->Radius  = this->Dimensions[2] < this->Dimensions[3]
        ? 0.5 * this->Dimensions[2] : 0.5 * this->Dimensions[3];
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
    this->Modified();
    }
}

void vtkPlotPie::SetDimensions(int arg[4])
{
  this->SetDimensions(arg[0],arg[1],arg[2],arg[3]);
}


//-----------------------------------------------------------------------------
void vtkPlotPie::SetColorSeries(vtkColorSeries *colorSeries)
{
  if (this->ColorSeries == colorSeries)
    {
    return;
    }
  this->ColorSeries = colorSeries;
  this->Modified();
}

//-----------------------------------------------------------------------------
vtkColorSeries *vtkPlotPie::GetColorSeries()
{
  return this->ColorSeries;
}

//-----------------------------------------------------------------------------
203 204
vtkIdType vtkPlotPie::GetNearestPoint(const vtkVector2f& point,
                                      const vtkVector2f&,
205
                                      vtkVector2f* value)
206
{
207 208
  float x = point.GetX() - this->Private->CenterX;
  float y = point.GetY() - this->Private->CenterY;
209 210 211 212 213 214 215 216 217

  if (sqrt((x*x) + (y*y)) <= this->Private->Radius)
    {
    float *angles = static_cast<float *>(this->Points->GetVoidPointer(0));
    float pointAngle = vtkMath::DegreesFromRadians(atan2(y,x));
    if (pointAngle < 0)
      {
      pointAngle = 180.0 + (180.0 + pointAngle);
      }
218
    float *lbound = std::lower_bound(angles,
219 220
                                     angles + (this->Points->GetNumberOfPoints() * 2),
                                     pointAngle);
221 222 223 224
    // Location in the array
    int ret = lbound - angles;
    // There are two of each angle in the array (start,end for each point)
    ret = ret / 2;
225 226 227 228 229

    vtkTable *table = this->Data->GetInput();
    vtkDataArray* data = this->Data->GetInputArrayToProcess(0, table);
    value->SetX(ret);
    value->SetY(data->GetTuple1(ret));
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
    return ret;
    }

  return -1;
}

//-----------------------------------------------------------------------------
void vtkPlotPie::PrintSelf(ostream &os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);
}

//-----------------------------------------------------------------------------
bool vtkPlotPie::UpdateTableCache(vtkTable *table)
{
  // Get the x and y arrays (index 0 and 1 respectively)
  vtkDataArray* data = this->Data->GetInputArrayToProcess(0, table);

  if (!data)
    {
    vtkErrorMacro(<< "No data set (index 0).");
    return false;
    }

  if (!this->Points)
    {
    this->Points = vtkPoints2D::New();
    }


  switch (data->GetDataType())
    {
    vtkTemplateMacro(
      CopyToPoints(this->Points,
                   static_cast<VTK_TT*>(data->GetVoidPointer(0)),
                   data->GetNumberOfTuples()));
    }

  this->BuildTime.Modified();
  return true;
}