OpenWalnut  1.5.0dev
WMFiberParameterColoring.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 <cmath>
27 #include <memory>
28 #include <string>
29 #include <vector>
30 
31 #include "WMFiberParameterColoring.h"
32 #include "WMFiberParameterColoring.xpm"
33 #include "core/common/WPropertyHelper.h"
34 #include "core/common/math/WMath.h"
35 #include "core/dataHandler/WDataHandler.h"
36 #include "core/kernel/WKernel.h"
37 
38 // This line is needed by the module loader to actually find your module. You need to add this to your module too. Do NOT add a ";" here.
39 W_LOADABLE_MODULE( WMFiberParameterColoring )
40 
42  WModule()
43 {
44 }
45 
47 {
48  // Cleanup!
49 }
50 
51 std::shared_ptr< WModule > WMFiberParameterColoring::factory() const
52 {
53  return std::shared_ptr< WModule >( new WMFiberParameterColoring() );
54 }
55 
57 {
58  return WMFiberParameterColoring_xpm;
59 }
60 
61 const std::string WMFiberParameterColoring::getName() const
62 {
63  return "Fiber Parameter Coloring";
64 }
65 
67 {
68  return "This module can color fibers according to different parameters and schemes.";
69 }
70 
72 {
73  // The input fiber dataset
74  m_fiberInput = std::shared_ptr< WModuleInputData < WDataSetFibers > >(
75  new WModuleInputData< WDataSetFibers >( shared_from_this(), "fibers", "The fiber dataset to color" )
76  );
77 
78  // As properties, every connector needs to be added to the list of connectors.
80 
81  // the selected fibers go to this output
82  m_fiberOutput = std::shared_ptr< WModuleOutputData < WDataSetFibers > >(
83  new WModuleOutputData< WDataSetFibers >( shared_from_this(),
84  "out", "The fiber dataset colored by this module." )
85  );
86 
87  // As above: make it known.
89 
90  // call WModule's initialization
92 }
93 
95 {
96  m_propCondition = std::shared_ptr< WCondition >( new WCondition() );
97 
98  m_baseColor = m_properties->addProperty( "Base Color", "The base color. Some kind of color offset.", WColor( 1.0, 1.0, 1.0, 0.0 ),
100  m_scaleColor = m_properties->addProperty( "Scale Color", "The color which gets scaled with the calculated value and added to the base color.",
101  WColor( 0.0, 0.0, 0.0, 1.0 ), m_propCondition );
102 
103  // call WModule's initialization
105 }
106 
107 inline double getSegmentVector( size_t segment, size_t offset, std::shared_ptr< std::vector< float > > verts, double* vec )
108 {
109  // get segment coordinates
110  double x = verts->at( ( 3 * segment ) + offset + 0 ) - verts->at( ( 3 * ( segment + 1 ) ) + offset + 0 );
111  double y = verts->at( ( 3 * segment ) + offset + 1 ) - verts->at( ( 3 * ( segment + 1 ) ) + offset + 1 );
112  double z = verts->at( ( 3 * segment ) + offset + 2 ) - verts->at( ( 3 * ( segment + 1 ) ) + offset + 2 );
113 
114  // get length
115  double len = std::sqrt( x * x + y * y + z * z );
116 
117  // create vector from this and the previous point
118  vec[0] = x / len;
119  vec[1] = y / len;
120  vec[2] = z / len;
121 
122  return len;
123 }
124 
126 {
127  // get notified about data changes
128  m_moduleState.setResetable( true, true );
129  m_moduleState.add( m_fiberInput->getDataChangedCondition() );
130  // Remember the condition provided to some properties in properties()? The condition can now be used with this condition set.
132 
133  ready();
134 
137 
138  // main loop
139  while( !m_shutdownFlag() )
140  {
141  debugLog() << "Waiting ...";
143 
144  // woke up since the module is requested to finish?
145  if( m_shutdownFlag() )
146  {
147  break;
148  }
149 
150  // To query whether an input was updated, simply ask the input:
151  bool dataUpdated = m_fiberInput->handledUpdate();
152  std::shared_ptr< WDataSetFibers > dataSet = m_fiberInput->getData();
153  bool dataValid = ( dataSet != NULL );
154  bool propUpdated = m_baseColor->changed() || m_scaleColor->changed();
155 
156  // reset everything if input was disconnected/invalid
157  if( !dataValid )
158  {
159  debugLog() << "Resetting output.";
160  m_fiberOutput->reset();
161  continue;
162  }
163 
164  if( dataValid && !( dataUpdated || propUpdated ) )
165  {
166  continue;
167  }
168 
169  // remove old colorings
170  dataSet->removeColorScheme( m_fibCurvatureColors ); // this can be safely used with NULL pointers
171  dataSet->removeColorScheme( m_fibLengthColors );
172 
173  // get the fiber definitions
174  std::shared_ptr< std::vector< size_t > > fibStart = dataSet->getLineStartIndexes();
175  std::shared_ptr< std::vector< size_t > > fibLen = dataSet->getLineLengths();
176  std::shared_ptr< std::vector< float > > fibVerts = dataSet->getVertices();
177  m_fibCurvatureColors = WDataSetFibers::ColorArray( new WDataSetFibers::ColorArray::element_type() );
178  m_fibLengthColors = WDataSetFibers::ColorArray( new WDataSetFibers::ColorArray::element_type() );
180  m_fibCurvatureColors->resize( colorMode * ( fibVerts->size() / 3 ), 0.0 ); // create an RGBA coloring
181  m_fibLengthColors->resize( colorMode * ( fibVerts->size() / 3 ), 0.0 ); // create an RGBA coloring
182 
183  // progress indication
184  std::shared_ptr< WProgress > progress1( new WProgress( "Coloring fibers.", fibStart->size() ) );
185  std::shared_ptr< WProgress > progress2( new WProgress( "Scaling Colors.", fibStart->size() ) );
186  m_progress->addSubProgress( progress1 );
187  m_progress->addSubProgress( progress2 );
188 
189  // for fastness:
190  WColor baseColor = m_baseColor->get( true );
191  double baseColorR = baseColor[0];
192  double baseColorG = baseColor[1];
193  double baseColorB = baseColor[2];
194  double baseColorA = baseColor[3];
195  WColor scaleColor = m_scaleColor->get( true );
196  double scaleColorR = scaleColor[0];
197  double scaleColorG = scaleColor[1];
198  double scaleColorB = scaleColor[2];
199  double scaleColorA = scaleColor[3];
200 
201  // for each fiber:
202  debugLog() << "Iterating over all fibers.";
203  std::vector< double > maxSegLengths;
204  maxSegLengths.resize( fibStart->size(), 0.0 );
205  for( size_t fidx = 0; fidx < fibStart->size() ; ++fidx )
206  {
207  ++*progress1;
208 
209  // the start vertex index
210  size_t sidx = fibStart->at( fidx ) * 3;
211  size_t cidx = fibStart->at( fidx ) * colorMode;
212 
213  // the length of the fiber, if a fiber is smaller than two segments, skip it ( it already is colored white by default )
214  size_t len = fibLen->at( fidx );
215  if( len < 3 )
216  {
217  continue;
218  }
219 
220  // get the first vector and second vertex
221  double prev[3];
222  // we do not need zero length segments
223  if( getSegmentVector( 0, sidx, fibVerts, &prev[0] ) == 0.0 )
224  {
225  continue;
226  }
227 
228  // walk along the fiber
229  double lenLast = 0.0;
230  double lenMax = 0.0;
231  for( size_t k = 1; k < len - 1; ++k ) // len -1 because we interpret it as segments
232  {
233  // get the vector of this segment
234  double current[3];
235  // we do not need zero length segments
236  double segLen = getSegmentVector( k, sidx, fibVerts, &current[0] );
237  if( segLen == 0.0 )
238  {
239  continue;
240  }
241 
242  // how to calculate the curvature?
243  // -------------------------------
244  // Variant 1:
245 
246  // calculate angle between both segments
247  // double dot = ( current[0] * prev[0] ) + ( current[1] * prev[1] ) + ( current[2] * prev[2] );
248  // dot = std::max( -1.0, std::min( dot, 1.0 ) ); // dot must not be larger than 1. Unfortunately it might get
249  // larger in the 10^-10th.
250 
251  // get angle and curvature
252  // double angleRad = std::acos( dot );
253  // double curvature2 = 2.0 * angleRad / ( lenLast + segLen );
254 
255  // Variant 2:
256 
257  double x = ( 2.0 / ( lenLast + segLen ) ) * ( current[0] - prev[0] );
258  double y = ( 2.0 / ( lenLast + segLen ) ) * ( current[1] - prev[1] );
259  double z = ( 2.0 / ( lenLast + segLen ) ) * ( current[2] - prev[2] );
260  double curvature = std::sqrt( x*x + y*y + z*z );
261 
262  ( *m_fibCurvatureColors )[ ( colorMode * k ) + cidx + 0 ] = baseColorR + ( 1.5 * scaleColorR * curvature );
263  ( *m_fibCurvatureColors )[ ( colorMode * k ) + cidx + 1 ] = baseColorG + ( 1.5 * scaleColorG * curvature );
264  ( *m_fibCurvatureColors )[ ( colorMode * k ) + cidx + 2 ] = baseColorB + ( 1.5 * scaleColorB * curvature );
265  ( *m_fibCurvatureColors )[ ( colorMode * k ) + cidx + 3 ] = baseColorA + ( 1.5 * scaleColorA * curvature );
266 
267  ( *m_fibLengthColors )[ ( colorMode * k ) + cidx + 0 ] = segLen;
268  ( *m_fibLengthColors )[ ( colorMode * k ) + cidx + 1 ] = 0.0;
269  ( *m_fibLengthColors )[ ( colorMode * k ) + cidx + 2 ] = 0.0;
270  ( *m_fibLengthColors )[ ( colorMode * k ) + cidx + 3 ] = 1.0;
271 
272  prev[0] = current[0];
273  prev[1] = current[1];
274  prev[2] = current[2];
275  lenLast = segLen;
276  lenMax = std::max( segLen, lenMax );
277  }
278  maxSegLengths[ fidx ] = lenMax;
279  }
280  progress1->finish();
281 
282  // finally, apply the global scalings needed
283  debugLog() << "Iterating over all fibers for scaling per fiber.";
284  for( size_t fidx = 0; fidx < fibStart->size() ; ++fidx )
285  {
286  ++*progress2;
287 
288  // the start vertex index
289  size_t cidx = fibStart->at( fidx ) * colorMode;
290  size_t len = fibLen->at( fidx );
291  if( len < 3 )
292  {
293  continue;
294  }
295 
296  // walk along the fiber
297  for( size_t k = 1; k < len - 1; ++k ) // len -1 because we interpret it as segments
298  {
299  double relSegLen = ( *m_fibLengthColors )[ ( colorMode * k ) + cidx + 0 ] / maxSegLengths[ fidx ];
300  ( *m_fibLengthColors )[ ( colorMode * k ) + cidx + 0 ] = baseColorR + ( scaleColorR * relSegLen );
301  ( *m_fibLengthColors )[ ( colorMode * k ) + cidx + 1 ] = baseColorG + ( scaleColorG * relSegLen );
302  ( *m_fibLengthColors )[ ( colorMode * k ) + cidx + 2 ] = baseColorB + ( scaleColorB * relSegLen );
303  ( *m_fibLengthColors )[ ( colorMode * k ) + cidx + 3 ] = baseColorA + ( scaleColorA * relSegLen );
304  }
305  }
306  progress2->finish();
307 
308  // add the new scheme
309  dataSet->addColorScheme( m_fibCurvatureColors, "Curvature Coloring",
310  "The speed of changing angles between consecutive segments represents the color." );
311  dataSet->addColorScheme( m_fibLengthColors, "Segment Length Coloring",
312  "The length of a segment in relation to the longest segment in the fiber." );
313 
314  // forward the data
315  m_fiberOutput->updateData( dataSet );
316 
317  // remove the progress indicators
318  m_progress->removeSubProgress( progress1 );
319  m_progress->removeSubProgress( progress2 );
320 
321  debugLog() << "Done";
322  }
323 }
324 
virtual void wait() const
Wait for the condition.
void setResetable(bool resetable=true, bool autoReset=true)
Sets the resetable flag.
virtual void add(std::shared_ptr< WCondition > condition)
Adds another condition to the set of conditions to wait for.
Class to encapsulate boost::condition_variable_any.
Definition: WCondition.h:42
ColorMode
different kinds of color arrays can be used in this class.
std::shared_ptr< std::vector< float > > ColorArray
Colors for each vertex in VertexArray.
This modules takes a dataset and equalizes its histogram.
virtual ~WMFiberParameterColoring()
Destructor.
std::shared_ptr< WModuleOutputData< WDataSetFibers > > m_fiberOutput
The output connector used to provide the calculated data to other modules.
virtual const std::string getDescription() const
Gives back a description of this module.
WMFiberParameterColoring()
Default constructor.
virtual std::shared_ptr< WModule > factory() const
Due to the prototype design pattern used to build modules, this method returns a new instance of this...
virtual void moduleMain()
Entry point after loading the module.
virtual const char ** getXPMIcon() const
Get the icon for this module in XPM format.
std::shared_ptr< WModuleInputData< WDataSetFibers > > m_fiberInput
The fiber dataset which is going to be filtered.
WPropColor m_scaleColor
The color gets scaled by the calculated color (i.e.
virtual void properties()
Initialize the properties for this module.
virtual void connectors()
Initialize the connectors this module is using.
WDataSetFibers::ColorArray m_fibLengthColors
The colors encoding the segment length.
std::shared_ptr< WCondition > m_propCondition
A condition used to notify about changes in several properties.
WPropColor m_baseColor
The offset color.
WDataSetFibers::ColorArray m_fibCurvatureColors
The colors encoding the curvature.
virtual const std::string getName() const
Gives back the name of this module.
Class offering an instantiate-able data connection between modules.
Class offering an instantiate-able data connection between modules.
Class representing a single module of OpenWalnut.
Definition: WModule.h:72
virtual void properties()
Initialize properties in this function.
Definition: WModule.cpp:212
wlog::WStreamedLogger debugLog() const
Logger instance for comfortable debug logging.
Definition: WModule.cpp:575
void addConnector(std::shared_ptr< WModuleInputConnector > con)
Adds the specified connector to the list of inputs.
Definition: WModule.cpp:108
std::shared_ptr< WProperties > m_properties
The property object for the module.
Definition: WModule.h:640
void ready()
Call this whenever your module is ready and can react on property changes.
Definition: WModule.cpp:505
WConditionSet m_moduleState
The internal state of the module.
Definition: WModule.h:703
std::shared_ptr< WProgressCombiner > m_progress
Progress indicator used as parent for all progress' of this module.
Definition: WModule.h:652
virtual void connectors()
Initialize connectors in this function.
Definition: WModule.cpp:208
Class managing progress inside of modules.
Definition: WProgress.h:42
WBoolFlag m_shutdownFlag
Condition getting fired whenever the thread should quit.