Hi.

      I try to update the class osgSim::ScalarBar to support for the
osgText::String title.

      it may be very simple. but I hope i can do something to OSG.

      Thanks.

            xiaodong






//================ header ==================
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified
under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * OpenSceneGraph Public License for more details.
*/

#ifndef OSGSIM_SCALARBAR
#define OSGSIM_SCALARBAR 1

#include <osgSim/Export>
#include <osgSim/ColorRange>    // The default ScalarsToColors is a
ColorRange
#include <osg/Geode>
#include <string>
*//adding by the Xiaodong Wu [EMAIL PROTECTED]
//to support for the osgText::String title;
#include <osgText/String>*

namespace osgSim
{
/**
A ScalarBar is an osg::Geode to render a colored bar representing a range
of scalars. The scalar/color ranges are specified by an instance of
ScalarsToColors. There are a number of configurable properties on the
ScalarBar, such as the orientation, the number of labels to be displayed
across the range, the number of distinct colors to use when rendering the
bar, text details etc.

In summary, the main configurables on the ScalarBar are:

 -# The range of scalars represented by the bar, and the colors
    corresponding to this range - these are specified by the
    ScalarsToColors object.
 -# The number of colors used when rendering the bar geometry -
    this may be thought of as the bar 'density'.
 -# The number of text labels to be used when displaying the bar.

The other configurables should be self-explanatory.
*/
class OSGSIM_EXPORT ScalarBar: public osg::Geode
{

public:

    /** ScalarBar orientation specification. */
    enum Orientation{
        HORIZONTAL, ///< a horizontally ascending scalar bar (x-axis)
        VERTICAL    ///< a vertically ascending scalar bar (y-axis)
    };

    /**
    Users may provide their own ScalarPrinter by deriving from this base
class and
    overriding the printScalar() method. Users may map the scalar float
passed in
    to any string they wish.
    */
    struct OSGSIM_EXPORT ScalarPrinter: public osg::Referenced
    {
        virtual std::string printScalar(float scalar);
    };

    /**
    TextProperties allows users to specify a number of properties for the
    text used to display the labels & title on the ScalarBar. Specifiying a
character
    size of 0 will cause the ScalarBar to estimate an appropriate size. Note
that
    the attributes are public, and may be set directly.
    */
    struct TextProperties
    {
        std::string         _fontFile;
        std::pair<int,int>  _fontResolution;
        float               _characterSize;
        osg::Vec4           _color;

        TextProperties():
            _fontFile("fonts/arial.ttf"),
            _fontResolution(40,40),
            _characterSize(0.0f),
            _color(1.0f,1.0f,1.0f,1.0f)
        {
        }
    };

    /** Default constructor. */
    ScalarBar(): osg::Geode(),
        _numColors(256),
        _numLabels(11),
        _stc(new ColorRange(0.0f,1.0f)),
        _title("Scalar Bar"),
        _position(0.0f,0.0f,0.0f),
        _width(1.0f),
        _aspectRatio(0.03),
        _orientation(HORIZONTAL),
        _sp(new ScalarPrinter)
    {
        createDrawables();
    }

    /**
    Construct a ScalarBar with the supplied parameters.
    @param numColors    Specify the number of colors in the scalar bar.
Color
                        interpolation occurs where necessary.
    @param numLabels    Specify the number of labels in the scalar bar.
    @param stc          The ScalarsToColors defining the range of scalars
                        and the colors they map to.
    @param title        The title to be used when displaying the ScalarBar.
                        Specify "" for no title.
    @param orientation  The orientation of the ScalarBar. @see Orientation.
    @param aspectRatio  The aspect ration (y/x) for the displayed bar. Bear
in mind you
                        may want to change this if you change the
orientation.
    @param sp           A ScalarPrinter object for the ScalarBar. For every
displayed
                        ScalarBar label, the scalar value will be passed to
the
                        ScalarPrinter object to turn it into a string. Users
may
                        override the default ScalarPrinter object to map
scalars to
                        whatever strings they wish. @see ScalarPrinter
    */
    ScalarBar(int numColors, int numLabels, ScalarsToColors* stc,
        const osgText::String& title,
                Orientation orientation = HORIZONTAL,
                float aspectRatio=0.25,
                ScalarPrinter* sp=new ScalarPrinter):
        osg::Geode(),
        _numColors(numColors),
        _numLabels(numLabels),
        _stc(stc),
        _title(title),
        _position(0.0f,0.0f,0.0f),
        _width(1.0f),
        _aspectRatio(aspectRatio),
        _orientation(orientation),
        _sp(sp)
    {
        createDrawables();
    }

