1
//---------------------------------------------------------------------------
3
// Project: OpenWalnut ( http://www.openwalnut.org )
5
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6
// For more information see http://www.openwalnut.org/copying
8
// This file is part of OpenWalnut.
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.
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.
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/>.
23
//---------------------------------------------------------------------------
28
#include "core/kernel/WKernel.h"
29
#include "core/common/WPropertyHelper.h"
30
#include "core/dataHandler/WDataHandler.h"
32
#include "WMSpatialDerivative.h"
33
#include "WMSpatialDerivative.xpm"
35
// 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.
36
W_LOADABLE_MODULE( WMSpatialDerivative )
38
WMSpatialDerivative::WMSpatialDerivative():
43
WMSpatialDerivative::~WMSpatialDerivative()
48
boost::shared_ptr< WModule > WMSpatialDerivative::factory() const
50
return boost::shared_ptr< WModule >( new WMSpatialDerivative() );
53
const char** WMSpatialDerivative::getXPMIcon() const
55
return WMSpatialDerivative_xpm;
58
const std::string WMSpatialDerivative::getName() const
60
return "Spatial Derivative";
63
const std::string WMSpatialDerivative::getDescription() const
65
return "This module a scalar field and derives it spatially.";
68
void WMSpatialDerivative::connectors()
70
// the dataset to process. Only accept scalar data.
71
m_scalarIn = WModuleInputData< WDataSetScalar >::createAndAdd( shared_from_this(), "scalars", "The scalar dataset."
72
"Needs to be in the same grid as the mesh." );
75
m_vectorOut = WModuleOutputData< WDataSetVector >::createAndAdd( shared_from_this(), "derived", "The vector dataset representing spatial"
76
" derivate of the input field." );
78
// call WModule's initialization
79
WModule::connectors();
82
void WMSpatialDerivative::properties()
84
m_propCondition = boost::shared_ptr< WCondition >( new WCondition() );
87
m_normalize = m_properties->addProperty( "Normalize", "If true, vectors get normalized.", true, m_propCondition );
89
// call WModule's initialization
90
WModule::properties();
93
void WMSpatialDerivative::moduleMain()
95
// get notified about data changes
96
m_moduleState.setResetable( true, true );
97
m_moduleState.add( m_scalarIn->getDataChangedCondition() );
98
// Remember the condition provided to some properties in properties()? The condition can now be used with this condition set.
99
m_moduleState.add( m_propCondition );
104
while( !m_shutdownFlag() )
106
debugLog() << "Waiting ...";
107
m_moduleState.wait();
109
// woke up since the module is requested to finish?
110
if( m_shutdownFlag() )
115
// To query whether an input was updated, simply ask the input:
116
bool dataUpdated = m_scalarIn->handledUpdate() || m_normalize->changed();
117
boost::shared_ptr< WDataSetScalar > dataSet = m_scalarIn->getData();
119
bool dataValid = ( dataSet );
121
// reset output if input was reset/disconnected
124
debugLog() << "Resetting output.";
125
m_vectorOut->reset();
128
if( dataValid && !dataUpdated )
133
// prepare progress indicators
134
boost::shared_ptr< WProgress > progress = boost::shared_ptr< WProgress >( new WProgress( "Processing", 0 ) );
135
m_progress->addSubProgress( progress );
137
// loop through each voxel
138
boost::shared_ptr< WGridRegular3D > grid = boost::shared_dynamic_cast< WGridRegular3D >( dataSet->getGrid() );
141
errorLog() << "Only regular 3D grids allowed.";
145
switch( dataSet->getValueSet()->getDataType() )
147
case W_DT_UNSIGNED_CHAR:
149
boost::shared_ptr<WValueSet<unsigned char> > vals;
150
vals = boost::shared_dynamic_cast<WValueSet<unsigned char> >( dataSet->getValueSet() );
151
WAssert( vals, "Data type and data type indicator must fit." );
152
derive( grid, vals );
157
boost::shared_ptr<WValueSet<int16_t> > vals;
158
vals = boost::shared_dynamic_cast<WValueSet<int16_t> >( dataSet->getValueSet() );
159
WAssert( vals, "Data type and data type indicator must fit." );
160
derive( grid, vals );
163
case W_DT_SIGNED_INT:
165
boost::shared_ptr<WValueSet<int32_t> > vals;
166
vals = boost::shared_dynamic_cast<WValueSet<int32_t> >( dataSet->getValueSet() );
167
WAssert( vals, "Data type and data type indicator must fit." );
168
derive( grid, vals );
173
boost::shared_ptr< WValueSet< float > > vals;
174
vals = boost::shared_dynamic_cast< WValueSet< float > >( dataSet->getValueSet() );
175
WAssert( vals, "Data type and data type indicator must fit." );
176
derive( grid, vals );
181
boost::shared_ptr< WValueSet< double > > vals;
182
vals = boost::shared_dynamic_cast< WValueSet< double > >( dataSet->getValueSet() );
183
WAssert( vals, "Data type and data type indicator must fit." );
184
derive( grid, vals );
188
WAssert( false, "Unknown data type in." );
193
m_progress->removeSubProgress( progress );
195
debugLog() << "Done";
199
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 )
201
return offset + ( elements * ( z * xDim * yDim + y * xDim + x ) );
204
template< typename T >
205
void WMSpatialDerivative::derive( boost::shared_ptr< WGridRegular3D > grid, boost::shared_ptr< WValueSet< T > > values )
207
size_t nX = grid->getNbCoordsX();
208
size_t nY = grid->getNbCoordsY();
209
size_t nZ = grid->getNbCoordsZ();
211
boost::shared_ptr< std::vector< double > > vectors =
212
boost::shared_ptr< std::vector< double > >( new std::vector< double >( 3 * nX * nY * nZ, 0.0 ) );
215
for( size_t z = 1; z < nZ - 1; z++ )
217
for( size_t y = 1; y < nY - 1; y++ )
219
for( size_t x = 1; x < nX - 1; x++ )
221
// TODO(ebaum): improve performance
222
// this loop should be quite slow but it works for now. Sorry.
223
float xp = values->getScalar( getId( nX, nY, nZ, x + 1, y, z ) );
224
float xm = values->getScalar( getId( nX, nY, nZ, x - 1, y, z ) );
225
float yp = values->getScalar( getId( nX, nY, nZ, x, y + 1, z ) );
226
float ym = values->getScalar( getId( nX, nY, nZ, x, y - 1, z ) );
227
float zp = values->getScalar( getId( nX, nY, nZ, x, y, z + 1 ) );
228
float zm = values->getScalar( getId( nX, nY, nZ, x, y, z - 1 ) );
230
float vx = ( xp - xm ) / 2.0;
231
float vy = ( yp - ym ) / 2.0;
232
float vz = ( zp - zm ) / 2.0;
234
float sqsum = vx * vx + vy * vy + vz * vz;
235
float len = sqrt( sqsum );
236
float scal = m_normalize->get( true ) ? 1.0 / len : 1.0;
240
( *vectors )[ getId( nX, nY, nZ, x, y, z, 0, 3 ) ] = scal * vx;
241
( *vectors )[ getId( nX, nY, nZ, x, y, z, 1, 3 ) ] = scal * vy;
242
( *vectors )[ getId( nX, nY, nZ, x, y, z, 2, 3 ) ] = scal * vz;
247
boost::shared_ptr< WValueSet< double > > valueset = boost::shared_ptr< WValueSet< double > >(
248
new WValueSet< double >( 1, 3, vectors, W_DT_DOUBLE )
251
m_vectorOut->updateData( boost::shared_ptr< WDataSetVector >( new WDataSetVector( valueset, grid ) ) );