OpenWalnut  1.2.5
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
WDataSetFibers.cpp
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #include <algorithm>
26 #include <iostream>
27 #include <string>
28 #include <utility>
29 #include <vector>
30 
31 // Use filesystem version 2 for compatibility with newer boost versions.
32 #ifndef BOOST_FILESYSTEM_VERSION
33  #define BOOST_FILESYSTEM_VERSION 2
34 #endif
35 #include <boost/filesystem/fstream.hpp>
36 #include <boost/lexical_cast.hpp>
37 
38 #include "../common/datastructures/WFiber.h"
39 #include "../common/WBoundingBox.h"
40 #include "../common/WColor.h"
41 #include "../common/WLogger.h"
42 #include "../common/WPredicateHelper.h"
43 #include "../common/WPropertyHelper.h"
44 #include "../graphicsEngine/WGEUtils.h"
45 #include "exceptions/WDHNoSuchDataSet.h"
46 #include "WCreateColorArraysThread.h"
47 #include "WDataSet.h"
48 #include "WDataSetFibers.h"
49 
50 // prototype instance as singleton
51 boost::shared_ptr< WPrototyped > WDataSetFibers::m_prototype = boost::shared_ptr< WPrototyped >();
52 
54  : WDataSet()
55 {
56  // default constructor used by the prototype mechanism
57 }
58 
60  WDataSetFibers::IndexArray lineStartIndexes,
61  WDataSetFibers::LengthArray lineLengths,
62  WDataSetFibers::IndexArray verticesReverse,
63  WBoundingBox boundingBox )
64  : WDataSet(),
65  m_vertices( vertices ),
66  m_lineStartIndexes( lineStartIndexes ),
67  m_lineLengths( lineLengths ),
68  m_verticesReverse( verticesReverse ),
69  m_bb( boundingBox )
70 {
71  WAssert( m_vertices->size() % 3 == 0, "Invalid vertex array." );
72  init();
73 }
74 
76  WDataSetFibers::IndexArray lineStartIndexes,
77  WDataSetFibers::LengthArray lineLengths,
78  WDataSetFibers::IndexArray verticesReverse )
79  : WDataSet(),
80  m_vertices( vertices ),
81  m_lineStartIndexes( lineStartIndexes ),
82  m_lineLengths( lineLengths ),
83  m_verticesReverse( verticesReverse )
84 {
85  WAssert( m_vertices->size() % 3 == 0, "Invalid vertex array." );
86  // determine bounding box
87  for( size_t i = 0; i < vertices->size()/3; ++i )
88  {
89  m_bb.expandBy( (*vertices)[ 3 * i + 0 ], (*vertices)[ 3 * i + 1 ], (*vertices)[ 3 * i + 2 ] );
90  }
91  // remaining initilisation
92  init();
93 }
94 
96 {
97  size_t size = m_vertices->size();
98  m_tangents = boost::shared_ptr< std::vector< float > >( new std::vector<float>( size ) );
99 
100  boost::shared_ptr< std::vector< float > > globalColors = boost::shared_ptr< std::vector< float > >( new std::vector<float>( size ) );
101  boost::shared_ptr< std::vector< float > > localColors = boost::shared_ptr< std::vector< float > >( new std::vector<float>( size ) );
102  boost::shared_ptr< std::vector< float > > customColors = boost::shared_ptr< std::vector< float > >( new std::vector<float>( size ) );
103 
104 
105  // TODO(all): use the new WThreadedJobs functionality
107  m_lineStartIndexes, m_lineLengths, globalColors, localColors, m_tangents );
108  WCreateColorArraysThread* t2 = new WCreateColorArraysThread( m_lineLengths->size()/4+1, m_lineLengths->size()/2, m_vertices,
109  m_lineStartIndexes, m_lineLengths, globalColors, localColors, m_tangents );
110  WCreateColorArraysThread* t3 = new WCreateColorArraysThread( m_lineLengths->size()/2+1, m_lineLengths->size()/4*3, m_vertices,
111  m_lineStartIndexes, m_lineLengths, globalColors, localColors, m_tangents );
112  WCreateColorArraysThread* t4 = new WCreateColorArraysThread( m_lineLengths->size()/4*3+1, m_lineLengths->size()-1, m_vertices,
113  m_lineStartIndexes, m_lineLengths, globalColors, localColors, m_tangents );
114  t1->run();
115  t2->run();
116  t3->run();
117  t4->run();
118 
119  t1->wait();
120  t2->wait();
121  t3->wait();
122  t4->wait();
123 
124  delete t1;
125  delete t2;
126  delete t3;
127  delete t4;
128 
129  // add both arrays to m_colors
130  m_colors = boost::shared_ptr< WItemSelection >( new WItemSelection() );
131  m_colors->push_back( boost::shared_ptr< WItemSelectionItem >(
132  new ColorScheme( "Global Color", "Colors direction by using start and end vertex per fiber.", NULL, globalColors, ColorScheme::RGB )
133  )
134  );
135  m_colors->push_back( boost::shared_ptr< WItemSelectionItem >(
136  new ColorScheme( "Local Color", "Colors direction by using start and end vertex per segment.", NULL, localColors, ColorScheme::RGB )
137  )
138  );
139 
140  for( size_t i = 0; i < size; ++i )
141  {
142  ( *customColors )[i] = ( *globalColors )[i];
143  }
144  m_colors->push_back( boost::shared_ptr< WItemSelectionItem >(
145  new ColorScheme( "Custom Color", "Colors copied from the global colors, will be used for bundle coloring.",
146  NULL, customColors, ColorScheme::RGB )
147  )
148  );
149 
150  // the colors can be selected by properties
151  m_colorProp = m_properties->addProperty( "Color Scheme", "Determines the coloring scheme to use for this data.", m_colors->getSelectorFirst() );
154 }
155 
157 {
158  return false;
159 }
160 
161 size_t WDataSetFibers::size() const
162 {
163  return m_lineStartIndexes->size();
164 }
165 
166 const std::string WDataSetFibers::getName() const
167 {
168  return "WDataSetFibers";
169 }
170 
171 const std::string WDataSetFibers::getDescription() const
172 {
173  return "Contains tracked fiber data.";
174 }
175 
176 boost::shared_ptr< WPrototyped > WDataSetFibers::getPrototype()
177 {
178  if( !m_prototype )
179  {
180  m_prototype = boost::shared_ptr< WPrototyped >( new WDataSetFibers() );
181  }
182 
183  return m_prototype;
184 }
185 
187 {
188  return m_vertices;
189 }
190 
192 {
193  return m_lineStartIndexes;
194 }
195 
197 {
198  return m_lineLengths;
199 }
200 
202 {
203  return m_verticesReverse;
204 }
205 
207 {
208  return m_tangents;
209 }
210 
212 {
213  return boost::shared_static_cast< const ColorScheme >( ( *m_colors )[0] )->getColor();
214 }
215 
217 {
218  return boost::shared_static_cast< const ColorScheme >( ( *m_colors )[1] )->getColor();
219 }
220 
221 void WDataSetFibers::addColorScheme( WDataSetFibers::ColorArray colors, std::string name, std::string description )
222 {
224 
225  // number of verts is needed to distinguish color mode.
226  size_t verts = m_vertices->size() / 3;
227  size_t cols = colors->size();
228  if( cols / verts == 3 )
229  {
230  mode = ColorScheme::RGB;
231  }
232  else if( cols / verts == 4 )
233  {
234  mode = ColorScheme::RGBA;
235  }
236 
237  m_colors->push_back( boost::shared_ptr< WItemSelectionItem >(
238  new ColorScheme( name, description, NULL, colors, mode )
239  )
240  );
241 }
242 
244 {
245  // this is nearly the same like std::remove_if
246  WItemSelection::WriteTicket l = m_colors->getWriteTicket();
247 
248  WItemSelection::Iterator i = l->get().begin();
249  while( i != l->get().end() )
250  {
251  if( boost::shared_static_cast< const ColorScheme >( *i )->getColor() == colors )
252  {
253  i = l->get().erase( i );
254  }
255  else
256  {
257  ++i;
258  }
259  }
260 }
261 
263 {
264  // this is nearly the same as std::replace_if
265  WItemSelection::WriteTicket l = m_colors->getWriteTicket();
266  for( WItemSelection::Iterator i = l->get().begin(); i != l->get().end(); ++i )
267  {
268  boost::shared_ptr< ColorScheme > ci = boost::shared_static_cast< ColorScheme >( *i );
269  if(ci->getColor() == oldColors )
270  {
271  ci->setColor( newColors );
272  }
273  }
274 }
275 
276 const boost::shared_ptr< WDataSetFibers::ColorScheme > WDataSetFibers::getColorScheme( std::string name ) const
277 {
278  WItemSelection::ReadTicket l = m_colors->getReadTicket();
279  WItemSelection::ConstIterator i = std::find_if( l->get().begin(), l->get().end(),
281  );
282  if( i == l->get().end() )
283  {
284  throw WDHNoSuchDataSet( std::string( "Color scheme with specified name could not be found." ) );
285  }
286 
287  return boost::shared_static_cast< ColorScheme >( *i );
288 }
289 
290 const boost::shared_ptr< WDataSetFibers::ColorScheme > WDataSetFibers::getColorScheme( size_t idx ) const
291 {
292  WItemSelection::ReadTicket l = m_colors->getReadTicket();
293  return boost::shared_static_cast< ColorScheme >( l->get()[ idx ] );
294 }
295 
296 const boost::shared_ptr< WDataSetFibers::ColorScheme > WDataSetFibers::getColorScheme() const
297 {
298  return boost::shared_static_cast< ColorScheme >( m_colorProp->get().at( 0 ) );
299 }
300 
301 const WPropSelection WDataSetFibers::getColorSchemeProperty() const
302 {
303  return m_colorProp;
304 }
305 
306 WPosition WDataSetFibers::getPosition( size_t fiber, size_t vertex ) const
307 {
308  size_t index = m_lineStartIndexes->at( fiber ) * 3;
309  index += vertex * 3;
310  return WPosition( m_vertices->at( index ), m_vertices->at( index + 1 ), m_vertices->at( index + 2 ) );
311 }
312 
313 WPosition WDataSetFibers::getTangent( size_t fiber, size_t vertex ) const
314 {
315  WPosition point = getPosition( fiber, vertex );
316  WPosition tangent;
317 
318  if( vertex == 0 ) // first point
319  {
320  WPosition pointNext = getPosition( fiber, vertex + 1 );
321  tangent = point - pointNext;
322  }
323  else if( vertex == m_lineLengths->at( fiber ) - 1 ) // last point
324  {
325  WPosition pointBefore = getPosition( fiber, vertex - 1 );
326  tangent = pointBefore - point;
327  }
328  else // somewhere in between
329  {
330  WPosition pointBefore = getPosition( fiber, vertex - 1 );
331  WPosition pointNext = getPosition( fiber, vertex + 1 );
332  tangent = pointBefore - pointNext;
333  }
334 
335  return normalize( tangent );
336 }
337 
339 {
340  return m_bb;
341 }
342 
343 WFiber WDataSetFibers::operator[]( size_t numTract ) const
344 {
345  WAssert( numTract < m_lineLengths->size(), "WDataSetFibers: out of bounds - invalid tract number requested." );
346  WFiber result;
347  result.reserve( ( *m_lineLengths )[ numTract ] );
348  size_t vIdx = ( *m_lineStartIndexes )[ numTract ] * 3;
349  for( size_t vertexNum = 0; vertexNum < ( *m_lineLengths )[ numTract ]; ++vertexNum )
350  {
351  result.push_back( WPosition( ( *m_vertices )[vIdx], ( *m_vertices )[vIdx + 1], ( *m_vertices )[vIdx + 2] ) );
352  vIdx += 3;
353  }
354  return result;
355 }