OpenWalnut
1.4.0
|
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 00029 #include "WDendrogramGeode.h" 00030 00031 /** 00032 * Class implements a dendrogram as an osg geode 00033 */ 00034 WDendrogramGeode::WDendrogramGeode( WHierarchicalTree* tree, size_t cluster, bool useLevel, size_t minClusterSize, 00035 float xSize, float ySize, float xOffset, float yOffset ) : 00036 osg::Geode(), 00037 m_tree( tree ), 00038 m_rootCluster( cluster ), 00039 m_minClusterSize( minClusterSize ), 00040 m_xSize( xSize ), 00041 m_ySize( ySize ), 00042 m_xOff( xOffset ), 00043 m_yOff( yOffset ), 00044 m_useLevel( useLevel ) 00045 { 00046 create(); 00047 } 00048 00049 WDendrogramGeode::~WDendrogramGeode() 00050 { 00051 } 00052 00053 void WDendrogramGeode::create() 00054 { 00055 m_colors = osg::ref_ptr<osg::Vec4Array>( new osg::Vec4Array ); 00056 00057 m_vertexArray = new osg::Vec3Array; 00058 00059 m_lineArray = new osg::DrawElementsUInt( osg::PrimitiveSet::LINES, 0 ); 00060 00061 float xMax = static_cast<float>( m_tree->size( m_rootCluster ) - 1 ); 00062 00063 m_xMult = m_xSize / xMax; 00064 00065 00066 if( m_useLevel ) 00067 { 00068 layoutLevel( m_rootCluster, 0.0f, static_cast<float>( m_tree->size( m_rootCluster ) - 1 ) ); 00069 float yMax = m_tree->getLevel( m_rootCluster ); 00070 m_yMult = m_ySize / yMax; 00071 } 00072 else 00073 { 00074 layoutValue( m_rootCluster, 0.0f, static_cast<float>( m_tree->size( m_rootCluster ) - 1 ) ); 00075 m_yMult = m_ySize; 00076 } 00077 00078 for( size_t i = 0; i < m_vertexArray->size(); ++i ) 00079 { 00080 (*m_vertexArray)[i].x() = (*m_vertexArray)[i].x() * m_xMult + m_xOff; 00081 (*m_vertexArray)[i].y() = (*m_vertexArray)[i].y() * m_yMult + m_yOff; 00082 } 00083 00084 osg::ref_ptr< osg::Geometry > geometry = osg::ref_ptr< osg::Geometry >( new osg::Geometry() ); 00085 00086 geometry->setVertexArray( m_vertexArray ); 00087 00088 geometry->addPrimitiveSet( m_lineArray ); 00089 00090 geometry->setColorArray( m_colors ); 00091 geometry->setColorBinding( osg::Geometry::BIND_PER_VERTEX ); 00092 00093 osg::StateSet* state = geometry->getOrCreateStateSet(); 00094 state->setMode( GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED ); 00095 00096 addDrawable( geometry ); 00097 } 00098 00099 void WDendrogramGeode::layoutLevel( size_t cluster, float left, float right ) 00100 { 00101 float height = m_tree->getLevel( cluster ); 00102 00103 float size = right - left; 00104 00105 if( m_tree->getLevel( cluster ) > 0 ) 00106 { 00107 size_t leftCluster = m_tree->getChildren( cluster ).first; 00108 size_t rightCluster = m_tree->getChildren( cluster ).second; 00109 00110 float leftHeight = m_tree->getLevel( leftCluster ); 00111 float leftSize = static_cast<float>( m_tree->size( leftCluster ) ); 00112 00113 float rightHeight = m_tree->getLevel( rightCluster ); 00114 float rightSize = static_cast<float>( m_tree->size( rightCluster ) ); 00115 00116 if( ( leftSize >= m_minClusterSize ) && ( rightSize < m_minClusterSize ) ) 00117 //if( rightSize < 2 ) 00118 { 00119 // left cluster is much bigger, draw only left 00120 m_vertexArray->push_back( osg::Vec3( ( left + size / 2.0 ), height, 0 ) ); 00121 m_vertexArray->push_back( osg::Vec3( ( left + size / 2.0 ), leftHeight, 0 ) ); 00122 00123 m_lineArray->push_back( m_vertexArray->size() - 2 ); 00124 m_lineArray->push_back( m_vertexArray->size() - 1 ); 00125 00126 m_colors->push_back( m_tree->getColor( cluster ) ); 00127 m_colors->push_back( m_tree->getColor( cluster ) ); 00128 00129 layoutLevel( leftCluster, left, right ); 00130 } 00131 else if( ( rightSize >= m_minClusterSize ) && ( leftSize < m_minClusterSize ) ) 00132 //else if( leftSize < 2 ) 00133 { 00134 // right cluster is much bigger, draw only right 00135 m_vertexArray->push_back( osg::Vec3( ( left + size / 2.0 ), height, 0 ) ); 00136 m_vertexArray->push_back( osg::Vec3( ( left + size / 2.0 ), rightHeight, 0 ) ); 00137 00138 m_lineArray->push_back( m_vertexArray->size() - 2 ); 00139 m_lineArray->push_back( m_vertexArray->size() - 1 ); 00140 00141 m_colors->push_back( m_tree->getColor( cluster ) ); 00142 m_colors->push_back( m_tree->getColor( cluster ) ); 00143 00144 layoutLevel( rightCluster, left, right ); 00145 } 00146 else 00147 { 00148 float mult = size / ( leftSize + rightSize ); 00149 00150 m_vertexArray->push_back( osg::Vec3( ( left + leftSize * mult / 2.0 ), height, 0 ) ); 00151 m_vertexArray->push_back( osg::Vec3( ( right - rightSize * mult / 2.0 ), height, 0 ) ); 00152 00153 m_lineArray->push_back( m_vertexArray->size() - 2 ); 00154 m_lineArray->push_back( m_vertexArray->size() - 1 ); 00155 00156 m_vertexArray->push_back( osg::Vec3( ( left + leftSize * mult / 2.0 ), leftHeight, 0 ) ); 00157 m_vertexArray->push_back( osg::Vec3( ( right - rightSize * mult / 2.0 ), rightHeight, 0 ) ); 00158 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 m_colors->push_back( m_tree->getColor( cluster ) ); 00163 00164 m_lineArray->push_back( m_vertexArray->size() - 4 ); 00165 m_lineArray->push_back( m_vertexArray->size() - 2 ); 00166 m_lineArray->push_back( m_vertexArray->size() - 3 ); 00167 m_lineArray->push_back( m_vertexArray->size() - 1 ); 00168 00169 layoutLevel( leftCluster, left, left + leftSize * mult ); 00170 layoutLevel( rightCluster, right - rightSize * mult, right ); 00171 } 00172 } 00173 } 00174 00175 void WDendrogramGeode::layoutValue( size_t cluster, float left, float right ) 00176 { 00177 float height = m_tree->getCustomData( cluster ); 00178 00179 float size = right - left; 00180 00181 if( m_tree->getLevel( cluster ) > 0 ) 00182 { 00183 size_t leftCluster = m_tree->getChildren( cluster ).first; 00184 size_t rightCluster = m_tree->getChildren( cluster ).second; 00185 00186 float leftHeight = m_tree->getCustomData( leftCluster ); 00187 float leftSize = static_cast<float>( m_tree->size( leftCluster ) ); 00188 00189 float rightHeight = m_tree->getCustomData( rightCluster ); 00190 float rightSize = static_cast<float>( m_tree->size( rightCluster ) ); 00191 00192 if( ( leftSize >= m_minClusterSize ) && ( rightSize < m_minClusterSize ) ) 00193 //if( rightSize < 2 ) 00194 { 00195 // left cluster is much bigger, draw only left 00196 m_vertexArray->push_back( osg::Vec3( ( left + size / 2.0 ), height, 0 ) ); 00197 m_vertexArray->push_back( osg::Vec3( ( left + size / 2.0 ), leftHeight, 0 ) ); 00198 00199 m_lineArray->push_back( m_vertexArray->size() - 2 ); 00200 m_lineArray->push_back( m_vertexArray->size() - 1 ); 00201 00202 m_colors->push_back( m_tree->getColor( cluster ) ); 00203 m_colors->push_back( m_tree->getColor( cluster ) ); 00204 00205 layoutValue( leftCluster, left, right ); 00206 } 00207 else if( ( rightSize >= m_minClusterSize ) && ( leftSize < m_minClusterSize ) ) 00208 //else if( leftSize < 2 ) 00209 { 00210 // right cluster is much bigger, draw only right 00211 m_vertexArray->push_back( osg::Vec3( ( left + size / 2.0 ), height, 0 ) ); 00212 m_vertexArray->push_back( osg::Vec3( ( left + size / 2.0 ), rightHeight, 0 ) ); 00213 00214 m_lineArray->push_back( m_vertexArray->size() - 2 ); 00215 m_lineArray->push_back( m_vertexArray->size() - 1 ); 00216 00217 m_colors->push_back( m_tree->getColor( cluster ) ); 00218 m_colors->push_back( m_tree->getColor( cluster ) ); 00219 00220 layoutValue( rightCluster, left, right ); 00221 } 00222 else 00223 { 00224 float mult = size / ( leftSize + rightSize ); 00225 00226 m_vertexArray->push_back( osg::Vec3( ( left + leftSize * mult / 2.0 ), height, 0 ) ); 00227 m_vertexArray->push_back( osg::Vec3( ( right - rightSize * mult / 2.0 ), height, 0 ) ); 00228 00229 m_lineArray->push_back( m_vertexArray->size() - 2 ); 00230 m_lineArray->push_back( m_vertexArray->size() - 1 ); 00231 00232 m_vertexArray->push_back( osg::Vec3( ( left + leftSize * mult / 2.0 ), leftHeight, 0 ) ); 00233 m_vertexArray->push_back( osg::Vec3( ( right - rightSize * mult / 2.0 ), rightHeight, 0 ) ); 00234 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 m_colors->push_back( m_tree->getColor( cluster ) ); 00239 00240 m_lineArray->push_back( m_vertexArray->size() - 4 ); 00241 m_lineArray->push_back( m_vertexArray->size() - 2 ); 00242 m_lineArray->push_back( m_vertexArray->size() - 3 ); 00243 m_lineArray->push_back( m_vertexArray->size() - 1 ); 00244 00245 layoutValue( leftCluster, left, left + leftSize * mult ); 00246 layoutValue( rightCluster, right - rightSize * mult, right ); 00247 } 00248 } 00249 } 00250 00251 size_t WDendrogramGeode::getClickedCluster( int xClick, int yClick ) 00252 { 00253 m_xClicked = ( xClick - m_xOff ) / m_xSize * ( m_tree->size( m_rootCluster ) ); 00254 00255 m_clickedCluster = m_rootCluster; 00256 00257 if( m_useLevel ) 00258 { 00259 m_yClicked = ( yClick - m_yOff ) / m_ySize * ( m_tree->getLevel( m_rootCluster ) ); 00260 getClickClusterRecursive( m_rootCluster, 0.0f, static_cast<float>( m_tree->size( m_rootCluster ) - 1 ) ); 00261 } 00262 else 00263 { 00264 m_yClicked = ( yClick - m_yOff ); 00265 getClickClusterRecursive2( m_rootCluster, 0.0f, static_cast<float>( m_tree->size( m_rootCluster ) - 1 ) ); 00266 } 00267 00268 return m_clickedCluster; 00269 } 00270 00271 void WDendrogramGeode::getClickClusterRecursive2( size_t cluster, float left, float right ) 00272 { 00273 int height = static_cast<int>( m_tree->getCustomData( cluster ) * m_ySize ); 00274 00275 if( abs( height - m_yClicked ) < 2 ) 00276 { 00277 m_clickedCluster = cluster; 00278 return; 00279 } 00280 00281 int size = right - left; 00282 00283 if( m_tree->getLevel( cluster ) > 0 ) 00284 { 00285 size_t leftCluster = m_tree->getChildren( cluster ).first; 00286 size_t rightCluster = m_tree->getChildren( cluster ).second; 00287 00288 float leftSize = static_cast<float>( m_tree->size( leftCluster ) ); 00289 float rightSize = static_cast<float>( m_tree->size( rightCluster ) ); 00290 00291 if( ( leftSize >= m_minClusterSize ) && ( rightSize < m_minClusterSize ) ) 00292 { 00293 // left cluster is much bigger, draw only left 00294 getClickClusterRecursive2( leftCluster, left, right ); 00295 } 00296 else if( ( rightSize >= m_minClusterSize ) && ( leftSize < m_minClusterSize ) ) 00297 { 00298 // right cluster is much bigger, draw only right 00299 getClickClusterRecursive2( rightCluster, left, right ); 00300 } 00301 else 00302 { 00303 float mult = size / ( leftSize + rightSize ); 00304 00305 if( m_xClicked < left + leftSize * mult ) 00306 { 00307 getClickClusterRecursive2( leftCluster, left, left + leftSize * mult ); 00308 } 00309 else 00310 { 00311 getClickClusterRecursive2( rightCluster, right - rightSize * mult, right ); 00312 } 00313 } 00314 } 00315 } 00316 00317 void WDendrogramGeode::getClickClusterRecursive( size_t cluster, float left, float right ) 00318 { 00319 int height = m_tree->getLevel( cluster ); 00320 00321 if( height == m_yClicked ) 00322 { 00323 m_clickedCluster = cluster; 00324 return; 00325 } 00326 00327 int size = right - left; 00328 00329 if( m_tree->getLevel( cluster ) > 0 ) 00330 { 00331 size_t leftCluster = m_tree->getChildren( cluster ).first; 00332 size_t rightCluster = m_tree->getChildren( cluster ).second; 00333 00334 float leftSize = static_cast<float>( m_tree->size( leftCluster ) ); 00335 float rightSize = static_cast<float>( m_tree->size( rightCluster ) ); 00336 00337 if( ( leftSize >= m_minClusterSize ) && ( rightSize < m_minClusterSize ) ) 00338 { 00339 // left cluster is much bigger, draw only left 00340 getClickClusterRecursive( leftCluster, left, right ); 00341 } 00342 else if( ( rightSize >= m_minClusterSize ) && ( leftSize < m_minClusterSize ) ) 00343 { 00344 // right cluster is much bigger, draw only right 00345 getClickClusterRecursive( rightCluster, left, right ); 00346 } 00347 else 00348 { 00349 float mult = size / ( leftSize + rightSize ); 00350 00351 if( m_xClicked < left + leftSize * mult ) 00352 { 00353 getClickClusterRecursive( leftCluster, left, left + leftSize * mult ); 00354 } 00355 else 00356 { 00357 getClickClusterRecursive( rightCluster, right - rightSize * mult, right ); 00358 } 00359 } 00360 } 00361 }