source: nanovis/trunk/Axis.h @ 4905

Last change on this file since 4905 was 3630, checked in by ldelgass, 11 years ago

Nanovis refactoring to fix problems with scaling and multiple results.
Do rendering in world space to properly place and scale multiple data sets.
Also fix flows to reduce resets of animations. More work toward removing
Cg dependency. Fix panning to convert viewport coords to world coords.

  • Property svn:eol-style set to native
File size: 8.0 KB
Line 
1/* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2/*
3 * Copyright (c) 2004-2013  HUBzero Foundation, LLC
4 *
5 * Authors: George A. Howlett <gah@purdue.edu>
6 */
7#ifndef NV_AXIS_H
8#define NV_AXIS_H
9
10#include <stdlib.h>
11#include <string.h>
12
13#include <cmath>
14#include <limits>
15
16#include "Chain.h"
17
18#ifndef NAN
19#define NAN (std::numeric_limits<double>::quiet_NaN())
20#endif
21
22namespace nv {
23
24class Axis;
25
26class TickIter
27{
28public:
29    void setStartingLink(ChainLink *linkPtr)
30    {
31        _linkPtr = linkPtr;
32    }
33
34    bool next()
35    {
36        if (_linkPtr == NULL) {
37            return false;
38        }
39        _linkPtr = _linkPtr->next();
40        return (_linkPtr != NULL);
41    }
42
43    float getValue()
44    {
45        union {
46            float x;
47            void *clientData;
48        } value;
49        value.clientData = _linkPtr->getValue();
50        return value.x;
51    }
52
53private:
54    ChainLink *_linkPtr;
55};
56
57/**
58 * Class containing information where the ticks (major or
59 * minor) will be displayed on the graph.
60 */
61class Ticks
62{
63public:
64    Ticks(int numTicks) :
65        reqNumTicks(numTicks),
66        _autoscale(true),
67        _numTicks(0),
68        _ticks(NULL)
69    {
70    }
71
72    ~Ticks()
73    {
74        if (_ticks != NULL) {
75            delete [] _ticks;
76        }
77        _chain.reset();
78    }
79
80    void setTicks(float *ticks, int nTicks)
81    {
82        _ticks = ticks, _numTicks = nTicks;
83    }
84
85    int numTicks()
86    {
87        return _numTicks;
88    }
89
90    double tick(int i)
91    {
92        if ((i < 0) || (i >= _numTicks)) {
93            return NAN;
94        }
95        return _ticks[i];
96    }
97
98    void reset()
99    {
100        _chain.reset();
101    }
102
103    float step()
104    {
105        return _step;
106    }
107
108    void append (float x)
109    {
110        _chain.append(getClientData(x));
111    }
112
113    void setValues(double initial, double step, unsigned int nSteps)
114    {
115        _initial = initial, _step = step, _nSteps = nSteps;
116    }
117
118    bool autoscale()
119    {
120        return _autoscale;
121    }
122
123    void sweepTicks()
124    {
125        if (_autoscale) {
126            if (_ticks != NULL) {
127                delete [] _ticks;
128            }
129            setTicks();
130        }
131    }
132
133    bool firstTick(TickIter &iter)
134    {
135        ChainLink *linkPtr;
136
137        linkPtr = _chain.firstLink();
138        iter.setStartingLink(linkPtr);
139        return (linkPtr != NULL);
140    }
141
142    int reqNumTicks;            /**< Default number of ticks to be displayed. */
143
144private:
145    void setTicks();    /**< Routine used internally to create the array
146                                 * of ticks as defined by a given sweep. */
147    void *getClientData(float x)
148    {
149        union {
150            float x;
151            void *clientData;
152        } value;
153        value.x = x;
154        return value.clientData;
155    }
156
157    bool _autoscale;            /**< Indicates if the ticks are autoscaled. */
158    /*
159     * Tick locations may be generated in two fashions
160     */
161    /* 1. an array of values provided by the user. */
162    int _numTicks;              /* # of ticks on axis */
163    float *_ticks;              /* Array of tick values (alloc-ed).  Right now
164                                 * it's a float so we don't have to allocate
165                                 * store for the list of ticks generated.  In
166                                 * the future when we store both the tick
167                                 * label and the value in the list, we may
168                                 * extend this to a double.
169                                 */
170    /*
171     * 2. a defined sweep of initial, step, and nsteps.  This in turn
172     *    will generate the an array of values.
173     */
174    double _initial;            /**< Initial value */
175    double _step;               /**< Size of interval */
176    unsigned int _nSteps;       /**< Number of intervals. */
177
178    /**
179     *This finally generates a list of ticks values that exclude duplicate
180     * minor ticks (that are always represented by major ticks).  In the
181     * future, the string representing the tick label will be stored in
182     * the chain.
183     */
184    Chain _chain;
185};
186
187/**
188 * Class contains options controlling how the axis will be
189 * displayed.
190 */
191class Axis
192{
193public:
194    /// Flags associated with the axis.
195    enum AxisFlags {
196        AUTOSCALE  = (1<<0),
197        DESCENDING = (1<<1),
198        LOGSCALE   = (1<<2),
199        TIGHT_MIN  = (1<<3),
200        TIGHT_MAX  = (1<<4)
201    };
202
203    Axis(const char *name);
204
205    ~Axis()
206    {
207        if (_name != NULL) {
208            free((void *)_name);
209        }
210        if (_units != NULL) {
211            free((void *)_units);
212        }
213        if (_title != NULL) {
214            free((void *)_title);
215        }
216    }
217
218    bool firstMajor(TickIter& iter)
219    {
220        return _major.firstTick(iter);
221    }
222
223    bool firstMinor(TickIter& iter)
224    {
225        return _minor.firstTick(iter);
226    }
227
228    void resetRange();
229
230    void fixRange(double min, double max);
231
232    void setScale(double min, double max);
233
234    double scale() const
235    {
236        return _scale;
237    }
238
239    double range() const
240    {
241        return _range;
242    }
243
244    double dataMin() const
245    {
246        return _valueMin;
247    }
248
249    double dataMax() const
250    {
251        return _valueMax;
252    }
253
254    double min() const
255    {
256        return _min;
257    }
258
259    double max() const
260    {
261        return _max;
262    }
263
264    void setLimits(double min, double max)
265    {
266        _reqMin = min, _reqMax = max;
267    }
268
269    void unsetLimits()
270    {
271        setLimits(NAN, NAN);
272    }
273
274    double map(double x);
275
276    double invMap(double x);
277
278    const char *name()
279    {
280        return _name;
281    }
282
283    void name(const char *name)
284    {
285        if (_name != NULL) {
286            free((void *)_name);
287        }
288        _name = strdup(name);
289    }
290
291    const char *units()
292    {
293        return _units;
294    }
295
296    void units(const char *units)
297    {
298        if (_units != NULL) {
299            free((void *)_units);
300        }
301        _units = strdup(units);
302    }
303
304    const char *title()
305    {
306        return _title;
307    }
308
309    void title(const char *title)
310    {
311        if (_title != NULL) {
312            free((void *)_title);
313        }
314        _title = strdup(title);
315    }
316
317    void setDescendingOption(bool value)
318    {
319        if (value) {
320            _flags |= DESCENDING;
321        } else {
322            _flags &= ~DESCENDING;
323        }
324    }
325
326    void setTightMinOption(bool value)
327    {
328        if (value) {
329            _flags |= TIGHT_MIN;
330        } else {
331            _flags &= ~TIGHT_MIN;
332        }
333    }
334
335    void setTightMaxOption(bool value)
336    {
337        if (value) {
338            _flags |= TIGHT_MAX;
339        } else {
340            _flags &= ~TIGHT_MAX;
341        }
342    }
343
344    void setLogScaleOption(bool value)
345    {
346        if (value) {
347            _flags |= LOGSCALE;
348        } else {
349            _flags &= ~LOGSCALE;
350        }
351    }
352
353    void setMajorStepOption(double value)
354    {
355        _reqStep = value;       // Setting to 0.0 resets step to "auto"
356    }
357
358    void setNumMinorTicksOption(int n)
359    {
360        _minor.reqNumTicks = n;
361    }
362
363    void setNumMajorTicksOption(int n)
364    {
365        _major.reqNumTicks = n;
366    }
367
368private:
369    void logScale();
370
371    void linearScale();
372
373    bool inRange(double x);
374
375    void makeTicks();
376
377    const char *_name;          /**< Name of the axis. Malloc-ed */
378
379    unsigned int _flags;
380
381    const char *_title;         /**< Title of the axis. */
382
383    const char *_units;         /**< Units of the axis. */
384
385    double _valueMin, _valueMax; /**< The limits of the data. */
386
387    double _reqMin, _reqMax;    /**< Requested axis bounds. Consult the
388                                 * axisPtr->flags field for
389                                 * Axis::CONFIG_MIN and Axis::CONFIG_MAX
390                                 * to see if the requested bound have
391                                 * been set.  They override the
392                                 * computed range of the axis
393                                 * (determined by auto-scaling). */
394
395    double _min, _max;          /**< Smallest and largest major tick values for
396                                 * the axis.  If loose, the tick values lie
397                                 * outside the range of data values.  If
398                                 * tight, they lie interior to the limits of
399                                 * the data. */
400
401    double _range;              /**< Range of values on axis (_max - _min) */
402    double _scale;              /**< Scale factor for axis (1.0/_range) */
403
404    double _reqStep;            /**< If > 0.0, overrides the computed major tick
405                                 * interval.  Otherwise a stepsize is
406                                 * automatically calculated, based upon the
407                                 * range of elements mapped to the axis. The
408                                 * default value is 0.0. */
409
410    Ticks _major, _minor;
411};
412
413}
414
415#endif
Note: See TracBrowser for help on using the repository browser.