OpenWalnut  1.5.0dev
WMVectorOperator.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 <cmath>
26 #include <fstream>
27 #include <iostream>
28 #include <memory>
29 #include <stdint.h>
30 #include <string>
31 #include <vector>
32 
33 #include <boost/variant.hpp>
34 
35 #include "WMVectorOperator.h"
36 #include "WMVectorOperator.xpm"
37 #include "core/common/WAssert.h"
38 #include "core/common/WProgress.h"
39 #include "core/common/WStringUtils.h"
40 #include "core/common/WTypeTraits.h"
41 #include "core/common/exceptions/WTypeMismatch.h"
42 #include "core/common/math/linearAlgebra/WVectorFixed.h"
43 #include "core/dataHandler/WDataHandler.h"
44 #include "core/dataHandler/WDataHandlerEnums.h"
45 #include "core/dataHandler/WGridRegular3D.h"
46 #include "core/dataHandler/exceptions/WDHValueSetMismatch.h"
47 #include "core/kernel/WKernel.h"
48 
49 // This line is needed by the module loader to actually find your module.
50 W_LOADABLE_MODULE( WMVectorOperator )
51 
53  WModule()
54 {
55  // initialize
56 }
57 
59 {
60  // cleanup
62 }
63 
64 std::shared_ptr< WModule > WMVectorOperator::factory() const
65 {
66  return std::shared_ptr< WModule >( new WMVectorOperator() );
67 }
68 
69 const char** WMVectorOperator::getXPMIcon() const
70 {
71  return WMVectorOperator_xpm;
72 }
73 
74 const std::string WMVectorOperator::getName() const
75 {
76  return "Vector Operator";
77 }
78 
79 const std::string WMVectorOperator::getDescription() const
80 {
81  return "Applies an selected operator on a specified vector field.";
82 }
83 
85 {
86  m_inputA = WModuleInputData< WDataSetVector >::createAndAdd( shared_from_this(), "operandA", "First operand of operation.." );
87 
88  m_output = WModuleOutputData< WDataSetScalar >::createAndAdd( shared_from_this(), "result", "Result of voxel-wise operation( A, B )." );
89 
90  // call WModules initialization
92 }
93 
95 {
96  m_propCondition = std::shared_ptr< WCondition >( new WCondition() );
97 
98  // create a list of operations here
99  m_operations = std::shared_ptr< WItemSelection >( new WItemSelection() );
100  m_operations->addItem( "Length", "Length of the vector." ); // NOTE: you can add XPM images here.
101  m_operations->addItem( "Curvature", "Curvature at each voxel." );
102 
103  m_opSelection = m_properties->addProperty( "Operation", "The operation to apply on A and B.", m_operations->getSelectorFirst(),
104  m_propCondition );
107 
109 }
110 
111 template< typename T >
112 T opLength( const WVector3d& vec,
113  const WVector3d& /*mx*/, const WVector3d& /*px*/,
114  const WVector3d& /*my*/, const WVector3d& /*py*/,
115  const WVector3d& /*mz*/, const WVector3d& /*pz*/ )
116 {
117  return length( vec );
118 }
119 
120 template< typename T >
121 T opCurvature( const WVector3d& vec,
122  const WVector3d& mx, const WVector3d& px,
123  const WVector3d& my, const WVector3d& py,
124  const WVector3d& mz, const WVector3d& pz )
125 {
126  // get partial differentiation in x direction:
127  WVector3d dx = ( px - mx ) / 2.0; // NOTE: step size h=2
128  WVector3d dy = ( py - my ) / 2.0;
129  WVector3d dz = ( pz - mz ) / 2.0;
130 
131  // get second derivative of tangent curve
132  WVector3d L2 = ( vec.x() * dx ) + ( vec.y() * dy ) + ( vec.z() * dz );
133 
134  WVector3d::ValueType l = length( vec );
135  return length( cross( vec, L2 ) ) / ( l * l * l );
136 }
137 
138 /**
139  * Get the ID of a voxel with the given coordinates.
140  *
141  * \param xDim number of voxels in x direction
142  * \param yDim number of voxels in y direction
143  * \param zDim number of voxels in z direction
144  * \param x x coordinate of point to get index for
145  * \param y y coordinate of point to get index for
146  * \param z z coordinate of point to get index for
147  * \param offset which coordinate? 0 = x, 3 = w
148  * \param elements number of elements
149  *
150  * \return the index
151  */
152 size_t getId( size_t xDim, size_t yDim, size_t /*zDim*/, size_t x, size_t y, size_t z, size_t offset = 0, size_t elements = 1 )
153 {
154  return offset + ( elements * ( z * xDim * yDim + y * xDim + x ) );
155 }
156 
157 /**
158  * Visitor for discriminating the type of the first valueset.
159  */
160 class VisitorVSetA: public boost::static_visitor< std::shared_ptr< WValueSetBase > >
161 {
162 public:
163  /**
164  * Create visitor instance.
165  *
166  * \param opIdx The operator index.
167  * \param grid the underlying grid
168  */
169  VisitorVSetA( std::shared_ptr< WGridRegular3D > grid, size_t opIdx = 0 ):
170  boost::static_visitor< result_type >(),
171  m_grid( grid ),
172  m_opIdx( opIdx )
173  {
174  }
175 
176  /**
177  * Called by boost::varying during static visiting.
178  *
179  * \tparam T the real integral type of the first value set.
180  * \param vsetA the first valueset currently visited.
181  *
182  * \return the result from the operation
183  */
184  template < typename T >
185  result_type operator()( const WValueSet< T >* const& vsetA ) const // NOLINT
186  {
187  // get some info
188  std::vector< T > data;
189  data.resize( vsetA->size() );
190 
191  // discriminate the right operation with the correct type. It would be nicer to use some kind of strategy pattern here, but the template
192  // character of the operators forbids it as template methods can't be virtual. Besides this, at some point in the module main the
193  // selector needs to be queried and its index mapped to a pointer. This is what we do here.
194  boost::function< T( const WVector3d&,
195  const WVector3d&, const WVector3d&,
196  const WVector3d&, const WVector3d&,
197  const WVector3d&, const WVector3d& ) > op;
198  switch( m_opIdx )
199  {
200  case 1:
201  op = &opCurvature< T >;
202  break;
203  case 0:
204  default:
205  op = &opLength< T >;
206  break;
207  }
208 
209  // some info needed for indexing the vector components
210  size_t nX = m_grid->getNbCoordsX();
211  size_t nY = m_grid->getNbCoordsY();
212  size_t nZ = m_grid->getNbCoordsZ();
213 
214  // apply op to each value
215  // iterate field
216  for( size_t z = 1; z < nZ - 1; z++ )
217  {
218  for( size_t y = 1; y < nY - 1; y++ )
219  {
220  for( size_t x = 1; x < nX - 1; x++ )
221  {
222  // this is ugly. We'll fix this crap with the upcoming new data handler
223  size_t idx = getId( nX, nY, nZ, x, y, z );
224  WVector3d vec = vsetA->getVector3D( idx );
225 
226  // also get the neighbours
227  WVector3d mx = vsetA->getVector3D( getId( nX, nY, nZ, x - 1, y, z ) );
228  WVector3d px = vsetA->getVector3D( getId( nX, nY, nZ, x + 1, y, z ) );
229  WVector3d my = vsetA->getVector3D( getId( nX, nY, nZ, x, y - 1, z ) );
230  WVector3d py = vsetA->getVector3D( getId( nX, nY, nZ, x, y + 1, z ) );
231  WVector3d mz = vsetA->getVector3D( getId( nX, nY, nZ, x, y, z - 1 ) );
232  WVector3d pz = vsetA->getVector3D( getId( nX, nY, nZ, x, y, z + 1 ) );
233 
234  data[ idx ] = op( vec, mx, px, my, py, mz, pz );
235  }
236  }
237  }
238 
239  // init the border values
240  for( size_t z = 0; z < 2; z++ )
241  {
242  for( size_t y = 1; y < 2; y++ )
243  {
244  for( size_t x = 1; x < 2; x++ )
245  {
246  size_t idx = getId( nX, nY, nZ, x * ( nX - 1 ), y * ( nY - 1 ), z * ( nZ - 1 ) );
247  data[ idx ] = 0.0;
248  }
249  }
250  }
251 
252  // create result value set
253  return std::shared_ptr< WValueSet< T > >( new WValueSet< T >( 0,
254  1,
255  std::shared_ptr< std::vector< T > >(
256  new std::vector< T >( data ) ),
258  }
259 
260  /**
261  * The underlying grid.
262  */
263  std::shared_ptr< WGridRegular3D > m_grid;
264 
265  /**
266  * The operator index.
267  */
268  size_t m_opIdx;
269 };
270 
272 {
273  // let the main loop awake if the data changes or the properties changed.
274  m_moduleState.setResetable( true, true );
275  m_moduleState.add( m_inputA->getDataChangedCondition() );
277 
278  // signal ready state
279  ready();
280 
281  // loop until the module container requests the module to quit
282  while( !m_shutdownFlag() )
283  {
284  // Now, the moduleState variable comes into play. The module can wait for the condition, which gets fired whenever the input receives data
285  // or an property changes. The main loop now waits until something happens.
286  debugLog() << "Waiting ...";
288 
289  // woke up since the module is requested to finish
290  if( m_shutdownFlag() )
291  {
292  break;
293  }
294 
295  // has the data changed?
296  if( m_opSelection->changed() || m_inputA->handledUpdate() )
297  {
298  std::shared_ptr< WDataSetVector > dataSetA = m_inputA->getData();
299 
300  WItemSelector s = m_opSelection->get( true );
301 
302  // valid data?
303  if( dataSetA )
304  {
305  std::shared_ptr< WValueSetBase > valueSetA = dataSetA->getValueSet();
306 
307  // use a custom progress combiner
308  std::shared_ptr< WProgress > prog = std::shared_ptr< WProgress >(
309  new WProgress( "Applying operator on data" ) );
310  m_progress->addSubProgress( prog );
311 
312  // apply the operation to each voxel
313  debugLog() << "Processing ...";
314  std::shared_ptr< WValueSetBase > newValueSet = valueSetA->applyFunction( VisitorVSetA(
315  std::dynamic_pointer_cast< WGridRegular3D >( dataSetA->getGrid() ), s )
316  );
317 
318  // Create the new dataset and export it
319  m_output->updateData( std::shared_ptr<WDataSetScalar>( new WDataSetScalar( newValueSet, m_inputA->getData()->getGrid() ) ) );
320 
321  // done
322  prog->finish();
323  m_progress->removeSubProgress( prog );
324  }
325  else
326  {
327  debugLog() << "Resetting output.";
328  m_output->reset();
329  }
330  }
331  }
332 }
333 
Visitor for discriminating the type of the first valueset.
std::shared_ptr< WGridRegular3D > m_grid
The underlying grid.
result_type operator()(const WValueSet< T > *const &vsetA) const
Called by boost::varying during static visiting.
VisitorVSetA(std::shared_ptr< WGridRegular3D > grid, size_t opIdx=0)
Create visitor instance.
size_t m_opIdx
The operator index.
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
This data set type contains scalars as values.
A class containing a list of named items.
This class represents a subset of a WItemSelection.
Definition: WItemSelector.h:53
Operators for processing two WDataSetScalar.
std::shared_ptr< WCondition > m_propCondition
A condition used to notify about changes in several properties.
std::shared_ptr< WModuleOutputData< WDataSetScalar > > m_output
The only output of this filter module.
WPropSelection m_opSelection
The currently selected operation.
virtual const char ** getXPMIcon() const
Get the icon for this module in XPM format.
WMVectorOperator()
Standard constructor.
~WMVectorOperator()
Destructor.
virtual const std::string getName() const
Gives back the name of this module.
std::shared_ptr< WItemSelection > m_operations
A list of operations that are possible.
virtual void moduleMain()
Entry point after loading the module.
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 properties()
Initialize the properties for this module.
std::shared_ptr< WModuleInputData< WDataSetVector > > m_inputA
Input connector required by this module.
virtual void connectors()
Initialize the connectors this module is using.
virtual const std::string getDescription() const
Gives back a description of this module.
ValueT & z()
Access z element of vector.
double ValueType
The integral type used in this matrix.
Definition: WMatrixFixed.h:166
ValueT & y()
Access y element of vector.
ValueT & x()
Access x element of vector.
static PtrType createAndAdd(std::shared_ptr< WModule > module, std::string name="", std::string description="")
Convenience method to create a new instance of this in data connector with proper type and add it to ...
static PtrType createAndAdd(std::shared_ptr< WModule > module, std::string name="", std::string description="")
Convenience method to create a new instance of this out data connector with proper type and add it to...
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 removeConnectors()
Removes all connectors properly.
Definition: WModule.cpp:194
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.
Base Class for all value set types.
Definition: WValueSet.h:47
void addTo(WPropSelection prop)
Add the PC_NOTEMPTY constraint to the property.
void addTo(WPropSelection prop)
Add the PC_SELECTONLYONE constraint to the property.
An object that knows an appropriate dataType flag for the typename T.