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 <algorithm> 00026 #include <iostream> 00027 #include <string> 00028 #include <utility> 00029 #include <vector> 00030 00031 // Use filesystem version 2 for compatibility with newer boost versions. 00032 #ifndef BOOST_FILESYSTEM_VERSION 00033 #define BOOST_FILESYSTEM_VERSION 2 00034 #endif 00035 #include <boost/filesystem/fstream.hpp> 00036 #include <boost/lexical_cast.hpp> 00037 00038 #include "../common/datastructures/WFiber.h" 00039 #include "../common/WBoundingBox.h" 00040 #include "../common/WColor.h" 00041 #include "../common/WLogger.h" 00042 #include "../common/WPredicateHelper.h" 00043 #include "../common/WPropertyHelper.h" 00044 #include "../graphicsEngine/WGEUtils.h" 00045 #include "exceptions/WDHNoSuchDataSet.h" 00046 #include "WCreateColorArraysThread.h" 00047 #include "WDataSet.h" 00048 #include "WDataSetFibers.h" 00049 00050 // prototype instance as singleton 00051 boost::shared_ptr< WPrototyped > WDataSetFibers::m_prototype = boost::shared_ptr< WPrototyped >(); 00052 00053 WDataSetFibers::WDataSetFibers() 00054 : WDataSet() 00055 { 00056 // default constructor used by the prototype mechanism 00057 } 00058 00059 WDataSetFibers::WDataSetFibers( WDataSetFibers::VertexArray vertices, 00060 WDataSetFibers::IndexArray lineStartIndexes, 00061 WDataSetFibers::LengthArray lineLengths, 00062 WDataSetFibers::IndexArray verticesReverse, 00063 WBoundingBox boundingBox ) 00064 : WDataSet(), 00065 m_vertices( vertices ), 00066 m_lineStartIndexes( lineStartIndexes ), 00067 m_lineLengths( lineLengths ), 00068 m_verticesReverse( verticesReverse ), 00069 m_bb( boundingBox ) 00070 { 00071 WAssert( m_vertices->size() % 3 == 0, "Invalid vertex array." ); 00072 init(); 00073 } 00074 00075 WDataSetFibers::WDataSetFibers( WDataSetFibers::VertexArray vertices, 00076 WDataSetFibers::IndexArray lineStartIndexes, 00077 WDataSetFibers::LengthArray lineLengths, 00078 WDataSetFibers::IndexArray verticesReverse ) 00079 : WDataSet(), 00080 m_vertices( vertices ), 00081 m_lineStartIndexes( lineStartIndexes ), 00082 m_lineLengths( lineLengths ), 00083 m_verticesReverse( verticesReverse ) 00084 { 00085 WAssert( m_vertices->size() % 3 == 0, "Invalid vertex array." ); 00086 // determine bounding box 00087 for( size_t i = 0; i < vertices->size()/3; ++i ) 00088 { 00089 m_bb.expandBy( (*vertices)[ 3 * i + 0 ], (*vertices)[ 3 * i + 1 ], (*vertices)[ 3 * i + 2 ] ); 00090 } 00091 // remaining initilisation 00092 init(); 00093 } 00094 00095 void WDataSetFibers::init() 00096 { 00097 size_t size = m_vertices->size(); 00098 m_tangents = boost::shared_ptr< std::vector< float > >( new std::vector<float>( size ) ); 00099 00100 boost::shared_ptr< std::vector< float > > globalColors = boost::shared_ptr< std::vector< float > >( new std::vector<float>( size ) ); 00101 boost::shared_ptr< std::vector< float > > localColors = boost::shared_ptr< std::vector< float > >( new std::vector<float>( size ) ); 00102 boost::shared_ptr< std::vector< float > > customColors = boost::shared_ptr< std::vector< float > >( new std::vector<float>( size ) ); 00103 00104 00105 // TODO(all): use the new WThreadedJobs functionality 00106 WCreateColorArraysThread* t1 = new WCreateColorArraysThread( 0, m_lineLengths->size()/4, m_vertices, 00107 m_lineStartIndexes, m_lineLengths, globalColors, localColors, m_tangents ); 00108 WCreateColorArraysThread* t2 = new WCreateColorArraysThread( m_lineLengths->size()/4+1, m_lineLengths->size()/2, m_vertices, 00109 m_lineStartIndexes, m_lineLengths, globalColors, localColors, m_tangents ); 00110 WCreateColorArraysThread* t3 = new WCreateColorArraysThread( m_lineLengths->size()/2+1, m_lineLengths->size()/4*3, m_vertices, 00111 m_lineStartIndexes, m_lineLengths, globalColors, localColors, m_tangents ); 00112 WCreateColorArraysThread* t4 = new WCreateColorArraysThread( m_lineLengths->size()/4*3+1, m_lineLengths->size()-1, m_vertices, 00113 m_lineStartIndexes, m_lineLengths, globalColors, localColors, m_tangents ); 00114 t1->run(); 00115 t2->run(); 00116 t3->run(); 00117 t4->run(); 00118 00119 t1->wait(); 00120 t2->wait(); 00121 t3->wait(); 00122 t4->wait(); 00123 00124 delete t1; 00125 delete t2; 00126 delete t3; 00127 delete t4; 00128 00129 // add both arrays to m_colors 00130 m_colors = boost::shared_ptr< WItemSelection >( new WItemSelection() ); 00131 m_colors->push_back( boost::shared_ptr< WItemSelectionItem >( 00132 new ColorScheme( "Global Color", "Colors direction by using start and end vertex per fiber.", NULL, globalColors, ColorScheme::RGB ) 00133 ) 00134 ); 00135 m_colors->push_back( boost::shared_ptr< WItemSelectionItem >( 00136 new ColorScheme( "Local Color", "Colors direction by using start and end vertex per segment.", NULL, localColors, ColorScheme::RGB ) 00137 ) 00138 ); 00139 00140 for( size_t i = 0; i < size; ++i ) 00141 { 00142 ( *customColors )[i] = ( *globalColors )[i]; 00143 } 00144 m_colors->push_back( boost::shared_ptr< WItemSelectionItem >( 00145 new ColorScheme( "Custom Color", "Colors copied from the global colors, will be used for bundle coloring.", 00146 NULL, customColors, ColorScheme::RGB ) 00147 ) 00148 ); 00149 00150 // the colors can be selected by properties 00151 m_colorProp = m_properties->addProperty( "Color Scheme", "Determines the coloring scheme to use for this data.", m_colors->getSelectorFirst() ); 00152 WPropertyHelper::PC_SELECTONLYONE::addTo( m_colorProp ); 00153 WPropertyHelper::PC_NOTEMPTY::addTo( m_colorProp ); 00154 } 00155 00156 bool WDataSetFibers::isTexture() const 00157 { 00158 return false; 00159 } 00160 00161 size_t WDataSetFibers::size() const 00162 { 00163 return m_lineStartIndexes->size(); 00164 } 00165 00166 const std::string WDataSetFibers::getName() const 00167 { 00168 return "WDataSetFibers"; 00169 } 00170 00171 const std::string WDataSetFibers::getDescription() const 00172 { 00173 return "Contains tracked fiber data."; 00174 } 00175 00176 boost::shared_ptr< WPrototyped > WDataSetFibers::getPrototype() 00177 { 00178 if( !m_prototype ) 00179 { 00180 m_prototype = boost::shared_ptr< WPrototyped >( new WDataSetFibers() ); 00181 } 00182 00183 return m_prototype; 00184 } 00185 00186 WDataSetFibers::VertexArray WDataSetFibers::getVertices() const 00187 { 00188 return m_vertices; 00189 } 00190 00191 WDataSetFibers::IndexArray WDataSetFibers::getLineStartIndexes() const 00192 { 00193 return m_lineStartIndexes; 00194 } 00195 00196 WDataSetFibers::LengthArray WDataSetFibers::getLineLengths() const 00197 { 00198 return m_lineLengths; 00199 } 00200 00201 WDataSetFibers::IndexArray WDataSetFibers::getVerticesReverse() const 00202 { 00203 return m_verticesReverse; 00204 } 00205 00206 WDataSetFibers::TangentArray WDataSetFibers::getTangents() const 00207 { 00208 return m_tangents; 00209 } 00210 00211 WDataSetFibers::ColorArray WDataSetFibers::getGlobalColors() const 00212 { 00213 return boost::shared_static_cast< const ColorScheme >( ( *m_colors )[0] )->getColor(); 00214 } 00215 00216 WDataSetFibers::ColorArray WDataSetFibers::getLocalColors() const 00217 { 00218 return boost::shared_static_cast< const ColorScheme >( ( *m_colors )[1] )->getColor(); 00219 } 00220 00221 void WDataSetFibers::addColorScheme( WDataSetFibers::ColorArray colors, std::string name, std::string description ) 00222 { 00223 ColorScheme::ColorMode mode = ColorScheme::GRAY; 00224 00225 // number of verts is needed to distinguish color mode. 00226 size_t verts = m_vertices->size() / 3; 00227 size_t cols = colors->size(); 00228 if( cols / verts == 3 ) 00229 { 00230 mode = ColorScheme::RGB; 00231 } 00232 else if( cols / verts == 4 ) 00233 { 00234 mode = ColorScheme::RGBA; 00235 } 00236 00237 m_colors->push_back( boost::shared_ptr< WItemSelectionItem >( 00238 new ColorScheme( name, description, NULL, colors, mode ) 00239 ) 00240 ); 00241 } 00242 00243 void WDataSetFibers::removeColorScheme( WDataSetFibers::ColorArray colors ) 00244 { 00245 // this is nearly the same like std::remove_if 00246 WItemSelection::WriteTicket l = m_colors->getWriteTicket(); 00247 00248 WItemSelection::Iterator i = l->get().begin(); 00249 while( i != l->get().end() ) 00250 { 00251 if( boost::shared_static_cast< const ColorScheme >( *i )->getColor() == colors ) 00252 { 00253 i = l->get().erase( i ); 00254 } 00255 else 00256 { 00257 ++i; 00258 } 00259 } 00260 } 00261 00262 void WDataSetFibers::replaceColorScheme( WDataSetFibers::ColorArray oldColors, WDataSetFibers::ColorArray newColors ) 00263 { 00264 // this is nearly the same as std::replace_if 00265 WItemSelection::WriteTicket l = m_colors->getWriteTicket(); 00266 for( WItemSelection::Iterator i = l->get().begin(); i != l->get().end(); ++i ) 00267 { 00268 boost::shared_ptr< ColorScheme > ci = boost::shared_static_cast< ColorScheme >( *i ); 00269 if(ci->getColor() == oldColors ) 00270 { 00271 ci->setColor( newColors ); 00272 } 00273 } 00274 } 00275 00276 const boost::shared_ptr< WDataSetFibers::ColorScheme > WDataSetFibers::getColorScheme( std::string name ) const 00277 { 00278 WItemSelection::ReadTicket l = m_colors->getReadTicket(); 00279 WItemSelection::ConstIterator i = std::find_if( l->get().begin(), l->get().end(), 00280 WPredicateHelper::Name< boost::shared_ptr< WItemSelectionItem > >( name ) 00281 ); 00282 if( i == l->get().end() ) 00283 { 00284 throw WDHNoSuchDataSet( std::string( "Color scheme with specified name could not be found." ) ); 00285 } 00286 00287 return boost::shared_static_cast< ColorScheme >( *i ); 00288 } 00289 00290 const boost::shared_ptr< WDataSetFibers::ColorScheme > WDataSetFibers::getColorScheme( size_t idx ) const 00291 { 00292 WItemSelection::ReadTicket l = m_colors->getReadTicket(); 00293 return boost::shared_static_cast< ColorScheme >( l->get()[ idx ] ); 00294 } 00295 00296 const boost::shared_ptr< WDataSetFibers::ColorScheme > WDataSetFibers::getColorScheme() const 00297 { 00298 return boost::shared_static_cast< ColorScheme >( m_colorProp->get().at( 0 ) ); 00299 } 00300 00301 const WPropSelection WDataSetFibers::getColorSchemeProperty() const 00302 { 00303 return m_colorProp; 00304 } 00305 00306 WPosition WDataSetFibers::getPosition( size_t fiber, size_t vertex ) const 00307 { 00308 size_t index = m_lineStartIndexes->at( fiber ) * 3; 00309 index += vertex * 3; 00310 return WPosition( m_vertices->at( index ), m_vertices->at( index + 1 ), m_vertices->at( index + 2 ) ); 00311 } 00312 00313 WPosition WDataSetFibers::getTangent( size_t fiber, size_t vertex ) const 00314 { 00315 WPosition point = getPosition( fiber, vertex ); 00316 WPosition tangent; 00317 00318 if( vertex == 0 ) // first point 00319 { 00320 WPosition pointNext = getPosition( fiber, vertex + 1 ); 00321 tangent = point - pointNext; 00322 } 00323 else if( vertex == m_lineLengths->at( fiber ) - 1 ) // last point 00324 { 00325 WPosition pointBefore = getPosition( fiber, vertex - 1 ); 00326 tangent = pointBefore - point; 00327 } 00328 else // somewhere in between 00329 { 00330 WPosition pointBefore = getPosition( fiber, vertex - 1 ); 00331 WPosition pointNext = getPosition( fiber, vertex + 1 ); 00332 tangent = pointBefore - pointNext; 00333 } 00334 00335 return normalize( tangent ); 00336 } 00337 00338 WBoundingBox WDataSetFibers::getBoundingBox() const 00339 { 00340 return m_bb; 00341 } 00342 00343 WFiber WDataSetFibers::operator[]( size_t numTract ) const 00344 { 00345 WAssert( numTract < m_lineLengths->size(), "WDataSetFibers: out of bounds - invalid tract number requested." ); 00346 WFiber result; 00347 result.reserve( ( *m_lineLengths )[ numTract ] ); 00348 size_t vIdx = ( *m_lineStartIndexes )[ numTract ] * 3; 00349 for( size_t vertexNum = 0; vertexNum < ( *m_lineLengths )[ numTract ]; ++vertexNum ) 00350 { 00351 result.push_back( WPosition( ( *m_vertices )[vIdx], ( *m_vertices )[vIdx + 1], ( *m_vertices )[vIdx + 2] ) ); 00352 vIdx += 3; 00353 } 00354 return result; 00355 }