vtkChartMatrix.cxx 8.66 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:    vtkChartMatrix.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 "vtkChartMatrix.h"

#include "vtkChartXY.h"
19
#include "vtkNew.h"
20
21
22
#include "vtkSmartPointer.h"
#include "vtkContext2D.h"
#include "vtkContextScene.h"
23
#include "vtkAxis.h"
24
25
26
27
28
29
30
#include "vtkObjectFactory.h"

#include <vector>

class vtkChartMatrix::PIMPL
{
public:
31
  PIMPL() : Geometry(0, 0) {}
32
33
  ~PIMPL() {}

34
  // Container for the vtkChart objects that make up the matrix.
35
  std::vector< vtkSmartPointer<vtkChart> > Charts;
36
37
  // Spans of the charts in the matrix, default is 1x1.
  std::vector< vtkVector2i > Spans;
38
39
40
41
42
  vtkVector2i Geometry;
};

vtkStandardNewMacro(vtkChartMatrix)

43
vtkChartMatrix::vtkChartMatrix() : Size(0, 0), Gutter(15.0, 15.0)
44
45
{
  this->Private = new PIMPL;
46
47
  this->Borders[vtkAxis::LEFT] = 50;
  this->Borders[vtkAxis::BOTTOM] = 40;
48
  this->Borders[vtkAxis::RIGHT] = 50;
49
  this->Borders[vtkAxis::TOP] = 40;
50
  this->LayoutIsDirty = true;
51
52
53
54
55
56
57
58
59
60
61
62
63
64
}

vtkChartMatrix::~vtkChartMatrix()
{
  delete this->Private;
}

void vtkChartMatrix::Update()
{

}

bool vtkChartMatrix::Paint(vtkContext2D *painter)
{
65
  if (this->LayoutIsDirty ||
66
67
      this->GetScene()->GetSceneWidth() != this->Private->Geometry.GetX() ||
      this->GetScene()->GetSceneHeight() != this->Private->Geometry.GetY())
68
69
70
71
    {
    // Update the chart element positions
    this->Private->Geometry.Set(this->GetScene()->GetSceneWidth(),
                                this->GetScene()->GetSceneHeight());
72
    if (this->Size.GetX() > 0 && this->Size.GetY() > 0)
73
      {
74
75
      // Calculate the increments without the gutters/borders that must be left
      vtkVector2f increments;
76
77
      increments.SetX((this->Private->Geometry.GetX() - (this->Size.GetX() - 1) *
                       this->Gutter.GetX() - this->Borders[vtkAxis::LEFT] -
78
                       this->Borders[vtkAxis::RIGHT]) /
79
80
81
                      this->Size.GetX());
      increments.SetY((this->Private->Geometry.GetY() - (this->Size.GetY() - 1) *
                       this->Gutter.GetY() - this->Borders[vtkAxis::TOP] -
82
                       this->Borders[vtkAxis::BOTTOM]) /
83
                      this->Size.GetY());
84
85
86

      float x = this->Borders[vtkAxis::LEFT];
      float y = this->Borders[vtkAxis::BOTTOM];
87
      for (int i = 0; i < this->Size.GetX(); ++i)
88
        {
89
90
        if (i > 0)
          {
91
          x += increments.GetX() + this->Gutter.GetX();
92
          }
93
        for (int j = 0; j < this->Size.GetY(); ++j)
94
          {
95
96
          if (j > 0)
            {
97
            y += increments.GetY() + this->Gutter.GetY();
98
99
100
101
102
            }
          else
            {
            y = this->Borders[vtkAxis::BOTTOM];
            }
103
          size_t index = j * this->Size.GetX() + i;
104
105
106
          if (this->Private->Charts[index])
            {
            vtkChart *chart = this->Private->Charts[index];
107
            vtkVector2i &span = this->Private->Spans[index];
108
            chart->SetSize(vtkRectf(x, y,
109
110
111
112
                                    increments.GetX() * span.GetX() +
                                    (span.GetX() - 1) * this->Gutter.GetX(),
                                    increments.GetY() * span.GetY() +
                                    (span.GetY() - 1) * this->Gutter.GetY()));
113
            }
114
115
116
          }
        }
      }
117
    this->LayoutIsDirty = false;
118
119
120
121
122
123
    }
  return Superclass::Paint(painter);
}

void vtkChartMatrix::SetSize(const vtkVector2i &size)
{
124
  if (this->Size.GetX() != size.GetX() || this->Size.GetY() != size.GetY())
125
126
    {
    this->Size = size;
127
    if (size.GetX() * size.GetY() < static_cast<int>(this->Private->Charts.size()))
128
129
      {
      for (int i = static_cast<int>(this->Private->Charts.size() - 1);
130
           i >= size.GetX() * size.GetY(); --i)
131
132
133
134
        {
        this->RemoveItem(this->Private->Charts[i]);
        }
      }
135
136
    this->Private->Charts.resize(size.GetX() * size.GetY());
    this->Private->Spans.resize(size.GetX() * size.GetY(), vtkVector2i(1, 1));
137
    this->LayoutIsDirty = true;
138
139
140
    }
}

141
142
143
144
145
146
147
148
149
void vtkChartMatrix::SetBorders(int left, int bottom, int right, int top)
{
  this->Borders[vtkAxis::LEFT] = left;
  this->Borders[vtkAxis::BOTTOM] = bottom;
  this->Borders[vtkAxis::RIGHT] = right;
  this->Borders[vtkAxis::TOP] = top;
  this->LayoutIsDirty = true;
}

