OpenWalnut  1.3.1
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 #include <boost/filesystem/fstream.hpp>
32 
33 #include "../common/datastructures/WFiber.h"
34 #include "../common/WBoundingBox.h"
35 #include "../common/WColor.h"
36 #include "../common/WLogger.h"
37 #include "../common/WPredicateHelper.h"
38 #include "../common/WPropertyHelper.h"
39 #include "../graphicsEngine/WGEUtils.h"
40 #include "exceptions/WDHNoSuchDataSet.h"
41 #include "WCreateColorArraysThread.h"
42 #include "WDataSet.h"
43 #include "WDataSetFibers.h"
44 
45 // prototype instance as singleton
46 boost::shared_ptr< WPrototyped > WDataSetFibers::m_prototype = boost::shared_ptr< WPrototyped >();
47 
49  : WDataSet()
50 {
51  // default constructor used by the prototype mechanism
52 }
53 
55  WDataSetFibers::IndexArray lineStartIndexes,
56  WDataSetFibers::LengthArray lineLengths,
57  WDataSetFibers::IndexArray verticesReverse,
58  WBoundingBox boundingBox )
59  : WDataSet(),
60  m_vertices( vertices ),
61  m_lineStartIndexes( lineStartIndexes ),
62  m_lineLengths( lineLengths ),
63  m_verticesReverse( verticesReverse ),
64  m_bb( boundingBox )
65 {
66  WAssert( m_vertices->size() % 3 == 0, "Invalid vertex array." );
67  init();
68 }
69 
71  WDataSetFibers::IndexArray lineStartIndexes,
72  WDataSetFibers::LengthArray lineLengths,
73  WDataSetFibers::IndexArray verticesReverse )
74  : WDataSet(),
75  m_vertices( vertices ),
76  m_lineStartIndexes( lineStartIndexes ),
77  m_lineLengths( lineLengths ),
78  m_verticesReverse( verticesReverse )
79 {
80  WAssert( m_vertices->size() % 3 == 0, "Invalid vertex array." );
81  // determine bounding box
82  for( size_t i = 0; i < vertices->size()/3; ++i )
83  {
84  m_bb.expandBy( (*vertices)[ 3 * i + 0 ], (*vertices)[ 3 * i + 1 ], (*vertices)[ 3 * i + 2 ] );
85  }
86  // remaining initilisation
87  init();
88 }
89 
91 {
92  size_t size = m_vertices->size();
93  m_tangents = boost::shared_ptr< std::vector< float > >( new std::vector<float>( size ) );
94 
95  boost::shared_ptr< std::vector< float > > globalColors = boost::shared_ptr< std::vector< float > >( new std::vector<float>( size ) );
96  boost::shared_ptr< std::vector< float > > localColors = boost::shared_ptr< std::vector< float > >( new std::vector<float>( size ) );
97  boost::shared_ptr< std::vector< float > > customColors = boost::shared_ptr< std::vector< float > >( new std::vector<float>( size ) );
98 
99 
100  // TODO(all): use the new WThreadedJobs functionality
102  m_lineStartIndexes, m_lineLengths, globalColors, localColors, m_tangents );
103  WCreateColorArraysThread* t2 = new WCreateColorArraysThread( m_lineLengths->size()/4+1, m_lineLengths->size()/2, m_vertices,
104  m_lineStartIndexes, m_lineLengths, globalColors, localColors, m_tangents );
105  WCreateColorArraysThread* t3 = new WCreateColorArraysThread( m_lineLengths->size()/2+1, m_lineLengths->size()/4*3, m_vertices,
106  m_lineStartIndexes, m_lineLengths, globalColors, localColors, m_tangents );
107  WCreateColorArraysThread* t4 = new WCreateColorArraysThread( m_lineLengths->size()/4*3+1, m_lineLengths->size()-1, m_vertices,
108  m_lineStartIndexes, m_lineLengths, globalColors, localColors, m_tangents );
109  t1->run();
110  t2->run();
111  t3->run();
112  t4->run();
113 
114  t1->wait();
115  t2->wait();
116  t3->wait();
117  t4->wait();
118 
119  delete t1;
120  delete t2;
121  delete t3;
122  delete t4;
123 
124  // add both arrays to m_colors
125  m_colors = boost::shared_ptr< WItemSelection >( new WItemSelection() );
126  m_colors->push_back( boost::shared_ptr< WItemSelectionItem >(
127  new ColorScheme( "Global Color", "Colors direction by using start and end vertex per fiber.", NULL, globalColors, ColorScheme::RGB )
128  )
129  );
130  m_colors->push_back( boost::shared_ptr< WItemSelectionItem >(
131  new ColorScheme( "Local Color", "Colors direction by using start and end vertex per segment.", NULL, localColors, ColorScheme::RGB )
132  )
133  );
134 
135  for( size_t i = 0; i < size; ++i )
136  {
137  ( *customColors )[i] = ( *globalColors )[i];
138  }
139  m_colors->push_back( boost::shared_ptr< WItemSelectionItem >(
140  new ColorScheme( "Custom Color", "Colors copied from the global colors, will be used for bundle coloring.",
141  NULL, customColors, ColorScheme::RGB )
142  )
143  );
144 
145  // the colors can be selected by properties
146  m_colorProp = m_properties->addProperty( "Color Scheme", "Determines the coloring scheme to use for this data.", m_colors->getSelectorFirst() );
149 }
150 
152 {
153  return false;
154 }
155 
156 size_t WDataSetFibers::size() const
157 {
158  return m_lineStartIndexes->size();
159 }
160 
161 const std::string WDataSetFibers::getName() const
162 {
163  return "WDataSetFibers";
164 }
165 
166 const std::string WDataSetFibers::getDescription() const
167 {
168  return "Contains tracked fiber data.";
169 }
170 
171 boost::shared_ptr< WPrototyped > WDataSetFibers::getPrototype()
172 {
173  if( !m_prototype )
174  {
175  m_prototype = boost::shared_ptr< WPrototyped >( new WDataSetFibers() );
176  }
177 
178  return m_prototype;
179 }
180 
182 {
183  return m_vertices;
184 }
185 
187 {
188  return m_lineStartIndexes;
189 }
190 
192 {
193  return m_lineLengths;
194 }
195 
197 {
198  return m_verticesReverse;
199 }
200 
202 {
203  return m_tangents;
204 }
205 
207 {
208  return boost::static_pointer_cast< const ColorScheme >( ( *m_colors )[0] )->getColor();
209 }
210 
212 {
213  return boost::static_pointer_cast< const ColorScheme >( ( *m_colors )[1] )->getColor();
214 }
215 
216 void WDataSetFibers::addColorScheme( WDataSetFibers::ColorArray colors, std::string name, std::string description )
217 {
219 
220  // number of verts is needed to distinguish color mode.
221  size_t verts = m_vertices->size() / 3;
222  size_t cols = colors->size();
223  if( cols / verts == 3 )
224  {
225  mode = ColorScheme::RGB;
226  }
227  else if( cols / verts == 4 )
228  {
229  mode = ColorScheme::RGBA;
230  }
231 
232  m_colors->push_back( boost::shared_ptr< WItemSelectionItem >(
233  new ColorScheme( name, description, NULL, colors, mode )
234  )
235  );
236 }
237 
239 {
240  // this is nearly the same like std::remove_if
241  WItemSelection::WriteTicket l = m_colors->getWriteTicket();
242 
243  WItemSelection::Iterator i = l->get().begin();
244  while( i != l->get().end() )
245  {
246  if( boost::static_pointer_cast< const ColorScheme >( *i )->getColor() == colors )
247  {
248  i = l->get().erase( i );
249  }
250  else
251  {
252  ++i;
253  }
254  }
255 }
256 
258 {
259  // this is nearly the same as std::replace_if
260  WItemSelection::WriteTicket l = m_colors->getWriteTicket();
261  for( WItemSelection::Iterator i = l->get().begin(); i != l->get().end(); ++i )
262  {
263  boost::shared_ptr< ColorScheme > ci = boost::static_pointer_cast< ColorScheme >( *i );
264  if(ci->getColor() == oldColors )
265  {
266  ci->setColor( newColors );
267  }
268  }
269 }
270 
271 const boost::shared_ptr< WDataSetFibers::ColorScheme > WDataSetFibers::getColorScheme( std::string name ) const
272 {
273  WItemSelection::ReadTicket l = m_colors->getReadTicket();
274  WItemSelection::ConstIterator i = std::find_if( l->get().begin(), l->get().end(),
276  );
277  if( i == l->get().end() )
278  {
279  throw WDHNoSuchDataSet( std::string( "Color scheme with specified name could not be found." ) );
280  }
281 
282  return boost::static_pointer_cast< ColorScheme >( *i );
283 }
284 
285 const boost::shared_ptr< WDataSetFibers::ColorScheme > WDataSetFibers::getColorScheme( size_t idx ) const
286 {
287  WItemSelection::ReadTicket l = m_colors->getReadTicket();
288  return boost::static_pointer_cast< ColorScheme >( l->get()[ idx ] );
289 }
290 
291 const boost::shared_ptr< WDataSetFibers::ColorScheme > WDataSetFibers::getColorScheme() const
292 {
293  return boost::static_pointer_cast< ColorScheme >( m_colorProp->get().at( 0 ) );
294 }
295 
296 const WPropSelection WDataSetFibers::getColorSchemeProperty() const
297 {
298  return m_colorProp;
299 }
300 
301 WPosition WDataSetFibers::getPosition( size_t fiber, size_t vertex ) const
302 {
303  size_t index = m_lineStartIndexes->at( fiber ) * 3;
304  index += vertex * 3;
305  return WPosition( m_vertices->at( index ), m_vertices->at( index + 1 ), m_vertices->at( index + 2 ) );
306 }
307 
308 WPosition WDataSetFibers::getTangent( size_t fiber, size_t vertex ) const
309 {
310  WPosition point = getPosition( fiber, vertex );
311  WPosition tangent;
312 
313  if( vertex == 0 ) // first point
314  {
315  WPosition pointNext = getPosition( fiber, vertex + 1 );
316  tangent = point - pointNext;
317  }
318  else if( vertex == m_lineLengths->at( fiber ) - 1 ) // last point
319  {
320  WPosition pointBefore = getPosition( fiber, vertex - 1 );
321  tangent = pointBefore - point;
322  }
323  else // somewhere in between
324  {
325  WPosition pointBefore = getPosition( fiber, vertex - 1 );
326  WPosition pointNext = getPosition( fiber, vertex + 1 );
327  tangent = pointBefore - pointNext;
328  }
329 
330  return normalize( tangent );
331 }
332 
334 {
335  return m_bb;
336 }
337 
338 WFiber WDataSetFibers::operator[]( size_t numTract ) const
339 {
340  WAssert( numTract < m_lineLengths->size(), "WDataSetFibers: out of bounds - invalid tract number requested." );
341  WFiber result;
342  result.reserve( ( *m_lineLengths )[ numTract ] );
343  size_t vIdx = ( *m_lineStartIndexes )[ numTract ] * 3;
344  for( size_t vertexNum = 0; vertexNum < ( *m_lineLengths )[ numTract ]; ++vertexNum )
345  {
346  result.push_back( WPosition( ( *m_vertices )[vIdx], ( *m_vertices )[vIdx + 1], ( *m_vertices )[vIdx + 2] ) );
347  vIdx += 3;
348  }
349  return result;
350 }