Commit 8a1e16a9 authored by Mathias Goldau's avatar Mathias Goldau
Browse files

[ADD] New simple tract resampler prepared...

parent d5917a47
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#include <iostream>
#include <vector>
#include "../../common/math/WPosition.h"
#include "WSimpleResampler.h"
WSimpleResampler::WSimpleResampler( size_t numSamples )
: m_numSamples( numSamples )
{
}
void WSimpleResampler::resample( boost::shared_ptr< const std::vector< double > > verts,
const size_t startIdx,
const size_t length,
boost::shared_ptr< std::vector< double > > newVerts,
const size_t newStartIdx ) const
{
if( length != m_numSamples && length > 0 && m_numSamples > 0 )
{
// 1. compute length of tract
// 2. compute new segment length
// 3. walk along the tract and make every new segment length a new sample point.
// 4. YES I know that this does not result in perfect equidistant
// sample points, but thats exactly the reason why this algo has the
// SIMPLE in its name :P
const double pathLength = lineIntegration( verts, startIdx, length );
const double newSegmentLength = pathLength / ( m_numSamples - 1 );
double remainingLength = 0.0;
(*newVerts)[newStartIdx * 3 ] = (*verts)[startIdx * 3 ];
(*newVerts)[newStartIdx * 3 + 1] = (*verts)[startIdx * 3 + 1];
(*newVerts)[newStartIdx * 3 + 2] = (*verts)[startIdx * 3 + 2];
for( size_t i = startIdx * 3, j = ( newStartIdx + 1 ) * 3; i < ( startIdx + length - 1 ) * 3; i += 3 )
{
wmath::WPosition current( ( *verts )[i], ( *verts )[i + 1], ( *verts )[i + 2] );
wmath::WPosition next( ( *verts )[i + 3], ( *verts )[i + 4], ( *verts )[i + 5] );
remainingLength += ( current - next ).norm();
while( remainingLength > newSegmentLength )
{
remainingLength -= newSegmentLength;
wmath::WPosition newPoint = next + remainingLength * ( current - next ).normalized();
( *newVerts )[j ] = newPoint[0];
( *newVerts )[j + 1] = newPoint[1];
( *newVerts )[j + 2] = newPoint[2];
j += 3;
}
}
}
}
double WSimpleResampler::lineIntegration( boost::shared_ptr< const std::vector< double > > verts,
const size_t startIdx,
const size_t length ) const
{
double result = 0.0;
size_t start = startIdx * 3;
wmath::WPosition last( ( *verts )[start], ( *verts )[start + 1], ( *verts )[start + 2] );
for( size_t i = startIdx * 3; i < ( startIdx + length - 1 ) * 3; i += 3 )
{
wmath::WPosition current( ( *verts )[i], ( *verts )[i + 1], ( *verts )[i + 2] );
wmath::WPosition next( ( *verts )[i + 3], ( *verts )[i + 4], ( *verts )[i + 5] );
result += ( current - next ).norm();
}
return result;
}
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#ifndef WSIMPLERESAMPLER_H
#define WSIMPLERESAMPLER_H
#include <vector>
#include <boost/shared_ptr.hpp>
/**
* Algorithm to resample a single tract into almost equidistant segments.
*
* \note Since this is a SIMPLE resampler, it measures along the given tract or
* curve an equidistant width, and places its sample points at each segment
* end. This clearly leads to shorter segments incase of strong curvature
* (which is taken to measure the segments) replaced by a straight segment line
* which may be shorter then.
*/
class WSimpleResampler
{
friend class WSimpleResamplerTest;
public:
/**
* Constructs a new Sampling instance for a given number of sample points.
*
* \param numSamples The new number of sample points.
*/
explicit WSimpleResampler( size_t numSamples );
/**
* Resamples a tract (given via <em>verts, startIdx</em> and \e length) to
* the number of samples points given in the constructor of this instance.
*
* \param verts Pointer to the original vertices array
*
* \param startIdx Start position of the first vertex.
*
* \param length The number of VERTICES (not components nor doubles) the
* tract is about.
*
* \param newVerts The place where to save the new sample points. Since all
* new tracts will have the same length the start index can be derived from
* startIdx.
*
* \param newStartIdx The new offset where to write the new sample points.
* This is also a direct component or double index (as startIdx is) but not
* a vertex index.
*
* \note The only reason for the fourth argument is that the memory can be
* allocated before the sampling takes places which could lead to
* performance losses when multithreading and dynamic allocation comes into
* play.
*/
void resample( boost::shared_ptr< const std::vector< double > > verts,
const size_t startIdx,
const size_t length,
boost::shared_ptr< std::vector< double > > newVerts,
const size_t newStartIdx ) const;
protected:
double lineIntegration( boost::shared_ptr< const std::vector< double > > verts,
const size_t startIdx,
const size_t length ) const;
private:
/**
* The new number of points where each given tract is sampled to.
*/
size_t m_numSamples;
};
#endif // WSIMPLERESAMPLER_H
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#ifndef WSIMPLERESAMPLER_TEST_H
#define WSIMPLERESAMPLER_TEST_H
#include <sstream>
#include <vector>
#include <cxxtest/TestSuite.h>
#include "../WSimpleResampler.h"
/**
* Testsuite for the simple resample method.
*/
class WSimpleResamplerTest : public CxxTest::TestSuite
{
public:
/**
* The line integrator sum's up all segment's length''''ssss. Damn I never
* know when to set the apostroph''ss...
*/
void testLineIntegration( void )
{
WSimpleResampler r( 0 );
TS_ASSERT_EQUALS( r.lineIntegration( m_equiTractVerts, m_startIdx, m_length ), std::sqrt( 3.0 ) * 4.0 );
}
/**
* If there is the same number of sample points given then the tract should
* be resampled equidistantly into \c n-1 segments when having \c n new
* sample points.
*/
void testResamplingWithGivenNumberOfNewSamplePoints( void )
{
WSimpleResampler r( 3 );
boost::shared_ptr< std::vector< double > > newTractVerts( new std::vector< double >( 9*3, -1.0 ) );
r.resample( m_equiTractVerts, m_startIdx, m_length, newTractVerts, 3 );
double verts[] = { -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, // NOLINT
0.0, 0.0, 0.0,
2.0, 2.0, 2.0,
4.0, 4.0, 4.0,
-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0 }; // NOLINT
std::vector< double > expected( verts, verts + sizeof( verts ) / sizeof( double ) );
TS_ASSERT_EQUALS( expected.size(), newTractVerts->size() );
for( size_t i = 0; i < expected.size(); ++i )
{
if( std::abs( expected[i] - (*newTractVerts)[i] ) > 1.0e-10 )
{
std::stringstream ss;
ss << "Positions differ in index: " << i << " with expected: " << expected[i] << " but got " << (*newTractVerts)[i];
TS_FAIL( ss.str() );
}
}
}
// /**
// * When a given new segment length is given, resample the fiber in segments
// * of this length, the last segment may be not that length.
// * TODO(math): please talk to sebastian, if that really makes sense??
// */
// void testResampleWithGivenSegmentLength( void )
// {
// }
/**
* If the tract is not equidistant sampled than this should work:
* TODO(math): describe the drawbacks of the simple resampler
*/
void testResamplingOnNonEquidistantTract( void )
{
}
/**
* The resampling should also work with equidistant sampled tracts.
*/
void testResamplingOnEquidistantTract( void )
{
}
/**
* Prepares two single fibers, one which is equidistant sampled and one
* which is not. Also the vertex array is simulated, as well as start index
* and length.
*/
void setUp( void )
{
double vertsE[] = { -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, // NOLINT array init list
0.0, 0.0, 0.0,
1.0, 1.0, 1.0,
2.0, 2.0, 2.0,
3.0, 3.0, 3.0,
4.0, 4.0, 4.0,
-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0 }; // NOLINT array init list
m_equiTractVerts = boost::shared_ptr< std::vector< double > >( new std::vector< double >( vertsE, vertsE + sizeof( vertsE ) / sizeof( double ) ) ); // NOLINT long line
m_startIdx = 5;
m_length = 5;
double vertsNE[] = { -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, // NOLINT array init list
0.75, 0.0, 0.0,
0.8, 0.9, 0.0,
1.0, 1.0, 0.0,
1.2, 0.9, 0.0,
1.25, 0.0, 0.0,
-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0 }; // NOLINT array init list
m_nonEquiTractVerts = boost::shared_ptr< std::vector< double > >( new std::vector< double >( vertsNE, vertsNE + sizeof( vertsNE ) / sizeof( double ) ) ); // NOLINT long line
}
/**
* We do not need to remove the arrays since the are not allocated via the
* NEW operator. But we should clear the vectors and reset the indices.
*/
void tearDown( void )
{
m_equiTractVerts->clear();
m_nonEquiTractVerts->clear();
m_startIdx = 0;
m_length = 0;
}
private:
/**
* Simulates a vertex array of equidistant sampled tracts as you will have
* with WDataSetFibers.
*/
boost::shared_ptr< std::vector< double > > m_equiTractVerts;
/**
* Simulates a vertex array of non equidistant sampled tracts as you maybe
* will have with WDataSetFibers.
*/
boost::shared_ptr< std::vector< double > > m_nonEquiTractVerts;
/**
* Simulates the start index of the a tract inside of the vertex array.
*/
size_t m_startIdx;
/**
* Simulates the length of the tract inside of the vertex array.
*/
size_t m_length;
};
#endif // WSIMPLERESAMPLER_TEST_H
......@@ -14,6 +14,7 @@ ADD_SUBDIRECTORY( effectiveConnectivityCluster )
ADD_SUBDIRECTORY( fiberDisplaySimple )
ADD_SUBDIRECTORY( fiberSelection )
ADD_SUBDIRECTORY( fiberTransform )
ADD_SUBDIRECTORY( fiberResampling )
ADD_SUBDIRECTORY( imageExtractor )
ADD_SUBDIRECTORY( lineGuidedSlice )
ADD_SUBDIRECTORY( probTractDisplay )
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment