diff options
Diffstat (limited to 'src/ProjectionGeometry3D.cpp')
-rw-r--r-- | src/ProjectionGeometry3D.cpp | 329 |
1 files changed, 329 insertions, 0 deletions
diff --git a/src/ProjectionGeometry3D.cpp b/src/ProjectionGeometry3D.cpp new file mode 100644 index 0000000..b78b7b8 --- /dev/null +++ b/src/ProjectionGeometry3D.cpp @@ -0,0 +1,329 @@ +/* +----------------------------------------------------------------------- +Copyright 2012 iMinds-Vision Lab, University of Antwerp + +Contact: astra@ua.ac.be +Website: http://astra.ua.ac.be + + +This file is part of the +All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). + +The ASTRA Toolbox is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +The ASTRA Toolbox 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with the ASTRA Toolbox. If not, see <http://www.gnu.org/licenses/>. + +----------------------------------------------------------------------- +$Id$ +*/ + +#include "astra/ProjectionGeometry3D.h" + +#include <boost/lexical_cast.hpp> + +using namespace std; + +namespace astra +{ + +//---------------------------------------------------------------------------------------- +// Check all variable values. +bool CProjectionGeometry3D::_check() +{ + ASTRA_CONFIG_CHECK(m_iDetectorRowCount > 0, "ProjectionGeometry3D", "DetectorRowCount should be positive."); + ASTRA_CONFIG_CHECK(m_iDetectorColCount > 0, "ProjectionGeometry3D", "DetectorColCount should be positive."); + ASTRA_CONFIG_CHECK(m_fDetectorSpacingX > 0.0f, "ProjectionGeometry3D", "m_fDetectorSpacingX should be positive."); + ASTRA_CONFIG_CHECK(m_fDetectorSpacingY > 0.0f, "ProjectionGeometry3D", "m_fDetectorSpacingY should be positive."); + ASTRA_CONFIG_CHECK(m_iProjectionAngleCount > 0, "ProjectionGeometry3D", "ProjectionAngleCount should be positive."); + ASTRA_CONFIG_CHECK(m_pfProjectionAngles != NULL, "ProjectionGeometry3D", "ProjectionAngles not initialized"); + +/* + // autofix: angles in [0,2pi[ + for (int i = 0; i < m_iProjectionAngleCount; i++) { + while (2*PI <= m_pfProjectionAngles[i]) m_pfProjectionAngles[i] -= 2*PI; + while (m_pfProjectionAngles[i] < 0) m_pfProjectionAngles[i] += 2*PI; + } +*/ + + // succes + return true; +} + +//---------------------------------------------------------------------------------------- +// Default constructor. +CProjectionGeometry3D::CProjectionGeometry3D() : configCheckData(0) +{ + _clear(); +} + +//---------------------------------------------------------------------------------------- +// Constructor. +CProjectionGeometry3D::CProjectionGeometry3D(int _iAngleCount, + int _iDetectorRowCount, + int _iDetectorColCount, + float32 _fDetectorSpacingX, + float32 _fDetectorSpacingY, + const float32 *_pfProjectionAngles, + const float32 *_pfExtraDetectorOffsetsX, + const float32 *_pfExtraDetectorOffsetsY) : configCheckData(0) +{ + _clear(); + _initialize(_iAngleCount, + _iDetectorRowCount, + _iDetectorColCount, + _fDetectorSpacingX, + _fDetectorSpacingY, + _pfProjectionAngles, + _pfExtraDetectorOffsetsX, + _pfExtraDetectorOffsetsY); +} + +//---------------------------------------------------------------------------------------- +// Copy constructor. +CProjectionGeometry3D::CProjectionGeometry3D(const CProjectionGeometry3D& _projGeom) +{ + _clear(); + _initialize(_projGeom.m_iProjectionAngleCount, + _projGeom.m_iDetectorRowCount, + _projGeom.m_iDetectorColCount, + _projGeom.m_fDetectorSpacingX, + _projGeom.m_fDetectorSpacingY, + _projGeom.m_pfProjectionAngles, + _projGeom.m_pfExtraDetectorOffsetsX, + _projGeom.m_pfExtraDetectorOffsetsY); +} + +//---------------------------------------------------------------------------------------- +// Destructor. +CProjectionGeometry3D::~CProjectionGeometry3D() +{ + if (m_bInitialized) { + clear(); + } +} + +//---------------------------------------------------------------------------------------- +// Clear all member variables, setting all numeric variables to 0 and all pointers to NULL. +// Should only be used by constructors. Otherwise use the clear() function. +void CProjectionGeometry3D::_clear() +{ + m_iProjectionAngleCount = 0; + m_iDetectorRowCount = 0; + m_iDetectorColCount = 0; + m_fDetectorSpacingX = 0.0f; + m_fDetectorSpacingY = 0.0f; + m_pfProjectionAngles = NULL; + m_pfExtraDetectorOffsetsX = NULL; + m_pfExtraDetectorOffsetsY = NULL; + m_bInitialized = false; +} + +//---------------------------------------------------------------------------------------- +// Clear all member variables, setting all numeric variables to 0 and all pointers to NULL. +void CProjectionGeometry3D::clear() +{ + m_iProjectionAngleCount = 0; + m_iDetectorRowCount = 0; + m_iDetectorColCount = 0; + m_fDetectorSpacingX = 0.0f; + m_fDetectorSpacingY = 0.0f; + if (m_pfProjectionAngles != NULL) { + delete [] m_pfProjectionAngles; + } + if (m_pfExtraDetectorOffsetsX != NULL) { + delete [] m_pfExtraDetectorOffsetsX; + } + if (m_pfExtraDetectorOffsetsY != NULL) { + delete [] m_pfExtraDetectorOffsetsY; + } + m_pfProjectionAngles = NULL; + m_pfExtraDetectorOffsetsX = NULL; + m_pfExtraDetectorOffsetsY = NULL; + m_bInitialized = false; +} + +//---------------------------------------------------------------------------------------- +// Initialization witha Config object +bool CProjectionGeometry3D::initialize(const Config& _cfg) +{ + ASTRA_ASSERT(_cfg.self); + ConfigStackCheck<CProjectionGeometry3D> CC("ProjectionGeometry3D", this, _cfg); + + if (m_bInitialized) { + clear(); + } + + ASTRA_ASSERT(_cfg.self); + + // Required: DetectorWidth + XMLNode* node = _cfg.self->getSingleNode("DetectorSpacingX"); + ASTRA_CONFIG_CHECK(node, "ProjectionGeometry3D", "No DetectorSpacingX tag specified."); + m_fDetectorSpacingX = boost::lexical_cast<float32>(node->getContent()); + ASTRA_DELETE(node); + CC.markNodeParsed("DetectorSpacingX"); + + // Required: DetectorHeight + node = _cfg.self->getSingleNode("DetectorSpacingY"); + ASTRA_CONFIG_CHECK(node, "ProjectionGeometry3D", "No DetectorSpacingY tag specified."); + m_fDetectorSpacingY = boost::lexical_cast<float32>(node->getContent()); + ASTRA_DELETE(node); + CC.markNodeParsed("DetectorSpacingY"); + + // Required: DetectorRowCount + node = _cfg.self->getSingleNode("DetectorRowCount"); + ASTRA_CONFIG_CHECK(node, "ProjectionGeometry3D", "No DetectorRowCount tag specified."); + m_iDetectorRowCount = boost::lexical_cast<int>(node->getContent()); + ASTRA_DELETE(node); + CC.markNodeParsed("DetectorRowCount"); + + // Required: DetectorCount + node = _cfg.self->getSingleNode("DetectorColCount"); + ASTRA_CONFIG_CHECK(node, "ProjectionGeometry3D", "No DetectorColCount tag specified."); + m_iDetectorColCount = boost::lexical_cast<int>(node->getContent()); + m_iDetectorTotCount = m_iDetectorRowCount * m_iDetectorColCount; + ASTRA_DELETE(node); + CC.markNodeParsed("DetectorColCount"); + + // Required: ProjectionAngles + node = _cfg.self->getSingleNode("ProjectionAngles"); + ASTRA_CONFIG_CHECK(node, "ProjectionGeometry3D", "No ProjectionAngles tag specified."); + vector<float32> angles = node->getContentNumericalArray(); + m_iProjectionAngleCount = angles.size(); + ASTRA_CONFIG_CHECK(m_iProjectionAngleCount > 0, "ProjectionGeometry3D", "Not enough ProjectionAngles specified."); + m_pfProjectionAngles = new float32[m_iProjectionAngleCount]; + for (int i = 0; i < m_iProjectionAngleCount; i++) { + m_pfProjectionAngles[i] = angles[i]; + } + CC.markNodeParsed("ProjectionAngles"); + ASTRA_DELETE(node); + + // Optional: ExtraDetectorOffsetX + node = _cfg.self->getSingleNode("ExtraDetectorOffsetsX"); + m_pfExtraDetectorOffsetsX = new float32[m_iProjectionAngleCount]; + if (node) { + vector<float32> translationsX = node->getContentNumericalArray(); + if (translationsX.size() < m_iProjectionAngleCount){ + cout << "Not enough ExtraDetectorOffsetsX components specified. " << endl; + for (int i = 0; i < m_iProjectionAngleCount; i++) { + m_pfExtraDetectorOffsetsX[i] = 0; + } + } + else { + for (int i = 0; i < m_iProjectionAngleCount; i++) { + m_pfExtraDetectorOffsetsX[i] = translationsX[i]; + } + } + } + else { + //cout << "No ExtraDetectorOffsetsX tag specified." << endl; + for (int i = 0; i < m_iProjectionAngleCount; i++) { + m_pfExtraDetectorOffsetsX[i] = 0; + } + } + CC.markOptionParsed("ExtraDetectorOffsetsX"); + ASTRA_DELETE(node); + + // Optional: ExtraDetectorOffsetsY + node = _cfg.self->getSingleNode("ExtraDetectorOffsetsY"); + m_pfExtraDetectorOffsetsY = new float32[m_iProjectionAngleCount]; + if (node) { + vector<float32> translationsX = node->getContentNumericalArray(); + if (translationsX.size() < m_iProjectionAngleCount){ + cout << "Not enough ExtraDetectorOffsetsY components specified. " << endl; + for (int i = 0; i < m_iProjectionAngleCount; i++) { + m_pfExtraDetectorOffsetsY[i] = 0; + } + } + else { + for (int i = 0; i < m_iProjectionAngleCount; i++) { + m_pfExtraDetectorOffsetsY[i] = translationsX[i]; + } + } + } + else { + //cout << "No ExtraDetectorOffsetsY tag specified." << endl; + for (int i = 0; i < m_iProjectionAngleCount; i++) { + m_pfExtraDetectorOffsetsY[i] = 0; + } + } + CC.markOptionParsed("ExtraDetectorOffsetsY"); + ASTRA_DELETE(node); + + // Interface class, so don't return true + return false; +} + +//---------------------------------------------------------------------------------------- +// Initialization. +bool CProjectionGeometry3D::_initialize(int _iProjectionAngleCount, + int _iDetectorRowCount, + int _iDetectorColCount, + float32 _fDetectorSpacingX, + float32 _fDetectorSpacingY, + const float32 *_pfProjectionAngles, + const float32 *_pfExtraDetectorOffsetsX, + const float32 *_pfExtraDetectorOffsetsY) +{ + if (m_bInitialized) { + clear(); + } + + // copy parameters + m_iProjectionAngleCount = _iProjectionAngleCount; + m_iDetectorRowCount = _iDetectorRowCount; + m_iDetectorColCount = _iDetectorColCount; + m_iDetectorTotCount = _iDetectorRowCount * _iDetectorColCount; + m_fDetectorSpacingX = _fDetectorSpacingX; + m_fDetectorSpacingY = _fDetectorSpacingY; + m_pfProjectionAngles = new float32[m_iProjectionAngleCount]; + m_pfExtraDetectorOffsetsX = new float32[m_iProjectionAngleCount]; + m_pfExtraDetectorOffsetsY = new float32[m_iProjectionAngleCount]; + for (int i = 0; i < m_iProjectionAngleCount; i++) { + m_pfProjectionAngles[i] = _pfProjectionAngles[i]; + m_pfExtraDetectorOffsetsX[i] = _pfExtraDetectorOffsetsX ? _pfExtraDetectorOffsetsX[i]:0; + m_pfExtraDetectorOffsetsY[i] = _pfExtraDetectorOffsetsY ? _pfExtraDetectorOffsetsY[i]:0; + //m_pfExtraDetectorOffsetsX[i] = 0; + //m_pfExtraDetectorOffsetsY[i] = 0; + } + + m_iDetectorTotCount = m_iProjectionAngleCount * m_iDetectorRowCount * m_iDetectorColCount; + + // Interface class, so don't return true + return false; +} + +//--------------------------------------------------------------------------------------- +// +AstraError CProjectionGeometry3D::setExtraDetectorOffsetsX(float32* _pfExtraDetectorOffsetsX) +{ + if (!m_bInitialized) + return ASTRA_ERROR_NOT_INITIALIZED; + + for (int iAngle = 0; iAngle<m_iProjectionAngleCount; iAngle++) + m_pfExtraDetectorOffsetsX[iAngle] = _pfExtraDetectorOffsetsX[iAngle]; + + return ASTRA_SUCCESS; +} + +//--------------------------------------------------------------------------------------- +// +AstraError CProjectionGeometry3D::setExtraDetectorOffsetsY(float32* _pfExtraDetectorOffsetsY) +{ + if (!m_bInitialized) + return ASTRA_ERROR_NOT_INITIALIZED; + + for (int iAngle = 0; iAngle<m_iProjectionAngleCount; iAngle++) + m_pfExtraDetectorOffsetsY[iAngle] = _pfExtraDetectorOffsetsY[iAngle]; + + return ASTRA_SUCCESS; +} +} // namespace astra |