    /** Copy constructor */
    ScalarBar(const ScalarBar& rhs, const osg::CopyOp& co):
osg::Geode(rhs,co),
        _numColors(rhs._numColors),
        _numLabels(rhs._numLabels),
        _stc(rhs._stc),                     // Consider clone for deep copy?
        _title(rhs._title),
        _position(rhs._position),
        _width(rhs._width),
        _aspectRatio(rhs._aspectRatio),
        _orientation(rhs._orientation),
        _sp(rhs._sp),                        // Consider clone for deep
copy?
        _textProperties(rhs._textProperties)
    {
    }


    META_Node(osgSim, ScalarBar);

    /** Set the number of distinct colours on the ScalarBar. */
    void setNumColors(int numColors);

    /** Get the number of distinct colours on the ScalarBar. */
    int getNumColors() const;

    /** Set the number of labels to display along the ScalarBar. There
    will be one label at each end point, and evenly distributed labels
    in between. */
    void setNumLabels(int numLabels);

    /** Get the number of labels displayed along the ScalarBar. */
    int getNumLabels() const;

    /** Set the ScalarsToColors mapping object for the ScalarBar. */
    void setScalarsToColors(ScalarsToColors* stc);

    /** Get the ScalarsToColors mapping object from the ScalarBar. */
    const ScalarsToColors* getScalarsToColors() const;

    /** Set the title for the ScalarBar, set ""  for no title. */
*    void setTitle(const osgText::String& title);*

    /** Get the title for the ScalarBar. */
    osgText::String getTitle() const;


    /** Set the position of scalar bar's lower left corner.*/
    void setPosition(const osg::Vec3& pos);

    /** Get the position of scalar bar.*/
    const osg::Vec3& getPosition() const { return _position; }

    /** Set the width of the scalar bar.*/
    void setWidth(float width);

    /** Get the width of the scalar bar.*/
    float getWidth() { return _width; }

    /** Set the aspect ration (y/x) for the displayed bar. Bear in mind you
    may want to change this if you change the orientation. */
    void setAspectRatio(float aspectRatio);

    /** Get the aspect ration (y/x) for the displayed bar. */
    float getAspectRatio() const;


    /** Set the orientation of the ScalarBar. @see Orientation */
    void setOrientation(ScalarBar::Orientation orientation);

    /** Get the orientation of the ScalarBar.  @see Orientation */
    ScalarBar::Orientation getOrientation() const;


    /** Set a ScalarPrinter object for the ScalarBar. For every displayed
    ScalarBar label, the scalar value will be passed to the ScalarPrinter
    object to turn it into a string. Users may override the default
ScalarPrinter
    object to map scalars to whatever strings they wish. @see ScalarPrinter
*/
    void setScalarPrinter(ScalarPrinter* sp);

    /** Get the ScalarPrinter object  */
    const ScalarPrinter* getScalarPrinter() const;

    /** Set the TextProperties for the labels & title. @see TextProperties
*/
    void setTextProperties(const TextProperties& tp);

    /** Get the TextProperties for the labels & title. @see TextProperties
*/
    const TextProperties& getTextProperties() const;

    /** force update the drawables used to render the scalar bar.*/
    void update() { createDrawables(); }

protected:
    virtual ~ScalarBar();

