00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <iostream>
00026
00027 #include "../../graphicsEngine/WGEUtils.h"
00028 #include "WDendrogramGeode.h"
00029
00030
00031
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
00117 {
00118
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
00132 {
00133
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
00193 {
00194
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
00208 {
00209
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
00293 getClickClusterRecursive2( leftCluster, left, right );
00294 }
00295 else if( ( rightSize >= m_minClusterSize ) && ( leftSize < m_minClusterSize ) )
00296 {
00297
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
00339 getClickClusterRecursive( leftCluster, left, right );
00340 }
00341 else if( ( rightSize >= m_minClusterSize ) && ( leftSize < m_minClusterSize ) )
00342 {
00343
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 }