Index: /nanovis/trunk/Axis.cpp
===================================================================
--- /nanovis/trunk/Axis.cpp	(revision 5477)
+++ /nanovis/trunk/Axis.cpp	(revision 5478)
@@ -3,6 +3,10 @@
  * Copyright (c) 2004-2013  HUBzero Foundation, LLC
  *
- * Authors: George A. Howlett <gah@purdue.edu>
- */
+ * Authors:
+ *   George A. Howlett <gah@purdue.edu>
+ *   Leif Delgass <ldelgass@purdue.edu>
+ */
+#include <string>
+
 #include <stdlib.h>
 #include <stdio.h>
@@ -12,10 +16,7 @@
 
 #include "Axis.h"
+#include "Trace.h"
 
 using namespace nv;
-
-inline bool DEFINED(double x) {
-    return !isnan(x);
-}
 
 inline double EXP10(double x) {
@@ -85,50 +86,22 @@
     _numTicks = 0;
     _ticks = new float[_nSteps];
-    if (_step == 0.0) { 
-        /* Hack: A zero step indicates to use log values. */
-        unsigned int i;
-        /* Precomputed log10 values [1..10] */
-        static double logTable[] = {
-            0.0, 
-            0.301029995663981, 
-            0.477121254719662, 
-            0.602059991327962, 
-            0.698970004336019, 
-            0.778151250383644, 
-            0.845098040014257,
-            0.903089986991944, 
-            0.954242509439325, 
-            1.0
-        };
-        for (i = 0; i < _nSteps; i++) {
-            _ticks[i] = logTable[i];
-        }
-    } else {
-        double value;
-        unsigned int i;
-    
-        value = _initial;        /* Start from smallest axis tick */
-        for (i = 0; i < _nSteps; i++) {
-            value = _initial + (_step * i);
-            _ticks[i] = UROUND(value, _step);
-        }
+    // Start from smallest axis tick
+    double value = _initial;
+    for (unsigned int i = 0; i < _nSteps; i++) {
+        value = _initial + (_step * i);
+        _ticks[i] = UROUND(value, _step);
     }
     _numTicks = _nSteps;
 }
 
-Axis::Axis(const char *axisName) :
-    _name(strdup(axisName)),
-    _flags(AUTOSCALE),
-    _title(NULL),
-    _units(NULL),
+Axis::Axis(const char *title) :
+    _title(title),
+    _tightMin(false),
+    _tightMax(false),
+    _reqStep(0.0),
     _valueMin(DBL_MAX),
     _valueMax(-DBL_MAX),
-    _reqMin(NAN),
-    _reqMax(NAN),
     _min(DBL_MAX),
     _max(-DBL_MAX),
-    _range(0.0),
-    _scale(0.0),
-    _reqStep(0.0),
     _major(5),
     _minor(2)
@@ -140,5 +113,5 @@
  *
  * The value is normalized by the current axis range. If the normalized
- * value is between [0.0..1.0] then it's in range.  The value is compared
+ * value is between [0.0,1.0] then it's in range.  The value is compared
  * to 0 and 1., where 0.0 is the minimum and 1.0 is the maximum.
  * DBL_EPSILON is the smallest number that can be represented on the host
@@ -147,5 +120,5 @@
  * Please note, *max* can't equal *min*.
  *
- * \return If the value is within the interval [min..max], 1 is returned; 0
+ * \return If the value is within the interval [min,max], 1 is returned; 0
  * otherwise.
  */
@@ -153,8 +126,8 @@
 Axis::inRange(double x)
 {
-    if (_range < DBL_EPSILON) {
+    if ((_max - _min) < DBL_EPSILON) {
         return (fabs(_max - x) >= DBL_EPSILON);
     } else {
-        x = (x - _min) * _scale;
+        x = map(x);
         return ((x >= -DBL_EPSILON) && ((x - 1.0) < DBL_EPSILON));
     }
@@ -165,22 +138,11 @@
 {
     if (min == DBL_MAX) {
-        if (DEFINED(_reqMin)) {
-            min = _reqMin;
-        } else {
-            min = (_flags & LOGSCALE) ? 0.001 : 0.0;
-        }
+        min = 0.0;
     }
     if (max == -DBL_MAX) {
-        if (DEFINED(_reqMax)) {
-            max = _reqMax;
-        } else {
-            max = 1.0;
-        }
+        max = 1.0;
     }
     if (min >= max) {
-        /*
-         * There is no range of data (i.e. min is not less than max), so
-         * manufacture one.
-         */
+        // No range, so pick a default
         if (min == 0.0) {
             min = 0.0, max = 1.0;
@@ -190,59 +152,29 @@
     }
 
-    /*   
-     * The axis limits are either the current data range or overridden by the
-     * values selected by the user with the -min or -max options.
-     */
-    _valueMin = (DEFINED(_reqMin)) ? _reqMin : min;
-    _valueMax = (DEFINED(_reqMax)) ? _reqMax : max;
-    if (_valueMax < _valueMin) {
-        /*   
-         * If the limits still don't make sense, it's because one limit
-         * configuration option (-min or -max) was set and the other default
-         * (based upon the data) is too small or large.  Remedy this by making
-         * up a new min or max from the user-defined limit.
-         */
-        if (!DEFINED(_reqMin)) {
-            _valueMin = _valueMax - (fabs(_valueMax) * 0.1);
-        }
-        if (!DEFINED(_reqMax)) {
-            _valueMax = _valueMin + (fabs(_valueMax) * 0.1);
-        }
-    }
-}
-
-/**
- * \brief Determine the range and units of a log scaled axis.
- *
- * Unless the axis limits are specified, the axis is scaled
- * automatically, where the smallest and largest major ticks encompass
- * the range of actual data values.  When an axis limit is specified,
- * that value represents the smallest(min)/largest(max) value in the
- * displayed range of values.
- *
- * Both manual and automatic scaling are affected by the step used.  By
- * default, the step is the largest power of ten to divide the range in
- * more than one piece.
- *
- * Automatic scaling:
- * Find the smallest number of units which contain the range of values.
- * The minimum and maximum major tick values will be represent the
- * range of values for the axis. This greatest number of major ticks
- * possible is 10.
- *
- * Manual scaling:
- * Make the minimum and maximum data values the represent the range of
- * the values for the axis.  The minimum and maximum major ticks will be
- * inclusive of this range.  This provides the largest area for plotting
- * and the expected results when the axis min and max values have be set
- * by the user (.e.g zooming).  The maximum number of major ticks is 20.
- *
- * For log scale, there's the possibility that the minimum and
- * maximum data values are the same magnitude.  To represent the
- * points properly, at least one full decade should be shown.
- * However, if you zoom a log scale plot, the results should be
- * predictable. Therefore, in that case, show only minor ticks.
- * Lastly, there should be an appropriate way to handle numbers
- * <=0.
+    _valueMin = min;
+    _valueMax = max;
+}
+
+/**
+ * \brief Determine the units of a linear scaled axis.
+ *
+ * The axis limits are either the range of the data values mapped
+ * to the axis (autoscaled), or the values specified by the -min
+ * and -max options (manual).
+ *
+ * If autoscaled, the smallest and largest major ticks will
+ * encompass the range of data values.  If the -loose option is
+ * selected, the next outer ticks are choosen.  If tight, the
+ * ticks are at or inside of the data limits are used.
+ *
+ * If manually set, the ticks are at or inside the data limits
+ * are used.  This makes sense for zooming.  You want the
+ * selected range to represent the next limit, not something a
+ * bit bigger.
+ *
+ * Note: I added an "always" value to the -loose option to force
+ * the manually selected axes to be loose. It's probably
+ * not a good idea.
+ *
  * <pre>
  *          maxY
@@ -268,125 +200,4 @@
  *           minY
  *
- *      numTicks = Number of ticks
- *      min = Minimum value of axis
- *      max = Maximum value of axis
- *      range = Range of values (max - min)
- *
- * </pre>
- *
- *      If the number of decades is greater than ten, it is assumed
- *      that the full set of log-style ticks can't be drawn properly.
- */
-void
-Axis::logScale()
-{
-    double range;
-    double tickMin, tickMax;
-    double majorStep, minorStep;
-    int nMajor, nMinor;
-    double min, max;
-
-    nMajor = nMinor = 0;
-    /* Suppress compiler warnings. */
-    majorStep = minorStep = 0.0;
-    tickMin = tickMax = NAN;
-    min = _valueMin, max = _valueMax;
-    if (min < max) {
-        min = (min != 0.0) ? log10(fabs(min)) : 0.0;
-        max = (max != 0.0) ? log10(fabs(max)) : 1.0;
-
-        tickMin = floor(min);
-        tickMax = ceil(max);
-        range = tickMax - tickMin;
-        
-        if (range > 10) {
-            /* There are too many decades to display a major tick at every
-             * decade.  Instead, treat the axis as a linear scale.  */
-            range = niceNum(range, 0);
-            majorStep = niceNum(range / _major.reqNumTicks, 1);
-            tickMin = UFLOOR(tickMin, majorStep);
-            tickMax = UCEIL(tickMax, majorStep);
-            nMajor = (int)((tickMax - tickMin) / majorStep) + 1;
-            minorStep = EXP10(floor(log10(majorStep)));
-            if (minorStep == majorStep) {
-                nMinor = 4, minorStep = 0.2;
-            } else {
-                nMinor = ROUND(majorStep / minorStep) - 1;
-            }
-        } else {
-            if (tickMin == tickMax) {
-                tickMax++;
-            }
-            majorStep = 1.0;
-            nMajor = (int)(tickMax - tickMin + 1); /* FIXME: Check this. */
-            
-            minorStep = 0.0;    /* This is a special hack to pass
-                                 * information to the SetTicks
-                                 * method. An interval of 0.0 indicates
-                                 *   1) this is a minor sweep and 
-                                 *   2) the axis is log scale.  
-                                 */
-            nMinor = 10;
-        }
-        if ((_flags & TIGHT_MIN) || (DEFINED(_reqMin))) {
-            tickMin = min;
-            nMajor++;
-        }
-        if ((_flags & TIGHT_MAX) || (DEFINED(_reqMax))) {
-            tickMax = max;
-        }
-    }
-    _major.setValues(floor(tickMin), majorStep, nMajor);
-    _minor.setValues(minorStep, minorStep, nMinor);
-    _min = tickMin;
-    _max = tickMax;
-    _range = _max - _min;
-    _scale = 1.0 / _range;
-}
-
-/**
- * \brief Determine the units of a linear scaled axis.
- *
- * The axis limits are either the range of the data values mapped
- * to the axis (autoscaled), or the values specified by the -min
- * and -max options (manual).
- *
- * If autoscaled, the smallest and largest major ticks will
- * encompass the range of data values.  If the -loose option is
- * selected, the next outer ticks are choosen.  If tight, the
- * ticks are at or inside of the data limits are used.
- *
- * If manually set, the ticks are at or inside the data limits
- * are used.  This makes sense for zooming.  You want the
- * selected range to represent the next limit, not something a
- * bit bigger.
- *
- * Note: I added an "always" value to the -loose option to force
- * the manually selected axes to be loose. It's probably
- * not a good idea.
- *
- * <pre>
- *          maxY
- *            |    units = magnitude (of least significant digit)
- *            |    high  = largest unit tick < max axis value
- *      high _|    low   = smallest unit tick > min axis value
- *            |
- *            |    range = high - low
- *            |    # ticks = greatest factor of range/units
- *           _|
- *        U   |
- *        n   |
- *        i   |
- *        t  _|
- *            |
- *            |
- *            |
- *       low _|
- *            |
- *            |_minX________________maxX__
- *            |   |       |      |       |
- *     minY  low                        high
- *           minY
- *
  * 	numTicks = Number of ticks
  * 	min = Minimum value of axis
@@ -403,16 +214,10 @@
 Axis::linearScale()
 {
-    double step;
-    double tickMin, tickMax;
-    unsigned int nTicks;
-
-    nTicks = 0;
-    step = 1.0;
-    /* Suppress compiler warning. */
-    tickMin = tickMax = 0.0;
+    double tickMin = 0., tickMax = 0.;
+    double step = 1.0;
+    unsigned int nTicks = 0;
+
     if (_valueMin < _valueMax) {
-        double range;
-
-        range = _valueMax - _valueMin;
+        double range = _valueMax - _valueMin;
         /* Calculate the major tick stepping. */
         if (_reqStep > 0.0) {
@@ -439,17 +244,12 @@
      * The limits of the axis are either the range of the data ("tight") or at
      * the next outer tick interval ("loose").  The looseness or tightness has
-     * to do with how the axis fits the range of data values.  This option is
-     * overridden when the user sets an axis limit (by either -min or -max
-     * option).  The axis limit is always at the selected limit (otherwise we
-     * assume that user would have picked a different number).
+     * to do with how the axis fits the range of data values.
      */
-    _min = ((_flags & TIGHT_MIN)||(DEFINED(_reqMin))) ? _valueMin : tickMin;
-    _max = ((_flags & TIGHT_MAX)||(DEFINED(_reqMax))) ? _valueMax : tickMax;
-    _range = _max - _min;
-    _scale = 1.0 / _range;
+    _min = _tightMin ? _valueMin : tickMin;
+    _max = _tightMax ? _valueMax : tickMax;
 
     /* Now calculate the minor tick step and number. */
 
-    if ((_minor.reqNumTicks > 0) && (_minor.autoscale())) {
+    if (_minor.reqNumTicks > 0) {
         nTicks = _minor.reqNumTicks - 1;
         step = 1.0 / (nTicks + 1);
@@ -463,19 +263,24 @@
 }
 
-
+/**
+ * \brief This sets the data range of the axis.
+ */
 void
-Axis::setScale(double min, double max)
-{
+Axis::setRange(double min, double max)
+{
+    // set valueMin/Max (overridden by requested min/max if present)
     fixRange(min, max);
-    if (_flags & LOGSCALE) {
-        logScale();
-    } else {
-        linearScale();
-    }
+    // Set steps
+    linearScale();
+    // Fill ticks float arrays based on spacing
     _major.sweepTicks();
     _minor.sweepTicks();
+    // Copy to linked lists
     makeTicks();
 }
 
+/**
+ * \brief Copy tick values to major/minor linked lists, skipping duplicate values
+ */
 void
 Axis::makeTicks()
@@ -483,13 +288,9 @@
     _major.reset();
     _minor.reset();
-    int i;
-    for (i = 0; i < _major.numTicks(); i++) {
-        double t1, t2;
-        int j;
-        
-        t1 = _major.tick(i);
+    for (int i = 0; i < _major.numTicks(); i++) {
+        double t1 = _major.tick(i);
         /* Minor ticks */
-        for (j = 0; j < _minor.numTicks(); j++) {
-            t2 = t1 + (_major.step() * _minor.tick(j));
+        for (int j = 0; j < _minor.numTicks(); j++) {
+            double t2 = t1 + (_major.step() * _minor.tick(j));
             if (!inRange(t2)) {
                 continue;
@@ -507,28 +308,21 @@
 }
 
+/**
+ * \brief Map world coordinate [_min,_max] to normalized coordinate [0,1]
+ */
 double
 Axis::map(double x)
 {
-    if ((_flags & LOGSCALE) && (x != 0.0)) {
-        x = log10(fabs(x));
-    }
-    /* Map graph coordinate to normalized coordinates [0..1] */
-    x = (x - _min) * _scale;
-    if (_flags & DESCENDING) {
-        x = 1.0 - x;
-    }
+    x = (x - _min) / (_max - _min);
     return x;
 }
 
+/**
+ * \brief Map normalized coordinate [0,1] to world coordinate [_min,_max]
+ */
 double
 Axis::invMap(double x)
 {
-    if (_flags & DESCENDING) {
-        x = 1.0 - x;
-    }
-    x = (x * _range) + _min;
-    if (_flags & LOGSCALE) {
-        x = EXP10(x);
-    }
+    x = (x * (_max - _min)) + _min;
     return x;
 }
Index: /nanovis/trunk/Axis.h
===================================================================
--- /nanovis/trunk/Axis.h	(revision 5477)
+++ /nanovis/trunk/Axis.h	(revision 5478)
@@ -3,16 +3,17 @@
  * Copyright (c) 2004-2013  HUBzero Foundation, LLC
  *
- * Authors: George A. Howlett <gah@purdue.edu>
+ * Authors:
+ *   George A. Howlett <gah@purdue.edu>
+ *   Leif Delgass <ldelgass@purdue.edu>
  */
 #ifndef NV_AXIS_H
 #define NV_AXIS_H
 
-#include <stdlib.h>
-#include <string.h>
-
 #include <cmath>
 #include <limits>
-
-#include "Chain.h"
+#include <list>
+#include <string>
+#include <cstdlib>
+#include <cstring>
 
 #ifndef NAN
@@ -23,35 +24,4 @@
 
 class Axis;
-
-class TickIter
-{
-public:
-    void setStartingLink(ChainLink *linkPtr)
-    {
-        _linkPtr = linkPtr;
-    }
-
-    bool next()
-    {
-        if (_linkPtr == NULL) {
-            return false;
-        }
-        _linkPtr = _linkPtr->next();
-        return (_linkPtr != NULL);
-    }
-
-    float getValue()
-    {
-        union {
-            float x;
-            void *clientData;
-        } value;
-        value.clientData = _linkPtr->getValue();
-        return value.x;
-    }
-
-private:
-    ChainLink *_linkPtr;
-};
 
 /**
@@ -62,7 +32,9 @@
 {
 public:
+    typedef std::list<double>::iterator Iterator;
+    typedef std::list<double>::const_iterator ConstIterator;
+
     Ticks(int numTicks) :
         reqNumTicks(numTicks),
-        _autoscale(true),
         _numTicks(0),
         _ticks(NULL)
@@ -75,13 +47,7 @@
             delete [] _ticks;
         }
-        _chain.reset();
-    }
-
-    void setTicks(float *ticks, int nTicks)
-    {
-        _ticks = ticks, _numTicks = nTicks;
-    }
-
-    int numTicks()
+    }
+
+    int numTicks() const
     {
         return _numTicks;
@@ -98,15 +64,15 @@
     void reset()
     {
-        _chain.reset();
-    }
-
-    float step()
+        _chain.clear();
+    }
+
+    float step() const
     {
         return _step;
     }
 
-    void append (float x)
-    {
-        _chain.append(getClientData(x));
+    void append(float x)
+    {
+        _chain.push_back(x);
     }
 
@@ -116,26 +82,20 @@
     }
 
-    bool autoscale()
-    {
-        return _autoscale;
-    }
-
     void sweepTicks()
     {
-        if (_autoscale) {
-            if (_ticks != NULL) {
-                delete [] _ticks;
-            }
-            setTicks();
+        if (_ticks != NULL) {
+            delete [] _ticks;
         }
-    }
-
-    bool firstTick(TickIter &iter)
-    {
-        ChainLink *linkPtr;
-
-        linkPtr = _chain.firstLink();
-        iter.setStartingLink(linkPtr);
-        return (linkPtr != NULL);
+        setTicks();
+    }
+
+    ConstIterator begin() const
+    {
+        return _chain.begin();
+    }
+
+    ConstIterator end() const
+    {
+        return _chain.end();
     }
 
@@ -144,14 +104,5 @@
 private:
     void setTicks();	/**< Routine used internally to create the array
-				 * of ticks as defined by a given sweep. */
-    void *getClientData(float x)
-    {
-        union {
-            float x;
-            void *clientData;
-        } value;
-        value.x = x;
-        return value.clientData;
-    }
+                         * of ticks as defined by a given sweep. */
 
     bool _autoscale;		/**< Indicates if the ticks are autoscaled. */
@@ -182,5 +133,5 @@
      * the chain.
      */
-    Chain _chain;
+    std::list<double> _chain;
 };
 
@@ -192,181 +143,109 @@
 {
 public:
-    /// Flags associated with the axis.
-    enum AxisFlags {
-        AUTOSCALE  = (1<<0),
-        DESCENDING = (1<<1),
-        LOGSCALE   = (1<<2),
-        TIGHT_MIN  = (1<<3),
-        TIGHT_MAX  = (1<<4)
-    };
-
-    Axis(const char *name);
+    Axis(const char *title);
 
     ~Axis()
     {
-        if (_name != NULL) {
-            free((void *)_name);
-        }
-        if (_units != NULL) {
-            free((void *)_units);
-        }
-        if (_title != NULL) {
-            free((void *)_title);
-        }
-    }
-
-    bool firstMajor(TickIter& iter)
-    {
-        return _major.firstTick(iter);
-    }
-
-    bool firstMinor(TickIter& iter)
-    {
-        return _minor.firstTick(iter);
-    }
-
+    }
+
+    Ticks::ConstIterator firstMajor() const
+    {
+        return _major.begin();
+    }
+    Ticks::ConstIterator lastMajor() const
+    {
+        return _major.end();
+    }
+    Ticks::ConstIterator firstMinor() const
+    {
+        return _minor.begin();
+    }
+    Ticks::ConstIterator lastMinor() const
+    {
+        return _minor.end();
+    }
+
+    double dataMin() const
+    {
+        return _valueMin;
+    }
+
+    double dataMax() const
+    {
+        return _valueMax;
+    }
+
+    double min() const
+    {
+        return _min;
+    }
+
+    double max() const
+    {
+        return _max;
+    }
+
+    double length() const
+    {
+        return (_max - _min);
+    }
+
+    void setRange(double min, double max);
+
+    double map(double x);
+
+    double invMap(double x);
+
+    const char *title() const
+    {
+        return _title.c_str();
+    }
+
+    void title(const char *title)
+    {
+        _title = title;
+    }
+
+    const char *units() const
+    {
+        return _units.c_str();
+    }
+
+    void units(const char *units)
+    {
+        _units = units;
+    }
+
+    void setTightMin(bool value)
+    {
+        _tightMin = value;
+    }
+
+    void setTightMax(bool value)
+    {
+        _tightMax = value;
+    }
+
+    void setMajorStep(double value)
+    {
+        // Setting to 0.0 resets step to "auto"
+        _reqStep = value;
+    }
+
+    void setNumMajorTicks(int n)
+    {
+        _major.reqNumTicks = n;
+    }
+
+    void setNumMinorTicks(int n)
+    {
+        _minor.reqNumTicks = n;
+    }
+
+private:
     void resetRange();
 
     void fixRange(double min, double max);
 
-    void setScale(double min, double max);
-
-    double scale() const
-    {
-        return _scale;
-    }
-
-    double range() const
-    {
-        return _range;
-    }
-
-    double dataMin() const
-    {
-        return _valueMin;
-    }
-
-    double dataMax() const
-    {
-        return _valueMax;
-    }
-
-    double min() const
-    {
-        return _min;
-    }
-
-    double max() const
-    {
-        return _max;
-    }
-
-    void setLimits(double min, double max)
-    {
-        _reqMin = min, _reqMax = max;
-    }
-
-    void unsetLimits()
-    {
-        setLimits(NAN, NAN);
-    }
-
-    double map(double x);
-
-    double invMap(double x);
-
-    const char *name()
-    {
-        return _name;
-    }
-
-    void name(const char *name)
-    {
-        if (_name != NULL) {
-            free((void *)_name);
-        }
-        _name = strdup(name);
-    }
-
-    const char *units()
-    {
-        return _units;
-    }
-
-    void units(const char *units)
-    {
-        if (_units != NULL) {
-            free((void *)_units);
-        }
-        _units = strdup(units);
-    }
-
-    const char *title()
-    {
-        return _title;
-    }
-
-    void title(const char *title)
-    {
-        if (_title != NULL) {
-            free((void *)_title);
-        }
-        _title = strdup(title);
-    }
-
-    void setDescendingOption(bool value)
-    {
-        if (value) {
-            _flags |= DESCENDING;
-        } else {
-            _flags &= ~DESCENDING;
-        }
-    }
-
-    void setTightMinOption(bool value)
-    {
-        if (value) {
-            _flags |= TIGHT_MIN;
-        } else {
-            _flags &= ~TIGHT_MIN;
-        }
-    }
-
-    void setTightMaxOption(bool value)
-    {
-        if (value) {
-            _flags |= TIGHT_MAX;
-        } else {
-            _flags &= ~TIGHT_MAX;
-        }
-    }
-
-    void setLogScaleOption(bool value)
-    {
-        if (value) {
-            _flags |= LOGSCALE;
-        } else {
-            _flags &= ~LOGSCALE;
-        }
-    }
-
-    void setMajorStepOption(double value)
-    {
-        _reqStep = value;	// Setting to 0.0 resets step to "auto"
-    }
-
-    void setNumMinorTicksOption(int n)
-    {
-        _minor.reqNumTicks = n;
-    }
-
-    void setNumMajorTicksOption(int n)
-    {
-        _major.reqNumTicks = n;
-    }
-
-private:
-    void logScale();
-
     void linearScale();
 
@@ -375,22 +254,16 @@
     void makeTicks();
 
-    const char *_name;		/**< Name of the axis. Malloc-ed */
-
-    unsigned int _flags;
-
-    const char *_title;		/**< Title of the axis. */
-
-    const char *_units;		/**< Units of the axis. */
-
-    double _valueMin, _valueMax; /**< The limits of the data. */
-
-    double _reqMin, _reqMax;	/**< Requested axis bounds. Consult the
-				 * axisPtr->flags field for
-				 * Axis::CONFIG_MIN and Axis::CONFIG_MAX
-				 * to see if the requested bound have
-				 * been set.  They override the
-				 * computed range of the axis
-				 * (determined by auto-scaling). */
-
+    std::string _title;		/**< Title of the axis */
+    std::string _units;		/**< Units of the axis */
+
+    bool _tightMin, _tightMax;  /**< Tight bounds option flags */
+
+    double _reqStep;		/**< If > 0.0, overrides the computed major tick
+				 * interval.  Otherwise a stepsize is
+				 * automatically calculated, based upon the
+				 * range of elements mapped to the axis. The
+				 * default value is 0.0. */
+
+    double _valueMin, _valueMax; /**< The limits of the data */
     double _min, _max;		/**< Smallest and largest major tick values for
 				 * the axis.  If loose, the tick values lie
@@ -399,13 +272,4 @@
 				 * the data. */
 
-    double _range;		/**< Range of values on axis (_max - _min) */
-    double _scale;		/**< Scale factor for axis (1.0/_range) */
-
-    double _reqStep;		/**< If > 0.0, overrides the computed major tick
-				 * interval.  Otherwise a stepsize is
-				 * automatically calculated, based upon the
-				 * range of elements mapped to the axis. The
-				 * default value is 0.0. */
-
     Ticks _major, _minor;
 };
Index: novis/trunk/Chain.cpp
===================================================================
--- /nanovis/trunk/Chain.cpp	(revision 5477)
+++ 	(revision )
@@ -1,254 +1,0 @@
-/* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/* The module implements a generic linked list package.
- *
- * Copyright 1991-2004 George A Howlett.
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include <stdlib.h>
-#include <stdio.h>
-
-#include "Chain.h"
-
-using namespace nv;
-
-typedef int (QSortCompareProc) (const void *, const void *);
-
-/**
- * Removes all the links from the chain, freeing the memory for each
- * link.  Memory pointed to by the link (clientData) is not freed.  It's
- * the caller's responsibility to deallocate it.
- */
-void
-Chain::reset()
-{
-    ChainLink *oldPtr;
-    ChainLink *linkPtr = _head;
-
-    while (linkPtr != NULL) {
-	oldPtr = linkPtr;
-	linkPtr = linkPtr->next();
-	delete oldPtr;
-    }
-    init();
-}
-
-/**
- * Inserts a link after another link.  If afterPtr is NULL, then the new
- * link is prepended to the beginning of the chain.
- */
-void
-Chain::linkAfter(ChainLink *linkPtr, ChainLink *afterPtr)
-{
-    if (_head == NULL) {
-	_tail = _head = linkPtr;
-    } else {
-	if (afterPtr == NULL) {
-	    /* Prepend to the front of the chain */
-	    linkPtr->_next = _head;
-	    linkPtr->_prev = NULL;
-	    _head->_prev = linkPtr;
-	    _head = linkPtr;
-	} else {
-	    linkPtr->_next = afterPtr->next();
-	    linkPtr->_prev = afterPtr;
-	    if (afterPtr == _tail) {
-		_tail = linkPtr;
-	    } else {
-		afterPtr->next()->_prev = linkPtr;
-	    }
-	    afterPtr->_next = linkPtr;
-	}
-    }
-    _nLinks++;
-}
-
-/**
- * Inserts a new link preceding a given link in a chain.  If beforePtr is
- * NULL, then the new link is placed at the beginning of the list.
- *
- * \param linkPtr New entry to be inserted
- * \param beforePtr Entry to link before
- */
-void
-Chain::linkBefore(ChainLink *linkPtr,
-                  ChainLink *beforePtr)
-{
-    if (_head == NULL) {
-	_tail = _head = linkPtr;
-    } else {
-	if (beforePtr == NULL) {
-	    // Append to the end of the chain.
-	    linkPtr->_next = NULL;
-	    linkPtr->_prev = _tail;
-	    _tail->_next = linkPtr;
-	    _tail = linkPtr;
-	} else {
-	    linkPtr->_prev = beforePtr->prev();
-	    linkPtr->_next = beforePtr;
-	    if (beforePtr == _head) {
-		_head = linkPtr;
-	    } else {
-		beforePtr->prev()->_next = linkPtr;
-	    }
-	    beforePtr->_prev = linkPtr;
-	}
-    }
-    _nLinks++;
-}
-
-/**
- * Unlinks a link from the chain. The link is not deallocated, 
- * but only removed from the chain.
- */
-void
-Chain::unlink(ChainLink *linkPtr)
-{
-    bool unlinked;		/* Indicates if the link is actually removed
-				 * from the chain. */
-
-    unlinked = false;
-    if (_head == linkPtr) {
-	_head = linkPtr->next();
-	unlinked = true;
-    }
-    if (_tail == linkPtr) {
-	_tail = linkPtr->prev();
-	unlinked = true;
-    }
-    if (linkPtr->next() != NULL) {
-	linkPtr->next()->_prev = linkPtr->prev();
-	unlinked = true;
-    }
-    if (linkPtr->prev() != NULL) {
-	linkPtr->prev()->_next = linkPtr->next();
-	unlinked = true;
-    }
-    if (unlinked) {
-	_nLinks--;
-    }
-    linkPtr->_prev = linkPtr->_next = NULL;
-}
-
-/**
- * Unlinks and frees the given link from the chain.  It's assumed that
- * the link belong to the chain. No error checking is performed to verify
- * this.
- */
-void
-Chain::deleteLink(ChainLink *linkPtr)
-{
-    unlink(linkPtr);
-    delete linkPtr;
-}
-
-/**
- * Creates and new link with the given data and appends it to the end of
- * the chain.
- *
- * \return a pointer to the link created.
- */
-ChainLink *
-Chain::append(void *clientData)
-{
-    ChainLink *linkPtr;
-
-    linkPtr = new ChainLink(clientData);
-    linkBefore(linkPtr, (ChainLink *)NULL);
-    return linkPtr;
-}
-
-/**
- * Creates and new link with the given data and prepends it to beginning
- * of the chain.
- *
- * \return a pointer to the link created.
- */
-ChainLink  *
-Chain::prepend(void *clientData)
-{
-    ChainLink *linkPtr;
-
-    linkPtr = new ChainLink(clientData);
-    linkAfter(linkPtr, (ChainLink *)NULL);
-    return linkPtr;
-}
-
-/**
- * Find the link at the given position in the chain.
- *
- * \param position Index of link to select from front or back of the chain.
- *
- * \return  the pointer to the link, if that numbered link
- * exists. Otherwise NULL.
- */
-ChainLink *
-Chain::getNthLink(long position)
-{
-    ChainLink *linkPtr;
-
-    for (linkPtr = _head; linkPtr != NULL; linkPtr = linkPtr->next()) {
-	if (position == 0) {
-	    return linkPtr;
-	}
-	position--;
-    }
-    return NULL;
-}
-
-/**
- * Sorts the chain according to the given comparison routine.  
- *
- * Side Effects:
- *   The chain is reordered.
- */
-void
-Chain::sort(ChainCompareProc *proc)
-{
-    ChainLink *linkPtr;
-    long i;
-
-    if (_nLinks < 2) {
-	return;
-    }
-    ChainLink **linkArr = new ChainLink *[_nLinks + 1];
-    if (linkArr == NULL) {
-	return;			/* Out of memory. */
-    }
-    i = 0;
-    for (linkPtr = _head; linkPtr != NULL; linkPtr = linkPtr->next()) { 
-	linkArr[i++] = linkPtr;
-    }
-    qsort((char *)linkArr, _nLinks, sizeof(ChainLink *), 
-	  (QSortCompareProc *)proc);
-
-    /* Rethread the chain. */
-    linkPtr = linkArr[0];
-    _head = linkPtr;
-    linkPtr->_prev = NULL;
-    for (i = 1; i < _nLinks; i++) {
-	linkPtr->_next = linkArr[i];
-	linkPtr->next()->_prev = linkPtr;
-	linkPtr = linkPtr->next();
-    }
-    _tail = linkPtr;
-    linkPtr->_next = NULL;
-    delete [] linkArr;
-}
Index: novis/trunk/Chain.h
===================================================================
--- /nanovis/trunk/Chain.h	(revision 5477)
+++ 	(revision )
@@ -1,149 +1,0 @@
-/* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- * Copyright 1993-2004 George A Howlett.
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef NV_CHAIN_H
-#define NV_CHAIN_H
-
-namespace nv {
-
-/**
- * \brief A ChainLink is the container structure for the Chain.
- */
-class ChainLink
-{
-public:
-    ChainLink()
-    {
-        _clientData = NULL;
-        _next = _prev = NULL;
-    }
-
-    ChainLink(void *clientData)
-    {
-        _clientData = clientData;
-         _next = _prev = NULL;
-    }
-
-    void *getValue()
-    {
-        return _clientData;
-    }
-
-    void setValue(void *clientData)
-    {
-        _clientData = clientData;
-    }
-
-    ChainLink *next()
-    {
-        return _next;
-    }
-
-    ChainLink *prev()
-    {
-        return _prev;
-    }
-
-    friend class Chain;
-
-private:
-    ChainLink *_prev;  ///< Link to the previous link
-    ChainLink *_next;  ///< Link to the next link
-    void *_clientData; ///< Pointer to the data object
-};
-
-typedef int (ChainCompareProc) (ChainLink *l1Ptr, ChainLink *l2Ptr);
-
-/**
- * \brief A Chain is a doubly linked list structure.
- */
-class Chain
-{
-public:
-    Chain()
-    {
-        init();
-    }
-    ~Chain()
-    {
-        reset();
-    }
-
-    void init()
-    {
-        _nLinks = 0;
-        _head = _tail = NULL;
-    }
-
-    ChainLink *append(void *clientData);
-
-    ChainLink *prepend(void *clientData);
-
-    ChainLink *getNthLink(long position);
-
-    void linkBefore(ChainLink *linkPtr, ChainLink *beforePtr);
-
-    void linkAfter(ChainLink *linkPtr, ChainLink *afterPtr);
-
-    void deleteLink(ChainLink *linkPtr);
-
-    void unlink(ChainLink *linkPtr);
-
-    void reset();
-
-    void sort(ChainCompareProc *proc);
-
-    long getLength()
-    {
-        return _nLinks;
-    }
-
-    ChainLink *firstLink()
-    {
-        return _head;
-    }
-
-    ChainLink *lastLink()
-    {
-        return _tail;
-    }
-
-    void appendLink(ChainLink *linkPtr)
-    {
-        linkBefore(linkPtr, (ChainLink *)NULL);
-    }
-
-    void prependLink(ChainLink *linkPtr)
-    {
-        linkAfter(linkPtr, (ChainLink *)NULL);
-    }
-
-private:
-    ChainLink *_head; ///< Pointer to first element in chain
-    ChainLink *_tail; ///< Pointer to last element in chain
-    long _nLinks;     ///< Number of elements in chain
-};
-
-}
-
-#endif
Index: /nanovis/trunk/Command.cpp
===================================================================
--- /nanovis/trunk/Command.cpp	(revision 5477)
+++ /nanovis/trunk/Command.cpp	(revision 5478)
@@ -2107,7 +2107,5 @@
     }
     if (NanoVis::grid != NULL) {
-        Axis *axisPtr;
-
-        axisPtr = NULL;     /* Suppress compiler warning. */
+        Axis *axisPtr = NULL;
         switch (axis) {
         case 0: axisPtr = &NanoVis::grid->xAxis; break;
@@ -2115,5 +2113,5 @@
         case 2: axisPtr = &NanoVis::grid->zAxis; break;
         }
-        axisPtr->name(Tcl_GetString(objv[3]));
+        axisPtr->title(Tcl_GetString(objv[3]));
         axisPtr->units(Tcl_GetString(objv[4]));
     }
Index: /nanovis/trunk/Grid.cpp
===================================================================
--- /nanovis/trunk/Grid.cpp	(revision 5477)
+++ /nanovis/trunk/Grid.cpp	(revision 5478)
@@ -43,7 +43,5 @@
 {
     bboxMin.set(xAxis.min(), yAxis.min(), zAxis.min());
-    bboxMax.set(xAxis.min() + xAxis.range(),
-                yAxis.min() + yAxis.range(),
-                zAxis.min() + zAxis.range());
+    bboxMax.set(xAxis.max(), yAxis.max(), zAxis.max());
 }
 
@@ -67,7 +65,7 @@
     glPushMatrix();
 
-    double xLen = xAxis.range();
-    double yLen = yAxis.range();
-    double zLen = zAxis.range();
+    double xLen = xAxis.length();
+    double yLen = yAxis.length();
+    double zLen = zAxis.length();
     double avgLen = 0.;
     double denom = 0.;
@@ -123,10 +121,7 @@
     glBegin(GL_LINES);
     {
-        bool result;
-        TickIter iter;
-
-        for (result = xAxis.firstMajor(iter); result; result = iter.next()) {
-            float x;
-            x = xAxis.map(iter.getValue());
+        Ticks::ConstIterator itr;
+        for (itr = xAxis.firstMajor(); itr != xAxis.lastMajor(); ++itr) {
+            float x = (float)xAxis.map(*itr);
             glVertex3f(x, 0.0f, 0.0f);
             glVertex3f(x, 1.0f, 0.0f);
@@ -134,7 +129,6 @@
             glVertex3f(x, 0.0f, 1.0f + zTickLen);
         }
-        for (result = yAxis.firstMajor(iter); result; result = iter.next()) {
-            float y;
-            y = yAxis.map(iter.getValue());
+        for (itr = yAxis.firstMajor(); itr != yAxis.lastMajor(); ++itr) {
+            float y = (float)yAxis.map(*itr);
             glVertex3f(0.0f, y, 0.0f);
             glVertex3f(1.0f + xTickLen, y, 0.0f);
@@ -142,7 +136,6 @@
             glVertex3f(0.0f, y, 1.0f);
         }
-        for (result = zAxis.firstMajor(iter); result; result = iter.next()) {
-            float z;
-            z = zAxis.map(iter.getValue());
+        for (itr = zAxis.firstMajor(); itr != zAxis.lastMajor(); ++itr) {
+            float z = (float)zAxis.map(*itr);
             glVertex3f(0.0f, 0.0f, z);
             glVertex3f(0.0f, 1.0f, z);
@@ -159,10 +152,7 @@
     glBegin(GL_LINES);
     {
-        bool result;
-        TickIter iter;
-
-        for (result = xAxis.firstMinor(iter); result; result = iter.next()) {
-            float x;
-            x = xAxis.map(iter.getValue());
+        Ticks::ConstIterator itr;
+        for (itr = xAxis.firstMinor(); itr != xAxis.lastMinor(); ++itr) {
+            float x = (float)xAxis.map(*itr);
             glVertex3f(x, 0.0f, 0.0f);
             glVertex3f(x, 1.0f, 0.0f);
@@ -170,7 +160,6 @@
             glVertex3f(x, 0.0f, 1.0f);
         }
-        for (result = yAxis.firstMinor(iter); result; result = iter.next()) {
-            float y;
-            y = yAxis.map(iter.getValue());
+        for (itr = yAxis.firstMinor(); itr != yAxis.lastMinor(); ++itr) {
+            float y = (float)yAxis.map(*itr);
             glVertex3f(0.0f, y, 0.0f);
             glVertex3f(1.0f, y, 0.0f);
@@ -178,7 +167,6 @@
             glVertex3f(0.0f, y, 1.0f);
         }
-        for (result = zAxis.firstMinor(iter); result; result = iter.next()) {
-            float z;
-            z = zAxis.map(iter.getValue());
+        for (itr = zAxis.firstMinor(); itr != zAxis.lastMinor(); ++itr) {
+            float z = (float)zAxis.map(*itr);
             glVertex3f(0.0f, 0.0f, z);
             glVertex3f(0.0f, 1.0f, z);
@@ -193,6 +181,4 @@
         int viewport[4];
         double wx, wy, wz;
-        bool result;
-        TickIter iter;
 
         glGetDoublev(GL_MODELVIEW_MATRIX, mv);
@@ -211,9 +197,9 @@
             glLoadIdentity();
             glTranslatef((int) wx, viewport[3] - (int) wy, 0);
-            const char *name = xAxis.name();
-            if (name == NULL) {
-                name = "???";
-            }
-            _font->draw(name);
+            const char *title = xAxis.title();
+            if (title == NULL) {
+                title = "???";
+            }
+            _font->draw(title);
         }
         
@@ -224,9 +210,9 @@
             glLoadIdentity();
             glTranslatef((int) wx, viewport[3] - (int)wy, 0);
-            const char *name = yAxis.name();
-            if (name == NULL) {
-                name = "???";
-            }
-            _font->draw(name);
+            const char *title = yAxis.title();
+            if (title == NULL) {
+                title = "???";
+            }
+            _font->draw(title);
         }
         
@@ -237,9 +223,9 @@
             glLoadIdentity();
             glTranslatef((int) wx, (int) viewport[3] - (int)wy, 0.0f);
-            const char *name = zAxis.name();
-            if (name == NULL) {
-                name = "???";
-            }
-            _font->draw(name);
+            const char *title = zAxis.title();
+            if (title == NULL) {
+                title = "???";
+            }
+            _font->draw(title);
         }
 
@@ -247,7 +233,7 @@
                   _majorColor.a);
 
-        for (result = xAxis.firstMajor(iter); result; result = iter.next()) {
-            float x;
-            x = xAxis.map(iter.getValue());
+        Ticks::ConstIterator itr;
+        for (itr = xAxis.firstMajor(); itr != xAxis.lastMajor(); ++itr) {
+            float x = (float)xAxis.map(*itr);
             if (gluProject(x, 0.0f, 1.0 + zLabelOfs,
                            mv, prjm, viewport,
@@ -257,11 +243,10 @@
                 glLoadIdentity();
                 glTranslatef((int) wx, (int) viewport[3] - (int)wy, 0.0f);
-                sprintf(buff, "%.*g", NUMDIGITS, iter.getValue());
+                sprintf(buff, "%.*g", NUMDIGITS, *itr);
                 _font->draw(buff);
             }
         }
-        for (result = yAxis.firstMajor(iter); result; result = iter.next()) {
-            float y;
-            y = yAxis.map(iter.getValue());
+        for (itr = yAxis.firstMajor(); itr != yAxis.lastMajor(); ++itr) {
+            float y = (float)yAxis.map(*itr);
             if (gluProject(1.0 + xLabelOfs, y, 0.0f,
                            mv, prjm, viewport,
@@ -271,11 +256,10 @@
                 glLoadIdentity();
                 glTranslatef((int) wx, (int) viewport[3] - (int)wy, 0.0f);
-                sprintf(buff, "%.*g", NUMDIGITS, iter.getValue());
+                sprintf(buff, "%.*g", NUMDIGITS, *itr);
                 _font->draw(buff);
             }
         }
-        for (result = zAxis.firstMajor(iter); result; result = iter.next()) {
-            float z;
-            z = zAxis.map(iter.getValue());
+        for (itr = zAxis.firstMajor(); itr != zAxis.lastMajor(); ++itr) {
+            float z = (float)zAxis.map(*itr);
             if (gluProject(1.0 + xLabelOfs, 0.0f, z,
                            mv, prjm, viewport,
@@ -285,5 +269,5 @@
                 glLoadIdentity();
                 glTranslatef((int) wx, (int) viewport[3] - (int)wy, 0.0f);
-                sprintf(buff, "%.*g", NUMDIGITS, iter.getValue());
+                sprintf(buff, "%.*g", NUMDIGITS, *itr);
                 _font->draw(buff);
             }
Index: /nanovis/trunk/HeightMap.cpp
===================================================================
--- /nanovis/trunk/HeightMap.cpp	(revision 5477)
+++ /nanovis/trunk/HeightMap.cpp	(revision 5478)
@@ -8,4 +8,5 @@
 #include <GL/glew.h>
 
+#include <vrmath/BBox.h>
 #include <graphics/RenderContext.h>
 
@@ -432,13 +433,19 @@
     reset();
 
+    BBox bbox;
+    grid->getBounds(bbox.min, bbox.max);
+
+    float xScale = 1.0 / (bbox.max.x - bbox.min.x);
+    float yScale = 1.0 / (bbox.max.y - bbox.min.y);
+    float zScale = 1.0 / (bbox.max.z - bbox.min.z);
+
     // The range of the grid's y-axis 0..1 represents the distance between the
     // smallest and largest major ticks for all surfaces plotted.  Translate
     // this surface's y-values (heights) into the grid's axis coordinates.
 
-    float yScale = 1.0 / (grid->yAxis.max() - grid->yAxis.min());
     float *p, *q, *pend;
     float *normHeights = new float[count];
     for (p = _heights, pend = p + count, q = normHeights; p < pend; p++, q++) {
-	*q = (*p - grid->yAxis.min()) * yScale;
+	*q = (*p - bbox.min.y) * yScale;
     }
     Vector3f *t, *texcoord;
@@ -450,14 +457,10 @@
     // Normalize the mesh coordinates (x and z min/max) the range of the major
     // ticks for the x and z grid axes as well.
-
-    float xScale, zScale;
     float xMin, xMax, zMin, zMax;
 
-    xScale = 1.0 / (grid->xAxis.max() - grid->xAxis.min());
-    xMin = (xAxis.min() - grid->xAxis.min()) * xScale;
-    xMax = (xAxis.max() - grid->xAxis.min()) * xScale;
-    zScale = 1.0 / (grid->zAxis.max() - grid->zAxis.min());
-    zMin = (zAxis.min() - grid->zAxis.min()) * zScale;
-    zMax = (zAxis.max() - grid->zAxis.min()) * zScale;
+    xMin = (xAxis.min() - bbox.min.x) * xScale;
+    xMax = (xAxis.max() - bbox.min.x) * xScale;
+    zMin = (zAxis.min() - bbox.min.z) * zScale;
+    zMax = (zAxis.max() - bbox.min.z) * zScale;
 
     Vector3f* vertices;
Index: /nanovis/trunk/Makefile.in
===================================================================
--- /nanovis/trunk/Makefile.in	(revision 5477)
+++ /nanovis/trunk/Makefile.in	(revision 5478)
@@ -158,5 +158,4 @@
 		BMPWriter.o \
 		Camera.o \
-		Chain.o \
 		CmdProc.o \
 		ColorTableShader.o \
@@ -335,9 +334,8 @@
 	$(RM) Makefile nvconf.h *~
 
-Axis.o: Axis.cpp Axis.h Chain.h
+Axis.o: Axis.cpp Axis.h
 BMPWriter.o: BMPWriter.cpp BMPWriter.h nanovis.h
 BucketSort.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
 Camera.o: Camera.cpp Camera.h config.h $(VRMATH_DIR)/include/vrmath/Matrix4x4d.h
-Chain.o: Chain.cpp Chain.h
 CmdProc.o: CmdProc.cpp CmdProc.h
 ColorTableShader.o: ColorTableShader.cpp ColorTableShader.h Shader.h
@@ -351,5 +349,5 @@
 FlowParticles.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
 GradientFilter.o: GradientFilter.cpp GradientFilter.h
-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
+Grid.o: Grid.cpp Grid.h Axis.h $(UTIL_DIR)/Fonts.h $(VRMATH_DIR)/include/vrmath/Color4f.h $(VRMATH_DIR)/include/vrmath/Vector4f.h
 HeightMap.o: HeightMap.cpp HeightMap.h Shader.h
 LIC.o: LIC.cpp LIC.h FlowTypes.h Shader.h define.h
@@ -394,4 +392,4 @@
 dxReader.o: dxReader.cpp ReaderCommon.h config.h nanovis.h Unirect.h ZincBlendeVolume.h ZincBlendeReconstructor.h
 md5.o: md5.h
-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
+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 $(UTIL_DIR)/Fonts.h
 nanovisServer.o: nanovisServer.cpp nanovisServer.h config.h nanovis.h define.h Command.h PPMWriter.h ReadBuffer.h Shader.h ResponseQueue.h Trace.h
Index: /nanovis/trunk/nanovis.cpp
===================================================================
--- /nanovis/trunk/nanovis.cpp	(revision 5477)
+++ /nanovis/trunk/nanovis.cpp	(revision 5478)
@@ -709,11 +709,11 @@
 
     if (!sceneBounds.isEmptyX()) {
-        grid->xAxis.setScale(sceneBounds.min.x, sceneBounds.max.x);
+        grid->xAxis.setRange(sceneBounds.min.x, sceneBounds.max.x);
     }
     if (!sceneBounds.isEmptyY()) {
-        grid->yAxis.setScale(sceneBounds.min.y, sceneBounds.max.y);
+        grid->yAxis.setRange(sceneBounds.min.y, sceneBounds.max.y);
     }
     if (!sceneBounds.isEmptyZ()) {
-        grid->zAxis.setScale(sceneBounds.min.z, sceneBounds.max.z);
+        grid->zAxis.setRange(sceneBounds.min.z, sceneBounds.max.z);
     }
 