    int _numColors;
    int _numLabels;
    osg::ref_ptr<ScalarsToColors> _stc;
    osgText::String _title;
    osg::Vec3 _position;
    float _width;
    float _aspectRatio;
    Orientation _orientation;
    osg::ref_ptr<ScalarPrinter> _sp;
    TextProperties  _textProperties;

    void createDrawables();

};

}

#endif
//==== cpp ============
#include <osgSim/ScalarBar>
#include <osgText/Text>
#include <osg/Geometry>
#include <sstream>

using namespace osgSim;

ScalarBar::~ScalarBar()
{
}

std::string ScalarBar::ScalarPrinter::printScalar(float scalar)
{
    std::stringstream ostr;
    ostr<<scalar;
    return ostr.str();
}

void ScalarBar::setNumColors(int numColors)
{
    _numColors = numColors;
    createDrawables();
}

int ScalarBar::getNumColors() const
{
    return _numColors;
}

void ScalarBar::setNumLabels(int numLabels)
{
    _numLabels = numLabels;
    createDrawables();
}

int ScalarBar::getNumLabels() const
{
    return _numLabels;
}

void ScalarBar::setScalarsToColors(ScalarsToColors* stc)
{
    _stc = stc;
    createDrawables();
}

const ScalarsToColors* ScalarBar::getScalarsToColors() const
{
    return _stc.get();
}

void ScalarBar::setTitle(const osgText::String& title)
{
    _title = title;
    createDrawables();
}

osgText::String ScalarBar::getTitle() const
{
    return _title;
}

void ScalarBar::setPosition(const osg::Vec3& pos)
{
    _position = pos;
    createDrawables();
}

void ScalarBar::setWidth(float width)
{
    _width = width;
    createDrawables();
}

void ScalarBar::setOrientation(ScalarBar::Orientation orientation)
{
    _orientation = orientation;
    createDrawables();
}

ScalarBar::Orientation ScalarBar::getOrientation() const
{
    return _orientation;
}

void ScalarBar::setAspectRatio(float aspectRatio)
{
    _aspectRatio = aspectRatio;
    createDrawables();
}

float ScalarBar::getAspectRatio() const
{
    return _aspectRatio;
}

void ScalarBar::setScalarPrinter(ScalarPrinter* sp)
{
    _sp = sp;
    createDrawables();
}

const ScalarBar::ScalarPrinter* ScalarBar::getScalarPrinter() const
{
    return _sp.get();
}


void ScalarBar::setTextProperties(const TextProperties& tp)
{
    _textProperties = tp;
    createDrawables();
}

const ScalarBar::TextProperties& ScalarBar::getTextProperties() const
{
    return _textProperties;
}


