~ubuntu-branches/ubuntu/raring/openwalnut/raring

« back to all changes in this revision

Viewing changes to src/modules/spatialDerivative/WMSpatialDerivative.cpp

  • Committer: Package Import Robot
  • Author(s): Sebastian Eichelbaum
  • Date: 2012-12-12 11:26:32 UTC
  • mfrom: (3.1.1 sid)
  • Revision ID: package-import@ubuntu.com-20121212112632-xhiuwkxuz5h0idkh
Tags: 1.3.1+hg5849-1
* Minor changes compared to 1.3.0 but included several bug fixes.
* See http://www.openwalnut.org/versions/4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 <vector>
 
26
#include <string>
 
27
 
 
28
#include "core/kernel/WKernel.h"
 
29
#include "core/common/WPropertyHelper.h"
 
30
#include "core/dataHandler/WDataHandler.h"
 
31
 
 
32
#include "WMSpatialDerivative.h"
 
33
#include "WMSpatialDerivative.xpm"
 
34
 
 
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 )
 
37
 
 
38
WMSpatialDerivative::WMSpatialDerivative():
 
39
    WModule()
 
40
{
 
41
}
 
42
 
 
43
WMSpatialDerivative::~WMSpatialDerivative()
 
44
{
 
45
    // Cleanup!
 
46
}
 
47
 
 
48
boost::shared_ptr< WModule > WMSpatialDerivative::factory() const
 
49
{
 
50
    return boost::shared_ptr< WModule >( new WMSpatialDerivative() );
 
51
}
 
52
 
 
53
const char** WMSpatialDerivative::getXPMIcon() const
 
54
{
 
55
    return WMSpatialDerivative_xpm;
 
56
}
 
57
 
 
58
const std::string WMSpatialDerivative::getName() const
 
59
{
 
60
    return "Spatial Derivative";
 
61
}
 
62
 
 
63
const std::string WMSpatialDerivative::getDescription() const
 
64
{
 
65
    return "This module a scalar field and derives it spatially.";
 
66
}
 
67
 
 
68
void WMSpatialDerivative::connectors()
 
69
{
 
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." );
 
73
 
 
74
    // output vector data
 
75
    m_vectorOut = WModuleOutputData< WDataSetVector >::createAndAdd( shared_from_this(), "derived", "The vector dataset representing spatial"
 
76
                                                                                                    " derivate of the input field." );
 
77
 
 
78
    // call WModule's initialization
 
79
    WModule::connectors();
 
80
}
 
81
 
 
82
void WMSpatialDerivative::properties()
 
83
{
 
84
    m_propCondition = boost::shared_ptr< WCondition >( new WCondition() );
 
85
 
 
86
    // normalizing?
 
87
    m_normalize = m_properties->addProperty( "Normalize", "If true, vectors get normalized.", true, m_propCondition );
 
88
 
 
89
    // call WModule's initialization
 
90
    WModule::properties();
 
91
}
 
92
 
 
93
void WMSpatialDerivative::moduleMain()
 
94
{
 
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 );
 
100
 
 
101
    ready();
 
102
 
 
103
    // main loop
 
104
    while( !m_shutdownFlag() )
 
105
    {
 
106
        debugLog() << "Waiting ...";
 
107
        m_moduleState.wait();
 
108
 
 
109
        // woke up since the module is requested to finish?
 
110
        if( m_shutdownFlag() )
 
111
        {
 
112
            break;
 
113
        }
 
114
 
 
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();
 
118
 
 
119
        bool dataValid = ( dataSet );
 
120
 
 
121
        // reset output if input was reset/disconnected
 
122
        if( !dataValid )
 
123
        {
 
124
            debugLog() << "Resetting output.";
 
125
            m_vectorOut->reset();
 
126
            continue;
 
127
        }
 
128
        if( dataValid && !dataUpdated )
 
129
        {
 
130
            continue;
 
131
        }
 
132
 
 
133
        // prepare progress indicators
 
134
        boost::shared_ptr< WProgress > progress = boost::shared_ptr< WProgress >( new WProgress( "Processing", 0 ) );
 
135
        m_progress->addSubProgress( progress );
 
136
 
 
137
        // loop through each voxel
 
138
        boost::shared_ptr< WGridRegular3D > grid = boost::shared_dynamic_cast< WGridRegular3D >( dataSet->getGrid() );
 
139
        if( !grid )
 
140
        {
 
141
            errorLog() << "Only regular 3D grids allowed.";
 
142
            continue;
 
143
        }
 
144
 
 
145
        switch( dataSet->getValueSet()->getDataType() )
 
146
        {
 
147
            case W_DT_UNSIGNED_CHAR:
 
148
            {
 
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 );
 
153
                break;
 
154
            }
 
155
            case W_DT_INT16:
 
156
            {
 
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 );
 
161
                break;
 
162
            }
 
163
            case W_DT_SIGNED_INT:
 
164
            {
 
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 );
 
169
                break;
 
170
            }
 
171
            case W_DT_FLOAT:
 
172
            {
 
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 );
 
177
                break;
 
178
            }
 
179
            case W_DT_DOUBLE:
 
180
            {
 
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 );
 
185
                break;
 
186
            }
 
187
            default:
 
188
                WAssert( false, "Unknown data type in." );
 
189
        }
 
190
 
 
191
        // work done
 
192
        progress->finish();
 
193
        m_progress->removeSubProgress( progress );
 
194
 
 
195
        debugLog() << "Done";
 
196
    }
 
197
}
 
198
 
 
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 )
 
200
{
 
201
    return offset + ( elements * ( z * xDim * yDim + y * xDim + x ) );
 
202
}
 
203
 
 
204
template< typename T >
 
205
void WMSpatialDerivative::derive( boost::shared_ptr< WGridRegular3D > grid, boost::shared_ptr< WValueSet< T > > values )
 
206
{
 
207
    size_t nX = grid->getNbCoordsX();
 
208
    size_t nY = grid->getNbCoordsY();
 
209
    size_t nZ = grid->getNbCoordsZ();
 
210
 
 
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 ) );
 
213
 
 
214
    // iterate field
 
215
    for( size_t z = 1; z < nZ - 1; z++ )
 
216
    {
 
217
        for( size_t y = 1; y < nY - 1; y++ )
 
218
        {
 
219
            for( size_t x = 1; x < nX - 1; x++ )
 
220
            {
 
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 ) );
 
229
 
 
230
                float vx = ( xp - xm ) / 2.0;
 
231
                float vy = ( yp - ym ) / 2.0;
 
232
                float vz = ( zp - zm ) / 2.0;
 
233
 
 
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;
 
237
                if( len == 0.0 )
 
238
                    scal = 0.0;
 
239
 
 
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;
 
243
            }
 
244
        }
 
245
    }
 
246
 
 
247
    boost::shared_ptr< WValueSet< double > > valueset = boost::shared_ptr< WValueSet< double > >(
 
248
                                                            new WValueSet< double >( 1, 3, vectors, W_DT_DOUBLE )
 
249
                                                        );
 
250
    // register new
 
251
    m_vectorOut->updateData( boost::shared_ptr< WDataSetVector >( new WDataSetVector( valueset, grid ) ) );
 
252
}
 
253