OpenWalnut
1.2.5
|
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 }