void ScalarBar::createDrawables()
{
    // Remove any existing Drawables
    _drawables.erase(_drawables.begin(), _drawables.end());

    if (_numColors==0) return;

    osg::Matrix matrix;
    if(_orientation==HORIZONTAL)
    {
        matrix = osg::Matrix::translate(_position);
    }
    else
    {
        matrix =
osg::Matrix::rotate(osg::DegreesToRadians(90.0f),1.0f,0.0f,0.0f) *
osg::Matrix::translate(_position);
    }

    // 1. First the bar
    // =================
    osg::ref_ptr<osg::Geometry> bar = new osg::Geometry();

    // Create the bar - created in 'real' coordinate space the moment,
    // with xyz values reflecting those of the actual scalar values in play.
    // FIXME: Consider positioning at origin! Should be easy enough to do.

    // Vertices
    osg::ref_ptr<osg::Vec3Array> vs(new osg::Vec3Array);
    vs->reserve(2*(_numColors+1));

    float incr = (_stc->getMax() - _stc->getMin()) / _numColors;
    float xincr = (_width) / _numColors;
    float arOffset = _width * _aspectRatio;

    int i;
    for(i=1; i<=_numColors; ++i)
    {
        vs->push_back(osg::Vec3((i-1) * xincr, 0.0f,     0.0f)*matrix);
        vs->push_back(osg::Vec3((i-1) * xincr, arOffset, 0.0f)*matrix);
        vs->push_back(osg::Vec3(i     * xincr, arOffset, 0.0f)*matrix);
        vs->push_back(osg::Vec3(i     * xincr, 0.0f,     0.0f)*matrix);
    }
    bar->setVertexArray(vs.get());

    // Colours
    osg::ref_ptr<osg::Vec4Array> cs(new osg::Vec4Array);
    cs->reserve(_numColors);
    const float halfIncr = incr*0.5;
    for(i=0; i<_numColors; ++i)
    {
        // We add half an increment to the color look-up to get the color
        // square in the middle of the 'block'.
        cs->push_back(_stc->getColor(_stc->getMin() + (i*incr)  +
halfIncr));
    }
    bar->setColorArray(cs.get());
    bar->setColorBinding(osg::Geometry::BIND_PER_PRIMITIVE);

    // Normal
    osg::ref_ptr<osg::Vec3Array> ns(new osg::Vec3Array);

ns->push_back(osg::Matrix::transform3x3(osg::Vec3(0.0f,0.0f,1.0f),matrix));
    bar->setNormalArray(ns.get());
    bar->setNormalBinding(osg::Geometry::BIND_OVERALL);

    // The Quad strip that represents the bar
    bar->addPrimitiveSet(new osg::DrawArrays(GL_QUADS,0,vs->size()));

    addDrawable(bar.get());

    // 2. Then the text labels
    // =======================

    // Check the character size, if it's 0, estimate a good character size
    float characterSize = _textProperties._characterSize;
    if(characterSize == 0) characterSize = _width * 0.03f;

    osgText::Font* font =
osgText::readFontFile(_textProperties._fontFile.c_str());

    std::vector<osgText::Text*> texts(_numLabels);      // We'll need to
collect pointers to these for later
    float labelIncr = (_numLabels>0) ?
(_stc->getMax()-_stc->getMin())/(_numLabels-1) : 0.0f;
    float labelxIncr = (_numLabels>0) ? (_width)/(_numLabels-1) : 0.0f;
    float labely = arOffset + characterSize*0.3f;
    for(i=0; i<_numLabels; ++i)
    {
        osgText::Text* text = new osgText::Text;
        text->setFont(font);
        text->setColor(_textProperties._color);

text->setFontResolution(_textProperties._fontResolution.first,_textProperties._fontResolution.second);
        text->setCharacterSize(characterSize);
        text->setText(_sp->printScalar(_stc->getMin()+(i*labelIncr)));

        text->setPosition(osg::Vec3((i*labelxIncr), labely, 0.0f)*matrix);
        text->setAlignment(osgText::Text::CENTER_BASE_LINE);
        text->setAxisAlignment( (_orientation==HORIZONTAL) ?
osgText::Text::XY_PLANE :  osgText::Text::XZ_PLANE );

        addDrawable(text);

        texts[i] = text;
    }


    // 3. And finally the title
    // ========================
    //to support the osgText::String, comment the code;
    //if(_title != "")
    if( _title.size() !=0 )
    {
        osgText::Text* text = new osgText::Text;
        text->setFont(font);
        text->setColor(_textProperties._color);

text->setFontResolution(_textProperties._fontResolution.first,_textProperties._fontResolution.second);
        text->setCharacterSize(characterSize);
        text->setText(_title);

        float titleY = (_numLabels>0) ? labely + characterSize : labely;

        // Position the title at the middle of the bar above any labels.
        text->setPosition(osg::Vec3((_width/2.0f), titleY, 0.0f)*matrix);
        text->setAlignment(osgText::Text::CENTER_BASE_LINE);
        text->setAxisAlignment( (_orientation==HORIZONTAL) ?
osgText::Text::XY_PLANE :  osgText::Text::XZ_PLANE );

        addDrawable(text);
    }
}


-- 
Xiaodong Wu
吴晓东
"'Xiao' means the time and the view when the sun rises and 'dong' means the
east in Chinese"
_______________________________________________
osg-users mailing list
osg-users@lists.openscenegraph.org
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to