Commit 36953055 authored by Mathias Goldau's avatar Mathias Goldau

[MERGE]

parent 48eabf0c
...@@ -4,8 +4,8 @@ ...@@ -4,8 +4,8 @@
[modules] [modules]
# use this to specify the default module to add during load. # use this to specify the default module to add during load.
# It is a comma seperated list. If this is not specified the default is assumed: # It is a comma seperated list. If this is not specified the default is assumed:
# "Coordinate System Module,HUD,Navigation Slice Module" # "Coordinate System Module,HUD"
default="Coordinate System Module,HUD,Navigation Slice Module" default="Coordinate System Module,HUD"
# MC.isoValue = 110 # set standard isovalue for marching cubes module (isosurface) # MC.isoValue = 110 # set standard isovalue for marching cubes module (isosurface)
[qt4gui] [qt4gui]
...@@ -21,3 +21,4 @@ default="Coordinate System Module,HUD,Navigation Slice Module" ...@@ -21,3 +21,4 @@ default="Coordinate System Module,HUD,Navigation Slice Module"
# bgColor.g = .9 # background color (green part) # bgColor.g = .9 # background color (green part)
# bgColor.b = .9 # background color (blue part) # bgColor.b = .9 # background color (blue part)
# zoomTrackballManipulator.allowThrow = yes # allow the auto-rotation thing when "throwing" an object with the mouse # zoomTrackballManipulator.allowThrow = yes # allow the auto-rotation thing when "throwing" an object with the mouse
# multiThreadedViewers = no # Use multiple threads for the multiple viewers. Causes hanging on some machines when opening a new view.
...@@ -96,7 +96,7 @@ IF( CMAKE_HOST_SYSTEM MATCHES Windows ) ...@@ -96,7 +96,7 @@ IF( CMAKE_HOST_SYSTEM MATCHES Windows )
SET( CMAKE_SHARED_LINKER_FLAGS " /STACK:10000000 /machine:I386 /NODEFAULTLIB:${EXCLUDE_LIBRARIES}" CACHE STRING "" FORCE ) SET( CMAKE_SHARED_LINKER_FLAGS " /STACK:10000000 /machine:I386 /NODEFAULTLIB:${EXCLUDE_LIBRARIES}" CACHE STRING "" FORCE )
SET( CMAKE_EXE_LINKER_FLAGS " /STACK:10000000 /machine:I386 /NODEFAULTLIB:${EXCLUDE_LIBRARIES}" CACHE STRING "" FORCE ) SET( CMAKE_EXE_LINKER_FLAGS " /STACK:10000000 /machine:I386 /NODEFAULTLIB:${EXCLUDE_LIBRARIES}" CACHE STRING "" FORCE )
ELSE() ELSE()
SET( CMAKE_CXX_FLAGS "-frtti -pedantic -ansi -Wall -Wno-long-long -Wextra" CACHE STRING "" FORCE ) SET( CMAKE_CXX_FLAGS "-frtti -pedantic -ansi -Wall -Wno-long-long -Wextra -Wold-style-cast" CACHE STRING "" FORCE )
SET( CMAKE_CXX_FLAGS_RELEASE "-O3" CACHE STRING "" FORCE ) SET( CMAKE_CXX_FLAGS_RELEASE "-O3" CACHE STRING "" FORCE )
SET( CMAKE_CXX_FLAGS_DEBUG "-g -DDEBUG -O0" CACHE STRING "" FORCE ) SET( CMAKE_CXX_FLAGS_DEBUG "-g -DDEBUG -O0" CACHE STRING "" FORCE )
ENDIF() ENDIF()
......
...@@ -68,6 +68,16 @@ namespace wlimits ...@@ -68,6 +68,16 @@ namespace wlimits
* Minimum double value * Minimum double value
*/ */
const double MIN_DOUBLE = std::numeric_limits< double >::min(); const double MIN_DOUBLE = std::numeric_limits< double >::min();
/**
* Smallest double such: 1.0 + DBL_EPS == 1.0 is still true.
*/
const double DBL_EPS = std::numeric_limits< double >::epsilon();
/**
* Smallest float such: 1.0 + FLT_EPS == 1.0 is still true.
*/
const float FLT_EPS = std::numeric_limits< float >::epsilon();
} }
#endif // WLIMITS_H #endif // WLIMITS_H
...@@ -73,7 +73,7 @@ public: ...@@ -73,7 +73,7 @@ public:
* *
* \return true if usable as texture. * \return true if usable as texture.
*/ */
// TODO(seralph): pure virtual? Are WDataSet instances useful? // TODO(schurade): pure virtual? Are WDataSet instances useful?
virtual bool isTexture() const; virtual bool isTexture() const;
/** /**
......
...@@ -135,16 +135,19 @@ osg::ref_ptr< osg::Image > WDataTexture3D::createTexture3D( unsigned char* sourc ...@@ -135,16 +135,19 @@ osg::ref_ptr< osg::Image > WDataTexture3D::createTexture3D( unsigned char* sourc
data[i] = source[i]; data[i] = source[i];
} }
} }
else
{
// TODO(schurade): throw exception if components!=1 or 3
wlog::error( "WDataTexture3D" ) << "Did not handle ( components != 1 || components != 3 ).";
}
return ima; return ima;
// TODO(seralph): throw exception if components!=1 or 3
} }
osg::ref_ptr< osg::Image > WDataTexture3D::createTexture3D( int16_t* source, int components ) osg::ref_ptr< osg::Image > WDataTexture3D::createTexture3D( int16_t* source, int components )
{ {
osg::ref_ptr< osg::Image > ima = new osg::Image; osg::ref_ptr< osg::Image > ima = new osg::Image;
// TODO(seralph): throw exception if components!=1 or 3 if( components == 1 )
if ( components == 1)
{ {
int nSize = m_grid->getNbCoordsX() * m_grid->getNbCoordsY() * m_grid->getNbCoordsZ(); int nSize = m_grid->getNbCoordsX() * m_grid->getNbCoordsY() * m_grid->getNbCoordsZ();
...@@ -194,33 +197,43 @@ osg::ref_ptr< osg::Image > WDataTexture3D::createTexture3D( int16_t* source, int ...@@ -194,33 +197,43 @@ osg::ref_ptr< osg::Image > WDataTexture3D::createTexture3D( int16_t* source, int
unsigned char* data = ima->data(); unsigned char* data = ima->data();
unsigned char* charSource = ( unsigned char* )&tempSource[0]; unsigned char* charSource = reinterpret_cast< unsigned char* >( &tempSource[0] );
for ( unsigned int i = 0; i < m_grid->getNbCoordsX() * m_grid->getNbCoordsY() * m_grid->getNbCoordsZ() * 2 ; ++i ) for ( unsigned int i = 0; i < m_grid->getNbCoordsX() * m_grid->getNbCoordsY() * m_grid->getNbCoordsZ() * 2 ; ++i )
{ {
data[i] = charSource[i]; data[i] = charSource[i];
} }
} }
else
{
// TODO(schurade): throw exception if components!=1
wlog::error( "WDataTexture3D" ) << "Did not handle ( components != 1 ).";
}
return ima; return ima;
} }
osg::ref_ptr< osg::Image > WDataTexture3D::createTexture3D( float* source, int components ) osg::ref_ptr< osg::Image > WDataTexture3D::createTexture3D( float* source, int components )
{ {
osg::ref_ptr< osg::Image > ima = new osg::Image; osg::ref_ptr< osg::Image > ima = new osg::Image;
// TODO(seralph): throw exception if texture generation failed // TODO(schurade): throw exception if texture generation failed
if ( components == 1) if ( components == 1)
{ {
ima->allocateImage( m_grid->getNbCoordsX(), m_grid->getNbCoordsY(), m_grid->getNbCoordsZ(), GL_LUMINANCE, GL_FLOAT ); ima->allocateImage( m_grid->getNbCoordsX(), m_grid->getNbCoordsY(), m_grid->getNbCoordsZ(), GL_LUMINANCE, GL_FLOAT );
unsigned char* data = ima->data(); unsigned char* data = ima->data();
unsigned char* charSource = ( unsigned char* )source; unsigned char* charSource = reinterpret_cast< unsigned char* >( source );
for ( unsigned int i = 0; i < m_grid->getNbCoordsX() * m_grid->getNbCoordsY() * m_grid->getNbCoordsZ() * 4 ; ++i ) for ( unsigned int i = 0; i < m_grid->getNbCoordsX() * m_grid->getNbCoordsY() * m_grid->getNbCoordsZ() * 4 ; ++i )
{ {
data[i] = charSource[i]; data[i] = charSource[i];
} }
} }
else
{
// TODO(schurade): throw exception if components!=1
wlog::error( "WDataTexture3D" ) << "Did not handle ( components != 1 ).";
}
return ima; return ima;
} }
...@@ -232,18 +245,21 @@ void WDataTexture3D::createTexture() ...@@ -232,18 +245,21 @@ void WDataTexture3D::createTexture()
if ( m_valueSet->getDataType() == W_DT_UINT8 ) if ( m_valueSet->getDataType() == W_DT_UINT8 )
{ {
wlog::debug( "WDataTexture3D" ) << "Handling W_DT_UINT8";
boost::shared_ptr< WValueSet< unsigned char > > vs = boost::shared_dynamic_cast< WValueSet< unsigned char > >( m_valueSet ); boost::shared_ptr< WValueSet< unsigned char > > vs = boost::shared_dynamic_cast< WValueSet< unsigned char > >( m_valueSet );
unsigned char* source = const_cast< unsigned char* > ( vs->rawData() ); unsigned char* source = const_cast< unsigned char* > ( vs->rawData() );
ima = createTexture3D( source, m_valueSet->dimension() ); ima = createTexture3D( source, m_valueSet->dimension() );
} }
else if ( m_valueSet->getDataType() == W_DT_INT16 ) else if ( m_valueSet->getDataType() == W_DT_INT16 )
{ {
wlog::debug( "WDataTexture3D" ) << "Handling W_DT_INT16";
boost::shared_ptr< WValueSet< int16_t > > vs = boost::shared_dynamic_cast< WValueSet< int16_t > >( m_valueSet ); boost::shared_ptr< WValueSet< int16_t > > vs = boost::shared_dynamic_cast< WValueSet< int16_t > >( m_valueSet );
int16_t* source = const_cast< int16_t* > ( vs->rawData() ); int16_t* source = const_cast< int16_t* > ( vs->rawData() );
ima = createTexture3D( source, m_valueSet->dimension() ); ima = createTexture3D( source, m_valueSet->dimension() );
} }
else if ( m_valueSet->getDataType() == W_DT_FLOAT ) else if ( m_valueSet->getDataType() == W_DT_FLOAT )
{ {
wlog::debug( "WDataTexture3D" ) << "Handling W_DT_FLOAT";
boost::shared_ptr< WValueSet< float > > vs = boost::shared_dynamic_cast< WValueSet< float > >( m_valueSet ); boost::shared_ptr< WValueSet< float > > vs = boost::shared_dynamic_cast< WValueSet< float > >( m_valueSet );
float* source = const_cast< float* > ( vs->rawData() ); float* source = const_cast< float* > ( vs->rawData() );
ima = createTexture3D( source, m_valueSet->dimension() ); ima = createTexture3D( source, m_valueSet->dimension() );
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include "../common/WColor.h" #include "../common/WColor.h"
#include "../common/WLogger.h" #include "../common/WLogger.h"
#include "../common/WPreferences.h"
#include "../math/WPosition.h" #include "../math/WPosition.h"
#include "WGEViewer.h" #include "WGEViewer.h"
#include "WGraphicsEngine.h" #include "WGraphicsEngine.h"
...@@ -65,14 +66,22 @@ WGraphicsEngine::WGraphicsEngine(): ...@@ -65,14 +66,22 @@ WGraphicsEngine::WGraphicsEngine():
// ThreadingModel: enum with the following possibilities // ThreadingModel: enum with the following possibilities
// //
// SingleThreadet // SingleThreaded
// CullDrawThreadPerContext // CullDrawThreadPerContext
// ThreadPerContext // ThreadPerContext
// DrawThreadPerContext // DrawThreadPerContext
// CullThreadPerCameraDrawThreadPerContext // CullThreadPerCameraDrawThreadPerContext
// ThreadPerCamera // ThreadPerCamera
// AutomaticSelection // AutomaticSelection
m_viewer->setThreadingModel( osgViewer::Viewer::CullThreadPerCameraDrawThreadPerContext ); bool multiThreadedViewers = true;
if( WPreferences::getPreference( "ge.multiThreadedViewers", &multiThreadedViewers ) && !multiThreadedViewers )
{
m_viewer->setThreadingModel( osgViewer::Viewer::SingleThreaded );
}
else
{
m_viewer->setThreadingModel( osgViewer::Viewer::CullThreadPerCameraDrawThreadPerContext );
}
// init resource manager ( it is a singleton and gets created during first "getResourceManager" request. // init resource manager ( it is a singleton and gets created during first "getResourceManager" request.
WGEResourceManager::getResourceManager(); WGEResourceManager::getResourceManager();
......
...@@ -124,6 +124,15 @@ void WMainWindow::setupGUI() ...@@ -124,6 +124,15 @@ void WMainWindow::setupGUI()
} }
} }
// we do not need the dummy widget if there are no other widgets.
if( m_navAxial || m_navCoronal || m_navSagittal )
{
m_dummyWidget = new QDockWidget( this );
m_dummyWidget->setFeatures( QDockWidget::NoDockWidgetFeatures );
m_dummyWidget->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Ignored );
addDockWidget( Qt::LeftDockWidgetArea, m_dummyWidget );
}
// Default background color from config file // Default background color from config file
{ {
WColor bgColor; WColor bgColor;
...@@ -549,6 +558,13 @@ void WMainWindow::slotActivateModule( QString module ) ...@@ -549,6 +558,13 @@ void WMainWindow::slotActivateModule( QString module )
void WMainWindow::newRoi() void WMainWindow::newRoi()
{ {
// do nothing if we can not get
if( !WKernel::getRunningKernel()->getRoiManager()->getDataSet() )
{
wlog::warn( "WMainWindow" ) << "Refused to add ROI, as ROIManager does not have data set associated.";
return;
}
if ( m_datasetBrowser->getSelectedRoi().get() == NULL ) if ( m_datasetBrowser->getSelectedRoi().get() == NULL )
{ {
boost::shared_ptr< WROIBox > newRoi = boost::shared_ptr< WROIBox >( new WROIBox( wmath::WPosition( 60., 60., 60. ), boost::shared_ptr< WROIBox > newRoi = boost::shared_ptr< WROIBox >( new WROIBox( wmath::WPosition( 60., 60., 60. ),
......
...@@ -208,6 +208,7 @@ private: ...@@ -208,6 +208,7 @@ private:
boost::shared_ptr< WQtNavGLWidget > m_navAxial; //!< the axial view widget GL widget of the GUI boost::shared_ptr< WQtNavGLWidget > m_navAxial; //!< the axial view widget GL widget of the GUI
boost::shared_ptr< WQtNavGLWidget > m_navCoronal; //!< the coronal view widget GL widget of the GUI boost::shared_ptr< WQtNavGLWidget > m_navCoronal; //!< the coronal view widget GL widget of the GUI
boost::shared_ptr< WQtNavGLWidget > m_navSagittal; //!< the sgittal view widget GL widget of the GUI boost::shared_ptr< WQtNavGLWidget > m_navSagittal; //!< the sgittal view widget GL widget of the GUI
QDockWidget* m_dummyWidget; //!< The dummywidget serves as spacer in the dockwidget area;
/** /**
* All registered WQtCustomDockWidgets. * All registered WQtCustomDockWidgets.
......
...@@ -45,17 +45,17 @@ WQtNavGLWidget::WQtNavGLWidget( QString title, QWidget* parent, int maxValue, st ...@@ -45,17 +45,17 @@ WQtNavGLWidget::WQtNavGLWidget( QString title, QWidget* parent, int maxValue, st
QSlider *slider = new QSlider( Qt::Horizontal ); QSlider *slider = new QSlider( Qt::Horizontal );
slider->setMaximum( maxValue ); slider->setMaximum( maxValue );
slider->setValue( maxValue / 2 ); slider->setValue( maxValue / 2 );
slider->resize( 150, 20 ); slider->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
QWidget* panel = new QWidget( this ); QWidget* panel = new QWidget( this );
QVBoxLayout* layout = new QVBoxLayout(); QVBoxLayout* layout = new QVBoxLayout();
m_glWidget = boost::shared_ptr<WQtGLWidget>( new WQtGLWidget( title.toStdString(), panel, WGECamera::ORTHOGRAPHIC ) ); m_glWidget = boost::shared_ptr<WQtGLWidget>( new WQtGLWidget( title.toStdString(), panel, WGECamera::ORTHOGRAPHIC ) );
m_glWidget->setFixedSize( 150, 150 ); m_glWidget->setFixedSize( 150, 150 );
m_glWidget->initialize(); m_glWidget->initialize();
setFixedSize( 160, 200 ); setMinimumSize( 160, 200 );
setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Maximum );
m_scene = new WGEScene(); m_scene = new WGEScene();
m_scene->setDataVariance( osg::Object::DYNAMIC ); m_scene->setDataVariance( osg::Object::DYNAMIC );
......
...@@ -219,7 +219,7 @@ void WQtDatasetBrowser::addModule2( boost::shared_ptr< WModule > module, int sub ...@@ -219,7 +219,7 @@ void WQtDatasetBrowser::addModule2( boost::shared_ptr< WModule > module, int sub
{ {
if ( boost::shared_dynamic_cast< WMData >( module ) ) if ( boost::shared_dynamic_cast< WMData >( module ) )
{ {
WQtSubjectTreeItem* subject = ( WQtSubjectTreeItem* )m_treeWidget->topLevelItem( subjectId + 1 ); WQtSubjectTreeItem* subject = static_cast< WQtSubjectTreeItem* >( m_treeWidget->topLevelItem( subjectId + 1 ) );
subject->setExpanded( true ); subject->setExpanded( true );
WQtDatasetTreeItem* item = subject->addDatasetItem( module ); WQtDatasetTreeItem* item = subject->addDatasetItem( module );
item->setDisabled( true ); item->setDisabled( true );
...@@ -235,7 +235,7 @@ void WQtDatasetBrowser::addModule2( boost::shared_ptr< WModule > module, int sub ...@@ -235,7 +235,7 @@ void WQtDatasetBrowser::addModule2( boost::shared_ptr< WModule > module, int sub
WQtDatasetTreeItem* WQtDatasetBrowser::addDataset( boost::shared_ptr< WModule > module, int subjectId ) WQtDatasetTreeItem* WQtDatasetBrowser::addDataset( boost::shared_ptr< WModule > module, int subjectId )
{ {
int c = getFirstSubject(); int c = getFirstSubject();
WQtSubjectTreeItem* subject = ( WQtSubjectTreeItem* )m_treeWidget->topLevelItem( subjectId + c ); WQtSubjectTreeItem* subject = static_cast< WQtSubjectTreeItem* >( m_treeWidget->topLevelItem( subjectId + c ) );
subject->setExpanded( true ); subject->setExpanded( true );
WQtDatasetTreeItem* item = subject->addDatasetItem( module ); WQtDatasetTreeItem* item = subject->addDatasetItem( module );
item->setDisabled( true ); item->setDisabled( true );
...@@ -258,7 +258,7 @@ void WQtDatasetBrowser::addRoi( boost::shared_ptr< WRMROIRepresentation > roi ) ...@@ -258,7 +258,7 @@ void WQtDatasetBrowser::addRoi( boost::shared_ptr< WRMROIRepresentation > roi )
{ {
case ROI : case ROI :
{ {
WQtRoiTreeItem* roiItem =( ( WQtRoiTreeItem* ) m_treeWidget->selectedItems().at( 0 ) ); WQtRoiTreeItem* roiItem =( static_cast< WQtRoiTreeItem* >( m_treeWidget->selectedItems().at( 0 ) ) );
m_tiRois->setExpanded( true ); m_tiRois->setExpanded( true );
roiItem->setExpanded( true ); roiItem->setExpanded( true );
WQtRoiTreeItem* item = roiItem->addRoiItem( roi ); WQtRoiTreeItem* item = roiItem->addRoiItem( roi );
...@@ -267,7 +267,7 @@ void WQtDatasetBrowser::addRoi( boost::shared_ptr< WRMROIRepresentation > roi ) ...@@ -267,7 +267,7 @@ void WQtDatasetBrowser::addRoi( boost::shared_ptr< WRMROIRepresentation > roi )
} }
case SUBROI : case SUBROI :
{ {
WQtRoiTreeItem* roiItem =( ( WQtRoiTreeItem* ) m_treeWidget->selectedItems().at( 0 )->parent() ); WQtRoiTreeItem* roiItem =( static_cast< WQtRoiTreeItem* >( m_treeWidget->selectedItems().at( 0 )->parent() ) );
m_tiRois->setExpanded( true ); m_tiRois->setExpanded( true );
roiItem->setExpanded( true ); roiItem->setExpanded( true );
WQtRoiTreeItem* item = roiItem->addRoiItem( roi ); WQtRoiTreeItem* item = roiItem->addRoiItem( roi );
...@@ -295,11 +295,11 @@ boost::shared_ptr< WModule > WQtDatasetBrowser::getSelectedModule() ...@@ -295,11 +295,11 @@ boost::shared_ptr< WModule > WQtDatasetBrowser::getSelectedModule()
{ {
if ( m_treeWidget->selectedItems().at( 0 )->type() == 1 ) if ( m_treeWidget->selectedItems().at( 0 )->type() == 1 )
{ {
return ( ( WQtDatasetTreeItem* ) m_treeWidget->selectedItems().at( 0 ) )->getModule(); return ( static_cast< WQtDatasetTreeItem* >( m_treeWidget->selectedItems().at( 0 ) )->getModule() );
} }
else if ( m_treeWidget->selectedItems().at( 0 )->type() == 3 ) else if ( m_treeWidget->selectedItems().at( 0 )->type() == 3 )
{ {
return ( ( WQtModuleTreeItem* ) m_treeWidget->selectedItems().at( 0 ) )->getModule(); return ( static_cast< WQtModuleTreeItem* >( m_treeWidget->selectedItems().at( 0 ) )->getModule() );
} }
return boost::shared_ptr< WModule >(); return boost::shared_ptr< WModule >();
......
...@@ -156,7 +156,7 @@ void WKernel::threadMain() ...@@ -156,7 +156,7 @@ void WKernel::threadMain()
// default modules // default modules
{ {
std::string stdModules = "Coordinate System Module,HUD,Navigation Slice Module"; std::string stdModules = "Coordinate System Module,HUD";
WPreferences::getPreference( "modules.default", &stdModules ); WPreferences::getPreference( "modules.default", &stdModules );
std::vector< std::string > defMods = string_utils::tokenize( stdModules, "," ); std::vector< std::string > defMods = string_utils::tokenize( stdModules, "," );
for ( std::vector< std::string >::iterator iter = defMods.begin(); iter != defMods.end(); ++iter ) for ( std::vector< std::string >::iterator iter = defMods.begin(); iter != defMods.end(); ++iter )
......
...@@ -23,8 +23,11 @@ ...@@ -23,8 +23,11 @@
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
#include <algorithm> #include <algorithm>
#include <iostream>
#include <vector> #include <vector>
#include "../common/WLimits.h"
#include "../common/WStringUtils.h"
#include "WLine.h" #include "WLine.h"
#include "WPosition.h" #include "WPosition.h"
...@@ -60,23 +63,39 @@ void WLine::resample( size_t numPoints ) ...@@ -60,23 +63,39 @@ void WLine::resample( size_t numPoints )
{ {
if( size() != numPoints && size() > 0 && numPoints > 0 ) if( size() != numPoints && size() > 0 && numPoints > 0 )
{ {
const double newSegmentLength = pathLength() / ( numPoints - 1 ); const double pathL = pathLength();
double newSegmentLength = pathL / ( numPoints - 1 );
WLine newLine; WLine newLine;
newLine.reserve( numPoints ); newLine.reserve( numPoints );
double remainingLength = 0.0; double remainingLength = 0.0;
newLine.push_back( front() ); newLine.push_back( front() );
for( size_t i = 1; i < size(); ++i ) double lengthSoFar = 0.0;
for( size_t i = 0; i < ( size() - 1 ); ++i )
{ {
remainingLength += ( at( i - 1 ) - at( i ) ).norm(); remainingLength += ( at( i ) - at( i + 1 ) ).norm();
while( remainingLength >= newSegmentLength ) // FLT_EPS since I don't know how to fix this any further
while( ( remainingLength > newSegmentLength ) || std::abs( remainingLength - newSegmentLength ) < wlimits::FLT_EPS )
{ {
remainingLength -= newSegmentLength; remainingLength -= newSegmentLength;
WPosition newPoint = at( i ) + remainingLength * ( at( i - 1 ) - at( i ) ).normalized(); lengthSoFar += newSegmentLength;
// TODO(math): fix numerical issuses: newSegmentLength may be wrong => great offset by many intraSegment sample points
// remainingLength may be wrong => ...
// Take a look at the unit test testNumericalStabilityOfResampling
WPosition newPoint = at( i + 1 ) + remainingLength * ( at( i ) - at( i + 1 ) ).normalized();
newLine.push_back( newPoint ); newLine.push_back( newPoint );
} // since numerical instability (newSegmentLength may have inproper value)
// newSegmentLength = ( pathL - lengthSoFar ) / ( numPoints - newLine.size() );
// std::cout << "line size so far" << newLine.size() << " lenght so far: " << newLine.pathLength() << std::endl;
// std::cout << numPoints - newLine.size() << std::endl;
}
} }
*this = newLine; // using string_utils::operator<<;
// std::cout << "this: " << *this << std::endl << "new: " << newLine << std::endl;
// std::cout << "|remL - newSegL|: " << std::abs( remainingLength - newSegmentLength ) << std::endl;
// std::cout << std::setprecision( 35 ) << "remainingLength: " << remainingLength << " newSegmentLength: " << newSegmentLength << std::endl;
// std::cout << "this size: " << size() << " new size: " << newLine.size() << std::endl;
this->WMixinVector< wmath::WPosition >::operator=( newLine );
} }
assert( size() == numPoints && "Resampling of a line has failed! Is your fiber of length 0 or even the new sample rate??" ); assert( size() == numPoints && "Resampling of a line has failed! Is your fiber of length 0 or even the new sample rate??" );
} }
......
...@@ -30,8 +30,9 @@ ...@@ -30,8 +30,9 @@
#include <cxxtest/TestSuite.h> #include <cxxtest/TestSuite.h>
#include "WLineTraits.h" #include "../../common/WLimits.h"
#include "../WLine.h" #include "../WLine.h"
#include "WLineTraits.h"
/** /**
* Unit tests the WLine class * Unit tests the WLine class
...@@ -149,13 +150,123 @@ public: ...@@ -149,13 +150,123 @@ public:
expected.push_back( WPosition( 0, 0, 0 ) ); expected.push_back( WPosition( 0, 0, 0 ) );
expected.push_back( WPosition( 1.5, 0.5, 0 ) ); expected.push_back( WPosition( 1.5, 0.5, 0 ) );
expected.push_back( WPosition( 3, 1, 0 ) ); expected.push_back( WPosition( 3, 1, 0 ) );
TS_ASSERT_EQUALS( line.size(), expected.size() ); assert_SAMELINES( expected, line );
for( size_t i = 0; i < line.size(); ++i ) }
/**
* If the resampling rate of a line has as many points as the original line,
* no sampling should be applied.
*/
void testSamplingWithSameNumberOfPoints( void )
{
using wmath::WPosition;
wmath::WLine line;
for( size_t i = 0; i < 10; ++i )
{
line.push_back( WPosition( i, 3 * i, 10 - i ) );
}
TS_ASSERT( line.size() == 10 );
wmath::WLine expected( line ); // make a copy of the original
line.resample( 10 );
assert_SAMELINES( line, expected );
}
/**
* If the points are exactly in between of a segement nothing should fail.
*/
void testSamplingPointsAreExactlyInTheOldSegmentCenterAndCorners( void )
{
using wmath::WPosition;
wmath::WLine line;
wmath::WLine expected;
for( size_t i = 0; i < 3; ++i )
{
line.push_back( WPosition( i, std::pow( -1, i % 2 ), 0 ) );
expected.push_back( WPosition( i, std::pow( -1, i % 2 ), 0 ) );
expected.push_back( WPosition( i + 0.5, 0, 0 ) );
}
expected.pop_back();
line.resample( 5 );
assert_SAMELINES( expected, line );
}
// void testNumericalStabilityOfResampling( void )
// {
// using wmath::WPosition;
// wmath::WLine line;
// wmath::WLine expected;
// for( size_t i = 0; i < 100; ++i )
// {
// line.push_back( WPosition( i, std::pow( -1, i % 2 ), 0 ) );
// expected.push_back( WPosition( i, std::pow( -1, i % 2 ), 0 ) );
// expected.push_back( WPosition( i + 0.25, std::pow( -1, i % 2 ) * 0.5, 0 ) );
// expected.push_back( WPosition( i + 0.5, 0, 0 ) );
// expected.push_back( WPosition( i + 0.75, std::pow( -1, ( i + 1 ) % 2 ) * 0.5, 0 ) );
// }
// expected.pop_back();
// expected.pop_back();
// expected.pop_back();
// line.resample( 3 * 99 );
// assert_SAMELINES( expected, line );
// }
//
// void testManySampelsInBetweenOfTwoOldPoints( void )
// {
// using wmath::WPosition;
// wmath::WLine line;
// line.push_back( WPosition( 0, 0, 0 ) );
// line.push_back( WPosition( 1, 1, 0 ) );
// line.resample( 1001 );
// wmath::WLine expected;
// expected.push_back( WPosition( 0, 0, 0 ) );
// for( size_t i = 1; i < 1001; ++i )
// {
// expected.push_back( WPosition( i / 1000.0, i / 1000.0, 0 ) );
// }
// assert_SAMELINES( expected, line );
// }
private:
/**
* TS_ASSERT_DELTA needs the operator+, operator- and operator< to be implemented especially for WPositions the operator< and operator +
* makes not really sense. Hence I implemented an assert by my one, giving reasonable out put.
*
* \param first First line to compare with