SoFCColorGradient.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (c) 2005 Werner Mayer <wmayer[at]users.sourceforge.net>     *
00003  *                                                                         *
00004  *   This file is part of the FreeCAD CAx development system.              *
00005  *                                                                         *
00006  *   This library is free software; you can redistribute it and/or         *
00007  *   modify it under the terms of the GNU Library General Public           *
00008  *   License as published by the Free Software Foundation; either          *
00009  *   version 2 of the License, or (at your option) any later version.      *
00010  *                                                                         *
00011  *   This library  is distributed in the hope that it will be useful,      *
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00014  *   GNU Library General Public License for more details.                  *
00015  *                                                                         *
00016  *   You should have received a copy of the GNU Library General Public     *
00017  *   License along with this library; see the file COPYING.LIB. If not,    *
00018  *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
00019  *   Suite 330, Boston, MA  02111-1307, USA                                *
00020  *                                                                         *
00021  ***************************************************************************/
00022 
00023 
00024 #include "PreCompiled.h"
00025 
00026 #ifndef _PreComp_
00027 # include <sstream>
00028 # include <Inventor/fields/SoMFString.h>
00029 # include <Inventor/nodes/SoBaseColor.h>
00030 # include <Inventor/nodes/SoCoordinate3.h>
00031 # include <Inventor/nodes/SoIndexedFaceSet.h>
00032 # include <Inventor/nodes/SoMaterial.h>
00033 # include <Inventor/nodes/SoText2.h>
00034 # include <Inventor/nodes/SoTransform.h>
00035 # include <Inventor/nodes/SoTransparencyType.h>
00036 #endif
00037 
00038 #include "SoFCColorGradient.h"
00039 #include "DlgSettingsColorGradientImp.h"
00040 #include "MainWindow.h"
00041 #include "MDIView.h"
00042 
00043 using namespace Gui;
00044 
00045 SO_NODE_SOURCE(SoFCColorGradient);
00046 
00050 SoFCColorGradient::SoFCColorGradient() : _fMaxX(4.5f), _fMinX(4.0f), _fMaxY(4.0f), _fMinY(-4.0f), _bOutInvisible(false), _precision(3)
00051 {
00052     SO_NODE_CONSTRUCTOR(SoFCColorGradient);
00053     coords = new SoCoordinate3;
00054     coords->ref();
00055     labels = new SoSeparator;
00056     labels->ref();
00057 
00058     _cColGrad.setStyle(App::ColorGradient::FLOW);
00059     setColorModel( App::ColorGradient::TRIA );
00060     setRange(-0.5f, 0.5f, 1);
00061 }
00062 
00066 SoFCColorGradient::~SoFCColorGradient()
00067 {
00068     //delete THIS;
00069     coords->unref();
00070     labels->unref();
00071 }
00072 
00073 // doc from parent
00074 void SoFCColorGradient::initClass(void)
00075 {
00076     SO_NODE_INIT_CLASS(SoFCColorGradient,SoFCColorBarBase,"Separator");
00077 }
00078 
00079 void SoFCColorGradient::finish()
00080 {
00081     atexit_cleanup();
00082 }
00083 
00084 void SoFCColorGradient::setMarkerLabel( const SoMFString& label )
00085 {
00086     labels->removeAllChildren();
00087 
00088     float fH=8.0f;
00089     int num = label.getNum();
00090     if ( num > 1 )
00091     {
00092         float fStep = fH / ((float)num-1);
00093         SoTransform* trans = new SoTransform;
00094         trans->translation.setValue(_fMaxX+0.1f,_fMaxY-0.05f+fStep,0.0f);
00095         labels->addChild(trans);
00096 
00097         for ( int i=0; i<num; i++ )
00098         {
00099             SoTransform* trans = new SoTransform;
00100             SoBaseColor* color = new SoBaseColor;
00101             SoText2    * text2 = new SoText2;
00102 
00103             trans->translation.setValue(0,-fStep,0);
00104             color->rgb.setValue(0,0,0);
00105             text2->string.setValue( label[i] );
00106             labels->addChild(trans);
00107             labels->addChild(color);
00108             labels->addChild(text2);
00109         }
00110     }
00111 }
00112 
00113 void SoFCColorGradient::setViewportSize( const SbVec2s& size )
00114 {
00115     // don't know why the parameter range isn't between [-1,+1]
00116     float fRatio = ((float)size[0])/((float)size[1]);
00117     float fMinX=  4.0f, fMaxX=4.5f;
00118     float fMinY= -4.0f, fMaxY=4.0f;
00119 
00120     if ( fRatio > 1.0f )
00121     {
00122         fMinX = 4.0f * fRatio;
00123         fMaxX = fMinX+0.5f;
00124     }
00125     else if ( fRatio < 1.0f )
00126     {
00127         fMinY =  -4.0f / fRatio;
00128         fMaxY =   4.0f / fRatio;
00129     }
00130 
00131     _fMaxX = fMaxX;
00132     _fMinX = fMinX;
00133     _fMaxY = fMaxY;
00134     _fMinY = fMinY;
00135 
00136     // search for the labels
00137     int num=0;
00138     for ( int i=0; i<labels->getNumChildren(); i++ )
00139     {
00140         if ( labels->getChild(i)->getTypeId() == SoTransform::getClassTypeId() )
00141             num++;
00142     }
00143 
00144     if ( num > 2 )
00145     {
00146         bool first=true;
00147         float fStep = (fMaxY-fMinY) / ((float)num-2);
00148 
00149         for ( int j=0; j<labels->getNumChildren(); j++ )
00150         {
00151             if ( labels->getChild(j)->getTypeId() == SoTransform::getClassTypeId() )
00152             {
00153                 if ( first )
00154                 {
00155                     first = false;
00156                     static_cast<SoTransform*>(labels->getChild(j))->translation.setValue(fMaxX+0.1f,fMaxY-0.05f+fStep,0.0f);
00157                 }
00158                 else
00159                 {
00160                     static_cast<SoTransform*>(labels->getChild(j))->translation.setValue(0,-fStep,0.0f);
00161                 }
00162             }
00163         }
00164     }
00165 
00166     // set the vertices spanning the faces for the color gradient
00167     int ct = coords->point.getNum()/2;
00168     for ( int j=0; j<ct; j++ )
00169     {
00170         float w = (float)j/(float)(ct-1);
00171         float fPosY = (1.0f-w)*_fMaxY + w*_fMinY;
00172         coords->point.set1Value(2*j, _fMinX, fPosY, 0.0f);
00173         coords->point.set1Value(2*j+1, _fMaxX, fPosY, 0.0f);
00174     }
00175 }
00176 
00177 void SoFCColorGradient::setRange( float fMin, float fMax, int prec )
00178 {
00179     _cColGrad.setRange(fMin, fMax);
00180 
00181     SoMFString label;
00182 
00183     float fFac = (float)pow(10.0, (double)prec);
00184 
00185     int i=0;
00186     std::vector<float> marks = getMarkerValues(fMin, fMax, _cColGrad.getCountColors());
00187     for ( std::vector<float>::iterator it = marks.begin(); it != marks.end(); ++it )
00188     {
00189         std::stringstream s;
00190         s.precision(prec);
00191         s.setf(std::ios::fixed | std::ios::showpoint | std::ios::showpos);
00192         float fValue = *it;
00193         if ( fabs(fValue*fFac) < 1.0 )
00194             fValue = 0.0f;
00195         s << fValue;
00196         label.set1Value(i++, s.str().c_str());
00197     }
00198 
00199     setMarkerLabel( label );
00200 }
00201 
00202 std::vector<float> SoFCColorGradient::getMarkerValues(float fMin, float fMax, int count) const
00203 {
00204     std::vector<float> labels;
00205 
00206     // the middle of the bar is zero
00207     if ( fMin < 0.0f && fMax > 0.0f && _cColGrad.getStyle() == App::ColorGradient::ZERO_BASED )
00208     {
00209         if ( count % 2 == 0) count++;
00210         int half = count / 2;
00211         for (int j=0; j<half+1; j++)
00212         {
00213             float w = (float)j/((float)half);
00214             float fValue = (1.0f-w)*fMax;
00215             labels.push_back( fValue );
00216         }
00217         for (int k=half+1; k<count; k++)
00218         {
00219             float w = (float)(k-half+1)/((float)(count-half));
00220             float fValue = w*fMin;
00221             labels.push_back( fValue );
00222         }
00223     }
00224     else // either not zero based or 0 is not in between [fMin,fMax]
00225     {
00226         for (int j=0; j<count; j++)
00227         {
00228             float w = (float)j/((float)count-1.0f);
00229             float fValue = (1.0f-w)*fMax+w*fMin;
00230             labels.push_back( fValue );
00231         }
00232     }
00233 
00234     return labels;
00235 }
00236 
00237 void SoFCColorGradient::setColorModel( App::ColorGradient::TColorModel tModel )
00238 {
00239     _cColGrad.setColorModel( tModel );
00240     rebuildGradient();
00241 }
00242 
00243 void SoFCColorGradient::setColorStyle (App::ColorGradient::TStyle tStyle)
00244 {
00245     _cColGrad.setStyle( tStyle );
00246     rebuildGradient();
00247 }
00248 
00249 void SoFCColorGradient::rebuildGradient()
00250 {
00251     App::ColorModel model = _cColGrad.getColorModel();
00252     int uCtColors = (int)model._usColors;
00253 
00254     coords->point.setNum(2*uCtColors);
00255     for ( int i=0; i<uCtColors; i++ )
00256     {
00257         float w = (float)i/(float)(uCtColors-1);
00258         float fPosY = (1.0f-w)*_fMaxY + w*_fMinY;
00259         coords->point.set1Value(2*i, _fMinX, fPosY, 0.0f);
00260         coords->point.set1Value(2*i+1, _fMaxX, fPosY, 0.0f);
00261     }
00262 
00263     // for uCtColors colors we need 2*(uCtColors-1) facets and therefore an array with
00264     // 8*(uCtColors-1) face indices
00265     SoIndexedFaceSet * faceset = new SoIndexedFaceSet;
00266     faceset->coordIndex.setNum(8*(uCtColors-1));
00267     for ( int j=0; j<uCtColors-1; j++ )
00268     {
00269         faceset->coordIndex.set1Value(8*j,   2*j);
00270         faceset->coordIndex.set1Value(8*j+1, 2*j+3);
00271         faceset->coordIndex.set1Value(8*j+2, 2*j+1);
00272         faceset->coordIndex.set1Value(8*j+3, SO_END_FACE_INDEX);
00273         faceset->coordIndex.set1Value(8*j+4, 2*j);
00274         faceset->coordIndex.set1Value(8*j+5, 2*j+2);
00275         faceset->coordIndex.set1Value(8*j+6, 2*j+3);
00276         faceset->coordIndex.set1Value(8*j+7, SO_END_FACE_INDEX);
00277     }
00278 
00279     // set an own transparency type for this color bar only
00280     SoTransparencyType* ttype = new SoTransparencyType;
00281     ttype->value = SoGLRenderAction::DELAYED_BLEND;
00282     SoMaterial* mat = new SoMaterial;
00283     //mat->transparency = 0.3f;
00284     mat->diffuseColor.setNum(2*uCtColors);
00285     for ( int k=0; k<uCtColors; k++ )
00286     {
00287         App::Color col = model._pclColors[uCtColors-k-1];
00288         mat->diffuseColor.set1Value(2*k, col.r, col.g, col.b);
00289         mat->diffuseColor.set1Value(2*k+1, col.r, col.g, col.b);
00290     }
00291 
00292     SoMaterialBinding* matBinding = new SoMaterialBinding;
00293     matBinding->value = SoMaterialBinding::PER_VERTEX_INDEXED;
00294 
00295     // first clear the children
00296     if ( getNumChildren() > 0 )
00297         removeAllChildren();
00298     addChild(ttype);
00299     addChild(labels);
00300     addChild(coords);
00301     addChild(mat);
00302     addChild(matBinding);
00303     addChild(faceset);
00304 }
00305 
00306 bool SoFCColorGradient::isVisible (float fVal) const
00307 {
00308     if (_bOutInvisible == true)
00309     {
00310         float fMin, fMax;
00311         _cColGrad.getRange(fMin, fMax);
00312         if ((fVal > fMax) || (fVal < fMin))
00313             return false;
00314         else
00315             return true;
00316     }
00317 
00318     return true;
00319 }
00320 
00321 bool SoFCColorGradient::customize()
00322 {
00323     QWidget* parent = Gui::getMainWindow()->activeWindow();
00324     Gui::Dialog::DlgSettingsColorGradientImp dlg(parent);
00325 
00326     dlg.setColorModel( _cColGrad.getColorModelType() );
00327     dlg.setColorStyle( _cColGrad.getStyle() );
00328     dlg.setOutGrayed( _cColGrad.isOutsideGrayed() );
00329     dlg.setOutInvisible( _bOutInvisible );
00330     dlg.setNumberOfLabels( _cColGrad.getCountColors() );
00331     dlg.setNumberOfDecimals( _precision );
00332     float fMin, fMax;
00333     _cColGrad.getRange(fMin, fMax);
00334     dlg.setRange(fMin, fMax);
00335 
00336     QPoint pos(QCursor::pos());
00337     pos += QPoint((int)(-1.1*dlg.width()),(int)(-0.1*dlg.height()));
00338     dlg.move( pos );
00339 
00340     if ( dlg.exec() == QDialog::Accepted )
00341     {
00342         _cColGrad.setColorModel( dlg.colorModel() );
00343         _cColGrad.setStyle( dlg.colorStyle() );
00344         _cColGrad.setOutsideGrayed( dlg.isOutGrayed() );
00345         _bOutInvisible = dlg.isOutInvisible();
00346         _cColGrad.setCountColors( dlg.numberOfLabels() );
00347         _precision = dlg.numberOfDecimals();
00348         dlg.getRange( fMin, fMax );
00349         int dec = dlg.numberOfDecimals();
00350         setRange( fMin, fMax, dec );
00351         rebuildGradient();
00352 
00353         return true;
00354     }
00355 
00356     return false;
00357 }

Generated on Wed Nov 23 19:00:39 2011 for FreeCAD by  doxygen 1.6.1