FreeCAD/src/Gui/SoFCColorLegend.cpp
2011-10-10 13:44:52 +00:00

244 lines
7.4 KiB
C++

/***************************************************************************
* Copyright (c) 2005 Werner Mayer <wmayer[at]users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 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 Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
# include <sstream>
# include <Inventor/fields/SoMFString.h>
# include <Inventor/nodes/SoBaseColor.h>
# include <Inventor/nodes/SoCoordinate3.h>
# include <Inventor/nodes/SoIndexedFaceSet.h>
# include <Inventor/nodes/SoMaterial.h>
# include <Inventor/nodes/SoText2.h>
# include <Inventor/nodes/SoTransform.h>
#endif
#include "SoFCColorLegend.h"
using namespace Gui;
SO_NODE_SOURCE(SoFCColorLegend);
/*!
Constructor.
*/
SoFCColorLegend::SoFCColorLegend() : _fPosX(4.0f), _fPosY(4.0f)
{
SO_NODE_CONSTRUCTOR(SoFCColorLegend);
_cColRamp.setStyle(App::ColorGradient::FLOW);
coords = new SoCoordinate3;
coords->ref();
labels = new SoSeparator;
labels->ref();
setColorModel( App::ColorGradient::TRIA );
setRange(-0.5f,0.5f,1);
}
/*!
Destructor.
*/
SoFCColorLegend::~SoFCColorLegend()
{
//delete THIS;
coords->unref();
labels->unref();
}
// doc from parent
void SoFCColorLegend::initClass(void)
{
SO_NODE_INIT_CLASS(SoFCColorLegend,SoFCColorBarBase,"Separator");
}
void SoFCColorLegend::finish()
{
atexit_cleanup();
}
void SoFCColorLegend::setMarkerLabel( const SoMFString& label )
{
labels->removeAllChildren();
int num = label.getNum();
if ( num > 1 )
{
float fStep = 8.0f / ((float)num-1);
SoTransform* trans = new SoTransform;
trans->translation.setValue(_fPosX+0.1f,_fPosY-0.05f+fStep,0.0f);
labels->addChild(trans);
for ( int i=0; i<num; i++ )
{
SoTransform* trans = new SoTransform;
SoBaseColor* color = new SoBaseColor;
SoText2 * text2 = new SoText2;
trans->translation.setValue(0,-fStep,0);
color->rgb.setValue(0,0,0);
text2->string.setValue( label[i] );
labels->addChild(trans);
labels->addChild(color);
labels->addChild(text2);
}
}
}
void SoFCColorLegend::setViewportSize( const SbVec2s& size )
{
float fRatio = ((float)size[0])/((float)size[1]);
float fMinX= 4.0f, fMaxX=4.5f;
float fMinY= -4.0f, fMaxY=4.0f;
if ( fRatio > 1.0f )
{
fMinX = 4.0f * fRatio;
fMaxX = fMinX+0.5f;
}
else if ( fRatio < 1.0f )
{
fMinY = -4.0f / fRatio;
fMaxY = 4.0f / fRatio;
}
_fPosX = fMaxX;
_fPosY = fMaxY;
// search for the labels
int num=0;
for ( int i=0; i<labels->getNumChildren(); i++ )
{
if ( labels->getChild(i)->getTypeId() == SoTransform::getClassTypeId() )
num++;
}
if ( num > 2 )
{
bool first=true;
float fStep = (fMaxY-fMinY) / ((float)num-2);
for ( int j=0; j<labels->getNumChildren(); j++ )
{
if ( labels->getChild(j)->getTypeId() == SoTransform::getClassTypeId() )
{
if ( first )
{
first = false;
static_cast<SoTransform*>(labels->getChild(j))->translation.setValue(fMaxX+0.1f,fMaxY-0.05f+fStep,0.0f);
}
else
{
static_cast<SoTransform*>(labels->getChild(j))->translation.setValue(0,-fStep,0.0f);
}
}
}
}
// set the vertices spanning the faces for the color gradient
int ct = coords->point.getNum()/2;
for ( int j=0; j<ct; j++ )
{
float w = (float)j/(float)(ct-1);
float fPosY = (1.0f-w)*fMaxY + w*fMinY;
coords->point.set1Value(2*j, fMinX, fPosY, 0.0f);
coords->point.set1Value(2*j+1, fMaxX, fPosY, 0.0f);
}
}
void SoFCColorLegend::setRange( float fMin, float fMax, int prec )
{
SoMFString label;
for (int j=0; j<9; j++)
{
std::stringstream s;
s.precision(prec);
s.setf(std::ios::fixed | std::ios::showpoint | std::ios::showpos);
float fValue = (1.0f-0.125f*(float)j)*fMax + (0.125f*(float)j)*fMin;
s << fValue;
label.set1Value(j, s.str().c_str());
}
setMarkerLabel( label );
_cColRamp.setRange(fMin, fMax);
}
void SoFCColorLegend::setColorModel( App::ColorGradient::TColorModel tModel )
{
_cColRamp.setColorModel( tModel );
App::ColorModel model = _cColRamp.getColorModel();
int uCtColors = (int)model._usColors;
// don't know why the parameter range isn't between [-1,+1]
float fMinX= 4.0f, fMaxX=4.5f;
float fMinY= -4.0f, fMaxY=4.0f;
coords->point.setNum(2*uCtColors);
for ( int i=0; i<uCtColors; i++ )
{
float w = (float)i/(float)(uCtColors-1);
float fPosY = (1.0f-w)*fMaxY + w*fMinY;
coords->point.set1Value(2*i, fMinX, fPosY, 0.0f);
coords->point.set1Value(2*i+1, fMaxX, fPosY, 0.0f);
}
// for uCtColors colors we need 2*(uCtColors-1) facets and therefore an array with
// 8*(uCtColors-1) face indices
SoIndexedFaceSet * faceset = new SoIndexedFaceSet;
faceset->coordIndex.setNum(8*(uCtColors-1));
for ( int j=0; j<uCtColors-1; j++ )
{
faceset->coordIndex.set1Value(8*j, 2*j);
faceset->coordIndex.set1Value(8*j+1, 2*j+3);
faceset->coordIndex.set1Value(8*j+2, 2*j+1);
faceset->coordIndex.set1Value(8*j+3, SO_END_FACE_INDEX);
faceset->coordIndex.set1Value(8*j+4, 2*j);
faceset->coordIndex.set1Value(8*j+5, 2*j+2);
faceset->coordIndex.set1Value(8*j+6, 2*j+3);
faceset->coordIndex.set1Value(8*j+7, SO_END_FACE_INDEX);
}
SoMaterial* mat = new SoMaterial;
//mat->transparency = 0.3f;
mat->diffuseColor.setNum(2*uCtColors);
for ( int k=0; k<uCtColors; k++ )
{
App::Color col = model._pclColors[uCtColors-k-1];
mat->diffuseColor.set1Value(2*k, col.r, col.g, col.b);
mat->diffuseColor.set1Value(2*k+1, col.r, col.g, col.b);
}
SoMaterialBinding* matBinding = new SoMaterialBinding;
matBinding->value = SoMaterialBinding::PER_VERTEX_INDEXED;
// first clear the children
if ( getNumChildren() > 0 )
removeAllChildren();
addChild(labels);
addChild(coords);
addChild(mat);
addChild(matBinding);
addChild(faceset);
}