OpenWalnut  1.4.0
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 <string>
27 #include <utility>
28 #include <vector>
29 
30 #include "../common/datastructures/WFiber.h"
31 #include "../common/WBoundingBox.h"
32 #include "../common/WColor.h"
33 #include "../common/WLogger.h"
34 #include "../common/WPredicateHelper.h"
35 #include "../common/WPropertyHelper.h"
36 #include "../graphicsEngine/WGEUtils.h"
37 #include "exceptions/WDHNoSuchDataSet.h"
38 #include "WCreateColorArraysThread.h"
39 #include "WDataSet.h"
40 #include "WDataSetFibers.h"
41 
42 // prototype instance as singleton
43 boost::shared_ptr< WPrototyped > WDataSetFibers::m_prototype = boost::shared_ptr< WPrototyped >();
44 
46  : WDataSet()
47 {
48  // default constructor used by the prototype mechanism
49 }
50 
52  WDataSetFibers::IndexArray lineStartIndexes,
53  WDataSetFibers::LengthArray lineLengths,
54  WDataSetFibers::IndexArray verticesReverse,
55  WBoundingBox boundingBox )
56  : WDataSet(),
57  m_vertices( vertices ),
58  m_lineStartIndexes( lineStartIndexes ),
59  m_lineLengths( lineLengths ),
60  m_verticesReverse( verticesReverse ),
61  m_bb( boundingBox )
62 {
63  WAssert( m_vertices->size() % 3 == 0, "Invalid vertex array." );
64  init();
65 }
66 
68  WDataSetFibers::IndexArray lineStartIndexes,
69  WDataSetFibers::LengthArray lineLengths,
70  WDataSetFibers::IndexArray verticesReverse )
71  : WDataSet(),
72  m_vertices( vertices ),
73  m_lineStartIndexes( lineStartIndexes ),
74  m_lineLengths( lineLengths ),
75  m_verticesReverse( verticesReverse )
76 {
77  WAssert( m_vertices->size() % 3 == 0, "Invalid vertex array." );
78  // determine bounding box
79  for( size_t i = 0; i < vertices->size()/3; ++i )
80  {
81  m_bb.expandBy( (*vertices)[ 3 * i + 0 ], (*vertices)[ 3 * i + 1 ], (*vertices)[ 3 * i + 2 ] );
82  }
83  // remaining initilisation
84  init();
85 }
86 
88  WDataSetFibers::IndexArray lineStartIndexes,
89  WDataSetFibers::LengthArray lineLengths,
90  WDataSetFibers::IndexArray verticesReverse,
91  WBoundingBox boundingBox,
92  WDataSetFibers::VertexParemeterArray vertexParameters )
93  : WDataSet(),
94  m_vertices( vertices ),
95  m_lineStartIndexes( lineStartIndexes ),
96  m_lineLengths( lineLengths ),
97  m_verticesReverse( verticesReverse ),
98  m_bb( boundingBox ),
99  m_vertexParameters( vertexParameters )
100 {
101  WAssert( m_vertices->size() % 3 == 0, "Invalid vertex array." );
102  init();
103 }
104 
106  WDataSetFibers::IndexArray lineStartIndexes,
107  WDataSetFibers::LengthArray lineLengths,
108  WDataSetFibers::IndexArray verticesReverse,
109  WDataSetFibers::VertexParemeterArray vertexParameters )
110  : WDataSet(),
111  m_vertices( vertices ),
112  m_lineStartIndexes( lineStartIndexes ),
113  m_lineLengths( lineLengths ),
114  m_verticesReverse( verticesReverse ),
115  m_vertexParameters( vertexParameters )
116 {
117  WAssert( m_vertices->size() % 3 == 0, "Invalid vertex array." );
118  // determine bounding box
119  for( size_t i = 0; i < vertices->size()/3; ++i )
120  {
121  m_bb.expandBy( (*vertices)[ 3 * i + 0 ], (*vertices)[ 3 * i + 1 ], (*vertices)[ 3 * i + 2 ] );
122  }
123  // remaining initilisation
124  init();
125 }
126 
128 {
129  size_t size = m_vertices->size();
130  m_tangents = boost::shared_ptr< std::vector< float > >( new std::vector<float>( size ) );
131 
132  boost::shared_ptr< std::vector< float > > globalColors( new std::vector<float>( size ) );
133  boost::shared_ptr< std::vector< float > > localColors( new std::vector<float>( size ) );
134  boost::shared_ptr< std::vector< float > > customColors( new std::vector<float>( size ) );
135 
136  // TODO(all): use the new WThreadedJobs functionality
138  m_lineLengths, globalColors, localColors, m_tangents );
139  WCreateColorArraysThread* t2 = new WCreateColorArraysThread( m_lineLengths->size()/4+1, m_lineLengths->size()/2, m_vertices,
140  m_lineLengths, globalColors, localColors, m_tangents );
141  WCreateColorArraysThread* t3 = new WCreateColorArraysThread( m_lineLengths->size()/2+1, m_lineLengths->size()/4*3, m_vertices,
142  m_lineLengths, globalColors, localColors, m_tangents );
143  WCreateColorArraysThread* t4 = new WCreateColorArraysThread( m_lineLengths->size()/4*3+1, m_lineLengths->size()-1, m_vertices,
144  m_lineLengths, globalColors, localColors, m_tangents );
145  t1->run();
146  t2->run();
147  t3->run();
148  t4->run();
149 
150  t1->wait();
151  t2->wait();
152  t3->wait();
153  t4->wait();
154 
155  delete t1;
156  delete t2;
157  delete t3;
158  delete t4;
159 
160  // add both arrays to m_colors
161  m_colors = boost::shared_ptr< WItemSelection >( new WItemSelection() );
162  m_colors->push_back( boost::shared_ptr< WItemSelectionItem >(
163  new ColorScheme( "Global Color", "Colors direction by using start and end vertex per fiber.", NULL, globalColors, ColorScheme::RGB )
164  )
165  );
166  m_colors->push_back( boost::shared_ptr< WItemSelectionItem >(
167  new ColorScheme( "Local Color", "Colors direction by using start and end vertex per segment.", NULL, localColors, ColorScheme::RGB )
168  )
169  );
170 
171  for( size_t i = 0; i < size; ++i )
172  {
173  ( *customColors )[i] = ( *globalColors )[i];
174  }
175  m_colors->push_back( boost::shared_ptr< WItemSelectionItem >(
176  new ColorScheme( "Custom Color", "Colors copied from the global colors, will be used for bundle coloring.",
177  NULL, customColors, ColorScheme::RGB )
178  )
179  );
180 
181  // the colors can be selected by properties
182  m_colorProp = m_properties->addProperty( "Color Scheme", "Determines the coloring scheme to use for this data.", m_colors->getSelectorFirst() );
185  m_infoProperties->addProperty( "#Fibers", "The number of fibers", static_cast< WPVBaseTypes::PV_INT >( m_lineLengths->size() ) );
186  m_infoProperties->addProperty( "#Vertices", "The number of vertices", static_cast< WPVBaseTypes::PV_INT >( m_vertices->size() ) );
187 }
188 
190 {
191  return false;
192 }
193 
194 size_t WDataSetFibers::size() const
195 {
196  return m_lineStartIndexes->size();
197 }
198 
199 const std::string WDataSetFibers::getName() const
200 {
201  return "WDataSetFibers";
202 }
203 
204 const std::string WDataSetFibers::getDescription() const
205 {
206  return "Contains tracked fiber data.";
207 }
208 
209 boost::shared_ptr< WPrototyped > WDataSetFibers::getPrototype()
210 {
211  if( !m_prototype )
212  {
213  m_prototype = boost::shared_ptr< WPrototyped >( new WDataSetFibers() );
214  }
215 
216  return m_prototype;
217 }
218 
220 {
221  return m_vertices;
222 }
223 
225 {
226  return m_lineStartIndexes;
227 }
228 
230 {
231  return m_lineLengths;
232 }
233 
235 {
236  return m_verticesReverse;
237 }
238 
240 {
241  return m_tangents;
242 }
243 
244 void WDataSetFibers::addColorScheme( WDataSetFibers::ColorArray colors, std::string name, std::string description )
245 {
247 
248  // number of verts is needed to distinguish color mode.
249  size_t verts = m_vertices->size() / 3;
250  size_t cols = colors->size();
251  if( cols / verts == 3 )
252  {
253  mode = ColorScheme::RGB;
254  }
255  else if( cols / verts == 4 )
256  {
257  mode = ColorScheme::RGBA;
258  }
259 
260  m_colors->push_back( boost::shared_ptr< WItemSelectionItem >(
261  new ColorScheme( name, description, NULL, colors, mode )
262  )
263  );
264 }
265 
267 {
268  // this is nearly the same like std::remove_if
269  WItemSelection::WriteTicket l = m_colors->getWriteTicket();
270 
271  WItemSelection::Iterator i = l->get().begin();
272  while( i != l->get().end() )
273  {
274  if( boost::static_pointer_cast< const ColorScheme >( *i )->getColor() == colors )
275  {
276  i = l->get().erase( i );
277  }
278  else
279  {
280  ++i;
281  }
282  }
283 }
284 
286 {
287  // this is nearly the same as std::replace_if
288  WItemSelection::WriteTicket l = m_colors->getWriteTicket();
289  for( WItemSelection::Iterator i = l->get().begin(); i != l->get().end(); ++i )
290  {
291  boost::shared_ptr< ColorScheme > ci = boost::static_pointer_cast< ColorScheme >( *i );
292  if(ci->getColor() == oldColors )
293  {
294  ci->setColor( newColors );
295  }
296  }
297 }
298 
299 const boost::shared_ptr< WDataSetFibers::ColorScheme > WDataSetFibers::getColorScheme( std::string name ) const
300 {
301  WItemSelection::ReadTicket l = m_colors->getReadTicket();
302  WItemSelection::ConstIterator i = std::find_if( l->get().begin(), l->get().end(),
304  );
305  if( i == l->get().end() )
306  {
307  throw WDHNoSuchDataSet( std::string( "Color scheme with specified name could not be found." ) );
308  }
309 
310  return boost::static_pointer_cast< ColorScheme >( *i );
311 }
312 
313 const boost::shared_ptr< WDataSetFibers::ColorScheme > WDataSetFibers::getColorScheme( size_t idx ) const
314 {
315  WItemSelection::ReadTicket l = m_colors->getReadTicket();
316  return boost::static_pointer_cast< ColorScheme >( l->get()[ idx ] );
317 }
318 
319 const boost::shared_ptr< WDataSetFibers::ColorScheme > WDataSetFibers::getColorScheme() const
320 {
321  return boost::static_pointer_cast< ColorScheme >( m_colorProp->get().at( 0 ) );
322 }
323 
324 const WPropSelection WDataSetFibers::getColorSchemeProperty() const
325 {
326  return m_colorProp;
327 }
328 
330 {
331  return m_vertexParameters;
332 }
333 
334 WPosition WDataSetFibers::getPosition( size_t fiber, size_t vertex ) const
335 {
336  size_t index = m_lineStartIndexes->at( fiber ) * 3;
337  index += vertex * 3;
338  return WPosition( m_vertices->at( index ), m_vertices->at( index + 1 ), m_vertices->at( index + 2 ) );
339 }
340 
341 WPosition WDataSetFibers::getTangent( size_t fiber, size_t vertex ) const
342 {
343  WPosition point = getPosition( fiber, vertex );
344  WPosition tangent;
345 
346  if( vertex == 0 ) // first point
347  {
348  WPosition pointNext = getPosition( fiber, vertex + 1 );
349  tangent = point - pointNext;
350  }
351  else if( vertex == m_lineLengths->at( fiber ) - 1 ) // last point
352  {
353  WPosition pointBefore = getPosition( fiber, vertex - 1 );
354  tangent = pointBefore - point;
355  }
356  else // somewhere in between
357  {
358  WPosition pointBefore = getPosition( fiber, vertex - 1 );
359  WPosition pointNext = getPosition( fiber, vertex + 1 );
360  tangent = pointBefore - pointNext;
361  }
362 
363  return normalize( tangent );
364 }
365 
367 {
368  return m_bb;
369 }
370 
371 WFiber WDataSetFibers::operator[]( size_t numTract ) const
372 {
373  WAssert( numTract < m_lineLengths->size(), "WDataSetFibers: out of bounds - invalid tract number requested." );
374  WFiber result;
375  result.reserve( ( *m_lineLengths )[ numTract ] );
376  size_t vIdx = ( *m_lineStartIndexes )[ numTract ] * 3;
377  for( size_t vertexNum = 0; vertexNum < ( *m_lineLengths )[ numTract ]; ++vertexNum )
378  {
379  result.push_back( WPosition( ( *m_vertices )[vIdx], ( *m_vertices )[vIdx + 1], ( *m_vertices )[vIdx + 2] ) );
380  vIdx += 3;
381  }
382  return result;
383 }
384 
386 {
387  return WFiberIterator( this, 0 );
388 }
389 
391 {
392  return WFiberIterator( this, m_lineLengths->size() );
393 }
394 
396  : m_fibers( NULL ),
397  m_index( 0 )
398 {
399 }
400 
401 WFiberIterator::WFiberIterator( WDataSetFibers const* fibers, std::size_t idx )
402  : m_fibers( fibers ),
403  m_index( idx )
404 {
405 }
406 
408  : m_fibers( iter.m_fibers ),
409  m_index( iter.m_index )
410 {
411 }
412 
414 {
415 }
416 
418 {
419  if( this == &iter )
420  {
421  return *this;
422  }
423 
424  m_fibers = iter.m_fibers;
425  m_index = iter.m_index;
426 
427  return *this;
428 }
429 
431 {
432  ++m_index;
433  return *this;
434 }
435 
437 {
439  ++m_index;
440  return t;
441 }
442 
444 {
445  --m_index;
446  return *this;
447 }
448 
450 {
452  --m_index;
453  return t;
454 }
455 
457 {
458  return m_fibers == rhs.m_fibers && m_index == rhs.m_index;
459 }
460 
462 {
463  return !( this->operator==( rhs ) );
464 }
465 
466 std::size_t WFiberIterator::numPoints() const
467 {
468  WAssert( m_index < m_fibers->getLineLengths()->size(), "" );
469 
470  return m_fibers->getLineLengths()->operator[] ( m_index );
471 }
472 
474 {
475  return WFiberPointsIterator( m_fibers, m_index, 0 );
476 }
477 
479 {
480  WAssert( numPoints() != 0, "" );
481 
483 }
484 
486 {
487  return WFiberPointsIterator( m_fibers, m_index, 0, true );
488 }
489 
491 {
492  WAssert( numPoints() != 0, "" );
493 
494  return WFiberPointsIterator( m_fibers, m_index, numPoints(), true );
495 }
496 
498 {
499  return m_fibers->getLineStartIndexes()->operator[]( getIndex() );
500 }
501 
502 std::size_t WFiberIterator::getIndex() const
503 {
504  return m_index;
505 }
506 
508  : m_fibers( NULL ),
509  m_fiberIndex( 0 ),
510  m_index( 0 ),
511  m_reverse( false )
512 {
513 }
514 
515 WFiberPointsIterator::WFiberPointsIterator( WDataSetFibers const* fibers, std::size_t fbIdx, std::size_t idx, bool reverse )
516  : m_fibers( fibers ),
517  m_fiberIndex( fbIdx ),
518  m_index( idx ),
519  m_reverse( reverse )
520 {
521 }
522 
524  : m_fibers( iter.m_fibers ),
525  m_fiberIndex( iter.m_fiberIndex ),
526  m_index( iter.m_index ),
527  m_reverse( iter.m_reverse )
528 {
529 }
530 
532 {
533 }
534 
536 {
537  if( this == &iter )
538  {
539  return *this;
540  }
541 
542  m_fibers = iter.m_fibers;
543  m_fiberIndex = iter.m_fiberIndex;
544  m_index = iter.m_index;
545  m_reverse = iter.m_reverse;
546 
547  return *this;
548 }
549 
551 {
552  ++m_index;
553  return *this;
554 }
555 
557 {
559  ++m_index;
560  return t;
561 }
562 
564 {
565  --m_index;
566  return *this;
567 }
568 
570 {
572  --m_index;
573  return t;
574 }
575 
577 {
578  WAssert( m_fibers, "" );
579  WAssert( m_fiberIndex < m_fibers->getLineLengths()->size(), "" );
580  WAssert( m_index < m_fibers->getLineLengths()->operator[] ( m_fiberIndex ), "" );
581 
582  std::size_t i = m_index;
583  if( m_reverse )
584  {
585  i = m_fibers->getLineLengths()->operator[] ( m_fiberIndex ) - i - 1;
586  }
587  return m_fibers->getLineStartIndexes()->operator[] ( m_fiberIndex ) + i;
588 }
589 
591 {
592  std::size_t v = getBaseIndex();
593  return WPosition( m_fibers->getVertices()->operator[]( 3 * v + 0 ),
594  m_fibers->getVertices()->operator[]( 3 * v + 1 ),
595  m_fibers->getVertices()->operator[]( 3 * v + 2 ) );
596 }
597 
599 {
600  if( m_reverse != rhs.m_reverse )
601  {
602  wlog::warn( "FiberPointsIterator" ) << "Comparing a reverse and a normal iterator!";
603  }
604 
605  return m_fibers == rhs.m_fibers && m_fiberIndex == rhs.m_fiberIndex && m_index == rhs.m_index && m_reverse == rhs.m_reverse;
606 }
607 
609 {
610  return !( this->operator==( rhs ) );
611 }
612 
613 double WFiberPointsIterator::getParameter( double def ) const
614 {
616  {
617  return m_fibers->getVertexParameters()->operator[]( getBaseIndex() );
618  }
619  return def;
620 }
621 
623 {
624  std::size_t v = getBaseIndex();
625  return WPosition( m_fibers->getTangents()->operator[]( 3 * v + 0 ),
626  m_fibers->getTangents()->operator[]( 3 * v + 1 ),
627  m_fibers->getTangents()->operator[]( 3 * v + 2 ) );
628 }
629 
630 
631 WColor WFiberPointsIterator::getColor( const boost::shared_ptr< WDataSetFibers::ColorScheme > scheme ) const
632 {
633  std::size_t v = getBaseIndex();
634  WColor ret;
635  switch( scheme->getMode() )
636  {
638  {
639  double r = scheme->getColor()->operator[]( 1 * v + 0 );
640  ret.set( r, r, r, 1.0 );
641  }
642  break;
644  {
645  double r = scheme->getColor()->operator[]( 3 * v + 0 );
646  double g = scheme->getColor()->operator[]( 3 * v + 1 );
647  double b = scheme->getColor()->operator[]( 3 * v + 2 );
648  ret.set( r, g, b, 1.0 );
649  }
650  break;
652  {
653  double r = scheme->getColor()->operator[]( 4 * v + 0 );
654  double g = scheme->getColor()->operator[]( 4 * v + 1 );
655  double b = scheme->getColor()->operator[]( 4 * v + 2 );
656  double a = scheme->getColor()->operator[]( 4 * v + 3 );
657  ret.set( r, g, b, a );
658  }
659  break;
660  default:
661  ret.set( 1.0, 1.0, 1.0, 1.0 );
662  break;
663  }
664  return ret;
665 }
666 
668 {
669  return getColor( m_fibers->getColorScheme() );
670 }
671 
672 WColor WFiberPointsIterator::getColor( std::size_t idx ) const
673 {
674  return getColor( m_fibers->getColorScheme( idx ) );
675 }
676 
677 WColor WFiberPointsIterator::getColor( std::string name ) const
678 {
679  return getColor( m_fibers->getColorScheme( name ) );
680 }
681