150
151
152
void vtkChartMatrix::SetGutter(const vtkVector2f &gutter)
{
  this->Gutter = gutter;
153
  this->LayoutIsDirty = true;
154
155
}

156
157
158
159
160
161
162
void vtkChartMatrix::Allocate()
{
  // Force allocation of all objects as vtkChartXY.
}

bool vtkChartMatrix::SetChart(const vtkVector2i &position, vtkChart *chart)
{
163
  if (position.GetX() < this->Size.GetX() && position.GetY() < this->Size.GetY())
164
    {
165
    size_t index = position.GetY() * this->Size.GetX() + position.GetX();
166
167
168
169
170
171
    if (this->Private->Charts[index])
      {
      this->RemoveItem(this->Private->Charts[index]);
      }
    this->Private->Charts[index] = chart;
    this->AddItem(chart);
172
    chart->SetLayoutStrategy(vtkChart::AXES_TO_RECT);
173
174
175
176
177
178
179
180
181
182
    return true;
    }
  else
    {
    return false;
    }
}

vtkChart* vtkChartMatrix::GetChart(const vtkVector2i &position)
{
183
  if (position.GetX() < this->Size.GetX() && position.GetY() < this->Size.GetY())
184
    {
185
    size_t index = position.GetY() * this->Size.GetX() + position.GetX();
186
187
    if (this->Private->Charts[index] == NULL)
      {
188
189
190
      vtkNew<vtkChartXY> chart;
      this->Private->Charts[index] = chart.GetPointer();
      this->AddItem(chart.GetPointer());
191
      chart->SetLayoutStrategy(vtkChart::AXES_TO_RECT);
192
193
194
195
196
197
198
199
200
      }
    return this->Private->Charts[index];
    }
  else
    {
    return NULL;
    }
}

201
202
203
bool vtkChartMatrix::SetChartSpan(const vtkVector2i& position,
                                  const vtkVector2i& span)
{
204
205
  if (this->Size.GetX() - position.GetX() - span.GetX() < 0 ||
      this->Size.GetY() - position.GetY() - span.GetY() < 0)
206
207
208
209
210
    {
    return false;
    }
  else
    {
211
    this->Private->Spans[position.GetY() * this->Size.GetX() + position.GetX()] = span;
212
    this->LayoutIsDirty = true;
213
214
215
216
217
218
    return true;
    }
}

vtkVector2i vtkChartMatrix::GetChartSpan(const vtkVector2i& position)
{
219
220
  size_t index = position.GetY() * this->Size.GetX() + position.GetX();
  if (position.GetX() < this->Size.GetX() && position.GetY() < this->Size.GetY())
221
222
223
224
225
226
227
228
229
    {
    return this->Private->Spans[index];
    }
  else
    {
    return vtkVector2i(0, 0);
    }
}

230
231
vtkVector2i vtkChartMatrix::GetChartIndex(const vtkVector2f &position)
{
232
  if (this->Size.GetX() > 0 && this->Size.GetY() > 0)
233
234
235
    {
    // Calculate the increments without the gutters/borders that must be left.
    vtkVector2f increments;
236
237
    increments.SetX((this->Private->Geometry.GetX() - (this->Size.GetX() - 1) *
                     this->Gutter.GetX() - this->Borders[vtkAxis::LEFT] -
238
                     this->Borders[vtkAxis::RIGHT]) /
239
240
241
                     this->Size.GetX());
    increments.SetY((this->Private->Geometry.GetY() - (this->Size.GetY() - 1) *
                     this->Gutter.GetY() - this->Borders[vtkAxis::TOP] -
242
                     this->Borders[vtkAxis::BOTTOM]) /
243
                     this->Size.GetY());
244
245
246

    float x = this->Borders[vtkAxis::LEFT];
    float y = this->Borders[vtkAxis::BOTTOM];
247
    for (int i = 0; i < this->Size.GetX(); ++i)
248
249
250
      {
      if (i > 0)
        {
251
        x += increments.GetX() + this->Gutter.GetX();
252
        }
253
      for (int j = 0; j < this->Size.GetY(); ++j)
254
255
256
        {
        if (j > 0)
          {
257
          y += increments.GetY() + this->Gutter.GetY();
258
259
260
261
262
          }
        else
          {
          y = this->Borders[vtkAxis::BOTTOM];
          }
263
        size_t index = j * this->Size.GetX() + i;
264
265
266
267
        if (this->Private->Charts[index])
          {
          vtkVector2i &span = this->Private->Spans[index];
          // Check if the supplied location is within this charts area.
268
269
270
271
272
273
          if (position.GetX() > x &&
              position.GetX() < (x + increments.GetX() * span.GetX()
                              + (span.GetX() - 1) * this->Gutter.GetX()) &&
              position.GetY() > y &&
              position.GetY() < (y + increments.GetY() * span.GetY()
                              + (span.GetY() - 1) * this->Gutter.GetY()))
274
275
276
277
278
279
280
281
            return vtkVector2i(i, j);
          }
        }
      }
    }
  return vtkVector2i(-1, -1);
}

282
283
284
285
void vtkChartMatrix::PrintSelf(ostream &os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);
}