WDendrogramGeode.cpp

00001 //---------------------------------------------------------------------------
00002 //
00003 // Project: OpenWalnut ( http://www.openwalnut.org )
00004 //
00005 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
00006 // For more information see http://www.openwalnut.org/copying
00007 //
00008 // This file is part of OpenWalnut.
00009 //
00010 // OpenWalnut is free software: you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as published by
00012 // the Free Software Foundation, either version 3 of the License, or
00013 // (at your option) any later version.
00014 //
00015 // OpenWalnut is distributed in the hope that it will be useful,
00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 // GNU Lesser General Public License for more details.
00019 //
00020 // You should have received a copy of the GNU Lesser General Public License
00021 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
00022 //
00023 //---------------------------------------------------------------------------
00024 
00025 #include <iostream>
00026 
00027 #include "../../graphicsEngine/WGEUtils.h"
00028 #include "WDendrogramGeode.h"
00029 
00030 /**
00031  * Class implements a dendrogram as an osg geode
00032  */
00033 WDendrogramGeode::WDendrogramGeode( WHierarchicalTree* tree, size_t cluster, bool useLevel, size_t minClusterSize,
00034                                     float xSize, float ySize, float xOffset, float yOffset ) :
00035     osg::Geode(),
00036     m_tree( tree ),
00037     m_rootCluster( cluster ),
00038     m_minClusterSize( minClusterSize ),
00039     m_xSize( xSize ),
00040     m_ySize( ySize ),
00041     m_xOff( xOffset ),
00042     m_yOff( yOffset ),
00043     m_useLevel( useLevel )
00044 {
00045     create();
00046 }
00047 
00048 WDendrogramGeode::~WDendrogramGeode()
00049 {
00050 }
00051 
00052 void WDendrogramGeode::create()
00053 {
00054     m_colors = osg::ref_ptr<osg::Vec4Array>( new osg::Vec4Array );
00055 
00056     m_vertexArray = new osg::Vec3Array;
00057 
00058     m_lineArray = new osg::DrawElementsUInt( osg::PrimitiveSet::LINES, 0 );
00059 
00060     float xMax = static_cast<float>( m_tree->size( m_rootCluster ) - 1 );
00061 
00062     m_xMult = m_xSize / xMax;
00063 
00064 
00065     if( m_useLevel )
00066     {
00067         layoutLevel( m_rootCluster, 0.0f, static_cast<float>( m_tree->size( m_rootCluster ) - 1 ) );
00068         float yMax = m_tree->getLevel( m_rootCluster );
00069         m_yMult = m_ySize / yMax;
00070     }
00071     else
00072     {
00073         layoutValue( m_rootCluster, 0.0f, static_cast<float>( m_tree->size( m_rootCluster ) - 1 ) );
00074         m_yMult = m_ySize;
00075     }
00076 
00077     for( size_t i = 0; i < m_vertexArray->size(); ++i )
00078     {
00079         (*m_vertexArray)[i].x() = (*m_vertexArray)[i].x() * m_xMult + m_xOff;
00080         (*m_vertexArray)[i].y() = (*m_vertexArray)[i].y() * m_yMult + m_yOff;
00081     }
00082 
00083     osg::ref_ptr< osg::Geometry > geometry = osg::ref_ptr< osg::Geometry >( new osg::Geometry() );
00084 
00085     geometry->setVertexArray( m_vertexArray );
00086 
00087     geometry->addPrimitiveSet( m_lineArray );
00088 
00089     geometry->setColorArray( m_colors );
00090     geometry->setColorBinding( osg::Geometry::BIND_PER_VERTEX );
00091 
00092     osg::StateSet* state = geometry->getOrCreateStateSet();
00093     state->setMode( GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED );
00094 
00095     addDrawable( geometry );
00096 }
00097 
00098 void WDendrogramGeode::layoutLevel( size_t cluster, float left, float right )
00099 {
00100     float height = m_tree->getLevel( cluster );
00101 
00102     float size = right - left;
00103 
00104     if( m_tree->getLevel( cluster ) > 0 )
00105     {
00106         size_t leftCluster = m_tree->getChildren( cluster ).first;
00107         size_t rightCluster = m_tree->getChildren( cluster ).second;
00108 
00109         float leftHeight = m_tree->getLevel( leftCluster );
00110         float leftSize = static_cast<float>( m_tree->size( leftCluster ) );
00111 
00112         float rightHeight = m_tree->getLevel( rightCluster );
00113         float rightSize = static_cast<float>( m_tree->size( rightCluster ) );
00114 
00115         if( ( leftSize >= m_minClusterSize ) &&  ( rightSize < m_minClusterSize ) )
00116         //if( rightSize < 2 )
00117         {
00118             // left cluster is much bigger, draw only left
00119             m_vertexArray->push_back( osg::Vec3( ( left + size / 2.0 ), height, 0 ) );
00120             m_vertexArray->push_back( osg::Vec3( ( left + size / 2.0 ), leftHeight, 0 ) );
00121 
00122             m_lineArray->push_back( m_vertexArray->size() - 2 );
00123             m_lineArray->push_back( m_vertexArray->size() - 1 );
00124 
00125             m_colors->push_back( m_tree->getColor( cluster ) );
00126             m_colors->push_back( m_tree->getColor( cluster ) );
00127 
00128             layoutLevel( leftCluster, left, right );
00129         }
00130         else if( ( rightSize >= m_minClusterSize ) &&  ( leftSize < m_minClusterSize ) )
00131         //else if( leftSize < 2 )
00132         {
00133             // right cluster is much bigger, draw only right
00134             m_vertexArray->push_back( osg::Vec3( ( left + size / 2.0 ), height, 0 ) );
00135             m_vertexArray->push_back( osg::Vec3( ( left + size / 2.0 ), rightHeight, 0 ) );
00136 
00137             m_lineArray->push_back( m_vertexArray->size() - 2 );
00138             m_lineArray->push_back( m_vertexArray->size() - 1 );
00139 
00140             m_colors->push_back( m_tree->getColor( cluster ) );
00141             m_colors->push_back( m_tree->getColor( cluster ) );
00142 
00143             layoutLevel( rightCluster, left, right );
00144         }
00145         else
00146         {
00147             float mult = size / ( leftSize + rightSize );
00148 
00149             m_vertexArray->push_back( osg::Vec3( ( left  + leftSize * mult  / 2.0 ), height, 0 ) );
00150             m_vertexArray->push_back( osg::Vec3( ( right - rightSize * mult / 2.0 ), height, 0 ) );
00151 
00152             m_lineArray->push_back( m_vertexArray->size() - 2 );
00153             m_lineArray->push_back( m_vertexArray->size() - 1 );
00154 
00155             m_vertexArray->push_back( osg::Vec3( ( left  + leftSize * mult  / 2.0 ), leftHeight, 0 ) );
00156             m_vertexArray->push_back( osg::Vec3( ( right - rightSize * mult / 2.0 ), rightHeight, 0 ) );
00157 
00158             m_colors->push_back( m_tree->getColor( cluster ) );
00159             m_colors->push_back( m_tree->getColor( cluster ) );
00160             m_colors->push_back( m_tree->getColor( cluster ) );
00161             m_colors->push_back( m_tree->getColor( cluster ) );
00162 
00163             m_lineArray->push_back( m_vertexArray->size() - 4 );
00164             m_lineArray->push_back( m_vertexArray->size() - 2 );
00165             m_lineArray->push_back( m_vertexArray->size() - 3 );
00166             m_lineArray->push_back( m_vertexArray->size() - 1 );
00167 
00168             layoutLevel( leftCluster, left, left + leftSize * mult );
00169             layoutLevel( rightCluster, right - rightSize * mult, right );
00170         }
00171     }
00172 }
00173 
00174 void WDendrogramGeode::layoutValue( size_t cluster, float left, float right )
00175 {
00176     float height = m_tree->getCustomData( cluster );
00177 
00178     float size = right - left;
00179 
00180     if( m_tree->getLevel( cluster ) > 0 )
00181     {
00182         size_t leftCluster = m_tree->getChildren( cluster ).first;
00183         size_t rightCluster = m_tree->getChildren( cluster ).second;
00184 
00185         float leftHeight = m_tree->getCustomData( leftCluster );
00186         float leftSize = static_cast<float>( m_tree->size( leftCluster ) );
00187 
00188         float rightHeight = m_tree->getCustomData( rightCluster );
00189         float rightSize = static_cast<float>( m_tree->size( rightCluster ) );
00190 
00191         if( ( leftSize >= m_minClusterSize ) &&  ( rightSize < m_minClusterSize ) )
00192         //if( rightSize < 2 )
00193         {
00194             // left cluster is much bigger, draw only left
00195             m_vertexArray->push_back( osg::Vec3( ( left + size / 2.0 ), height, 0 ) );
00196             m_vertexArray->push_back( osg::Vec3( ( left + size / 2.0 ), leftHeight, 0 ) );
00197 
00198             m_lineArray->push_back( m_vertexArray->size() - 2 );
00199             m_lineArray->push_back( m_vertexArray->size() - 1 );
00200 
00201             m_colors->push_back( m_tree->getColor( cluster ) );
00202             m_colors->push_back( m_tree->getColor( cluster ) );
00203 
00204             layoutValue( leftCluster, left, right );
00205         }
00206         else if( ( rightSize >= m_minClusterSize ) &&  ( leftSize < m_minClusterSize ) )
00207         //else if( leftSize < 2 )
00208         {
00209             // right cluster is much bigger, draw only right
00210             m_vertexArray->push_back( osg::Vec3( ( left + size / 2.0 ), height, 0 ) );
00211             m_vertexArray->push_back( osg::Vec3( ( left + size / 2.0 ), rightHeight, 0 ) );
00212 
00213             m_lineArray->push_back( m_vertexArray->size() - 2 );
00214             m_lineArray->push_back( m_vertexArray->size() - 1 );
00215 
00216             m_colors->push_back( m_tree->getColor( cluster ) );
00217             m_colors->push_back( m_tree->getColor( cluster ) );
00218 
00219             layoutValue( rightCluster, left, right );
00220         }
00221         else
00222         {
00223             float mult = size / ( leftSize + rightSize );
00224 
00225             m_vertexArray->push_back( osg::Vec3( ( left  + leftSize * mult  / 2.0 ), height, 0 ) );
00226             m_vertexArray->push_back( osg::Vec3( ( right - rightSize * mult / 2.0 ), height, 0 ) );
00227 
00228             m_lineArray->push_back( m_vertexArray->size() - 2 );
00229             m_lineArray->push_back( m_vertexArray->size() - 1 );
00230 
00231             m_vertexArray->push_back( osg::Vec3( ( left  + leftSize * mult  / 2.0 ), leftHeight, 0 ) );
00232             m_vertexArray->push_back( osg::Vec3( ( right - rightSize * mult / 2.0 ), rightHeight, 0 ) );
00233 
00234             m_colors->push_back( m_tree->getColor( cluster ) );
00235             m_colors->push_back( m_tree->getColor( cluster ) );
00236             m_colors->push_back( m_tree->getColor( cluster ) );
00237             m_colors->push_back( m_tree->getColor( cluster ) );
00238 
00239             m_lineArray->push_back( m_vertexArray->size() - 4 );
00240             m_lineArray->push_back( m_vertexArray->size() - 2 );
00241             m_lineArray->push_back( m_vertexArray->size() - 3 );
00242             m_lineArray->push_back( m_vertexArray->size() - 1 );
00243 
00244             layoutValue( leftCluster, left, left + leftSize * mult );
00245             layoutValue( rightCluster, right - rightSize * mult, right );
00246         }
00247     }
00248 }
00249 
00250 size_t WDendrogramGeode::getClickedCluster( int xClick, int yClick )
00251 {
00252     m_xClicked = ( xClick - m_xOff ) / m_xSize * ( m_tree->size( m_rootCluster ) );
00253 
00254     m_clickedCluster = m_rootCluster;
00255 
00256     if( m_useLevel )
00257     {
00258         m_yClicked = ( yClick - m_yOff ) / m_ySize * ( m_tree->getLevel( m_rootCluster ) );
00259         getClickClusterRecursive( m_rootCluster, 0.0f, static_cast<float>( m_tree->size( m_rootCluster ) - 1 ) );
00260     }
00261     else
00262     {
00263         m_yClicked = ( yClick - m_yOff );
00264         getClickClusterRecursive2( m_rootCluster, 0.0f, static_cast<float>( m_tree->size( m_rootCluster ) - 1 ) );
00265     }
00266 
00267     return m_clickedCluster;
00268 }
00269 
00270 void WDendrogramGeode::getClickClusterRecursive2( size_t cluster, float left, float right )
00271 {
00272     int height = static_cast<int>( m_tree->getCustomData( cluster ) * m_ySize );
00273 
00274     if( abs( height - m_yClicked ) < 2 )
00275     {
00276         m_clickedCluster = cluster;
00277         return;
00278     }
00279 
00280     int size = right - left;
00281 
00282     if( m_tree->getLevel( cluster ) > 0 )
00283     {
00284         size_t leftCluster = m_tree->getChildren( cluster ).first;
00285         size_t rightCluster = m_tree->getChildren( cluster ).second;
00286 
00287         float leftSize = static_cast<float>( m_tree->size( leftCluster ) );
00288         float rightSize = static_cast<float>( m_tree->size( rightCluster ) );
00289 
00290         if( ( leftSize >= m_minClusterSize ) &&  ( rightSize < m_minClusterSize ) )
00291         {
00292             // left cluster is much bigger, draw only left
00293             getClickClusterRecursive2( leftCluster, left, right );
00294         }
00295         else if( ( rightSize >= m_minClusterSize ) &&  ( leftSize < m_minClusterSize ) )
00296         {
00297             // right cluster is much bigger, draw only right
00298             getClickClusterRecursive2( rightCluster, left, right );
00299         }
00300         else
00301         {
00302             float mult = size / ( leftSize + rightSize );
00303 
00304             if( m_xClicked < left + leftSize * mult )
00305             {
00306                 getClickClusterRecursive2( leftCluster, left, left + leftSize * mult );
00307             }
00308             else
00309             {
00310                 getClickClusterRecursive2( rightCluster, right - rightSize * mult, right );
00311             }
00312         }
00313     }
00314 }
00315 
00316 void WDendrogramGeode::getClickClusterRecursive( size_t cluster, float left, float right )
00317 {
00318     int height = m_tree->getLevel( cluster );
00319 
00320     if( height == m_yClicked )
00321     {
00322         m_clickedCluster = cluster;
00323         return;
00324     }
00325 
00326     int size = right - left;
00327 
00328     if( m_tree->getLevel( cluster ) > 0 )
00329     {
00330         size_t leftCluster = m_tree->getChildren( cluster ).first;
00331         size_t rightCluster = m_tree->getChildren( cluster ).second;
00332 
00333         float leftSize = static_cast<float>( m_tree->size( leftCluster ) );
00334         float rightSize = static_cast<float>( m_tree->size( rightCluster ) );
00335 
00336         if( ( leftSize >= m_minClusterSize ) &&  ( rightSize < m_minClusterSize ) )
00337         {
00338             // left cluster is much bigger, draw only left
00339             getClickClusterRecursive( leftCluster, left, right );
00340         }
00341         else if( ( rightSize >= m_minClusterSize ) &&  ( leftSize < m_minClusterSize ) )
00342         {
00343             // right cluster is much bigger, draw only right
00344             getClickClusterRecursive( rightCluster, left, right );
00345         }
00346         else
00347         {
00348             float mult = size / ( leftSize + rightSize );
00349 
00350             if( m_xClicked < left + leftSize * mult )
00351             {
00352                 getClickClusterRecursive( leftCluster, left, left + leftSize * mult );
00353             }
00354             else
00355             {
00356                 getClickClusterRecursive( rightCluster, right - rightSize * mult, right );
00357             }
00358         }
00359     }
00360 }
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends