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