1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkChartXYZ.h
5 
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 
16 // .NAME vtkChartXYZ - Factory class for drawing 3D XYZ charts.
17 //
18 // .SECTION Description
19 
20 #ifndef vtkChartXYZ_h
21 #define vtkChartXYZ_h
22 
23 #include "vtkChartsCoreModule.h" // For export macro
24 #include "vtkContextItem.h"
25 #include "vtkColor.h"        // For vtkColor4ub
26 #include "vtkRect.h"         // For vtkRectf ivars
27 #include "vtkNew.h"          // For ivars
28 #include "vtkSmartPointer.h" // For ivars
29 #include <vector>            // For ivars
30 
31 class vtkAnnotationLink;
32 class vtkAxis;
33 class vtkContext3D;
34 class vtkContextMouseEvent;
35 class vtkPen;
36 class vtkPlaneCollection;
37 class vtkPlot3D;
38 class vtkTable;
39 class vtkTransform;
40 class vtkUnsignedCharArray;
41 
42 class VTKCHARTSCORE_EXPORT vtkChartXYZ : public vtkContextItem
43 {
44 public:
45   vtkTypeMacro(vtkChartXYZ, vtkContextItem);
46   virtual void PrintSelf(ostream &os, vtkIndent indent);
47 
48   static vtkChartXYZ * New();
49 
50   // Description:
51   // Set the geometry in pixel coordinates (origin and width/height).
52   // This method also sets up the end points of the axes of the chart.
53   // For this reason, if you call SetAroundX(), you should call SetGeometry()
54   // afterwards.
55   void SetGeometry(const vtkRectf &bounds);
56 
57   // Description:
58   // Set the rotation angle for the chart (AutoRotate mode only).
59   void SetAngle(double angle);
60 
61   // Description:
62   // Set whether or not we're rotating about the X axis.
63   void SetAroundX(bool isX);
64 
65   // Description:
66   // Set the vtkAnnotationLink for the chart.
67   virtual void SetAnnotationLink(vtkAnnotationLink *link);
68 
69   // Description:
70   // Get the x (0), y (1) or z (2) axis.
71   vtkAxis * GetAxis(int axis);
72 
73   // Description:
74   // Set the color for the axes.
75   void SetAxisColor(const vtkColor4ub& color);
76   vtkColor4ub GetAxisColor();
77 
78   // Description:
79   // Set whether or not we're using this chart to rotate on a timer.
80   // Default value is false.
81   void SetAutoRotate(bool b);
82 
83   // Description:
84   // Set whether or not axes labels & tick marks should be drawn.
85   // Default value is true.
86   void SetDecorateAxes(bool b);
87 
88   // Description:
89   // Set whether or not the chart should automatically resize itself to fill
90   // the scene.  Default value is true.
91   void SetFitToScene(bool b);
92 
93   // Description:
94   // Perform any updates to the item that may be necessary before rendering.
95   virtual void Update();
96 
97   // Description:
98   // Paint event for the chart, called whenever the chart needs to be drawn.
99   virtual bool Paint(vtkContext2D *painter);
100 
101   // Description:
102   // Adds a plot to the chart.
103   virtual vtkIdType AddPlot(vtkPlot3D* plot);
104 
105   // Description:
106   // Remove all the plots from this chart.
107   void ClearPlots();
108 
109   // Description:
110   // Determine the XYZ bounds of the plots within this chart.
111   // This information is then used to set the range of the axes.
112   void RecalculateBounds();
113 
114   // Description:
115   // Use this chart's Geometry to set the endpoints of its axes.
116   // This method also sets up a transformation that is used to
117   // properly render the data within the chart.
118   void RecalculateTransform();
119 
120   //BTX
121   // Description:
122   // Returns true if the transform is interactive, false otherwise.
123   virtual bool Hit(const vtkContextMouseEvent &mouse);
124 
125   // Description:
126   // Mouse press event. Keep track of zoom anchor position.
127   virtual bool MouseButtonPressEvent(const vtkContextMouseEvent &mouse);
128 
129   // Description:
130   // Mouse move event. Perform pan or zoom as specified by the mouse bindings.
131   virtual bool MouseMoveEvent(const vtkContextMouseEvent &mouse);
132 
133   // Description:
134   // Mouse wheel event.  Zooms in or out.
135   virtual bool MouseWheelEvent(const vtkContextMouseEvent &mouse, int delta);
136 
137   // Description:
138   // Key press event.  This allows the user to snap the chart to one of three
139   // different 2D views.  "x" changes the view so we're looking down the X axis.
140   // Similar behavior occurs for "y" or "z".
141   virtual bool KeyPressEvent(const vtkContextKeyEvent &key);
142   //ETX
143 
144 protected:
145   vtkChartXYZ();
146   ~vtkChartXYZ();
147 
148   // Description:
149   // Calculate the transformation matrices used to draw data points and axes
150   // in the scene.  This function also sets up clipping planes that determine
151   // whether or not a data point is within range.
152   virtual void CalculateTransforms();
153 
154   // Description:
155   // Given the x, y and z vtkAxis, and a transform, calculate the transform that
156   // the points in a chart would need to be drawn within the axes. This assumes
157   // that the axes have the correct start and end positions, and that they are
158   // perpendicular.
159   bool CalculatePlotTransform(vtkAxis *x, vtkAxis *y, vtkAxis *z,
160                               vtkTransform *transform);
161 
162   // Description:
163   // Rotate the chart in response to a mouse movement.
164   bool Rotate(const vtkContextMouseEvent &mouse);
165 
166   // Description:
167   // Pan the data within the chart in response to a mouse movement.
168   bool Pan(const vtkContextMouseEvent &mouse);
169 
170   // Description:
171   // Zoom in or out on the data in response to a mouse movement.
172   bool Zoom(const vtkContextMouseEvent &mouse);
173 
174   // Description:
175   // Spin the chart in response to a mouse movement.
176   bool Spin(const vtkContextMouseEvent &mouse);
177 
178   // Description:
179   // Adjust the rotation of the chart so that we are looking down the X axis.
180   void LookDownX();
181 
182   // Description:
183   // Adjust the rotation of the chart so that we are looking down the Y axis.
184   void LookDownY();
185 
186   // Description:
187   // Adjust the rotation of the chart so that we are looking down the Z axis.
188   void LookDownZ();
189 
190   // Description:
191   // Adjust the rotation of the chart so that we are looking up the X axis.
192   void LookUpX();
193 
194   // Description:
195   // Adjust the rotation of the chart so that we are looking up the Y axis.
196   void LookUpY();
197 
198   // Description:
199   // Adjust the rotation of the chart so that we are looking up the Z axis.
200   void LookUpZ();
201 
202   // Description:
203   // Check to see if the scene changed size since the last render.
204   bool CheckForSceneResize();
205 
206   // Description:
207   // Scale the axes up or down in response to a scene resize.
208   void RescaleAxes();
209 
210   // Description:
211   // Scale up the axes when the scene gets larger.
212   void ScaleUpAxes();
213 
214   // Description:
215   // Scale down the axes when the scene gets smaller.
216   void ScaleDownAxes();
217 
218   // Description:
219   // Change the scaling of the axes by a specified amount.
220   void ZoomAxes(int delta);
221 
222   // Description:
223   // Initialize a list of "test points".  These are used to determine whether
224   // or not the chart fits completely within the bounds of the current scene.
225   void InitializeAxesBoundaryPoints();
226 
227   // Description:
228   // Initialize the "future box" transform.  This transform is a duplicate of
229   // the Box transform, which dictates how the chart's axes should be drawn.
230   // In ScaleUpAxes() and ScaleDownAxes(), we incrementally change the scaling
231   // of the FutureBox transform to determine how much we need to zoom in or
232   // zoom out to fit the chart within the newly resized scene.  Using a
233   // separate transform for this process allows us to resize the Box in a
234   // single step.
235   void InitializeFutureBox();
236 
237   // Description:
238   // Compute a bounding box for the data that is rendered within the axes.
239   void ComputeDataBounds();
240 
241   // Description:
242   // Draw the cube axes of this chart.
243   void DrawAxes(vtkContext3D *context);
244 
245   // Description:
246   // For each of the XYZ dimensions, find the axis line that is furthest
247   // from the rendered data.
248   void DetermineWhichAxesToLabel();
249 
250   // Description:
251   // Draw tick marks and tick mark labels along the axes.
252   void DrawTickMarks(vtkContext2D *painter);
253 
254   // Description:
255   // Label the axes.
256   void DrawAxesLabels(vtkContext2D *painter);
257 
258   // Description:
259   // Compute how some text should be offset from an axis.  The parameter
260   // bounds contains the bounding box of the text to be rendered.  The
261   // result is stored in the parameter offset.
262   void GetOffsetForAxisLabel(int axis, float *bounds, float *offset);
263 
264   // Description:
265   // Calculate the next "nicest" numbers above and below the current minimum.
266   // \return the "nice" spacing of the numbers.
267   // This function was mostly copied from vtkAxis.
268   double CalculateNiceMinMax(double &min, double &max, int axis);
269 
270   // Description:
271   // Get the equation for the ith face of our bounding cube.
272   void GetClippingPlaneEquation(int i, double *planeEquation);
273 
274   // Description:
275   // The size and position of this chart.
276   vtkRectf Geometry;
277 
278   // Description:
279   // The 3 axes of this chart.
280   std::vector< vtkSmartPointer<vtkAxis> > Axes;
281 
282   // Description:
283   // This boolean indicates whether or not we're using this chart to rotate
284   // on a timer.
285   bool AutoRotate;
286 
287   // Description:
288   // When we're in AutoRotate mode, this boolean tells us if we should rotate
289   // about the X axis or the Y axis.
290   bool IsX;
291 
292   // Description:
293   // When we're in AutoRotate mode, this value tells the chart how much it
294   // should be rotated.
295   double Angle;
296 
297   // Description:
298   // This boolean indicates whether or not we should draw tick marks
299   // and axes labels.
300   bool DrawAxesDecoration;
301 
302   // Description:
303   // This boolean indicates whether or not we should automatically resize the
304   // chart so that it snugly fills up the scene.
305   bool FitToScene;
306 
307   // Description:
308   // This is the transform that is applied when rendering data from the plots.
309   vtkNew<vtkTransform> ContextTransform;
310 
311   // Description:
312   // This transform translates and scales the plots' data points so that they
313   // appear within the axes of this chart.  It is one of the factors that
314   // makes up the ContextTransform.
315   vtkNew<vtkTransform> PlotTransform;
316 
317   // Description:
318   // This is the transform that is applied when rendering data from the plots.
319   vtkNew<vtkTransform> Box;
320 
321   // Description:
322   // This transform keeps track of how the chart has been rotated.
323   vtkNew<vtkTransform> Rotation;
324 
325   // Description:
326   // This transform keeps track of how the data points have been panned within
327   // the chart.
328   vtkNew<vtkTransform> Translation;
329 
330   // Description:
331   // This transform keeps track of how the data points have been scaled
332   // (zoomed in or zoomed out) within the chart.
333   vtkNew<vtkTransform> Scale;
334 
335   // Description:
336   // This transform keeps track of how the axes have been scaled
337   // (zoomed in or zoomed out).
338   vtkNew<vtkTransform> BoxScale;
339 
340   // Description:
341   // This transform is initialized as a copy of Box.  It is used within
342   // ScaleUpAxes() and ScaleDownAxes() to figure out how much we need to
343   // zoom in or zoom out to fit our chart within the newly resized scene.
344   vtkNew<vtkTransform> FutureBox;
345 
346   // Description:
347   // This transform keeps track of the Scale of the FutureBox transform.
348   vtkNew<vtkTransform> FutureBoxScale;
349 
350   // Description:
351   // This is the pen that is used to draw data from the plots.
352   vtkNew<vtkPen> Pen;
353 
354   // Description:
355   // This is the pen that is used to draw the axes.
356   vtkNew<vtkPen> AxisPen;
357 
358   // Description:
359   // This link is used to share selected points with other classes.
360   vtkSmartPointer<vtkAnnotationLink> Link;
361 
362   // Description:
363   // The plots that are drawn within this chart.
364   std::vector<vtkPlot3D *> Plots;
365 
366   // Description:
367   // The label for the X Axis.
368   std::string XAxisLabel;
369 
370   // Description:
371   // The label for the Y Axis.
372   std::string YAxisLabel;
373 
374   // Description:
375   // The label for the Z Axis.
376   std::string ZAxisLabel;
377 
378   // Description:
379   // The six planes that define the bounding cube of our 3D axes.
380   vtkNew<vtkPlaneCollection> BoundingCube;
381 
382   // Description:
383   // Points used to determine whether the axes will fit within the scene as
384   // currently sized, regardless of rotation.
385   float AxesBoundaryPoints[14][3];
386 
387   // Description:
388   // This member variable stores the size of the tick labels for each axis.
389   // It is used to determine the position of the axis labels.
390   float TickLabelOffset[3][2];
391 
392   // Description:
393   // The height of the scene, as of the most recent call to Paint().
394   int SceneHeight;
395 
396   // Description:
397   // The weight of the scene, as of the most recent call to Paint().
398   int SceneWidth;
399 
400   // Description:
401   // Which line to label.
402   int XAxisToLabel[3];
403   int YAxisToLabel[3];
404   int ZAxisToLabel[3];
405 
406   // Description:
407   // What direction the data is from each labeled axis line.
408   int DirectionToData[3];
409 
410   // Description:
411   // A bounding box surrounding the currently rendered data points.
412   double DataBounds[4];
413 
414 private:
415   vtkChartXYZ(const vtkChartXYZ &);    // Not implemented.
416   void operator=(const vtkChartXYZ &); // Not implemented.
417 };
418 
419 #endif
420