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

      float x = this->Borders[vtkAxis::LEFT];
      float y = this->Borders[vtkAxis::BOTTOM];
87
      for (int i = 0; i < this->Size.X(); ++i)
88
        {
89
90
91
92
        if (i > 0)
          {
          x += increments.X() + this->Gutter.X();
          }
93
        for (int j = 0; j < this->Size.Y(); ++j)
94
          {
95
96
97
98
99
100
101
102
          if (j > 0)
            {
            y += increments.Y() + this->Gutter.Y();
            }
          else
            {
            y = this->Borders[vtkAxis::BOTTOM];
            }
103
104
105
106
          size_t index = j * this->Size.X() + i;
          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.X() * span.X() +
                                    (span.X() - 1) * this->Gutter.X(),
                                    increments.Y() * span.Y() +
                                    (span.Y() - 1) * this->Gutter.Y()));
113
            }
114
115
116
          }
        }
      }
117
    this->LayoutIsDirty = false;
118
119
120
121
122
123
124
125
126
    }
  return Superclass::Paint(painter);
}

void vtkChartMatrix::SetSize(const vtkVector2i &size)
{
  if (this->Size.X() != size.X() || this->Size.Y() != size.Y())
    {
    this->Size = size;
127
128
129
130
131
132
133
134
    if (size.X() * size.Y() < static_cast<int>(this->Private->Charts.size()))
      {
      for (int i = static_cast<int>(this->Private->Charts.size() - 1);
           i >= size.X() * size.Y(); --i)
        {
        this->RemoveItem(this->Private->Charts[i]);
        }
      }
135
    this->Private->Charts.resize(size.X() * size.Y());
136
    this->Private->Spans.resize(size.X() * size.Y(), 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
163
164
165
166
167
168
169
170
171
void vtkChartMatrix::Allocate()
{
  // Force allocation of all objects as vtkChartXY.
}

bool vtkChartMatrix::SetChart(const vtkVector2i &position, vtkChart *chart)
{
  if (position.X() < this->Size.X() && position.Y() < this->Size.Y())
    {
    size_t index = position.Y() * this->Size.X() + position.X();
    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
183
184
185
186
187
    return true;
    }
  else
    {
    return false;
    }
}

vtkChart* vtkChartMatrix::GetChart(const vtkVector2i &position)
{
  if (position.X() < this->Size.X() && position.Y() < this->Size.Y())
    {
    size_t index = position.Y() * this->Size.X() + position.X();
    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
204
205
206
207
208
209
210
211
bool vtkChartMatrix::SetChartSpan(const vtkVector2i& position,
                                  const vtkVector2i& span)
{
  if (this->Size.X() - position.X() - span.X() < 0 ||
      this->Size.Y() - position.Y() - span.Y() < 0)
    {
    return false;
    }
  else
    {
    this->Private->Spans[position.Y() * this->Size.X() + position.X()] = span;
212
    this->LayoutIsDirty = true;
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
    return true;
    }
}

vtkVector2i vtkChartMatrix::GetChartSpan(const vtkVector2i& position)
{
  size_t index = position.Y() * this->Size.X() + position.X();
  if (position.X() < this->Size.X() && position.Y() < this->Size.Y())
    {
    return this->Private->Spans[index];
    }
  else
    {
    return vtkVector2i(0, 0);
    }
}

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
271
272
273
274
275
276
277
278
279
280
281
vtkVector2i vtkChartMatrix::GetChartIndex(const vtkVector2f &position)
{
  if (this->Size.X() > 0 && this->Size.Y() > 0)
    {
    // Calculate the increments without the gutters/borders that must be left.
    vtkVector2f increments;
    increments.SetX((this->Private->Geometry.X() - (this->Size.X() - 1) *
                     this->Gutter.X() - this->Borders[vtkAxis::LEFT] -
                     this->Borders[vtkAxis::RIGHT]) /
                     this->Size.X());
    increments.SetY((this->Private->Geometry.Y() - (this->Size.Y() - 1) *
                     this->Gutter.Y() - this->Borders[vtkAxis::TOP] -
                     this->Borders[vtkAxis::BOTTOM]) /
                     this->Size.Y());

    float x = this->Borders[vtkAxis::LEFT];
    float y = this->Borders[vtkAxis::BOTTOM];
    for (int i = 0; i < this->Size.X(); ++i)
      {
      if (i > 0)
        {
        x += increments.X() + this->Gutter.X();
        }
      for (int j = 0; j < this->Size.Y(); ++j)
        {
        if (j > 0)
          {
          y += increments.Y() + this->Gutter.Y();
          }
        else
          {
          y = this->Borders[vtkAxis::BOTTOM];
          }
        size_t index = j * this->Size.X() + i;
        if (this->Private->Charts[index])
          {
          vtkVector2i &span = this->Private->Spans[index];
          // Check if the supplied location is within this charts area.
          if (position.X() > x &&
              position.X() < (x + increments.X() * span.X()
                              + (span.X() - 1) * this->Gutter.X()) &&
              position.Y() > y &&
              position.Y() < (y + increments.Y() * span.Y()
                              + (span.Y() - 1) * this->Gutter.Y()))
            return vtkVector2i(i, j);
          }
        }
      }
    }
  return vtkVector2i(-1, -1);
}

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