Changeset 5542 for nanovis


Ignore:
Timestamp:
May 18, 2015, 5:47:29 AM (4 years ago)
Author:
ldelgass
Message:

Merge r5478,r5480 from nanovis trunk (grid refactoring)

Location:
nanovis/branches/1.2
Files:
2 deleted
8 edited

Legend:

Unmodified
Added
Removed
  • nanovis/branches/1.2

  • nanovis/branches/1.2/Axis.cpp

    r4889 r5542  
    33 * Copyright (c) 2004-2013  HUBzero Foundation, LLC
    44 *
    5  * Authors: George A. Howlett <gah@purdue.edu>
    6  */
     5 * Authors:
     6 *   George A. Howlett <gah@purdue.edu>
     7 *   Leif Delgass <ldelgass@purdue.edu>
     8 */
     9#include <string>
     10
    711#include <stdlib.h>
    812#include <stdio.h>
     
    1216
    1317#include "Axis.h"
     18#include "Trace.h"
    1419
    1520using namespace nv;
    16 
    17 inline bool DEFINED(double x) {
    18     return !isnan(x);
    19 }
    2021
    2122inline double EXP10(double x) {
     
    8586    _numTicks = 0;
    8687    _ticks = new float[_nSteps];
    87     if (_step == 0.0) {
    88         /* Hack: A zero step indicates to use log values. */
    89         unsigned int i;
    90         /* Precomputed log10 values [1..10] */
    91         static double logTable[] = {
    92             0.0,
    93             0.301029995663981,
    94             0.477121254719662,
    95             0.602059991327962,
    96             0.698970004336019,
    97             0.778151250383644,
    98             0.845098040014257,
    99             0.903089986991944,
    100             0.954242509439325,
    101             1.0
    102         };
    103         for (i = 0; i < _nSteps; i++) {
    104             _ticks[i] = logTable[i];
    105         }
    106     } else {
    107         double value;
    108         unsigned int i;
    109    
    110         value = _initial;        /* Start from smallest axis tick */
    111         for (i = 0; i < _nSteps; i++) {
    112             value = _initial + (_step * i);
    113             _ticks[i] = UROUND(value, _step);
    114         }
     88    // Start from smallest axis tick
     89    double value = _initial;
     90    for (unsigned int i = 0; i < _nSteps; i++) {
     91        value = _initial + (_step * i);
     92        _ticks[i] = UROUND(value, _step);
    11593    }
    11694    _numTicks = _nSteps;
    11795}
    11896
    119 Axis::Axis(const char *axisName) :
    120     _name(strdup(axisName)),
    121     _flags(AUTOSCALE),
    122     _title(NULL),
    123     _units(NULL),
     97Axis::Axis(const char *title) :
     98    _title(title),
     99    _tightMin(false),
     100    _tightMax(false),
     101    _reqStep(0.0),
    124102    _valueMin(DBL_MAX),
    125103    _valueMax(-DBL_MAX),
    126     _reqMin(NAN),
    127     _reqMax(NAN),
    128104    _min(DBL_MAX),
    129105    _max(-DBL_MAX),
    130     _range(0.0),
    131     _scale(0.0),
    132     _reqStep(0.0),
    133106    _major(5),
    134107    _minor(2)
     
    140113 *
    141114 * The value is normalized by the current axis range. If the normalized
    142  * value is between [0.0..1.0] then it's in range.  The value is compared
     115 * value is between [0.0,1.0] then it's in range.  The value is compared
    143116 * to 0 and 1., where 0.0 is the minimum and 1.0 is the maximum.
    144117 * DBL_EPSILON is the smallest number that can be represented on the host
     
    147120 * Please note, *max* can't equal *min*.
    148121 *
    149  * \return If the value is within the interval [min..max], 1 is returned; 0
     122 * \return If the value is within the interval [min,max], 1 is returned; 0
    150123 * otherwise.
    151124 */
     
    153126Axis::inRange(double x)
    154127{
    155     if (_range < DBL_EPSILON) {
     128    if ((_max - _min) < DBL_EPSILON) {
    156129        return (fabs(_max - x) >= DBL_EPSILON);
    157130    } else {
    158         x = (x - _min) * _scale;
     131        x = map(x);
    159132        return ((x >= -DBL_EPSILON) && ((x - 1.0) < DBL_EPSILON));
    160133    }
     
    165138{
    166139    if (min == DBL_MAX) {
    167         if (DEFINED(_reqMin)) {
    168             min = _reqMin;
    169         } else {
    170             min = (_flags & LOGSCALE) ? 0.001 : 0.0;
    171         }
     140        min = 0.0;
    172141    }
    173142    if (max == -DBL_MAX) {
    174         if (DEFINED(_reqMax)) {
    175             max = _reqMax;
    176         } else {
    177             max = 1.0;
    178         }
     143        max = 1.0;
    179144    }
    180145    if (min >= max) {
    181         /*
    182          * There is no range of data (i.e. min is not less than max), so
    183          * manufacture one.
    184          */
     146        // No range, so pick a default
    185147        if (min == 0.0) {
    186148            min = 0.0, max = 1.0;
     
    190152    }
    191153
    192     /*   
    193      * The axis limits are either the current data range or overridden by the
    194      * values selected by the user with the -min or -max options.
    195      */
    196     _valueMin = (DEFINED(_reqMin)) ? _reqMin : min;
    197     _valueMax = (DEFINED(_reqMax)) ? _reqMax : max;
    198     if (_valueMax < _valueMin) {
    199         /*   
    200          * If the limits still don't make sense, it's because one limit
    201          * configuration option (-min or -max) was set and the other default
    202          * (based upon the data) is too small or large.  Remedy this by making
    203          * up a new min or max from the user-defined limit.
    204          */
    205         if (!DEFINED(_reqMin)) {
    206             _valueMin = _valueMax - (fabs(_valueMax) * 0.1);
    207         }
    208         if (!DEFINED(_reqMax)) {
    209             _valueMax = _valueMin + (fabs(_valueMax) * 0.1);
    210         }
    211     }
    212 }
    213 
    214 /**
    215  * \brief Determine the range and units of a log scaled axis.
    216  *
    217  * Unless the axis limits are specified, the axis is scaled
    218  * automatically, where the smallest and largest major ticks encompass
    219  * the range of actual data values.  When an axis limit is specified,
    220  * that value represents the smallest(min)/largest(max) value in the
    221  * displayed range of values.
    222  *
    223  * Both manual and automatic scaling are affected by the step used.  By
    224  * default, the step is the largest power of ten to divide the range in
    225  * more than one piece.
    226  *
    227  * Automatic scaling:
    228  * Find the smallest number of units which contain the range of values.
    229  * The minimum and maximum major tick values will be represent the
    230  * range of values for the axis. This greatest number of major ticks
    231  * possible is 10.
    232  *
    233  * Manual scaling:
    234  * Make the minimum and maximum data values the represent the range of
    235  * the values for the axis.  The minimum and maximum major ticks will be
    236  * inclusive of this range.  This provides the largest area for plotting
    237  * and the expected results when the axis min and max values have be set
    238  * by the user (.e.g zooming).  The maximum number of major ticks is 20.
    239  *
    240  * For log scale, there's the possibility that the minimum and
    241  * maximum data values are the same magnitude.  To represent the
    242  * points properly, at least one full decade should be shown.
    243  * However, if you zoom a log scale plot, the results should be
    244  * predictable. Therefore, in that case, show only minor ticks.
    245  * Lastly, there should be an appropriate way to handle numbers
    246  * <=0.
     154    _valueMin = min;
     155    _valueMax = max;
     156}
     157
     158/**
     159 * \brief Determine the units of a linear scaled axis.
     160 *
     161 * The axis limits are either the range of the data values mapped
     162 * to the axis (autoscaled), or the values specified by the -min
     163 * and -max options (manual).
     164 *
     165 * If autoscaled, the smallest and largest major ticks will
     166 * encompass the range of data values.  If the -loose option is
     167 * selected, the next outer ticks are choosen.  If tight, the
     168 * ticks are at or inside of the data limits are used.
     169 *
     170 * If manually set, the ticks are at or inside the data limits
     171 * are used.  This makes sense for zooming.  You want the
     172 * selected range to represent the next limit, not something a
     173 * bit bigger.
     174 *
     175 * Note: I added an "always" value to the -loose option to force
     176 * the manually selected axes to be loose. It's probably
     177 * not a good idea.
     178 *
    247179 * <pre>
    248180 *          maxY
     
    268200 *           minY
    269201 *
    270  *      numTicks = Number of ticks
    271  *      min = Minimum value of axis
    272  *      max = Maximum value of axis
    273  *      range = Range of values (max - min)
    274  *
    275  * </pre>
    276  *
    277  *      If the number of decades is greater than ten, it is assumed
    278  *      that the full set of log-style ticks can't be drawn properly.
    279  */
    280 void
    281 Axis::logScale()
    282 {
    283     double range;
    284     double tickMin, tickMax;
    285     double majorStep, minorStep;
    286     int nMajor, nMinor;
    287     double min, max;
    288 
    289     nMajor = nMinor = 0;
    290     /* Suppress compiler warnings. */
    291     majorStep = minorStep = 0.0;
    292     tickMin = tickMax = NAN;
    293     min = _valueMin, max = _valueMax;
    294     if (min < max) {
    295         min = (min != 0.0) ? log10(fabs(min)) : 0.0;
    296         max = (max != 0.0) ? log10(fabs(max)) : 1.0;
    297 
    298         tickMin = floor(min);
    299         tickMax = ceil(max);
    300         range = tickMax - tickMin;
    301        
    302         if (range > 10) {
    303             /* There are too many decades to display a major tick at every
    304              * decade.  Instead, treat the axis as a linear scale.  */
    305             range = niceNum(range, 0);
    306             majorStep = niceNum(range / _major.reqNumTicks, 1);
    307             tickMin = UFLOOR(tickMin, majorStep);
    308             tickMax = UCEIL(tickMax, majorStep);
    309             nMajor = (int)((tickMax - tickMin) / majorStep) + 1;
    310             minorStep = EXP10(floor(log10(majorStep)));
    311             if (minorStep == majorStep) {
    312                 nMinor = 4, minorStep = 0.2;
    313             } else {
    314                 nMinor = ROUND(majorStep / minorStep) - 1;
    315             }
    316         } else {
    317             if (tickMin == tickMax) {
    318                 tickMax++;
    319             }
    320             majorStep = 1.0;
    321             nMajor = (int)(tickMax - tickMin + 1); /* FIXME: Check this. */
    322            
    323             minorStep = 0.0;    /* This is a special hack to pass
    324                                  * information to the SetTicks
    325                                  * method. An interval of 0.0 indicates
    326                                  *   1) this is a minor sweep and
    327                                  *   2) the axis is log scale. 
    328                                  */
    329             nMinor = 10;
    330         }
    331         if ((_flags & TIGHT_MIN) || (DEFINED(_reqMin))) {
    332             tickMin = min;
    333             nMajor++;
    334         }
    335         if ((_flags & TIGHT_MAX) || (DEFINED(_reqMax))) {
    336             tickMax = max;
    337         }
    338     }
    339     _major.setValues(floor(tickMin), majorStep, nMajor);
    340     _minor.setValues(minorStep, minorStep, nMinor);
    341     _min = tickMin;
    342     _max = tickMax;
    343     _range = _max - _min;
    344     _scale = 1.0 / _range;
    345 }
    346 
    347 /**
    348  * \brief Determine the units of a linear scaled axis.
    349  *
    350  * The axis limits are either the range of the data values mapped
    351  * to the axis (autoscaled), or the values specified by the -min
    352  * and -max options (manual).
    353  *
    354  * If autoscaled, the smallest and largest major ticks will
    355  * encompass the range of data values.  If the -loose option is
    356  * selected, the next outer ticks are choosen.  If tight, the
    357  * ticks are at or inside of the data limits are used.
    358  *
    359  * If manually set, the ticks are at or inside the data limits
    360  * are used.  This makes sense for zooming.  You want the
    361  * selected range to represent the next limit, not something a
    362  * bit bigger.
    363  *
    364  * Note: I added an "always" value to the -loose option to force
    365  * the manually selected axes to be loose. It's probably
    366  * not a good idea.
    367  *
    368  * <pre>
    369  *          maxY
    370  *            |    units = magnitude (of least significant digit)
    371  *            |    high  = largest unit tick < max axis value
    372  *      high _|    low   = smallest unit tick > min axis value
    373  *            |
    374  *            |    range = high - low
    375  *            |    # ticks = greatest factor of range/units
    376  *           _|
    377  *        U   |
    378  *        n   |
    379  *        i   |
    380  *        t  _|
    381  *            |
    382  *            |
    383  *            |
    384  *       low _|
    385  *            |
    386  *            |_minX________________maxX__
    387  *            |   |       |      |       |
    388  *     minY  low                        high
    389  *           minY
    390  *
    391202 *      numTicks = Number of ticks
    392203 *      min = Minimum value of axis
     
    403214Axis::linearScale()
    404215{
    405     double step;
    406     double tickMin, tickMax;
    407     unsigned int nTicks;
    408 
    409     nTicks = 0;
    410     step = 1.0;
    411     /* Suppress compiler warning. */
    412     tickMin = tickMax = 0.0;
     216    double tickMin = 0., tickMax = 0.;
     217    double step = 1.0;
     218    unsigned int nTicks = 0;
     219
    413220    if (_valueMin < _valueMax) {
    414         double range;
    415 
    416         range = _valueMax - _valueMin;
     221        double range = _valueMax - _valueMin;
    417222        /* Calculate the major tick stepping. */
    418223        if (_reqStep > 0.0) {
     
    439244     * The limits of the axis are either the range of the data ("tight") or at
    440245     * the next outer tick interval ("loose").  The looseness or tightness has
    441      * to do with how the axis fits the range of data values.  This option is
    442      * overridden when the user sets an axis limit (by either -min or -max
    443      * option).  The axis limit is always at the selected limit (otherwise we
    444      * assume that user would have picked a different number).
     246     * to do with how the axis fits the range of data values.
    445247     */
    446     _min = ((_flags & TIGHT_MIN)||(DEFINED(_reqMin))) ? _valueMin : tickMin;
    447     _max = ((_flags & TIGHT_MAX)||(DEFINED(_reqMax))) ? _valueMax : tickMax;
    448     _range = _max - _min;
    449     _scale = 1.0 / _range;
     248    _min = _tightMin ? _valueMin : tickMin;
     249    _max = _tightMax ? _valueMax : tickMax;
    450250
    451251    /* Now calculate the minor tick step and number. */
    452252
    453     if ((_minor.reqNumTicks > 0) && (_minor.autoscale())) {
     253    if (_minor.reqNumTicks > 0) {
    454254        nTicks = _minor.reqNumTicks - 1;
    455255        step = 1.0 / (nTicks + 1);
     
    463263}
    464264
    465 
     265/**
     266 * \brief This sets the data range of the axis.
     267 */
    466268void
    467 Axis::setScale(double min, double max)
    468 {
     269Axis::setRange(double min, double max)
     270{
     271    // set valueMin/Max (overridden by requested min/max if present)
    469272    fixRange(min, max);
    470     if (_flags & LOGSCALE) {
    471         logScale();
    472     } else {
    473         linearScale();
    474     }
     273    // Set steps
     274    linearScale();
     275    // Fill ticks float arrays based on spacing
    475276    _major.sweepTicks();
    476277    _minor.sweepTicks();
     278    // Copy to linked lists
    477279    makeTicks();
    478280}
    479281
     282/**
     283 * \brief Copy tick values to major/minor linked lists, skipping duplicate values
     284 */
    480285void
    481286Axis::makeTicks()
     
    483288    _major.reset();
    484289    _minor.reset();
    485     int i;
    486     for (i = 0; i < _major.numTicks(); i++) {
    487         double t1, t2;
    488         int j;
    489        
    490         t1 = _major.tick(i);
     290    for (int i = 0; i < _major.numTicks(); i++) {
     291        double t1 = _major.tick(i);
    491292        /* Minor ticks */
    492         for (j = 0; j < _minor.numTicks(); j++) {
    493             t2 = t1 + (_major.step() * _minor.tick(j));
     293        for (int j = 0; j < _minor.numTicks(); j++) {
     294            double t2 = t1 + (_major.step() * _minor.tick(j));
    494295            if (!inRange(t2)) {
    495296                continue;
     
    507308}
    508309
     310/**
     311 * \brief Map world coordinate [_min,_max] to normalized coordinate [0,1]
     312 */
    509313double
    510314Axis::map(double x)
    511315{
    512     if ((_flags & LOGSCALE) && (x != 0.0)) {
    513         x = log10(fabs(x));
    514     }
    515     /* Map graph coordinate to normalized coordinates [0..1] */
    516     x = (x - _min) * _scale;
    517     if (_flags & DESCENDING) {
    518         x = 1.0 - x;
    519     }
     316    x = (x - _min) / (_max - _min);
    520317    return x;
    521318}
    522319
     320/**
     321 * \brief Map normalized coordinate [0,1] to world coordinate [_min,_max]
     322 */
    523323double
    524324Axis::invMap(double x)
    525325{
    526     if (_flags & DESCENDING) {
    527         x = 1.0 - x;
    528     }
    529     x = (x * _range) + _min;
    530     if (_flags & LOGSCALE) {
    531         x = EXP10(x);
    532     }
     326    x = (x * (_max - _min)) + _min;
    533327    return x;
    534328}
  • nanovis/branches/1.2/Axis.h

    r4904 r5542  
    33 * Copyright (c) 2004-2013  HUBzero Foundation, LLC
    44 *
    5  * Authors: George A. Howlett <gah@purdue.edu>
     5 * Authors:
     6 *   George A. Howlett <gah@purdue.edu>
     7 *   Leif Delgass <ldelgass@purdue.edu>
    68 */
    79#ifndef NV_AXIS_H
    810#define NV_AXIS_H
    911
    10 #include <stdlib.h>
    11 #include <string.h>
    12 
    1312#include <cmath>
    1413#include <limits>
    15 
    16 #include "Chain.h"
     14#include <list>
     15#include <string>
     16#include <cstdlib>
     17#include <cstring>
    1718
    1819#ifndef NAN
     
    2324
    2425class Axis;
    25 
    26 class TickIter
    27 {
    28 public:
    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 
    53 private:
    54     ChainLink *_linkPtr;
    55 };
    5626
    5727/**
     
    6232{
    6333public:
     34    typedef std::list<double>::iterator Iterator;
     35    typedef std::list<double>::const_iterator ConstIterator;
     36
    6437    Ticks(int numTicks) :
    6538        reqNumTicks(numTicks),
    66         _autoscale(true),
    6739        _numTicks(0),
    6840        _ticks(NULL)
     
    7547            delete [] _ticks;
    7648        }
    77         _chain.reset();
    78     }
    79 
    80     void setTicks(float *ticks, int nTicks)
    81     {
    82         _ticks = ticks, _numTicks = nTicks;
    83     }
    84 
    85     int numTicks()
     49    }
     50
     51    int numTicks() const
    8652    {
    8753        return _numTicks;
     
    9864    void reset()
    9965    {
    100         _chain.reset();
    101     }
    102 
    103     float step()
     66        _chain.clear();
     67    }
     68
     69    float step() const
    10470    {
    10571        return _step;
    10672    }
    10773
    108     void append (float x)
    109     {
    110         _chain.append(getClientData(x));
     74    void append(float x)
     75    {
     76        _chain.push_back(x);
    11177    }
    11278
     
    11682    }
    11783
    118     bool autoscale()
    119     {
    120         return _autoscale;
    121     }
    122 
    12384    void sweepTicks()
    12485    {
    125         if (_autoscale) {
    126             if (_ticks != NULL) {
    127                 delete [] _ticks;
    128             }
    129             setTicks();
     86        if (_ticks != NULL) {
     87            delete [] _ticks;
    13088        }
    131     }
    132 
    133     bool firstTick(TickIter &iter)
    134     {
    135         ChainLink *linkPtr;
    136 
    137         linkPtr = _chain.firstLink();
    138         iter.setStartingLink(linkPtr);
    139         return (linkPtr != NULL);
     89        setTicks();
     90    }
     91
     92    ConstIterator begin() const
     93    {
     94        return _chain.begin();
     95    }
     96
     97    ConstIterator end() const
     98    {
     99        return _chain.end();
    140100    }
    141101
     
    144104private:
    145105    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. */
     106                         * of ticks as defined by a given sweep. */
     107
    158108    /*
    159109     * Tick locations may be generated in two fashions
     
    182132     * the chain.
    183133     */
    184     Chain _chain;
     134    std::list<double> _chain;
    185135};
    186136
     
    192142{
    193143public:
    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);
     144    Axis(const char *title);
    204145
    205146    ~Axis()
    206147    {
    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 
     148    }
     149
     150    Ticks::ConstIterator firstMajor() const
     151    {
     152        return _major.begin();
     153    }
     154    Ticks::ConstIterator lastMajor() const
     155    {
     156        return _major.end();
     157    }
     158    Ticks::ConstIterator firstMinor() const
     159    {
     160        return _minor.begin();
     161    }
     162    Ticks::ConstIterator lastMinor() const
     163    {
     164        return _minor.end();
     165    }
     166
     167    /**
     168     * This returns the minimum bound of the data, which may
     169     * be different than the min() of the axis because of
     170     * tight/loose placement of major ticks
     171     */
     172    double dataMin() const
     173    {
     174        return _valueMin;
     175    }
     176
     177    /**
     178     * This returns the maximum bound of the data, which may
     179     * be different than the min() of the axis because of
     180     * tight/loose placement of major ticks
     181     */
     182    double dataMax() const
     183    {
     184        return _valueMax;
     185    }
     186
     187    /**
     188     * The minimum bound of the axis
     189     */
     190    double min() const
     191    {
     192        return _min;
     193    }
     194
     195    /**
     196     * The maximum bound of the axis
     197     */
     198    double max() const
     199    {
     200        return _max;
     201    }
     202
     203    /**
     204     * The length of the axis
     205     */
     206    double length() const
     207    {
     208        return (_max - _min);
     209    }
     210
     211    void setRange(double min, double max);
     212
     213    double map(double x);
     214
     215    double invMap(double x);
     216
     217    const char *title() const
     218    {
     219        return _title.c_str();
     220    }
     221
     222    void title(const char *title)
     223    {
     224        _title = title;
     225    }
     226
     227    const char *units() const
     228    {
     229        return _units.c_str();
     230    }
     231
     232    void units(const char *units)
     233    {
     234        _units = units;
     235    }
     236
     237    void setTightMin(bool value)
     238    {
     239        _tightMin = value;
     240    }
     241
     242    void setTightMax(bool value)
     243    {
     244        _tightMax = value;
     245    }
     246
     247    void setMajorStep(double value)
     248    {
     249        // Setting to 0.0 resets step to "auto"
     250        _reqStep = value;
     251    }
     252
     253    void setNumMajorTicks(int n)
     254    {
     255        _major.reqNumTicks = n;
     256    }
     257
     258    void setNumMinorTicks(int n)
     259    {
     260        _minor.reqNumTicks = n;
     261    }
     262
     263private:
    228264    void resetRange();
    229265
    230266    void fixRange(double min, double max);
    231267
    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 
    368 private:
    369     void logScale();
    370 
    371268    void linearScale();
    372269
     
    375272    void makeTicks();
    376273
    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 
     274    std::string _title;         /**< Title of the axis */
     275    std::string _units;         /**< Units of the axis */
     276
     277    bool _tightMin, _tightMax;  /**< Tight bounds option flags */
     278
     279    double _reqStep;            /**< If > 0.0, overrides the computed major tick
     280                                 * interval.  Otherwise a stepsize is
     281                                 * automatically calculated, based upon the
     282                                 * range of elements mapped to the axis. The
     283                                 * default value is 0.0. */
     284
     285    double _valueMin, _valueMax; /**< The limits of the data */
    395286    double _min, _max;          /**< Smallest and largest major tick values for
    396287                                 * the axis.  If loose, the tick values lie
     
    399290                                 * the data. */
    400291
    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 
    410292    Ticks _major, _minor;
    411293};
  • nanovis/branches/1.2/Command.cpp

    r5523 r5542  
    21352135        case 2: axisPtr = &NanoVis::grid->zAxis; break;
    21362136        }
    2137         axisPtr->name(Tcl_GetString(objv[3]));
     2137        axisPtr->title(Tcl_GetString(objv[3]));
    21382138        axisPtr->units(Tcl_GetString(objv[4]));
    21392139    }
  • nanovis/branches/1.2/Grid.cpp

    r4904 r5542  
    4343{
    4444    bboxMin.set(xAxis.min(), yAxis.min(), zAxis.min());
    45     bboxMax.set(xAxis.min() + xAxis.range(),
    46                 yAxis.min() + yAxis.range(),
    47                 zAxis.min() + zAxis.range());
     45    bboxMax.set(xAxis.max(), yAxis.max(), zAxis.max());
    4846}
    4947
     
    7573    double paspectZ = zDataRange / xDataRange;
    7674 
    77     double xscale = xAxis.range() / xDataRange;
    78     double yscale = yAxis.range() / xDataRange;
    79     double zscale = zAxis.range() / xDataRange;
    80 
    81     double xoffset = (xAxis.min() - xAxis.dataMin()) * xAxis.scale();
    82     double yoffset = (yAxis.min() - yAxis.dataMin()) * yAxis.scale();
    83     double zoffset = (zAxis.min() - zAxis.dataMin()) * zAxis.scale();
     75    double xscale = xAxis.length() / xDataRange;
     76    double yscale = yAxis.length() / xDataRange;
     77    double zscale = zAxis.length() / xDataRange;
     78
     79    double xoffset = (xAxis.min() - xAxis.dataMin()) / xAxis.length();
     80    double yoffset = (yAxis.min() - yAxis.dataMin()) / yAxis.length();
     81    double zoffset = (zAxis.min() - zAxis.dataMin()) / zAxis.length();
    8482
    8583    float xTickLen = TICK_LENGTH;
     
    9391    float zTitleOfs = TITLE_OFFSET;
    9492
    95     TRACE("Axis ranges: %g %g %g", xAxis.range(), yAxis.range(), zAxis.range());
    96     TRACE("Axis scales: %g %g %g", xAxis.scale(), yAxis.scale(), zAxis.scale());
     93    TRACE("Axis lengths: %g %g %g",
     94          xAxis.length(),
     95          yAxis.length(),
     96          zAxis.length());
    9797    TRACE("Axis min/max: %g,%g %g,%g %g,%g",
    9898          xAxis.min(), xAxis.max(),
     
    131131    glBegin(GL_LINES);
    132132    {
    133         bool result;
    134         TickIter iter;
    135 
    136         for (result = xAxis.firstMajor(iter); result; result = iter.next()) {
    137             float x;
    138             x = xAxis.map(iter.getValue());
     133        Ticks::ConstIterator itr;
     134        for (itr = xAxis.firstMajor(); itr != xAxis.lastMajor(); ++itr) {
     135            float x = (float)xAxis.map(*itr);
    139136            glVertex3f(x, 0.0f, 0.0f);
    140137            glVertex3f(x, 1.0f, 0.0f);
     
    142139            glVertex3f(x, 0.0f, 1.0f + zTickLen);
    143140        }
    144         for (result = yAxis.firstMajor(iter); result; result = iter.next()) {
    145             float y;
    146             y = yAxis.map(iter.getValue());
     141        for (itr = yAxis.firstMajor(); itr != yAxis.lastMajor(); ++itr) {
     142            float y = (float)yAxis.map(*itr);
    147143            glVertex3f(0.0f, y, 0.0f);
    148144            glVertex3f(1.0f + xTickLen, y, 0.0f);
     
    150146            glVertex3f(0.0f, y, 1.0f);
    151147        }
    152         for (result = zAxis.firstMajor(iter); result; result = iter.next()) {
    153             float z;
    154             z = zAxis.map(iter.getValue());
     148        for (itr = zAxis.firstMajor(); itr != zAxis.lastMajor(); ++itr) {
     149            float z = (float)zAxis.map(*itr);
    155150            glVertex3f(0.0f, 0.0f, z);
    156151            glVertex3f(0.0f, 1.0f, z);
     
    167162    glBegin(GL_LINES);
    168163    {
    169         bool result;
    170         TickIter iter;
    171 
    172         for (result = xAxis.firstMinor(iter); result; result = iter.next()) {
    173             float x;
    174             x = xAxis.map(iter.getValue());
     164        Ticks::ConstIterator itr;
     165        for (itr = xAxis.firstMinor(); itr != xAxis.lastMinor(); ++itr) {
     166            float x = (float)xAxis.map(*itr);
    175167            glVertex3f(x, 0.0f, 0.0f);
    176168            glVertex3f(x, 1.0f, 0.0f);
     
    178170            glVertex3f(x, 0.0f, 1.0f);
    179171        }
    180         for (result = yAxis.firstMinor(iter); result; result = iter.next()) {
    181             float y;
    182             y = yAxis.map(iter.getValue());
     172        for (itr = yAxis.firstMinor(); itr != yAxis.lastMinor(); ++itr) {
     173            float y = (float)yAxis.map(*itr);
    183174            glVertex3f(0.0f, y, 0.0f);
    184175            glVertex3f(1.0f, y, 0.0f);
     
    186177            glVertex3f(0.0f, y, 1.0f);
    187178        }
    188         for (result = zAxis.firstMinor(iter); result; result = iter.next()) {
    189             float z;
    190             z = zAxis.map(iter.getValue());
     179        for (itr = zAxis.firstMinor(); itr != zAxis.lastMinor(); ++itr) {
     180            float z = (float)zAxis.map(*itr);
    191181            glVertex3f(0.0f, 0.0f, z);
    192182            glVertex3f(0.0f, 1.0f, z);
     
    201191        int viewport[4];
    202192        double wx, wy, wz;
    203         bool result;
    204         TickIter iter;
    205193
    206194        glGetDoublev(GL_MODELVIEW_MATRIX, mv);
     
    219207            glLoadIdentity();
    220208            glTranslatef((int) wx, viewport[3] - (int) wy, 0);
    221             const char *name = xAxis.name();
    222             if (name == NULL) {
    223                 name = "???";
    224             }
    225             _font->draw(name);
     209            const char *title = xAxis.title();
     210            if (title == NULL) {
     211                title = "???";
     212            }
     213            _font->draw(title);
    226214        }
    227215       
     
    232220            glLoadIdentity();
    233221            glTranslatef((int) wx, viewport[3] - (int)wy, 0);
    234             const char *name = yAxis.name();
    235             if (name == NULL) {
    236                 name = "???";
    237             }
    238             _font->draw(name);
     222            const char *title = yAxis.title();
     223            if (title == NULL) {
     224                title = "???";
     225            }
     226            _font->draw(title);
    239227        }
    240228       
     
    245233            glLoadIdentity();
    246234            glTranslatef((int) wx, (int) viewport[3] - (int)wy, 0.0f);
    247             const char *name = zAxis.name();
    248             if (name == NULL) {
    249                 name = "???";
    250             }
    251             _font->draw(name);
     235            const char *title = zAxis.title();
     236            if (title == NULL) {
     237                title = "???";
     238            }
     239            _font->draw(title);
    252240        }
    253241
     
    255243                  _majorColor.a);
    256244
    257         for (result = xAxis.firstMajor(iter); result; result = iter.next()) {
    258             float x;
    259             x = xAxis.map(iter.getValue());
     245        Ticks::ConstIterator itr;
     246        for (itr = xAxis.firstMajor(); itr != xAxis.lastMajor(); ++itr) {
     247            float x = (float)xAxis.map(*itr);
    260248            if (gluProject(x, 0.0f, 1.0 + zLabelOfs,
    261249                           mv, prjm, viewport,
     
    265253                glLoadIdentity();
    266254                glTranslatef((int) wx, (int) viewport[3] - (int)wy, 0.0f);
    267                 sprintf(buff, "%.*g", NUMDIGITS, iter.getValue());
     255                sprintf(buff, "%.*g", NUMDIGITS, *itr);
    268256                _font->draw(buff);
    269257            }
    270258        }
    271         for (result = yAxis.firstMajor(iter); result; result = iter.next()) {
    272             float y;
    273             y = yAxis.map(iter.getValue());
     259        for (itr = yAxis.firstMajor(); itr != yAxis.lastMajor(); ++itr) {
     260            float y = (float)yAxis.map(*itr);
    274261            if (gluProject(1.0 + xLabelOfs, y, 0.0f,
    275262                           mv, prjm, viewport,
     
    279266                glLoadIdentity();
    280267                glTranslatef((int) wx, (int) viewport[3] - (int)wy, 0.0f);
    281                 sprintf(buff, "%.*g", NUMDIGITS, iter.getValue());
     268                sprintf(buff, "%.*g", NUMDIGITS, *itr);
    282269                _font->draw(buff);
    283270            }
    284271        }
    285         for (result = zAxis.firstMajor(iter); result; result = iter.next()) {
    286             float z;
    287             z = zAxis.map(iter.getValue());
     272        for (itr = zAxis.firstMajor(); itr != zAxis.lastMajor(); ++itr) {
     273            float z = (float)zAxis.map(*itr);
    288274            if (gluProject(1.0 + xLabelOfs, 0.0f, z,
    289275                           mv, prjm, viewport,
     
    293279                glLoadIdentity();
    294280                glTranslatef((int) wx, (int) viewport[3] - (int)wy, 0.0f);
    295                 sprintf(buff, "%.*g", NUMDIGITS, iter.getValue());
     281                sprintf(buff, "%.*g", NUMDIGITS, *itr);
    296282                _font->draw(buff);
    297283            }
  • nanovis/branches/1.2/HeightMap.cpp

    r4904 r5542  
    88#include <GL/glew.h>
    99
     10#include <vrmath/BBox.h>
    1011#include <graphics/RenderContext.h>
    1112
     
    432433    reset();
    433434
     435    BBox bbox;
     436    grid->getBounds(bbox.min, bbox.max);
     437
     438    float xScale = 1.0 / (bbox.max.x - bbox.min.x);
     439    float yScale = 1.0 / (bbox.max.y - bbox.min.y);
     440    float zScale = 1.0 / (bbox.max.z - bbox.min.z);
     441
    434442    // The range of the grid's y-axis 0..1 represents the distance between the
    435443    // smallest and largest major ticks for all surfaces plotted.  Translate
    436444    // this surface's y-values (heights) into the grid's axis coordinates.
    437445
    438     float yScale = 1.0 / (grid->yAxis.max() - grid->yAxis.min());
    439446    float *p, *q, *pend;
    440447    float *normHeights = new float[count];
    441448    for (p = _heights, pend = p + count, q = normHeights; p < pend; p++, q++) {
    442         *q = (*p - grid->yAxis.min()) * yScale;
     449        *q = (*p - bbox.min.y) * yScale;
    443450    }
    444451    Vector3f *t, *texcoord;
     
    450457    // Normalize the mesh coordinates (x and z min/max) the range of the major
    451458    // ticks for the x and z grid axes as well.
    452 
    453     float xScale, zScale;
    454459    float xMin, xMax, zMin, zMax;
    455460
    456     xScale = 1.0 / (grid->xAxis.max() - grid->xAxis.min());
    457     xMin = (xAxis.min() - grid->xAxis.min()) * xScale;
    458     xMax = (xAxis.max() - grid->xAxis.min()) * xScale;
    459     zScale = 1.0 / (grid->zAxis.max() - grid->zAxis.min());
    460     zMin = (zAxis.min() - grid->zAxis.min()) * zScale;
    461     zMax = (zAxis.max() - grid->zAxis.min()) * zScale;
     461    xMin = (xAxis.min() - bbox.min.x) * xScale;
     462    xMax = (xAxis.max() - bbox.min.x) * xScale;
     463    zMin = (zAxis.min() - bbox.min.z) * zScale;
     464    zMax = (zAxis.max() - bbox.min.z) * zScale;
    462465
    463466    Vector3f* vertices;
  • nanovis/branches/1.2/Makefile.in

    r5499 r5542  
    139139                BMPWriter.o \
    140140                Camera.o \
    141                 Chain.o \
    142141                CmdProc.o \
    143142                ColorTableShader.o \
     
    313312        $(RM) Makefile nvconf.h *~
    314313
    315 Axis.o: Axis.cpp Axis.h Chain.h
     314Axis.o: Axis.cpp Axis.h
    316315BMPWriter.o: BMPWriter.cpp BMPWriter.h nanovis.h
    317316BucketSort.o: BucketSort.cpp BucketSort.h $(VRMATH_DIR)/include/vrmath/Vector3f.h $(VRMATH_DIR)/include/vrmath/Vector4f.h $(VRMATH_DIR)/include/vrmath/Matrix4x4d.h PCASplit.h
    318317Camera.o: Camera.cpp Camera.h config.h $(VRMATH_DIR)/include/vrmath/Matrix4x4d.h
    319 Chain.o: Chain.cpp Chain.h
    320318CmdProc.o: CmdProc.cpp CmdProc.h
    321319ColorTableShader.o: ColorTableShader.cpp ColorTableShader.h Shader.h
     
    329327FlowParticles.o: FlowParticles.cpp FlowParticles.h FlowTypes.h FlowCmd.h Switch.h Trace.h ParticleRenderer.h Volume.h $(VRMATH_DIR)/include/vrmath/Vector3f.h $(VRMATH_DIR)/include/vrmath/Vector4f.h
    330328GradientFilter.o: GradientFilter.cpp GradientFilter.h
    331 Grid.o: Grid.cpp Grid.h Axis.h Chain.h $(UTIL_DIR)/Fonts.h $(VRMATH_DIR)/include/vrmath/Color4f.h $(VRMATH_DIR)/include/vrmath/Vector4f.h
     329Grid.o: Grid.cpp Grid.h Axis.h $(UTIL_DIR)/Fonts.h $(VRMATH_DIR)/include/vrmath/Color4f.h $(VRMATH_DIR)/include/vrmath/Vector4f.h
    332330HeightMap.o: HeightMap.cpp HeightMap.h Shader.h
    333331LIC.o: LIC.cpp LIC.h FlowTypes.h Shader.h define.h
     
    371369dxReader.o: dxReader.cpp ReaderCommon.h config.h nanovis.h Unirect.h ZincBlendeVolume.h ZincBlendeReconstructor.h
    372370md5.o: md5.h
    373 nanovis.o: nanovis.cpp nanovis.h nanovisServer.h config.h define.h Command.h Flow.h Grid.h HeightMap.h Camera.h LIC.h ZincBlendeReconstructor.h OrientationIndicator.h PerfQuery.h PlaneRenderer.h PointSetRenderer.h PointSet.h Switch.h Trace.h Unirect.h VelocityArrowsSlice.h VolumeInterpolator.h VolumeRenderer.h ZincBlendeVolume.h Axis.h Chain.h $(UTIL_DIR)/Fonts.h
     371nanovis.o: nanovis.cpp nanovis.h nanovisServer.h config.h define.h Command.h Flow.h Grid.h HeightMap.h Camera.h LIC.h ZincBlendeReconstructor.h OrientationIndicator.h PerfQuery.h PlaneRenderer.h PointSetRenderer.h PointSet.h Switch.h Trace.h Unirect.h VelocityArrowsSlice.h VolumeInterpolator.h VolumeRenderer.h ZincBlendeVolume.h Axis.h $(UTIL_DIR)/Fonts.h
    374372nanovisServer.o: nanovisServer.cpp nanovisServer.h config.h nanovis.h define.h Command.h PPMWriter.h ReadBuffer.h Shader.h ResponseQueue.h Trace.h
  • nanovis/branches/1.2/nanovis.cpp

    r5523 r5542  
    671671    }
    672672    if ((xMin < DBL_MAX) && (xMax > -DBL_MAX)) {
    673         grid->xAxis.setScale(xMin, xMax);
     673        grid->xAxis.setRange(xMin, xMax);
    674674    }
    675675    if ((yMin < DBL_MAX) && (yMax > -DBL_MAX)) {
    676         grid->yAxis.setScale(yMin, yMax);
     676        grid->yAxis.setRange(yMin, yMax);
    677677    }
    678678    if ((zMin < DBL_MAX) && (zMax > -DBL_MAX)) {
    679         grid->zAxis.setScale(zMin, zMax);
     679        grid->zAxis.setRange(zMin, zMax);
    680680    }
    681681    if ((valueMin < DBL_MAX) && (valueMax > -DBL_MAX)) {
     
    729729    }
    730730    if ((xMin < DBL_MAX) && (xMax > -DBL_MAX)) {
    731         grid->xAxis.setScale(xMin, xMax);
     731        grid->xAxis.setRange(xMin, xMax);
    732732    }
    733733    if ((yMin < DBL_MAX) && (yMax > -DBL_MAX)) {
    734         grid->yAxis.setScale(yMin, yMax);
     734        grid->yAxis.setRange(yMin, yMax);
    735735    }
    736736    if ((zMin < DBL_MAX) && (zMax > -DBL_MAX)) {
    737         grid->zAxis.setScale(zMin, zMax);
     737        grid->zAxis.setRange(zMin, zMax);
    738738    }
    739739    if ((valueMin < DBL_MAX) && (valueMax > -DBL_MAX)) {
     
    754754    if (Flow::updatePending) {
    755755        setFlowRanges();
    756         grid->xAxis.setScale(xMin, xMax);
    757         grid->yAxis.setScale(yMin, yMax);
    758         grid->zAxis.setScale(zMin, zMax);
     756        grid->xAxis.setRange(xMin, xMax);
     757        grid->yAxis.setRange(yMin, yMax);
     758        grid->zAxis.setRange(zMin, zMax);
    759759    }
    760760
     
    10071007    if (Flow::updatePending) {
    10081008        setFlowRanges();
    1009         grid->xAxis.setScale(xMin, xMax);
    1010         grid->yAxis.setScale(yMin, yMax);
    1011         grid->zAxis.setScale(zMin, zMax);
     1009        grid->xAxis.setRange(xMin, xMax);
     1010        grid->yAxis.setRange(yMin, yMax);
     1011        grid->zAxis.setRange(zMin, zMax);
    10121012    }
    10131013    if (HeightMap::updatePending) {
Note: See TracChangeset for help on using the changeset viewer.