OpenWalnut 1.3.1
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 #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 }