OpenWalnut 1.2.5
WDataSetFibers.cpp
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 }
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends