File: [Development] / inventor / apps / nodes / BarChart / BarChart.c++ (download)
Revision 1.1.1.1 (vendor branch), Tue Aug 15 12:55:59 2000 UTC (17 years, 2 months ago) by naaman
Branch: sgi, MAIN
CVS Tags: start, release-2_1_5-9, release-2_1_5-8, release-2_1_5-10, HEAD Changes since 1.1: +0 -0
lines
Initial check-in based on 2.1.5 (SGI IRIX) source tree.
|
/*
*
* Copyright (C) 2000 Silicon Graphics, Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* 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 GNU
* Lesser General Public License for more details.
*
* Further, this software is distributed without any warranty that it is
* free of the rightful claim of any third person regarding infringement
* or the like. Any license provided herein, whether implied or
* otherwise, applies only to this software file. Patent licenses, if
* any, provided herein do not apply to combinations of this program with
* other software, or any other product whatsoever.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
* Mountain View, CA 94043, or:
*
* http://www.sgi.com
*
* For further information regarding this notice, see:
*
* http://oss.sgi.com/projects/GenInfo/NoticeExplan/
*
*/
//
// Source file for "BarChart" shape node.
//
#include <assert.h>
#include <GL/gl.h>
#include <Inventor/SoDB.h>
#include <Inventor/SbBox.h>
#include <Inventor/actions/SoGLRenderAction.h>
#include <Inventor/actions/SoGetBoundingBoxAction.h>
#include <Inventor/nodes/SoDrawStyle.h>
#include <Inventor/nodes/SoLightModel.h>
#include <Inventor/nodes/SoSeparator.h>
#include <Inventor/nodes/SoTranslation.h>
#include <Inventor/nodes/SoScale.h>
#include <Inventor/nodes/SoRotationXYZ.h>
#include <Inventor/nodes/SoTransform.h>
#include <Inventor/nodes/SoCube.h>
#include <Inventor/nodes/SoText3.h>
#include <Inventor/nodes/SoCylinder.h>
#include <Inventor/nodes/SoSphere.h>
#include <Inventor/nodes/SoMaterial.h>
#include "BarChart.h"
SO_NODE_SOURCE(BarChart);
#define MAX(x,y) ((x) > (y) ? (x) : (y))
#define MIN(x,y) ((x) < (y) ? (x) : (y))
#define TWOPI (2.0*M_PI)
//
// This initializes the BarChart class.
//
void
BarChart::initClass()
{
SO_NODE_INIT_CLASS(BarChart, SoShape, "Shape");
}
//
// Constructor
//
BarChart::BarChart()
{
children = new SoChildList(this);
SO_NODE_CONSTRUCTOR(BarChart);
SO_NODE_ADD_FIELD(plateColor, (0.3, 0.3, 0.3, 0));
SO_NODE_ADD_FIELD(poleColor, (0, 0.3, 0.5, 0));
SO_NODE_ADD_FIELD(values, (1.0));
SO_NODE_ADD_FIELD(valueColors, (0.8, 0, 0, 0));
SO_NODE_ADD_FIELD(xLabels, ("X Label"));
SO_NODE_ADD_FIELD(xLabelColors, (0.8, 0, 0, 0));
SO_NODE_ADD_FIELD(xLabelScale, (1, 1, 1));
SO_NODE_ADD_FIELD(yLabels, ("Y Label"));
SO_NODE_ADD_FIELD(yLabelColors, (0.8, 0.8, 0, 0));
SO_NODE_ADD_FIELD(yLabelScale, (1, 1, 1));
SO_NODE_ADD_FIELD(xDimension, (1));
SO_NODE_ADD_FIELD(yDimension, (1));
SO_NODE_ADD_FIELD(xBarProportion, (0.7));
SO_NODE_ADD_FIELD(yBarProportion, (0.7));
SO_NODE_ADD_FIELD(minValue, (0));
SO_NODE_ADD_FIELD(maxValue, (1.0));
SO_NODE_ADD_FIELD(zLabelColor, (0.8, 0.8, 0, 0));
SO_NODE_ADD_FIELD(zMarkerColor, (0.8, 0, 0, 0));
SO_NODE_ADD_FIELD(zLabelScale, (1, 1, 1));
SO_NODE_ADD_FIELD(zLabelIncrement, (0.2));
SO_NODE_ADD_FIELD(barStyle, (BAR));
}
//
// Destructor
//
BarChart::~BarChart()
{
}
//
// Implements the SoGetBoundingBoxAction for the BarChart node.
//
SbBox3f
BarChart::getBbox() const
{
// everything inside BarChart normalizes to a unit volume
SbVec3f max( 1, 1, 1 );
return SbBox3f(-max, max);
}
void
BarChart::computeBBox(SoAction *, SbBox3f &box, SbVec3f ¢er)
{
box = getBbox();
center.setValue(0.0, 0.0, 0.0);
}
//
// Implements the SoGLRenderAction for the BarChart node.
//
void
BarChart::GLRender(SoGLRenderAction *action)
{
if (! shouldGLRender(action))
return;
if (children->getLength() == 0) generateChildren();
children->traverse(action);
}
void
BarChart::generatePrimitives(SoAction *action)
{
if (children->getLength() == 0) generateChildren();
children->traverse(action);
}
SoChildList
*BarChart::getChildren() const
{
return children;
}
void
BarChart::generateChildren()
{
SoTranslation *tr;
SoScale *sc;
SoRotationXYZ *rot;
SoMaterial *mtl;
SoSeparator *sep;
// this should get called only once so there should be no children yet.
assert(children->getLength() == 0);
// for testing, a wireframe cube surrounding the volume
/*
sep = new SoSeparator();
children->append(sep);
SoDrawStyle *ds = new SoDrawStyle();
ds->style = SoDrawStyle::LINES;
SoLightModel *lm = new SoLightModel();
lm->model = SoLightModel::BASE_COLOR;
sep->addChild(ds);
sep->addChild(lm);
sep->addChild(new SoCube);
*/
// base plate
sep = new SoSeparator();
children->append(sep);
tr = new SoTranslation();
tr->translation.setValue(0, -0.95, 0);
sep->addChild(tr);
mtl = new SoMaterial();
mtl->diffuseColor.setValue( plateColor.getValue()[0],
plateColor.getValue()[1],
plateColor.getValue()[2] );
mtl->transparency.setValue( plateColor.getValue()[3] );
sep->addChild(mtl);
SoCube *plate = new SoCube();
plate->height = 0.1;
plate->width = 1.9;
plate->depth = 1.9;
sep->addChild(plate);
// boundary poles
sep = new SoSeparator();
children->append(sep);
mtl = new SoMaterial();
mtl->diffuseColor.setValue( poleColor.getValue()[0],
poleColor.getValue()[1],
poleColor.getValue()[2] );
mtl->transparency.setValue( poleColor.getValue()[3] );
sep->addChild(mtl);
SoCylinder *pole = new SoCylinder();
pole->radius = 0.03;
tr = new SoTranslation();
tr->translation.setValue(-0.95, 0, -0.95);
sep->addChild(tr);
sep->addChild(pole);
tr = new SoTranslation();
tr->translation.setValue(0, 0, 1.9);
sep->addChild(tr);
sep->addChild(pole);
tr = new SoTranslation();
tr->translation.setValue(1.9, 0, 0);
sep->addChild(tr);
sep->addChild(pole);
tr = new SoTranslation();
tr->translation.setValue(0, 0, -1.9);
sep->addChild(tr);
sep->addChild(pole);
// generate appropriate bars
float barXSpace = 1.8/MAX(xDimension.getValue(), 1);
float barYSpace = 1.8/MAX(yDimension.getValue(), 1);
float barWidth = barXSpace*MIN(xBarProportion.getValue(), 1);
float barDepth = barYSpace*MIN(yBarProportion.getValue(), 1);
switch (barStyle.getValue())
{
case BAR: generateBars(barXSpace, barYSpace, barWidth, barDepth);
break;
}
// add X labels
sep = new SoSeparator();
children->append(sep);
tr = new SoTranslation();
tr->translation.setValue(-0.9+barXSpace/2, -0.95, 0.98);
sep->addChild(tr);
sc = new SoScale();
sc->scaleFactor.setValue( xLabelScale.getValue()[0]*0.01,
xLabelScale.getValue()[1]*0.01,
xLabelScale.getValue()[2]*0.01 );
sep->addChild(sc);
int i;
for (i = 0; i < xLabels.getNum() && i < xDimension.getValue(); ++i)
{
SoMaterial *mtl = new SoMaterial();
int c = i % xLabelColors.getNum();
mtl->diffuseColor.setValue( xLabelColors[c][0],
xLabelColors[c][1],
xLabelColors[c][2] );
mtl->transparency.setValue( xLabelColors[c][3] );
sep->addChild(mtl);
SoText3 *text = new SoText3();
text->string = xLabels[i];
text->justification = SoText3::CENTER;
text->parts = SoText3::ALL;
sep->addChild(text);
tr = new SoTranslation();
tr->translation.setValue(barXSpace/(xLabelScale.getValue()[0]*0.01),
0, 0);
sep->addChild(tr);
}
// add Y labels (just rotate -90 degrees about XZ and do same as xlabels
sep = new SoSeparator();
children->append(sep);
rot = new SoRotationXYZ();
rot->axis = SoRotationXYZ::Y;
rot->angle = TWOPI/4;
sep->addChild(rot);
tr = new SoTranslation();
tr->translation.setValue(-0.9+barYSpace/2, -0.95, 0.98);
sep->addChild(tr);
sc = new SoScale();
sc->scaleFactor.setValue( yLabelScale.getValue()[0]*0.01,
yLabelScale.getValue()[1]*0.01,
yLabelScale.getValue()[2]*0.01 );
sep->addChild(sc);
for (i = 0; i < yLabels.getNum() && i < yDimension.getValue(); ++i)
{
SoMaterial *mtl = new SoMaterial();
int c = i % yLabelColors.getNum();
mtl->diffuseColor.setValue( yLabelColors[c][0],
yLabelColors[c][1],
yLabelColors[c][2] );
mtl->transparency.setValue( yLabelColors[c][3] );
sep->addChild(mtl);
SoText3 *text = new SoText3();
text->string = yLabels[i];
text->justification = SoText3::CENTER;
text->parts = SoText3::ALL;
sep->addChild(text);
tr = new SoTranslation();
tr->translation.setValue(barYSpace/(yLabelScale.getValue()[0]*0.01),
0, 0);
sep->addChild(tr);
}
// add Z markings
SoSeparator *zsep = new SoSeparator();
children->append(zsep);
tr = new SoTranslation();
tr->translation.setValue(-0.95, -0.95, 0.95);
zsep->addChild(tr);
sep = new SoSeparator();
zsep->addChild(sep);
float nzLabels = (maxValue.getValue() - minValue.getValue()) /
zLabelIncrement.getValue();
// first add the spheres for markers
mtl = new SoMaterial();
mtl->diffuseColor.setValue( zMarkerColor.getValue()[0],
zMarkerColor.getValue()[1],
zMarkerColor.getValue()[2] );
mtl->transparency.setValue( zMarkerColor.getValue()[3] );
sep->addChild(mtl);
float val;
SoSphere *sph = new SoSphere(); // sphere for instancing
sph->radius = 0.04;
for (val = minValue.getValue() + zLabelIncrement.getValue();
val <= maxValue.getValue();
val += zLabelIncrement.getValue())
{
tr = new SoTranslation();
tr->translation.setValue(0, (1.8/nzLabels), 0);
sep->addChild(tr);
sep->addChild(sph);
}
// now do the labels
sep = new SoSeparator();
zsep->addChild(sep);
SoTransform *xform = new SoTransform();
xform->scaleFactor.setValue(zLabelScale.getValue()[0]*0.01,
zLabelScale.getValue()[1]*0.01,
zLabelScale.getValue()[2]*0.01 );
xform->center.setValue(0, 0, 0.05);
xform->rotation.setValue(SbVec3f(0, 1, 0), TWOPI/10);
sep->addChild(xform);
mtl = new SoMaterial();
mtl->diffuseColor.setValue( zLabelColor.getValue()[0],
zLabelColor.getValue()[1],
zLabelColor.getValue()[2] );
mtl->transparency.setValue( zLabelColor.getValue()[3] );
sep->addChild(mtl);
for (val = minValue.getValue();
val <= maxValue.getValue();
val += zLabelIncrement.getValue())
{
SoText3 *text = new SoText3();
char s[40];
sprintf(s, "%hg", val);
text->string = s;
text->justification = SoText3::CENTER;
text->parts = SoText3::ALL;
sep->addChild(text);
tr = new SoTranslation();
tr->translation.setValue(0, (1.8/nzLabels) /
(zLabelScale.getValue()[0]*0.01), 0);
sep->addChild(tr);
}
}
void BarChart::generateBars(float barXSpace, float barYSpace,
float barWidth, float barDepth)
{
// first, figure out the tallest bar for scaling
float maxbar = values[0];
float minbar = minValue.getValue();
int i = values.getNum();
while (--i > 0)
if (values[i] > maxbar) maxbar = values[i];
if (maxbar > maxValue.getValue()) maxbar = maxValue.getValue();
// bars
SoSeparator *sep = new SoSeparator();
children->append(sep);
SoTranslation *tr = new SoTranslation();
tr->translation.setValue(-0.9+barXSpace/2, 0.09, 0.9-barYSpace/2);
sep->addChild(tr);
int n = 0;
int j = 0;
// traversal in both directions will go 1.8 units, so
// each movement will be 1.8 / ({x,y}Dim - 1)
for ( ; ; )
{
SoSeparator *ysep = new SoSeparator();
sep->addChild(ysep);
if (n >= values.getNum()) break;
float curPlant = 0;
int i = 0;
for ( ; ; )
{
if (n >= values.getNum()) break;
// translate in Y to plant on base plate
float curZ = (values[n]-minbar) / maxbar * 1.8;
tr = new SoTranslation();
tr->translation.setValue(0, curPlant-(1-curZ/2), 0);
curPlant = (1-curZ/2);
ysep->addChild(tr);
SoMaterial *mtl = new SoMaterial();
int c = n % valueColors.getNum();
mtl->diffuseColor.setValue( valueColors[c][0],
valueColors[c][1],
valueColors[c][2] );
mtl->transparency.setValue( valueColors[c][3] );
ysep->addChild(mtl);
SoCube *bar = new SoCube();
bar->width = barWidth;
bar->depth = barDepth;
bar->height = curZ;
ysep->addChild(bar);
n++;
if (++i >= xDimension.getValue()) break;
tr = new SoTranslation();
tr->translation.setValue(barXSpace, 0, 0);
ysep->addChild(tr);
}
if (++j >= yDimension.getValue()) break;
tr = new SoTranslation();
tr->translation.setValue(0, 0, -barYSpace);
sep->addChild(tr);
}
}