summaryrefslogtreecommitdiffstats
path: root/include/astra
diff options
context:
space:
mode:
authorWillem Jan Palenstijn <WillemJan.Palenstijn@uantwerpen.be>2013-07-01 22:34:11 +0000
committerwpalenst <WillemJan.Palenstijn@uantwerpen.be>2013-07-01 22:34:11 +0000
commitb2fc6c70434674d74551c3a6c01ffb3233499312 (patch)
treeb17f080ebc504ab85ebb7c3d89f917fd87ce9e00 /include/astra
downloadastra-b2fc6c70434674d74551c3a6c01ffb3233499312.tar.gz
astra-b2fc6c70434674d74551c3a6c01ffb3233499312.tar.bz2
astra-b2fc6c70434674d74551c3a6c01ffb3233499312.tar.xz
astra-b2fc6c70434674d74551c3a6c01ffb3233499312.zip
Update version to 1.3
Diffstat (limited to 'include/astra')
-rw-r--r--include/astra/Algorithm.h135
-rw-r--r--include/astra/AlgorithmTypelist.h108
-rw-r--r--include/astra/ArtAlgorithm.h196
-rw-r--r--include/astra/AstraObjectFactory.h149
-rw-r--r--include/astra/AstraObjectManager.h290
-rw-r--r--include/astra/AsyncAlgorithm.h128
-rw-r--r--include/astra/BackProjectionAlgorithm.h155
-rw-r--r--include/astra/CglsAlgorithm.h182
-rw-r--r--include/astra/ConeProjectionGeometry3D.h213
-rw-r--r--include/astra/ConeVecProjectionGeometry3D.h154
-rw-r--r--include/astra/Config.h80
-rw-r--r--include/astra/CudaBackProjectionAlgorithm.h110
-rw-r--r--include/astra/CudaBackProjectionAlgorithm3D.h152
-rw-r--r--include/astra/CudaCglsAlgorithm.h122
-rw-r--r--include/astra/CudaCglsAlgorithm3D.h173
-rw-r--r--include/astra/CudaDartMaskAlgorithm.h126
-rw-r--r--include/astra/CudaDartMaskAlgorithm3D.h122
-rw-r--r--include/astra/CudaDartSmoothingAlgorithm.h125
-rw-r--r--include/astra/CudaDartSmoothingAlgorithm3D.h122
-rw-r--r--include/astra/CudaDataOperationAlgorithm.h128
-rw-r--r--include/astra/CudaEMAlgorithm.h92
-rw-r--r--include/astra/CudaFDKAlgorithm3D.h164
-rw-r--r--include/astra/CudaFilteredBackProjectionAlgorithm.h94
-rw-r--r--include/astra/CudaForwardProjectionAlgorithm.h169
-rw-r--r--include/astra/CudaForwardProjectionAlgorithm3D.h135
-rw-r--r--include/astra/CudaProjector2D.h122
-rw-r--r--include/astra/CudaProjector3D.h131
-rw-r--r--include/astra/CudaReconstructionAlgorithm2D.h176
-rw-r--r--include/astra/CudaRoiSelectAlgorithm.h123
-rw-r--r--include/astra/CudaSartAlgorithm.h112
-rw-r--r--include/astra/CudaSirtAlgorithm.h131
-rw-r--r--include/astra/CudaSirtAlgorithm3D.h187
-rw-r--r--include/astra/DataProjector.h327
-rw-r--r--include/astra/DataProjectorPolicies.h382
-rw-r--r--include/astra/DataProjectorPolicies.inl855
-rw-r--r--include/astra/FanFlatBeamLineKernelProjector2D.h194
-rw-r--r--include/astra/FanFlatBeamLineKernelProjector2D.inl740
-rw-r--r--include/astra/FanFlatBeamStripKernelProjector2D.h191
-rw-r--r--include/astra/FanFlatBeamStripKernelProjector2D.inl961
-rw-r--r--include/astra/FanFlatProjectionGeometry2D.h244
-rw-r--r--include/astra/FanFlatVecProjectionGeometry2D.h155
-rw-r--r--include/astra/FilteredBackProjectionAlgorithm.h155
-rw-r--r--include/astra/Float32Data.h88
-rw-r--r--include/astra/Float32Data2D.h544
-rw-r--r--include/astra/Float32Data3D.h199
-rw-r--r--include/astra/Float32Data3DMemory.h338
-rw-r--r--include/astra/Float32ProjectionData2D.h247
-rw-r--r--include/astra/Float32ProjectionData3D.h257
-rw-r--r--include/astra/Float32ProjectionData3DMemory.h218
-rw-r--r--include/astra/Float32VolumeData2D.h183
-rw-r--r--include/astra/Float32VolumeData3D.h265
-rw-r--r--include/astra/Float32VolumeData3DMemory.h213
-rw-r--r--include/astra/ForwardProjectionAlgorithm.h225
-rw-r--r--include/astra/Fourier.h127
-rw-r--r--include/astra/Globals.h309
-rw-r--r--include/astra/Logger.h72
-rw-r--r--include/astra/ParallelBeamBlobKernelProjector2D.h232
-rw-r--r--include/astra/ParallelBeamBlobKernelProjector2D.inl212
-rw-r--r--include/astra/ParallelBeamLineKernelProjector2D.h186
-rw-r--r--include/astra/ParallelBeamLineKernelProjector2D.inl731
-rw-r--r--include/astra/ParallelBeamLinearKernelProjector2D.h194
-rw-r--r--include/astra/ParallelBeamLinearKernelProjector2D.inl416
-rw-r--r--include/astra/ParallelBeamStripKernelProjector2D.h191
-rw-r--r--include/astra/ParallelBeamStripKernelProjector2D.inl739
-rw-r--r--include/astra/ParallelProjectionGeometry2D.h153
-rw-r--r--include/astra/ParallelProjectionGeometry3D.h165
-rw-r--r--include/astra/ParallelVecProjectionGeometry3D.h157
-rw-r--r--include/astra/PlatformDepSystemCode.h83
-rw-r--r--include/astra/ProjectionGeometry2D.h373
-rw-r--r--include/astra/ProjectionGeometry3D.h589
-rw-r--r--include/astra/Projector2D.h204
-rw-r--r--include/astra/Projector2DImpl.inl37
-rw-r--r--include/astra/Projector3D.h185
-rw-r--r--include/astra/ProjectorTypelist.h104
-rw-r--r--include/astra/ReconstructionAlgorithm2D.h222
-rw-r--r--include/astra/ReconstructionAlgorithm3D.h223
-rw-r--r--include/astra/SartAlgorithm.h226
-rw-r--r--include/astra/Singleton.h87
-rw-r--r--include/astra/SirtAlgorithm.h217
-rw-r--r--include/astra/SparseMatrix.h144
-rw-r--r--include/astra/SparseMatrixProjectionGeometry2D.h154
-rw-r--r--include/astra/SparseMatrixProjector2D.h210
-rw-r--r--include/astra/SparseMatrixProjector2D.inl90
-rw-r--r--include/astra/TypeList.h236
-rw-r--r--include/astra/Utilities.h131
-rw-r--r--include/astra/Vector3D.h131
-rw-r--r--include/astra/VolumeGeometry2D.h608
-rw-r--r--include/astra/VolumeGeometry3D.h842
-rw-r--r--include/astra/XMLDocument.h101
-rw-r--r--include/astra/XMLNode.h325
-rw-r--r--include/astra/jama_wrapper.h35
-rw-r--r--include/astra/swrap.h41
92 files changed, 21069 insertions, 0 deletions
diff --git a/include/astra/Algorithm.h b/include/astra/Algorithm.h
new file mode 100644
index 0000000..d4c73f9
--- /dev/null
+++ b/include/astra/Algorithm.h
@@ -0,0 +1,135 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_ALGORITHM
+#define _INC_ASTRA_ALGORITHM
+
+#include <boost/any.hpp>
+
+#include "Globals.h"
+#include "Config.h"
+
+namespace astra {
+
+/**
+ * This class contains the interface for an algorithm implementation.
+ */
+class _AstraExport CAlgorithm {
+
+public:
+
+ /** Default constructor, containing no code.
+ */
+ CAlgorithm();
+
+ /** Destructor.
+ */
+ virtual ~CAlgorithm();
+
+ /** Initialize the algorithm with a config object.
+ *
+ * @param _cfg Configuration Object
+ * @return initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg) = 0;
+
+ /** Get all information parameters
+ *
+ * @return map with all boost::any object
+ */
+ virtual map<string,boost::any> getInformation();
+
+ /** Get a single piece of information represented as a boost::any
+ *
+ * @param _sIdentifier identifier string to specify which piece of information you want
+ * @return boost::any object
+ */
+ virtual boost::any getInformation(std::string _sIdentifier);
+
+ /** Perform a number of iterations.
+ *
+ * @param _iNrIterations amount of iterations to perform.
+ */
+ virtual void run(int _iNrIterations = 0) = 0;
+
+ /** Has this class been initialized?
+ *
+ * @return initialized
+ */
+ bool isInitialized();
+
+ /** get a description of the class
+ *
+ * @return description string
+ */
+ virtual std::string description() const;
+
+ /** Signal the algorithm it should abort soon.
+ * This is intended to be called from a different thread
+ * while the algorithm is running. There are no guarantees
+ * on how soon the algorithm will abort. The state of the
+ * algorithm object will be consistent (so it is safe to delete it
+ * normally afterwards), but the algorithm's output is undefined.
+ *
+ * Note that specific algorithms may give guarantees on their
+ * state after an abort. Check their documentation for details.
+ */
+ virtual void signalAbort() { m_bShouldAbort = true; }
+
+protected:
+
+ //< Has this class been initialized?
+ bool m_bIsInitialized;
+
+ //< If this is set, the algorithm should try to abort as soon as possible.
+ volatile bool m_bShouldAbort;
+
+private:
+ /**
+ * Private copy constructor to prevent CAlgorithms from being copied.
+ */
+ CAlgorithm(const CAlgorithm&);
+
+ /**
+ * Private assignment operator to prevent CAlgorithms from being copied.
+ */
+ CAlgorithm& operator=(const CAlgorithm&);
+
+ //< For Config unused argument checking
+ ConfigCheckData* configCheckData;
+ friend class ConfigStackCheck<CAlgorithm>;
+
+};
+
+// inline functions
+inline std::string CAlgorithm::description() const { return "Algorithm"; };
+inline bool CAlgorithm::isInitialized() { return m_bIsInitialized; }
+
+} // end namespace
+
+#endif
diff --git a/include/astra/AlgorithmTypelist.h b/include/astra/AlgorithmTypelist.h
new file mode 100644
index 0000000..615c143
--- /dev/null
+++ b/include/astra/AlgorithmTypelist.h
@@ -0,0 +1,108 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_ALGORITHMTYPELIST
+#define _INC_ASTRA_ALGORITHMTYPELIST
+
+#include "Algorithm.h"
+#include "TypeList.h"
+
+#include "ArtAlgorithm.h"
+#include "SirtAlgorithm.h"
+#include "SartAlgorithm.h"
+#include "ForwardProjectionAlgorithm.h"
+#include "BackProjectionAlgorithm.h"
+#include "FilteredBackProjectionAlgorithm.h"
+#include "CudaBackProjectionAlgorithm.h"
+#include "CudaSartAlgorithm.h"
+#include "CudaSirtAlgorithm.h"
+#include "CudaCglsAlgorithm.h"
+#include "CudaEMAlgorithm.h"
+#include "CudaForwardProjectionAlgorithm.h"
+#include "CglsAlgorithm.h"
+#include "CudaCglsAlgorithm3D.h"
+#include "CudaSirtAlgorithm3D.h"
+#include "CudaForwardProjectionAlgorithm3D.h"
+#include "CudaBackProjectionAlgorithm3D.h"
+#include "CudaFDKAlgorithm3D.h"
+#include "CudaDartMaskAlgorithm.h"
+#include "CudaDartMaskAlgorithm3D.h"
+#include "CudaDartSmoothingAlgorithm.h"
+#include "CudaDartSmoothingAlgorithm3D.h"
+#include "CudaDataOperationAlgorithm.h"
+#include "CudaRoiSelectAlgorithm.h"
+
+using namespace astra;
+
+#ifdef ASTRA_CUDA
+
+#include "CudaFilteredBackProjectionAlgorithm.h"
+
+typedef TYPELIST_25(
+ CArtAlgorithm,
+ CSartAlgorithm,
+ CSirtAlgorithm,
+ CCglsAlgorithm,
+ CBackProjectionAlgorithm,
+ CForwardProjectionAlgorithm,
+ CCudaSartAlgorithm,
+ CFilteredBackProjectionAlgorithm,
+ CCudaBackProjectionAlgorithm,
+ CCudaDartMaskAlgorithm,
+ CCudaDartMaskAlgorithm3D,
+ CCudaDartSmoothingAlgorithm,
+ CCudaDartSmoothingAlgorithm3D,
+ CCudaDataOperationAlgorithm,
+ CCudaRoiSelectAlgorithm,
+ CCudaSirtAlgorithm,
+ CCudaCglsAlgorithm,
+ CCudaEMAlgorithm,
+ CCudaForwardProjectionAlgorithm,
+ CCudaCglsAlgorithm3D,
+ CCudaFilteredBackProjectionAlgorithm,
+ CCudaFDKAlgorithm3D,
+ CCudaSirtAlgorithm3D,
+ CCudaForwardProjectionAlgorithm3D,
+ CCudaBackProjectionAlgorithm3D
+ )
+ AlgorithmTypeList;
+#else
+
+typedef TYPELIST_7(
+ CArtAlgorithm,
+ CSartAlgorithm,
+ CSirtAlgorithm,
+ CCglsAlgorithm,
+ CBackProjectionAlgorithm,
+ CForwardProjectionAlgorithm,
+ CFilteredBackProjectionAlgorithm
+ ) AlgorithmTypeList;
+
+#endif
+
+#endif
diff --git a/include/astra/ArtAlgorithm.h b/include/astra/ArtAlgorithm.h
new file mode 100644
index 0000000..bd02fc4
--- /dev/null
+++ b/include/astra/ArtAlgorithm.h
@@ -0,0 +1,196 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_ARTALGORITHM
+#define _INC_ASTRA_ARTALGORITHM
+
+#include "Globals.h"
+#include "Config.h"
+
+#include "Algorithm.h"
+#include "ReconstructionAlgorithm2D.h"
+
+#include "Projector2D.h"
+#include "Float32ProjectionData2D.h"
+#include "Float32VolumeData2D.h"
+
+namespace astra {
+
+/**
+ * This class contains the implementation of the ART (Algebraic Reconstruction Technique) algorithm.
+ *
+ * The update step of pixel \f$v_j\f$ for ray \f$i\f$ and iteration \f$k\f$ is given by:
+ * \f[
+ * v_j^{(k+1)} = v_j^{(k)} + \lambda \frac{p_i - \sum_{r=1}^{N} w_{ir}v_r^{(k)}}{\sum_{k=1}^{N} w_{ik}^2}
+ * \f]
+ *
+ * \par XML Configuration
+ * \astra_xml_item{ProjectorId, integer, Identifier of a projector as it is stored in the ProjectorManager.}
+ * \astra_xml_item{ProjectionDataId, integer, Identifier of a projection data object as it is stored in the DataManager.}
+ * \astra_xml_item{ReconstructionDataId, integer, Identifier of a volume data object as it is stored in the DataManager.}
+ * \astra_xml_item_option{ReconstructionMaskId, integer, not used, Identifier of a volume data object that acts as a reconstruction mask. 1 = reconstruct on this pixel. 0 = don't reconstruct on this pixel.}
+ * \astra_xml_item_option{SinogramMaskId, integer, not used, Identifier of a projection data object that acts as a projection mask. 1 = reconstruct using this ray. 0 = don't use this ray while reconstructing.}
+ * \astra_xml_item_option{UseMinConstraint, bool, false, Use minimum value constraint.}
+ * \astra_xml_item_option{MinConstraintValue, float, 0, Minimum constraint value.}
+ * \astra_xml_item_option{UseMaxConstraint, bool, false, Use maximum value constraint.}
+ * \astra_xml_item_option{MaxConstraintValue, float, 255, Maximum constraint value.}
+ * \astra_xml_item_option{Lamda, float, 1, The relaxation factor.}
+ * \astra_xml_item_option{RayOrder, string, "sequential", the order in which the rays are updated. 'sequential' or 'custom'}
+ * \astra_xml_item_option{RayOrderList, n by 2 vector of float, not used, if RayOrder='custom': use this ray order. Each row consist of a projection id and detector id.}
+ *
+ * \par MATLAB example
+ * \astra_code{
+ * cfg = astra_struct('ART');\n
+ * cfg.ProjectorId = proj_id;\n
+ * cfg.ProjectionDataId = sino_id;\n
+ * cfg.ReconstructionDataId = recon_id;\n
+ * cfg.option.MaskId = mask_id;\n
+ * cfg.option.UseMinConstraint = 'yes';\n
+ * cfg.option.UseMaxConstraint = 'yes';\n
+ * cfg.option.MaxConstraintValue = 1024;\n
+ * cfg.option.Lamda = 0.7;\n
+ * cfg.option.RayOrder = 'custom';\n
+ * cfg.option.RayOrderList = [0\,0; 0\,2; 1\,0];\n
+ * alg_id = astra_mex_algorithm('create'\, cfg);\n
+ * astra_mex_algorithm('iterate'\, alg_id\, 1000);\n
+ * astra_mex_algorithm('delete'\, alg_id);\n
+ * }
+ */
+class _AstraExport CArtAlgorithm : public CReconstructionAlgorithm2D {
+
+protected:
+
+ /** Initial clearing. Only to be used by constructors.
+ */
+ virtual void _clear();
+
+ /** Check the values of this object. If everything is ok, the object can be set to the initialized state.
+ * The following statements are then guaranteed to hold:
+ * - no NULL pointers
+ * - all sub-objects are initialized properly
+ * - the projector is compatible with both data objects
+ * - the ray order list only contains valid values
+ */
+ virtual bool _check();
+
+public:
+
+ // type of the algorithm, needed to register with CAlgorithmFactory
+ static std::string type;
+
+ /** Default constructor, containing no code.
+ */
+ CArtAlgorithm();
+
+ /** Destructor.
+ */
+ virtual ~CArtAlgorithm();
+
+ /** Initialize the algorithm with a config object.
+ *
+ * @param _cfg Configuration Object
+ * @return initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ /** Initialize class, use sequential ray order.
+ *
+ * @param _pProjector Projector Object.
+ * @param _pSinogram ProjectionData2D object containing the sinogram data.
+ * @param _pReconstruction VolumeData2D object for storing the reconstructed volume.
+ */
+ bool initialize(CProjector2D* _pProjector,
+ CFloat32ProjectionData2D* _pSinogram,
+ CFloat32VolumeData2D* _pReconstruction);
+
+ /** Clear this class.
+ */
+ virtual void clear();
+
+ /** Set the relaxation factor.
+ *
+ * @param _fLambda Relaxation factor
+ */
+ void setLambda(float32 _fLambda);
+
+ /** Set the order in which the rays will be selected
+ *
+ * @param _piProjectionOrder Order of the rays, the projections. (size should be _piRayCount)
+ * @param _piDetectorOrder Order of the rays, the detectors. (size should be _piRayCount)
+ * @param _piRayCount Number of rays in the two previous arrays.
+ */
+ void setRayOrder(int* _piProjectionOrder, int* _piDetectorOrder, int _piRayCount);
+
+ /** Get all information parameters
+ *
+ * @return map with all boost::any object
+ */
+ virtual map<string,boost::any> getInformation();
+
+ /** Get a single piece of information represented as a boost::any
+ *
+ * @param _sIdentifier identifier string to specify which piece of information you want
+ * @return boost::any object
+ */
+ virtual boost::any getInformation(std::string _sIdentifier);
+
+ /** Perform a number of iterations.
+ *
+ * @param _iNrIterations amount of iterations to perform.
+ */
+ virtual void run(int _iNrIterations = 0);
+
+ /** Get a description of the class.
+ *
+ * @return description string
+ */
+ virtual std::string description() const;
+
+protected:
+
+ //< Relaxation Factor
+ float32 m_fLambda;
+
+ //< Order of the rays, the projections.
+ int* m_piProjectionOrder;
+ //< Order of the rays, the detectors.
+ int* m_piDetectorOrder;
+ //< Number of rays specified in the ray order arrays.
+ int m_iRayCount;
+ //< Current index in the ray order arrays.
+ int m_iCurrentRay;
+
+};
+
+// inline functions
+inline std::string CArtAlgorithm::description() const { return CArtAlgorithm::type; };
+
+
+} // end namespace
+
+#endif
diff --git a/include/astra/AstraObjectFactory.h b/include/astra/AstraObjectFactory.h
new file mode 100644
index 0000000..784d698
--- /dev/null
+++ b/include/astra/AstraObjectFactory.h
@@ -0,0 +1,149 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_ASTRAOBJECTFACTORY
+#define _INC_ASTRA_ASTRAOBJECTFACTORY
+
+#include "Globals.h"
+#include "Config.h"
+#include "Singleton.h"
+#include "Utilities.h"
+#include "TypeList.h"
+
+#include "ProjectorTypelist.h"
+
+
+#include "AlgorithmTypelist.h"
+
+
+namespace astra {
+
+/**
+ * This class contains functionality to create data objects based on their type or on a configuration object.
+ */
+template <typename T, typename TypeList>
+class CAstraObjectFactory : public Singleton<CAstraObjectFactory<T, TypeList> > {
+
+public:
+
+ /** A default constructor that contains not a single line of code.
+ */
+ CAstraObjectFactory();
+
+ /** Destructor.
+ */
+ ~CAstraObjectFactory();
+
+ /** Create, but don't initialize, a new projector object.
+ *
+ * @param _sType Type of the new projector.
+ * @return Pointer to a new, unitialized projector.
+ */
+ T* create(std::string _sType);
+
+ /** Create and initialize a new projector object.
+ *
+ * @param _cfg Configuration object to create and initialize a new projector.
+ * @return Pointer to a new, initialized projector.
+ */
+ T* create(const Config& _cfg);
+
+
+};
+
+
+//----------------------------------------------------------------------------------------
+// Constructor
+template <typename T, typename TypeList>
+CAstraObjectFactory<T, TypeList>::CAstraObjectFactory()
+{
+
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor
+template <typename T, typename TypeList>
+CAstraObjectFactory<T, TypeList>::~CAstraObjectFactory()
+{
+
+}
+
+//----------------------------------------------------------------------------------------
+// Create
+template <typename T, typename TypeList>
+T* CAstraObjectFactory<T, TypeList>::create(std::string _sType)
+{
+ functor_find<T> finder = functor_find<T>();
+ finder.tofind = _sType;
+ CreateObject<TypeList>::find(finder);
+ return finder.res;
+}
+
+//----------------------------------------------------------------------------------------
+// Create with XML
+template <typename T, typename TypeList>
+T* CAstraObjectFactory<T, TypeList>::create(const Config& _cfg)
+{
+ functor_find<T> finder = functor_find<T>();
+ finder.tofind = _cfg.self->getAttribute("type");
+ CreateObject<TypeList>::find(finder);
+ if (finder.res == NULL) return NULL;
+ if (finder.res->initialize(_cfg))
+ return finder.res;
+
+ delete finder.res;
+ return NULL;
+}
+//----------------------------------------------------------------------------------------
+
+
+
+
+//----------------------------------------------------------------------------------------
+// Create the necessary Object Managers
+/**
+ * Class used to create algorithms from a string or a config object
+*/
+class _AstraExport CAlgorithmFactory : public CAstraObjectFactory<CAlgorithm, AlgorithmTypeList> {};
+
+/**
+ * Class used to create 2D projectors from a string or a config object
+*/
+class _AstraExport CProjector2DFactory : public CAstraObjectFactory<CProjector2D, Projector2DTypeList> {};
+
+/**
+ * Class used to create 3D projectors from a string or a config object
+*/
+class _AstraExport CProjector3DFactory : public CAstraObjectFactory<CProjector3D, Projector3DTypeList> {};
+
+
+
+
+} // end namespace
+
+#endif
diff --git a/include/astra/AstraObjectManager.h b/include/astra/AstraObjectManager.h
new file mode 100644
index 0000000..afb6312
--- /dev/null
+++ b/include/astra/AstraObjectManager.h
@@ -0,0 +1,290 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_ASTRAOBJECTMANAGER
+#define _INC_ASTRA_ASTRAOBJECTMANAGER
+
+#include <map>
+#include <sstream>
+
+#include "Globals.h"
+#include "Singleton.h"
+#include "Projector2D.h"
+#include "Projector3D.h"
+#include "Float32Data2D.h"
+#include "Float32Data3D.h"
+#include "SparseMatrix.h"
+#include "Algorithm.h"
+
+namespace astra {
+
+/**
+ * This class contains functionality to store objects. A unique index handle
+ * will be assigned to each data object by which it can be accessed in the
+ * future. Indices are always >= 1.
+ *
+ * We store them in a special common base class to make indices unique
+ * among all ObjectManagers.
+ */
+
+
+class CAstraIndexManager {
+protected:
+ /** The index of the previously stored data object.
+ */
+ static int m_iPreviousIndex;
+};
+
+
+template <typename T>
+class CAstraObjectManager : public Singleton<CAstraObjectManager<T> >, CAstraIndexManager {
+
+public:
+
+ /** Default constructor.
+ */
+ CAstraObjectManager();
+
+ /** Destructor.
+ */
+ ~CAstraObjectManager();
+
+ /** Store the object in the manager and assign a unique index handle to it.
+ *
+ * @param _pObject A pointer to the object that should be stored.
+ * @return The index of the stored data object. If the index in negative, an error occurred
+ * and the object was NOT stored.
+ */
+ int store(T* _pObject);
+
+ /** Does the manager contain an object with the index _iIndex?
+ *
+ * @param _iIndex Index handle to the data object in question.
+ * @return True if the manager contains an object with the index handle _iIndex.
+ */
+ bool hasIndex(int _iIndex) const;
+
+ /** Fetch the object to which _iIndex refers to.
+ *
+ * @param _iIndex Index handle to the data object in question.
+ * @return Pointer to the stored data object. A null pointer is returned if no object with index _iIndex is found.
+ */
+ T* get(int _iIndex) const;
+
+ /** Delete an object that was previously stored. This actually DELETES the objecy. Therefore, after this
+ * function call, the object in question will have passed on. It will be no more. It will have ceased
+ * to be. It will be expired and will go to meet its maker. Bereft of life, it will rest in peace.
+ * It will be an EX-OBJECT.
+ *
+ * @param _iIndex Index handle to the object in question.
+ * @return Error code. 0 for success.
+ */
+ void remove(int _iIndex);
+
+ /** Get the index of the object, zero if it doesn't exist.
+ *
+ * @param _pObject The data object.
+ * @return Index of the stored object, 0 if not found.
+ */
+ int getIndex(const T* _pObject) const;
+
+ /** Clear all data. This will also delete all the content of each object.
+ */
+ void clear();
+
+ /** Get info.
+ */
+ std::string info();
+
+protected:
+
+ /** Map each data object to a unique index.
+ */
+ std::map<int, T*> m_mIndexToObject;
+
+};
+
+//----------------------------------------------------------------------------------------
+// Constructor
+template <typename T>
+CAstraObjectManager<T>::CAstraObjectManager()
+{
+}
+
+//----------------------------------------------------------------------------------------
+// Destructor
+template <typename T>
+CAstraObjectManager<T>::~CAstraObjectManager()
+{
+
+}
+
+//----------------------------------------------------------------------------------------
+// store data
+template <typename T>
+int CAstraObjectManager<T>::store(T* _pDataObject)
+{
+ m_iPreviousIndex++;
+ m_mIndexToObject[m_iPreviousIndex] = _pDataObject;
+ return m_iPreviousIndex;
+}
+
+//----------------------------------------------------------------------------------------
+// has data?
+template <typename T>
+bool CAstraObjectManager<T>::hasIndex(int _iIndex) const
+{
+ typename map<int,T*>::const_iterator it = m_mIndexToObject.find(_iIndex);
+ return it != m_mIndexToObject.end();
+}
+
+//----------------------------------------------------------------------------------------
+// get data
+template <typename T>
+T* CAstraObjectManager<T>::get(int _iIndex) const
+{
+ typename map<int,T*>::const_iterator it = m_mIndexToObject.find(_iIndex);
+ if (it != m_mIndexToObject.end())
+ return it->second;
+ else
+ return 0;
+}
+
+//----------------------------------------------------------------------------------------
+// delete data
+template <typename T>
+void CAstraObjectManager<T>::remove(int _iIndex)
+{
+ if (!hasIndex(_iIndex)) {
+ return;
+ }
+ // find data
+ typename map<int,T*>::iterator it = m_mIndexToObject.find(_iIndex);
+ // delete data
+ delete (*it).second;
+ // delete from map
+ m_mIndexToObject.erase(it);
+}
+
+//----------------------------------------------------------------------------------------
+// Get Index
+template <typename T>
+int CAstraObjectManager<T>::getIndex(const T* _pObject) const
+{
+ for (typename map<int,T*>::const_iterator it = m_mIndexToObject.begin(); it != m_mIndexToObject.end(); it++) {
+ if ((*it).second == _pObject) return (*it).first;
+ }
+ return 0;
+}
+
+
+//----------------------------------------------------------------------------------------
+// clear
+template <typename T>
+void CAstraObjectManager<T>::clear()
+{
+ for (typename map<int,T*>::iterator it = m_mIndexToObject.begin(); it != m_mIndexToObject.end(); it++) {
+ // delete data
+ delete (*it).second;
+ (*it).second = 0;
+ }
+
+ m_mIndexToObject.clear();
+}
+
+//----------------------------------------------------------------------------------------
+// Print info to string
+template <typename T>
+std::string CAstraObjectManager<T>::info() {
+ std::stringstream res;
+ res << "id init description" << std::endl;
+ res << "-----------------------------------------" << std::endl;
+ for (typename map<int,T*>::iterator it = m_mIndexToObject.begin(); it != m_mIndexToObject.end(); it++) {
+ res << (*it).first << " \t";
+ T* pObject = m_mIndexToObject[(*it).first];
+ if (pObject->isInitialized()) {
+ res << "v ";
+ } else {
+ res << "x ";
+ }
+ res << pObject->description() << endl;
+ }
+ res << "-----------------------------------------" << std::endl;
+ return res.str();
+}
+
+
+
+//----------------------------------------------------------------------------------------
+// Create the necessary Object Managers
+/**
+ * This class contains functionality to store 2D projector objects. A unique index handle will be
+ * assigned to each data object by which it can be accessed in the future.
+ * Indices are always >= 1.
+ */
+class _AstraExport CProjector2DManager : public CAstraObjectManager<CProjector2D>{};
+
+/**
+ * This class contains functionality to store 3D projector objects. A unique index handle will be
+ * assigned to each data object by which it can be accessed in the future.
+ * Indices are always >= 1.
+ */
+class _AstraExport CProjector3DManager : public CAstraObjectManager<CProjector3D>{};
+
+/**
+ * This class contains functionality to store 2D data objects. A unique index handle will be
+ * assigned to each data object by which it can be accessed in the future.
+ * Indices are always >= 1.
+ */
+class _AstraExport CData2DManager : public CAstraObjectManager<CFloat32Data2D>{};
+
+/**
+ * This class contains functionality to store 3D data objects. A unique index handle will be
+ * assigned to each data object by which it can be accessed in the future.
+ * Indices are always >= 1.
+ */
+class _AstraExport CData3DManager : public CAstraObjectManager<CFloat32Data3D>{};
+
+/**
+ * This class contains functionality to store algorithm objects. A unique index handle will be
+ * assigned to each data object by which it can be accessed in the future.
+ * Indices are always >= 1.
+ */
+class _AstraExport CAlgorithmManager : public CAstraObjectManager<CAlgorithm>{};
+
+/**
+ * This class contains functionality to store matrix objects. A unique index handle will be
+ * assigned to each data object by which it can be accessed in the future.
+ * Indices are always >= 1.
+ */
+class _AstraExport CMatrixManager : public CAstraObjectManager<CSparseMatrix>{};
+
+
+} // end namespace
+
+#endif
diff --git a/include/astra/AsyncAlgorithm.h b/include/astra/AsyncAlgorithm.h
new file mode 100644
index 0000000..64f70c3
--- /dev/null
+++ b/include/astra/AsyncAlgorithm.h
@@ -0,0 +1,128 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_ASYNCALGORITHM
+#define _INC_ASTRA_ASYNCALGORITHM
+
+#include "Config.h"
+#include "Algorithm.h"
+
+#ifdef __linux__
+#define USE_PTHREADS
+#include <pthread.h>
+#else
+#include <boost/thread.hpp>
+#endif
+
+
+namespace astra {
+
+/**
+ * \brief
+ * This class contains an wrapper algorithm that allows termination of its wrapped algorithm.
+ *
+ * This is used to allow algorithm termination from matlab command line.
+ */
+
+class _AstraExport CAsyncAlgorithm : public CAlgorithm {
+public:
+ /** Default constructor, containing no code.
+ */
+ CAsyncAlgorithm();
+
+ /** Constructor.
+ */
+ explicit CAsyncAlgorithm(CAlgorithm* _pAlg);
+
+ /** Destructor.
+ */
+ virtual ~CAsyncAlgorithm();
+
+ /** Initialize using config object.
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ /** Initialize using algorithm pointer.
+ */
+ virtual bool initialize(CAlgorithm* _pAlg);
+
+ /** Run the algorithm.
+ */
+ virtual void run(int _iNrIterations = 0);
+
+ /** Wait for thread to complete and delete thread.
+ */
+ virtual void timedJoin(int _milliseconds);
+
+ /** Return pointer to the wrapped algorithm.
+ */
+ CAlgorithm* getWrappedAlgorithm() { return m_pAlg; }
+
+ /** Is the wrapped algorithm done.
+ */
+ bool isDone() const { return m_bDone; }
+
+ /** Signal abort to the wrapped algorithm.
+ */
+ void signalAbort();
+
+protected:
+ //< Has this class been initialized?
+ bool m_bInitialized;
+
+ //< Should wrapped algorithm be deleted after completion?
+ bool m_bAutoFree;
+
+ //< Pointer to wrapped algorithm.
+ CAlgorithm* m_pAlg;
+
+ //< Is the wrapped algorithm done.
+ volatile bool m_bDone;
+
+#ifndef USE_PTHREADS
+ //< Handle to boost thread object running the wrapped algorithm.
+ boost::thread* m_pThread;
+#else
+ pthread_t m_thread;
+ struct AsyncThreadInfo {
+ int m_iIterations;
+ CAlgorithm* m_pAlg;
+ volatile bool* m_pDone;
+ } m_ThreadInfo;
+ friend void* runAsync_pthreads(void*);
+#endif
+ bool m_bThreadStarted;
+
+ //< Run the wrapped algorithm.
+ void runWrapped(int _iNrIterations);
+
+};
+
+}
+
+#endif
diff --git a/include/astra/BackProjectionAlgorithm.h b/include/astra/BackProjectionAlgorithm.h
new file mode 100644
index 0000000..d50b406
--- /dev/null
+++ b/include/astra/BackProjectionAlgorithm.h
@@ -0,0 +1,155 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_BACKPROJECTIONALGORITHM
+#define _INC_ASTRA_BACKPROJECTIONALGORITHM
+
+#include "Globals.h"
+#include "Config.h"
+
+#include "Algorithm.h"
+#include "ReconstructionAlgorithm2D.h"
+
+#include "Projector2D.h"
+#include "Float32ProjectionData2D.h"
+#include "Float32VolumeData2D.h"
+
+#include "DataProjector.h"
+
+namespace astra {
+
+/**
+ * \brief
+ * This class performs an unfiltered backprojection.
+ *
+ * \par XML Configuration
+ * \astra_xml_item{ProjectorId, integer, Identifier of a projector as it is stored in the ProjectorManager.}
+ * \astra_xml_item{ProjectionDataId, integer, Identifier of a projection data object as it is stored in the DataManager.}
+ * \astra_xml_item{ReconstructionDataId, integer, Identifier of a volume data object as it is stored in the DataManager.}
+ * \astra_xml_item_option{ReconstructionMaskId, integer, not used, Identifier of a volume data object that acts as a reconstruction mask. 1 = reconstruct on this pixel. 0 = don't reconstruct on this pixel.}
+ * \astra_xml_item_option{SinogramMaskId, integer, not used, Identifier of a projection data object that acts as a projection mask. 1 = reconstruct using this ray. 0 = don't use this ray while reconstructing.}
+ *
+ */
+class _AstraExport CBackProjectionAlgorithm : public CReconstructionAlgorithm2D {
+
+protected:
+
+ /** Init stuff
+ */
+ virtual void _init();
+
+ /** Initial clearing. Only to be used by constructors.
+ */
+ virtual void _clear();
+
+ /** Check the values of this object. If everything is ok, the object can be set to the initialized state.
+ * The following statements are then guaranteed to hold:
+ * - valid projector
+ * - valid data objects
+ */
+ virtual bool _check();
+
+public:
+
+ // type of the algorithm, needed to register with CAlgorithmFactory
+ static std::string type;
+
+ /** Default constructor, containing no code.
+ */
+ CBackProjectionAlgorithm();
+
+ /** Default constructor
+ *
+ * @param _pProjector Projector Object.
+ * @param _pSinogram ProjectionData2D object containing the sinogram data.
+ * @param _pReconstruction VolumeData2D object for storing the reconstructed volume.
+ */
+ CBackProjectionAlgorithm(CProjector2D* _pProjector,
+ CFloat32ProjectionData2D* _pSinogram,
+ CFloat32VolumeData2D* _pReconstruction);
+
+ /** Destructor.
+ */
+ virtual ~CBackProjectionAlgorithm();
+
+ /** Clear this class.
+ */
+ virtual void clear();
+
+ /** Initialize the algorithm with a config object.
+ *
+ * @param _cfg Configuration Object
+ * @return Initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ /** Initialize class.
+ *
+ * @param _pProjector Projector Object.
+ * @param _pSinogram ProjectionData2D object containing the sinogram data.
+ * @param _pReconstruction VolumeData2D object for storing the reconstructed volume.
+ * @return Initialization successful?
+ */
+ bool initialize(CProjector2D* _pProjector,
+ CFloat32ProjectionData2D* _pSinogram,
+ CFloat32VolumeData2D* _pReconstruction);
+
+ /** Get all information parameters.
+ *
+ * @return Map with all available identifier strings and their values.
+ */
+ virtual map<string,boost::any> getInformation();
+
+ /** Get a single piece of information represented as a boost::any
+ *
+ * @param _sIdentifier Identifier string to specify which piece of information you want.
+ * @return One piece of information.
+ */
+ virtual boost::any getInformation(std::string _sIdentifier);
+
+ /** Perform a number of iterations.
+ *
+ * @param _iNrIterations amount of iterations to perform.
+ */
+ virtual void run(int _iNrIterations = 0);
+
+ /** Get a description of the class.
+ *
+ * @return description string
+ */
+ virtual std::string description() const;
+
+};
+
+// inline functions
+inline std::string CBackProjectionAlgorithm::description() const { return CBackProjectionAlgorithm::type; };
+
+
+} // end namespace
+
+#endif
diff --git a/include/astra/CglsAlgorithm.h b/include/astra/CglsAlgorithm.h
new file mode 100644
index 0000000..1700d74
--- /dev/null
+++ b/include/astra/CglsAlgorithm.h
@@ -0,0 +1,182 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_CGLSALGORITHM
+#define _INC_ASTRA_CGLSALGORITHM
+
+#include "Globals.h"
+#include "Config.h"
+
+#include "Algorithm.h"
+#include "ReconstructionAlgorithm2D.h"
+
+#include "Projector2D.h"
+#include "Float32ProjectionData2D.h"
+#include "Float32VolumeData2D.h"
+
+#include "DataProjector.h"
+
+namespace astra {
+
+/**
+ * \brief
+ * This class contains the implementation of the CGLS (Conguent Gradient Algorithm) algorithm.
+ *
+ * \par XML Configuration
+ * \astra_xml_item{ProjectorId, integer, Identifier of a projector as it is stored in the ProjectorManager.}
+ * \astra_xml_item{ProjectionDataId, integer, Identifier of a projection data object as it is stored in the DataManager.}
+ * \astra_xml_item{ReconstructionDataId, integer, Identifier of a volume data object as it is stored in the DataManager.}
+ * \astra_xml_item_option{ReconstructionMaskId, integer, not used, Identifier of a volume data object that acts as a reconstruction mask. 0 = reconstruct on this pixel. 1 = don't reconstruct on this pixel.}
+ * \astra_xml_item_option{SinogramMaskId, integer, not used, Identifier of a projection data object that acts as a projection mask. 0 = reconstruct using this ray. 1 = don't use this ray while reconstructing.}
+ * \astra_xml_item_option{UseMinConstraint, bool, false, Use minimum value constraint.}
+ * \astra_xml_item_option{MinConstraintValue, float, 0, Minimum constraint value.}
+ * \astra_xml_item_option{UseMaxConstraint, bool, false, Use maximum value constraint.}
+ * \astra_xml_item_option{MaxConstraintValue, float, 255, Maximum constraint value.}
+ *
+ * \par MATLAB example
+ * \astra_code{
+ * cfg = astra_struct('CGLS');\n
+ * cfg.ProjectorId = proj_id;\n
+ * cfg.ProjectionDataId = sino_id;\n
+ * cfg.ReconstructionDataId = recon_id;\n
+ * cfg.option.MaskId = mask_id;\n
+ * cfg.option.UseMinConstraint = 'yes';\n
+ * cfg.option.UseMaxConstraint = 'yes';\n
+ * cfg.option.MaxConstraintValue = 1024;\n
+ * alg_id = astra_mex_algorithm('create'\, cfg);\n
+ * astra_mex_algorithm('iterate'\, alg_id\, 10);\n
+ * astra_mex_algorithm('delete'\, alg_id);\n
+ * }
+ *
+ */
+class _AstraExport CCglsAlgorithm : public CReconstructionAlgorithm2D {
+
+protected:
+
+ /** Initial clearing. Only to be used by constructors.
+ */
+ virtual void _clear();
+
+ /** Check the values of this object. If everything is ok, the object can be set to the initialized state.
+ * The following statements are then guaranteed to hold:
+ * - valid projector
+ * - valid data objects
+ */
+ virtual bool _check();
+
+ CFloat32ProjectionData2D* r;
+ CFloat32ProjectionData2D* w;
+ CFloat32VolumeData2D* z;
+ CFloat32VolumeData2D* p;
+
+ float32 alpha;
+ float32 beta;
+ float32 gamma;
+
+
+ int m_iIteration;
+
+public:
+
+ // type of the algorithm, needed to register with CAlgorithmFactory
+ static std::string type;
+
+ /** Default constructor, containing no code.
+ */
+ CCglsAlgorithm();
+
+ /** Default constructor
+ *
+ * @param _pProjector Projector Object.
+ * @param _pSinogram ProjectionData2D object containing the sinogram data.
+ * @param _pReconstruction VolumeData2D object for storing the reconstructed volume.
+ */
+ CCglsAlgorithm(CProjector2D* _pProjector,
+ CFloat32ProjectionData2D* _pSinogram,
+ CFloat32VolumeData2D* _pReconstruction);
+
+ /** Destructor.
+ */
+ virtual ~CCglsAlgorithm();
+
+ /** Clear this class.
+ */
+ virtual void clear();
+
+ /** Initialize the algorithm with a config object.
+ *
+ * @param _cfg Configuration Object
+ * @return Initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ /** Initialize class.
+ *
+ * @param _pProjector Projector Object.
+ * @param _pSinogram ProjectionData2D object containing the sinogram data.
+ * @param _pReconstruction VolumeData2D object for storing the reconstructed volume.
+ * @return Initialization successful?
+ */
+ bool initialize(CProjector2D* _pProjector,
+ CFloat32ProjectionData2D* _pSinogram,
+ CFloat32VolumeData2D* _pReconstruction);
+
+ /** Get all information parameters.
+ *
+ * @return Map with all available identifier strings and their values.
+ */
+ virtual map<string,boost::any> getInformation();
+
+ /** Get a single piece of information represented as a boost::any
+ *
+ * @param _sIdentifier Identifier string to specify which piece of information you want.
+ * @return One piece of information.
+ */
+ virtual boost::any getInformation(std::string _sIdentifier);
+
+ /** Perform a number of iterations.
+ *
+ * @param _iNrIterations amount of iterations to perform.
+ */
+ virtual void run(int _iNrIterations = 0);
+
+ /** Get a description of the class.
+ *
+ * @return description string
+ */
+ virtual std::string description() const;
+
+};
+
+// inline functions
+inline std::string CCglsAlgorithm::description() const { return CCglsAlgorithm::type; };
+
+
+} // end namespace
+
+#endif
diff --git a/include/astra/ConeProjectionGeometry3D.h b/include/astra/ConeProjectionGeometry3D.h
new file mode 100644
index 0000000..497ce7d
--- /dev/null
+++ b/include/astra/ConeProjectionGeometry3D.h
@@ -0,0 +1,213 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_CONEPROJECTIONGEOMETRY3D
+#define _INC_ASTRA_CONEPROJECTIONGEOMETRY3D
+
+#include "ProjectionGeometry3D.h"
+
+namespace astra
+{
+
+/**
+ * This class defines a 3D cone beam projection geometry.
+ *
+ * \par XML Configuration
+ * \astra_xml_item{DetectorRowCount, int, Number of detectors for each projection.}
+ * \astra_xml_item{DetectorColCount, int, Number of detectors for each projection.}
+ * \astra_xml_item{DetectorWidth, float, Width of each detector.}
+ * \astra_xml_item{DetectorHeight, float, Width of each detector.}
+ * \astra_xml_item{ProjectionAngles, vector of float, projection angles in radians.}
+ * \astra_xml_item{DistanceOriginDetector, float, Distance between the center of rotation and the detectorarray.}
+ * \astra_xml_item{DistanceOriginSource, float, Distance between the center of rotation the the x-ray source.}
+ *
+ * \par MATLAB example
+ * \astra_code{
+ * proj_geom = astra_struct('cone');\n
+ * proj_geom.DetectorRowCount = 512;\n
+ * proj_geom.DetectorColCount = 512;\n
+ * proj_geom.DetectorWidth = 1.0;\n
+ * proj_geom.DetectorHeight = 1.0;\n
+ * proj_geom.ProjectionAngles = linspace(0,pi,100);\n
+ * proj_geom.DistanceOriginDetector = 10000;\n
+ * proj_geom.DistanceOriginSource = 10000;\n
+ * }
+ */
+class _AstraExport CConeProjectionGeometry3D : public CProjectionGeometry3D
+{
+protected:
+
+ /**
+ * Distance from the origin of the coordinate system to the source.
+ */
+ float32 m_fOriginSourceDistance;
+
+ /**
+ * Distance from the origin of the coordinate system to the detector (i.e., the distance between the origin and its orthogonal projection
+ * onto the detector array).
+ */
+ float32 m_fOriginDetectorDistance;
+
+public:
+
+ /** Default constructor. Sets all numeric member variables to 0 and all pointer member variables to NULL.
+ *
+ * If an object is constructed using this default constructor, it must always be followed by a call
+ * to one of the initialize() methods before the object can be used. Any use before calling initialize()
+ * is not allowed, except calling the member function isInitialized().
+ */
+ CConeProjectionGeometry3D();
+
+ /** Constructor. Create an instance of the CParallelProjectionGeometry3D class.
+ *
+ * @param _iProjectionAngleCount Number of projection angles.
+ * @param _iDetectorRowCount Number of rows of detectors.
+ * @param _iDetectorColCount Number of columns detectors.
+ * @param _fDetectorWidth Width of a detector cell, in unit lengths. All detector cells are assumed to have equal width.
+ * @param _fDetectorHeight Height of a detector cell, in unit lengths. All detector cells are assumed to have equal width.
+ * @param _pfProjectionAngles Pointer to an array of projection angles. The angles will be copied from this array. All angles
+ * are represented in radians and lie in the [0,2pi[ interval.
+ */
+ CConeProjectionGeometry3D(int _iProjectionAngleCount,
+ int _iDetectorRowCount,
+ int _iDetectorColCount,
+ float32 _fDetectorWidth,
+ float32 _fDetectorHeight,
+ const float32* _pfProjectionAngles,
+ float32 _fOriginSourceDistance,
+ float32 _fOriginDetectorDistance);
+
+ /** Copy constructor.
+ */
+ CConeProjectionGeometry3D(const CConeProjectionGeometry3D& _projGeom);
+
+ /** Destructor.
+ */
+ ~CConeProjectionGeometry3D();
+
+ /** Initialize the geometry with a config object.
+ *
+ * @param _cfg Configuration Object
+ * @return initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ /** Initialize the geometry. If the object has been initialized before, the object is reinitialized
+ * and memory is freed and reallocated if necessary.
+ *
+ * @param _iProjectionAngleCount Number of projection angles.
+ * @param _iDetectorRowCount Number of rows of detectors.
+ * @param _iDetectorColCount Number of columns detectors.
+ * @param _fDetectorWidth Width of a detector cell, in unit lengths. All detector cells are assumed to have equal width.
+ * @param _fDetectorHeight Height of a detector cell, in unit lengths. All detector cells are assumed to have equal height.
+ * @param _pfProjectionAngles Pointer to an array of projection angles. The angles will be copied from this array. All angles
+ * are represented in radians and lie in the [0,2pi[ interval.
+ */
+ bool initialize(int _iProjectionAngleCount,
+ int _iDetectorRowCount,
+ int _iDetectorColCount,
+ float32 _fDetectorWidth,
+ float32 _fDetectorHeight,
+ const float32* _pfProjectionAngles,
+ float32 _fOriginSourceDistance,
+ float32 _fOriginDetectorDistance);
+
+
+ /** Create a hard copy.
+ */
+ virtual CProjectionGeometry3D* clone() const;
+
+ /** Return true if this geometry instance is the same as the one specified.
+ *
+ * @return true if this geometry instance is the same as the one specified.
+ */
+ virtual bool isEqual(const CProjectionGeometry3D*) const;
+
+ /** Returns true if the type of geometry defined in this class is the one specified in _sType.
+ *
+ * @param _sType geometry type to compare to.
+ * @return true if _sType == "cone".
+ */
+ virtual bool isOfType(const std::string& _sType) const;
+
+ /** Turn this object into an XML object.
+ *
+ * @param _sNode The XML object to fill.
+ */
+ virtual void toXML(XMLNode* _sNode) const;
+
+ /** Returns the distance from the origin of the coordinate system to the source.
+ *
+ * @return Distance from the origin of the coordinate system to the source
+ */
+ float32 getOriginSourceDistance() const;
+
+ /** Returns the distance from the origin of the coordinate system to the detector
+ * (i.e., the distance between the origin and its orthogonal projection onto the detector array).
+ *
+ * @return Distance from the origin of the coordinate system to the detector
+ */
+ float32 getOriginDetectorDistance() const;
+
+ /** Returns the distance from the source to the detector
+ * (i.e., the distance between the source and its orthogonal projection onto the detector array).
+ *
+ * @return Distance from the source to the detector
+ */
+ float32 getSourceDetectorDistance() const;
+
+ /**
+ * Returns a vector giving the projection direction for a projection and detector index
+ */
+ virtual CVector3D getProjectionDirection(int _iProjectionIndex, int _iDetectorIndex) const;
+};
+
+// Returns the distance from the origin of the coordinate system to the source.
+inline float32 CConeProjectionGeometry3D::getOriginSourceDistance() const
+{
+ return m_fOriginSourceDistance;
+}
+
+
+// Returns the distance from the origin of the coordinate system to the detector.
+inline float32 CConeProjectionGeometry3D::getOriginDetectorDistance() const
+{
+ return m_fOriginDetectorDistance;
+}
+
+
+// Returns the distance from the source to the detector.
+inline float32 CConeProjectionGeometry3D::getSourceDetectorDistance() const
+{
+ return (m_fOriginSourceDistance + m_fOriginDetectorDistance);
+}
+
+
+} // namespace astra
+
+#endif /* _INC_ASTRA_PARALLELPROJECTIONGEOMETRY3D */
diff --git a/include/astra/ConeVecProjectionGeometry3D.h b/include/astra/ConeVecProjectionGeometry3D.h
new file mode 100644
index 0000000..1765cdd
--- /dev/null
+++ b/include/astra/ConeVecProjectionGeometry3D.h
@@ -0,0 +1,154 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_CONEVECPROJECTIONGEOMETRY3D
+#define _INC_ASTRA_CONEVECPROJECTIONGEOMETRY3D
+
+#include "ProjectionGeometry3D.h"
+#include "../cuda/3d/dims3d.h"
+
+namespace astra
+{
+
+/**
+ * This class defines a 3D cone beam projection geometry.
+ *
+ * \par XML Configuration
+ * \astra_xml_item{DetectorRowCount, int, Number of detectors for each projection.}
+ * \astra_xml_item{DetectorColCount, int, Number of detectors for each projection.}
+ * \astra_xml_item{Vectors, matrix defining the 3D position of source and detector.}
+ *
+ * \par MATLAB example
+ * \astra_code{
+ * proj_geom = astra_struct('cone_vec');\n
+ * proj_geom.DetectorRowCount = 512;\n
+ * proj_geom.DetectorColCount = 512;\n
+ * proj_geom.Vectors = V;\n
+ * }
+ *
+ * \par Vectors
+ * Vectors is a matrix containing the actual geometry. Each row corresponds
+ * to a single projection, and consists of:
+ * ( srcX, srcY, srcZ, dX, dY, dZ, uX, uY, uZ, vX, vY, vZ )
+ * src: the ray source
+ * d : the corner of the detector
+ * u : the vector from detector pixel (0,0) to (0,1)
+ * v : the vector from detector pixel (0,0) to (1,0)
+ */
+class _AstraExport CConeVecProjectionGeometry3D : public CProjectionGeometry3D
+{
+protected:
+
+ SConeProjection *m_pProjectionAngles;
+
+public:
+
+ /** Default constructor. Sets all numeric member variables to 0 and all pointer member variables to NULL.
+ *
+ * If an object is constructed using this default constructor, it must always be followed by a call
+ * to one of the initialize() methods before the object can be used. Any use before calling initialize()
+ * is not allowed, except calling the member function isInitialized().
+ */
+ CConeVecProjectionGeometry3D();
+
+ /** Constructor. Create an instance of the CConeVecProjectionGeometry3D class.
+ *
+ * @param _iProjectionAngleCount Number of projection angles.
+ * @param _iDetectorRowCount Number of rows of detectors.
+ * @param _iDetectorColCount Number of columns detectors.
+ * @param _pfProjectionAngles Pointer to an array of projection angles. The angles will be copied from this array.
+ */
+ CConeVecProjectionGeometry3D(int _iProjectionAngleCount,
+ int _iDetectorRowCount,
+ int _iDetectorColCount,
+ const SConeProjection* _pProjectionAngles);
+
+ /** Copy constructor.
+ */
+ CConeVecProjectionGeometry3D(const CConeVecProjectionGeometry3D& _projGeom);
+
+ /** Destructor.
+ */
+ ~CConeVecProjectionGeometry3D();
+
+ /** Initialize the geometry with a config object.
+ *
+ * @param _cfg Configuration Object
+ * @return initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ /** Initialize the geometry. If the object has been initialized before, the object is reinitialized
+ * and memory is freed and reallocated if necessary.
+ *
+ * @param _iProjectionAngleCount Number of projection angles.
+ * @param _iDetectorRowCount Number of rows of detectors.
+ * @param _iDetectorColCount Number of columns detectors.
+ * @param _pProjectionAngles Pointer to an array of projection angles. The angles will be copied from this array.
+ */
+ bool initialize(int _iProjectionAngleCount,
+ int _iDetectorRowCount,
+ int _iDetectorColCount,
+ const SConeProjection* _pProjectionAngles);
+
+ virtual bool _check();
+
+ /** Create a hard copy.
+ */
+ virtual CProjectionGeometry3D* clone() const;
+
+ /** Return true if this geometry instance is the same as the one specified.
+ *
+ * @return true if this geometry instance is the same as the one specified.
+ */
+ virtual bool isEqual(const CProjectionGeometry3D*) const;
+
+ /** Returns true if the type of geometry defined in this class is the one specified in _sType.
+ *
+ * @param _sType geometry type to compare to.
+ * @return true if _sType == "cone_vec".
+ */
+ virtual bool isOfType(const std::string& _sType) const;
+
+ /** Turn this object into an XML object.
+ *
+ * @param _sNode The XML object to fill.
+ */
+ virtual void toXML(XMLNode* _sNode) const;
+
+ /**
+ * Returns a vector giving the projection direction for a projection and detector index
+ */
+ virtual CVector3D getProjectionDirection(int _iProjectionIndex, int _iDetectorIndex) const;
+
+ const SConeProjection* getProjectionVectors() const { return m_pProjectionAngles; }
+};
+
+} // namespace astra
+
+#endif /* _INC_ASTRA_CONEVECPROJECTIONGEOMETRY3D */
diff --git a/include/astra/Config.h b/include/astra/Config.h
new file mode 100644
index 0000000..5a629a2
--- /dev/null
+++ b/include/astra/Config.h
@@ -0,0 +1,80 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_CONFIG
+#define _INC_ASTRA_CONFIG
+
+#include "Globals.h"
+#include "XMLNode.h"
+
+#include <set>
+
+namespace astra {
+
+
+/**
+ * Configuration options for an ASTRA class.
+ */
+struct _AstraExport Config {
+
+ Config();
+ Config(XMLNode* _self);
+ ~Config();
+
+ XMLNode* self;
+ XMLNode* global;
+};
+
+struct ConfigCheckData {
+ // For checking for unparsed nodes/options
+ std::set<std::string> parsedNodes;
+ std::set<std::string> parsedOptions;
+ unsigned int parseDepth;
+};
+
+
+template<class T>
+class ConfigStackCheck {
+public:
+ ConfigStackCheck(const char *_name, T* _obj, const Config& _cfg);
+ ~ConfigStackCheck();
+
+ bool stopParsing(); // returns true if no unused nodes/options
+ void markNodeParsed(const std::string& name);
+ void markOptionParsed(const std::string& name);
+
+
+private:
+ T* object;
+ const Config* cfg;
+ const char* name;
+};
+
+} // end namespace
+
+#endif
diff --git a/include/astra/CudaBackProjectionAlgorithm.h b/include/astra/CudaBackProjectionAlgorithm.h
new file mode 100644
index 0000000..965c734
--- /dev/null
+++ b/include/astra/CudaBackProjectionAlgorithm.h
@@ -0,0 +1,110 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_CUDABACKPROJECTIONALGORITHM
+#define _INC_ASTRA_CUDABACKPROJECTIONALGORITHM
+
+#include "Globals.h"
+#include "Config.h"
+
+#include "CudaReconstructionAlgorithm2D.h"
+
+#ifdef ASTRA_CUDA
+
+namespace astra {
+
+/**
+ * \brief
+ * This class contains a GPU implementation of backprojection.
+ *
+ * \par XML Configuration
+ * \astra_xml_item{ProjectionDataId, integer, Identifier of a projection data object as it is stored in the DataManager.}
+ * \astra_xml_item{ReconstructionDataId, integer, Identifier of a volume data object as it is stored in the DataManager.}
+ *
+ * \par MATLAB example
+ * \astra_code{
+ * cfg = astra_struct('BP_CUDA');\n
+ * cfg.ProjectionDataId = sino_id;\n
+ * cfg.ReconstructionDataId = recon_id;\n
+ * alg_id = astra_mex_algorithm('create'\, cfg);\n
+ * astra_mex_algorithm('iterate'\, alg_id\, 1);\n
+ * astra_mex_algorithm('delete'\, alg_id);\n
+ * }
+ *
+ */
+class _AstraExport CCudaBackProjectionAlgorithm : public CCudaReconstructionAlgorithm2D
+{
+
+public:
+
+ // type of the algorithm, needed to register with CAlgorithmFactory
+ static std::string type;
+
+ /** Default constructor, containing no code.
+ */
+ CCudaBackProjectionAlgorithm();
+
+ /** Destructor.
+ */
+ virtual ~CCudaBackProjectionAlgorithm();
+
+ /** Initialize the algorithm with a config object.
+ *
+ * @param _cfg Configuration Object
+ * @return initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ /** Initialize class.
+ *
+ * @param _pProjector Projector Object. (Ignored)
+ * @param _pSinogram ProjectionData2D object containing the sinogram data.
+ * @param _pReconstruction VolumeData2D object for storing the reconstructed volume.
+ * @param _iGPUindex GPU to use.
+ * @param _iPixelSuperSampling Square root of number of samples per voxel, used to compute the backprojection
+ */
+ bool initialize(CProjector2D* _pProjector,
+ CFloat32ProjectionData2D* _pSinogram,
+ CFloat32VolumeData2D* _pReconstruction,
+ int _iGPUindex = 0, int _iPixelSuperSampling = 1);
+
+ /** Get a description of the class.
+ *
+ * @return description string
+ */
+ virtual std::string description() const;
+};
+
+// inline functions
+inline std::string CCudaBackProjectionAlgorithm::description() const { return CCudaBackProjectionAlgorithm::type; };
+
+} // end namespace
+
+#endif // ASTRA_CUDA
+
+#endif
diff --git a/include/astra/CudaBackProjectionAlgorithm3D.h b/include/astra/CudaBackProjectionAlgorithm3D.h
new file mode 100644
index 0000000..b069da6
--- /dev/null
+++ b/include/astra/CudaBackProjectionAlgorithm3D.h
@@ -0,0 +1,152 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_CUDABACKPROJECTIONALGORITHM3D
+#define _INC_ASTRA_CUDABACKPROJECTIONALGORITHM3D
+
+#include "Globals.h"
+#include "Config.h"
+
+#include "Algorithm.h"
+
+#include "Float32ProjectionData3DMemory.h"
+#include "Float32VolumeData3DMemory.h"
+#include "ReconstructionAlgorithm3D.h"
+
+#ifdef ASTRA_CUDA
+
+namespace astra {
+
+class _AstraExport CCudaBackProjectionAlgorithm3D : public CReconstructionAlgorithm3D {
+
+protected:
+
+ /** Check the values of this object. If everything is ok, the object can be set to the initialized state.
+ * The following statements are then guaranteed to hold:
+ * - no NULL pointers
+ * - all sub-objects are initialized properly
+ * - the projector is compatible with both data objects
+ */
+ virtual bool _check();
+
+public:
+
+ // type of the algorithm, needed to register with CAlgorithmFactory
+ static std::string type;
+
+ /** Default constructor, does not initialize the object.
+ */
+ CCudaBackProjectionAlgorithm3D();
+
+ /** Constructor with initialization.
+ *
+ * @param _pProjector Projector Object.
+ * @param _pProjectionData ProjectionData3D object containing the projection data.
+ * @param _pReconstruction VolumeData3D object for storing the reconstructed volume.
+ */
+ CCudaBackProjectionAlgorithm3D(CProjector3D* _pProjector,
+ CFloat32ProjectionData3DMemory* _pProjectionData,
+ CFloat32VolumeData3DMemory* _pReconstruction);
+
+ /** Copy constructor.
+ */
+ CCudaBackProjectionAlgorithm3D(const CCudaBackProjectionAlgorithm3D&);
+
+ /** Destructor.
+ */
+ virtual ~CCudaBackProjectionAlgorithm3D();
+
+ /** Clear this class.
+ */
+/* virtual void clear();*/
+
+ /** Initialize the algorithm with a config object.
+ *
+ * @param _cfg Configuration Object
+ * @return initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ /** Initialize class.
+ *
+ * @param _pProjector Projector Object.
+ * @param _pProjectionData ProjectionData3D object containing the projection data.
+ * @param _pReconstruction VolumeData3D object for storing the reconstructed volume.
+ * @return initialization successful?
+ */
+ bool initialize(CProjector3D* _pProjector,
+ CFloat32ProjectionData3DMemory* _pSinogram,
+ CFloat32VolumeData3DMemory* _pReconstruction);
+
+ /** Get all information parameters
+ *
+ * @return map with all boost::any object
+ */
+ virtual map<string,boost::any> getInformation();
+
+ /** Get a single piece of information represented as a boost::any
+ *
+ * @param _sIdentifier identifier string to specify which piece of information you want
+ * @return boost::any object
+ */
+ virtual boost::any getInformation(std::string _sIdentifier);
+
+ /** Perform a number of iterations.
+ *
+ * @param _iNrIterations amount of iterations to perform.
+ */
+ virtual void run(int _iNrIterations = 0);
+
+ /** Get a description of the class.
+ *
+ * @return description string
+ */
+ virtual std::string description() const;
+
+ /**
+ * Sets the index of the used GPU index: first GPU has index 0
+ *
+ * @param _iGPUIndex New GPU index.
+ */
+ void setGPUIndex(int _iGPUIndex);
+
+protected:
+
+ int m_iGPUIndex;
+ int m_iVoxelSuperSampling;
+
+};
+
+// inline functions
+inline std::string CCudaBackProjectionAlgorithm3D::description() const { return CCudaBackProjectionAlgorithm3D::type; };
+
+} // end namespace
+
+#endif
+
+#endif
diff --git a/include/astra/CudaCglsAlgorithm.h b/include/astra/CudaCglsAlgorithm.h
new file mode 100644
index 0000000..7734d6e
--- /dev/null
+++ b/include/astra/CudaCglsAlgorithm.h
@@ -0,0 +1,122 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_CUDACGLSALGORITHM
+#define _INC_ASTRA_CUDACGLSALGORITHM
+
+#include "Globals.h"
+#include "Config.h"
+
+#include "CudaReconstructionAlgorithm2D.h"
+
+#ifdef ASTRA_CUDA
+
+namespace astra {
+
+/**
+ * \brief
+ * This class contains a GPU implementation of the CGLS algorithm.
+ *
+ * \par XML Configuration
+ * \astra_xml_item{ProjectionGeometry, integer, Geometry of the projection data.}
+ * \astra_xml_item{VolumeGeometry, integer, Geometry of the volume data.}
+ * \astra_xml_item{ProjectionDataId, integer, Identifier of a projection data object as it is stored in the DataManager.}
+ * \astra_xml_item{ReconstructionDataId, integer, Identifier of a volume data object as it is stored in the DataManager.}
+ * \astra_xml_item_option{ReconstructionMaskId, integer, not used, Identifier of a volume data object that acts as a reconstruction mask. 0 = reconstruct on this pixel. 1 = don't reconstruct on this pixel.}
+ *
+ * \par MATLAB example
+ * \astra_code{
+ * cfg = astra_struct('CGLS_CUDA');\n
+ * cfg.ProjectionGeometry = proj_geom;\n
+ * cfg.VolumeGeometry = vol_geom;\n
+ * cfg.ProjectionDataId = sino_id;\n
+ * cfg.ReconstructionDataId = recon_id;\n
+ * cfg.option.ReconstructionMaskId = mask_id;\n
+ * alg_id = astra_mex_algorithm('create'\, cfg);\n
+ * astra_mex_algorithm('iterate'\, alg_id\, 10);\n
+ * astra_mex_algorithm('delete'\, alg_id);\n
+ * }
+ *
+ */
+
+class AstraCGLS;
+
+class _AstraExport CCudaCglsAlgorithm : public CCudaReconstructionAlgorithm2D
+{
+
+public:
+
+ // type of the algorithm, needed to register with CAlgorithmFactory
+ static std::string type;
+
+ /** Default constructor, containing no code.
+ */
+ CCudaCglsAlgorithm();
+
+ /** Destructor.
+ */
+ virtual ~CCudaCglsAlgorithm();
+
+ /** Initialize the algorithm with a config object.
+ *
+ * @param _cfg Configuration Object
+ * @return initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ /** Initialize class, use sequential order.
+ *
+ * @param _pProjector Projector Object. (Ignored)
+ * @param _pSinogram ProjectionData2D object containing the sinogram
+ * @param _pReconstruction VolumeData2D for storing the reconstruction
+ * @param _iGPUindex Index of GPU to use. (Starting at 0.)
+ * @param _iDetectorSuperSampling Supersampling factor for the FP.
+ * @param _iPixelSuperSampling Square root of number of samples per voxel, used to compute the backprojection
+ */
+ bool initialize(CProjector2D* _pProjector,
+ CFloat32ProjectionData2D* _pSinogram,
+ CFloat32VolumeData2D* _pReconstruction,
+ int _iGPUindex = 0, int _iDetectorSuperSampling = 1,
+ int _iPixelSuperSampling = 1);
+
+ /** Get a description of the class.
+ *
+ * @return description string
+ */
+ virtual std::string description() const;
+
+};
+
+// inline functions
+inline std::string CCudaCglsAlgorithm::description() const { return CCudaCglsAlgorithm::type; };
+
+} // end namespace
+
+#endif // ASTRA_CUDA
+
+#endif
diff --git a/include/astra/CudaCglsAlgorithm3D.h b/include/astra/CudaCglsAlgorithm3D.h
new file mode 100644
index 0000000..47b61af
--- /dev/null
+++ b/include/astra/CudaCglsAlgorithm3D.h
@@ -0,0 +1,173 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_CUDACGLSALGORITHM3D
+#define _INC_ASTRA_CUDACGLSALGORITHM3D
+
+#include "Globals.h"
+#include "Config.h"
+
+#include "Algorithm.h"
+
+#include "Float32ProjectionData3DMemory.h"
+#include "Float32VolumeData3DMemory.h"
+#include "ReconstructionAlgorithm3D.h"
+
+#ifdef ASTRA_CUDA
+
+namespace astra {
+
+class AstraCGLS3d;
+
+/**
+ * \brief
+ * This class contains the 3D implementation of the CGLS algorithm
+ *
+ */
+class _AstraExport CCudaCglsAlgorithm3D : public CReconstructionAlgorithm3D {
+
+protected:
+
+ /** Check the values of this object. If everything is ok, the object can be set to the initialized state.
+ * The following statements are then guaranteed to hold:
+ * - no NULL pointers
+ * - all sub-objects are initialized properly
+ * - the projector is compatible with both data objects
+ */
+ virtual bool _check();
+
+public:
+
+ // type of the algorithm, needed to register with CAlgorithmFactory
+ static std::string type;
+
+ /** Default constructor, does not initialize the object.
+ */
+ CCudaCglsAlgorithm3D();
+
+ /** Constructor with initialization.
+ *
+ * @param _pProjector Projector Object.
+ * @param _pProjectionData ProjectionData3D object containing the projection data.
+ * @param _pReconstruction VolumeData3D object for storing the reconstructed volume.
+ */
+ CCudaCglsAlgorithm3D(CProjector3D* _pProjector,
+ CFloat32ProjectionData3DMemory* _pProjectionData,
+ CFloat32VolumeData3DMemory* _pReconstruction);
+
+ /** Copy constructor.
+ */
+ CCudaCglsAlgorithm3D(const CCudaCglsAlgorithm3D&);
+
+ /** Destructor.
+ */
+ virtual ~CCudaCglsAlgorithm3D();
+
+ /** Clear this class.
+ */
+/* virtual void clear();*/
+
+ /** Initialize the algorithm with a config object.
+ *
+ * @param _cfg Configuration Object
+ * @return initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ /** Initialize class.
+ *
+ * @param _pProjector Projector Object.
+ * @param _pProjectionData ProjectionData3D object containing the projection data.
+ * @param _pReconstruction VolumeData3D object for storing the reconstructed volume.
+ * @return initialization successful?
+ */
+ bool initialize(CProjector3D* _pProjector,
+ CFloat32ProjectionData3DMemory* _pSinogram,
+ CFloat32VolumeData3DMemory* _pReconstruction);
+
+ /** Get all information parameters
+ *
+ * @return map with all boost::any object
+ */
+ virtual map<string,boost::any> getInformation();
+
+ /** Get a single piece of information represented as a boost::any
+ *
+ * @param _sIdentifier identifier string to specify which piece of information you want
+ * @return boost::any object
+ */
+ virtual boost::any getInformation(std::string _sIdentifier);
+
+ /** Perform a number of iterations.
+ *
+ * @param _iNrIterations amount of iterations to perform.
+ */
+ virtual void run(int _iNrIterations = 0);
+
+ /** Get a description of the class.
+ *
+ * @return description string
+ */
+ virtual std::string description() const;
+
+ /**
+ * Sets the index of the used GPU index: first GPU has index 0
+ *
+ * @param _iGPUIndex New GPU index.
+ */
+ void setGPUIndex(int _iGPUIndex);
+
+
+ virtual void signalAbort();
+
+ /** Get the norm of the residual image.
+ * Only a few algorithms support this method.
+ *
+ * @param _fNorm if supported, the norm is returned here
+ * @return true if this operation is supported
+ */
+ virtual bool getResidualNorm(float32& _fNorm);
+
+protected:
+
+ AstraCGLS3d* m_pCgls;
+
+ int m_iGPUIndex;
+ bool m_bAstraCGLSInit;
+ int m_iDetectorSuperSampling;
+ int m_iVoxelSuperSampling;
+};
+
+// inline functions
+inline std::string CCudaCglsAlgorithm3D::description() const { return CCudaCglsAlgorithm3D::type; };
+
+} // end namespace
+
+#endif
+
+#endif
diff --git a/include/astra/CudaDartMaskAlgorithm.h b/include/astra/CudaDartMaskAlgorithm.h
new file mode 100644
index 0000000..f370f42
--- /dev/null
+++ b/include/astra/CudaDartMaskAlgorithm.h
@@ -0,0 +1,126 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_CUDADARTMASKALGORITHM
+#define _INC_ASTRA_CUDADARTMASKALGORITHM
+
+#include "Globals.h"
+#include "Config.h"
+#include "Algorithm.h"
+#include "Float32VolumeData2D.h"
+
+
+#ifdef ASTRA_CUDA
+
+namespace astraCUDA {
+class PDART;
+}
+
+namespace astra {
+
+ class _AstraExport CCudaDartMaskAlgorithm : public CAlgorithm
+{
+
+public:
+
+ // type of the algorithm, needed to register with CAlgorithmFactory
+ static std::string type;
+
+ /** Default constructor, containing no code.
+ */
+ CCudaDartMaskAlgorithm();
+
+ /** Destructor.
+ */
+ virtual ~CCudaDartMaskAlgorithm();
+
+ /** Initialize the algorithm with a config object.
+ *
+ * @param _cfg Configuration Object
+ * @return initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ /** Initialize class, use sequential order.
+ *
+ * @param _pSegmentation ...
+ * @param iConn ...
+ */
+ //bool initialize(CFloat32VolumeData2D* _pSegmentation, int _iConn);
+
+ /** Get all information parameters
+ *
+ * @return map with all boost::any object
+ */
+ virtual map<string,boost::any> getInformation();
+
+ /** Get a single piece of information represented as a boost::any
+ *
+ * @param _sIdentifier identifier string to specify which piece of information you want
+ * @return boost::any object
+ */
+ virtual boost::any getInformation(std::string _sIdentifier);
+
+ /** Get a description of the class.
+ *
+ * @return description string
+ */
+ virtual std::string description() const;
+
+ /** Perform a number of iterations.
+ *
+ * @param _iNrIterations amount of iterations to perform.
+ */
+ virtual void run(int _iNrIterations = 0);
+
+
+protected:
+ /** Check this object.
+ *
+ * @return object initialized
+ */
+ bool _check();
+
+ unsigned int m_iConn;
+ unsigned int m_iThreshold;
+ unsigned int m_iRadius;
+ int m_iGPUIndex;
+
+ CFloat32VolumeData2D* m_pSegmentation;
+ CFloat32VolumeData2D* m_pMask;
+
+};
+
+// inline functions
+inline std::string CCudaDartMaskAlgorithm::description() const { return CCudaDartMaskAlgorithm::type; };
+
+} // end namespace
+
+#endif // ASTRA_CUDA
+
+#endif
diff --git a/include/astra/CudaDartMaskAlgorithm3D.h b/include/astra/CudaDartMaskAlgorithm3D.h
new file mode 100644
index 0000000..bdbce2b
--- /dev/null
+++ b/include/astra/CudaDartMaskAlgorithm3D.h
@@ -0,0 +1,122 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_CUDADARTMASKALGORITHM3D
+#define _INC_ASTRA_CUDADARTMASKALGORITHM3D
+
+#include "Globals.h"
+#include "Config.h"
+#include "Algorithm.h"
+#include "Float32VolumeData3DMemory.h"
+
+
+#ifdef ASTRA_CUDA
+
+namespace astra {
+
+ class _AstraExport CCudaDartMaskAlgorithm3D : public CAlgorithm
+{
+
+public:
+
+ // type of the algorithm, needed to register with CAlgorithmFactory
+ static std::string type;
+
+ /** Default constructor, containing no code.
+ */
+ CCudaDartMaskAlgorithm3D();
+
+ /** Destructor.
+ */
+ virtual ~CCudaDartMaskAlgorithm3D();
+
+ /** Initialize the algorithm with a config object.
+ *
+ * @param _cfg Configuration Object
+ * @return initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ /** Initialize class, use sequential order.
+ *
+ * @param _pSegmentation ...
+ * @param iConn ...
+ */
+ //bool initialize(CFloat32VolumeData2D* _pSegmentation, int _iConn);
+
+ /** Get all information parameters
+ *
+ * @return map with all boost::any object
+ */
+ virtual map<string,boost::any> getInformation();
+
+ /** Get a single piece of information represented as a boost::any
+ *
+ * @param _sIdentifier identifier string to specify which piece of information you want
+ * @return boost::any object
+ */
+ virtual boost::any getInformation(std::string _sIdentifier);
+
+ /** Get a description of the class.
+ *
+ * @return description string
+ */
+ virtual std::string description() const;
+
+ /** Perform a number of iterations.
+ *
+ * @param _iNrIterations amount of iterations to perform.
+ */
+ virtual void run(int _iNrIterations = 0);
+
+
+protected:
+ /** Check this object.
+ *
+ * @return object initialized
+ */
+ bool _check();
+
+ unsigned int m_iConn;
+ unsigned int m_iThreshold;
+ unsigned int m_iRadius;
+ int m_iGPUIndex;
+
+ CFloat32VolumeData3DMemory* m_pSegmentation;
+ CFloat32VolumeData3DMemory* m_pMask;
+
+};
+
+// inline functions
+inline std::string CCudaDartMaskAlgorithm3D::description() const { return CCudaDartMaskAlgorithm3D::type; };
+
+} // end namespace
+
+#endif // ASTRA_CUDA
+
+#endif
diff --git a/include/astra/CudaDartSmoothingAlgorithm.h b/include/astra/CudaDartSmoothingAlgorithm.h
new file mode 100644
index 0000000..f90f9cf
--- /dev/null
+++ b/include/astra/CudaDartSmoothingAlgorithm.h
@@ -0,0 +1,125 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_CUDADARTSMOOTHINGALGORITHM
+#define _INC_ASTRA_CUDADARTSMOOTHINGALGORITHM
+
+#include "Globals.h"
+#include "Config.h"
+#include "Algorithm.h"
+#include "Float32VolumeData2D.h"
+
+
+#ifdef ASTRA_CUDA
+
+namespace astraCUDA {
+class PDART;
+}
+
+namespace astra {
+
+ class _AstraExport CCudaDartSmoothingAlgorithm : public CAlgorithm
+{
+
+public:
+
+ // type of the algorithm, needed to register with CAlgorithmFactory
+ static std::string type;
+
+ /** Default constructor, containing no code.
+ */
+ CCudaDartSmoothingAlgorithm();
+
+ /** Destructor.
+ */
+ virtual ~CCudaDartSmoothingAlgorithm();
+
+ /** Initialize the algorithm with a config object.
+ *
+ * @param _cfg Configuration Object
+ * @return initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ /** Initialize class, use sequential order.
+ *
+ * @param _pSegmentation ...
+ * @param iConn ...
+ */
+ //bool initialize(CFloat32VolumeData2D* _pSegmentation, int _iConn);
+
+ /** Get all information parameters
+ *
+ * @return map with all boost::any object
+ */
+ virtual map<string,boost::any> getInformation();
+
+ /** Get a single piece of information represented as a boost::any
+ *
+ * @param _sIdentifier identifier string to specify which piece of information you want
+ * @return boost::any object
+ */
+ virtual boost::any getInformation(std::string _sIdentifier);
+
+ /** Get a description of the class.
+ *
+ * @return description string
+ */
+ virtual std::string description() const;
+
+ /** Perform a number of iterations.
+ *
+ * @param _iNrIterations amount of iterations to perform.
+ */
+ virtual void run(int _iNrIterations = 0);
+
+
+protected:
+ /** Check this object.
+ *
+ * @return object initialized
+ */
+ bool _check();
+
+ float m_fB;
+ unsigned int m_iRadius;
+ int m_iGPUIndex;
+
+ CFloat32VolumeData2D* m_pIn;
+ CFloat32VolumeData2D* m_pOut;
+
+};
+
+// inline functions
+inline std::string CCudaDartSmoothingAlgorithm::description() const { return CCudaDartSmoothingAlgorithm::type; };
+
+} // end namespace
+
+#endif // ASTRA_CUDA
+
+#endif
diff --git a/include/astra/CudaDartSmoothingAlgorithm3D.h b/include/astra/CudaDartSmoothingAlgorithm3D.h
new file mode 100644
index 0000000..9942de8
--- /dev/null
+++ b/include/astra/CudaDartSmoothingAlgorithm3D.h
@@ -0,0 +1,122 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_CUDADARTSMOOTHINGALGORITHM3D
+#define _INC_ASTRA_CUDADARTSMOOTHINGALGORITHM3D
+
+#include "Globals.h"
+#include "Config.h"
+#include "Algorithm.h"
+#include "Float32VolumeData3DMemory.h"
+
+
+#ifdef ASTRA_CUDA
+
+namespace astra {
+
+ class _AstraExport CCudaDartSmoothingAlgorithm3D : public CAlgorithm
+{
+
+public:
+
+ // type of the algorithm, needed to register with CAlgorithmFactory
+ static std::string type;
+
+ /** Default constructor, containing no code.
+ */
+ CCudaDartSmoothingAlgorithm3D();
+
+ /** Destructor.
+ */
+ virtual ~CCudaDartSmoothingAlgorithm3D();
+
+ /** Initialize the algorithm with a config object.
+ *
+ * @param _cfg Configuration Object
+ * @return initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ /** Initialize class, use sequential order.
+ *
+ * @param _pSegmentation ...
+ * @param iConn ...
+ */
+ //bool initialize(CFloat32VolumeData2D* _pSegmentation, int _iConn);
+
+ /** Get all information parameters
+ *
+ * @return map with all boost::any object
+ */
+ virtual map<string,boost::any> getInformation();
+
+ /** Get a single piece of information represented as a boost::any
+ *
+ * @param _sIdentifier identifier string to specify which piece of information you want
+ * @return boost::any object
+ */
+ virtual boost::any getInformation(std::string _sIdentifier);
+
+ /** Get a description of the class.
+ *
+ * @return description string
+ */
+ virtual std::string description() const;
+
+ /** Perform a number of iterations.
+ *
+ * @param _iNrIterations amount of iterations to perform.
+ */
+ virtual void run(int _iNrIterations = 0);
+
+
+protected:
+
+ /** Check this object.
+ *
+ * @return object initialized
+ */
+ bool _check();
+
+ float m_fB;
+ unsigned int m_iRadius;
+ int m_iGPUIndex;
+
+ CFloat32VolumeData3DMemory* m_pIn;
+ CFloat32VolumeData3DMemory* m_pOut;
+
+};
+
+// inline functions
+inline std::string CCudaDartSmoothingAlgorithm3D::description() const { return CCudaDartSmoothingAlgorithm3D::type; };
+
+} // end namespace
+
+#endif // ASTRA_CUDA
+
+#endif
diff --git a/include/astra/CudaDataOperationAlgorithm.h b/include/astra/CudaDataOperationAlgorithm.h
new file mode 100644
index 0000000..a5ab01a
--- /dev/null
+++ b/include/astra/CudaDataOperationAlgorithm.h
@@ -0,0 +1,128 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_CUDADATAOPERATIONALGORITHM
+#define _INC_ASTRA_CUDADATAOPERATIONALGORITHM
+
+#include "Globals.h"
+#include "Config.h"
+#include "Algorithm.h"
+#include "Float32VolumeData2D.h"
+
+#ifdef ASTRA_CUDA
+
+namespace astraCUDA {
+class PDART;
+}
+
+namespace astra {
+
+ class _AstraExport CCudaDataOperationAlgorithm : public CAlgorithm
+{
+
+public:
+
+ // type of the algorithm, needed to register with CAlgorithmFactory
+ static std::string type;
+
+ /** Default constructor, containing no code.
+ */
+ CCudaDataOperationAlgorithm();
+
+ /** Destructor.
+ */
+ virtual ~CCudaDataOperationAlgorithm();
+
+ /** Initialize the algorithm with a config object.
+ *
+ * @param _cfg Configuration Object
+ * @return initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ /** Initialize class, use sequential order.
+ *
+ * @param _pSegmentation ...
+ * @param iConn ...
+ */
+ //bool initialize(CFloat32VolumeData2D* _pSegmentation, int _iConn);
+
+ /** Get all information parameters
+ *
+ * @return map with all boost::any object
+ */
+ virtual map<string,boost::any> getInformation();
+
+ /** Get a single piece of information represented as a boost::any
+ *
+ * @param _sIdentifier identifier string to specify which piece of information you want
+ * @return boost::any object
+ */
+ virtual boost::any getInformation(std::string _sIdentifier);
+
+ /** Get a description of the class.
+ *
+ * @return description string
+ */
+ virtual std::string description() const;
+
+ /** Perform a number of iterations.
+ *
+ * @param _iNrIterations amount of iterations to perform.
+ */
+ virtual void run(int _iNrIterations = 0);
+
+
+protected:
+ /** Check this object.
+ *
+ * @return object initialized
+ */
+ bool _check();
+
+
+
+ int m_iGPUIndex;
+
+ CFloat32Data2D* m_pMask;
+
+ vector<CFloat32Data2D*> m_pData;
+ vector<float> m_fScalar;
+
+ string m_sOperation;
+
+};
+
+// inline functions
+inline std::string CCudaDataOperationAlgorithm::description() const { return CCudaDataOperationAlgorithm::type; };
+
+} // end namespace
+
+#endif // ASTRA_CUDA
+
+#endif
diff --git a/include/astra/CudaEMAlgorithm.h b/include/astra/CudaEMAlgorithm.h
new file mode 100644
index 0000000..ff22dd4
--- /dev/null
+++ b/include/astra/CudaEMAlgorithm.h
@@ -0,0 +1,92 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_CUDAEMALGORITHM
+#define _INC_ASTRA_CUDAEMALGORITHM
+
+#include "Globals.h"
+#include "Config.h"
+
+#include "CudaReconstructionAlgorithm2D.h"
+
+#ifdef ASTRA_CUDA
+
+namespace astra {
+
+class _AstraExport CCudaEMAlgorithm : public CCudaReconstructionAlgorithm2D
+{
+
+public:
+
+ // type of the algorithm, needed to register with CAlgorithmFactory
+ static std::string type;
+
+ /** Default constructor, containing no code.
+ */
+ CCudaEMAlgorithm();
+
+ /** Destructor.
+ */
+ virtual ~CCudaEMAlgorithm();
+
+ /** Initialize the algorithm with a config object.
+ *
+ * @param _cfg Configuration Object
+ * @return initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ /** Initialize class.
+ *
+ * @param _pProjector Projector Object. (Ignored)
+ * @param _pSinogram ProjectionData2D object containing the sinogram data.
+ * @param _pReconstruction VolumeData2D object for storing the reconstructed volume.
+ * @param _iGPUindex GPU to use.
+ * @param _iDetectorSuperSampling Supersampling factor for the FP.
+ */
+ bool initialize(CProjector2D* _pProjector,
+ CFloat32ProjectionData2D* _pSinogram,
+ CFloat32VolumeData2D* _pReconstruction,
+ int _iGPUindex = 0, int _iDetectorSuperSampling = 1,
+ int _iPixelSuperSampling = 1);
+
+ /** Get a description of the class.
+ *
+ * @return description string
+ */
+ virtual std::string description() const;
+};
+
+// inline functions
+inline std::string CCudaEMAlgorithm::description() const { return CCudaEMAlgorithm::type; };
+
+} // end namespace
+
+#endif // ASTRA_CUDA
+
+#endif
diff --git a/include/astra/CudaFDKAlgorithm3D.h b/include/astra/CudaFDKAlgorithm3D.h
new file mode 100644
index 0000000..7ab9bbe
--- /dev/null
+++ b/include/astra/CudaFDKAlgorithm3D.h
@@ -0,0 +1,164 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_CUDAFDKALGORITHM3D
+#define _INC_ASTRA_CUDAFDKALGORITHM3D
+
+#include "Globals.h"
+#include "Config.h"
+
+#include "Algorithm.h"
+
+#include "Float32ProjectionData3DMemory.h"
+#include "Float32VolumeData3DMemory.h"
+#include "ReconstructionAlgorithm3D.h"
+
+#ifdef ASTRA_CUDA
+
+namespace astra {
+
+/**
+ * \brief
+ * This class contains the 3D implementation of the FDK algorithm.
+ *
+ * \par XML Configuration
+ *
+ * \par MATLAB example
+ * \astra_code{
+ *
+ * }
+ *
+ */
+class _AstraExport CCudaFDKAlgorithm3D : public CReconstructionAlgorithm3D {
+
+protected:
+
+ /** Check the values of this object. If everything is ok, the object can be set to the initialized state.
+ * The following statements are then guaranteed to hold:
+ * - no NULL pointers
+ * - all sub-objects are initialized properly
+ * - the projector is compatible with both data objects
+ */
+ virtual bool _check();
+
+public:
+
+ // type of the algorithm, needed to register with CAlgorithmFactory
+ static std::string type;
+
+ /** Default constructor, does not initialize the object.
+ */
+ CCudaFDKAlgorithm3D();
+
+ /** Constructor with initialization.
+ *
+ * @param _pProjector Projector Object.
+ * @param _pProjectionData ProjectionData3D object containing the projection data.
+ * @param _pReconstruction VolumeData3D object for storing the reconstructed volume.
+ */
+ CCudaFDKAlgorithm3D(CProjector3D* _pProjector,
+ CFloat32ProjectionData3DMemory* _pProjectionData,
+ CFloat32VolumeData3DMemory* _pReconstruction);
+
+ /** Copy constructor.
+ */
+ CCudaFDKAlgorithm3D(const CCudaFDKAlgorithm3D&);
+
+ /** Destructor.
+ */
+ virtual ~CCudaFDKAlgorithm3D();
+
+ /** Clear this class.
+ */
+/* virtual void clear();*/
+
+ /** Initialize the algorithm with a config object.
+ *
+ * @param _cfg Configuration Object
+ * @return initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ /** Initialize class.
+ *
+ * @param _pProjector Projector Object.
+ * @param _pProjectionData ProjectionData3D object containing the projection data.
+ * @param _pReconstruction VolumeData3D object for storing the reconstructed volume.
+ * @return initialization successful?
+ */
+ bool initialize(CProjector3D* _pProjector,
+ CFloat32ProjectionData3DMemory* _pSinogram,
+ CFloat32VolumeData3DMemory* _pReconstruction);
+
+ /** Get all information parameters
+ *
+ * @return map with all boost::any object
+ */
+ virtual map<string,boost::any> getInformation();
+
+ /** Get a single piece of information represented as a boost::any
+ *
+ * @param _sIdentifier identifier string to specify which piece of information you want
+ * @return boost::any object
+ */
+ virtual boost::any getInformation(std::string _sIdentifier);
+
+ /** Perform a number of iterations.
+ *
+ * @param _iNrIterations amount of iterations to perform.
+ */
+ virtual void run(int _iNrIterations = 0);
+
+ /** Get a description of the class.
+ *
+ * @return description string
+ */
+ virtual std::string description() const;
+
+ /**
+ * Sets the index of the used GPU index: first GPU has index 0
+ *
+ * @param _iGPUIndex New GPU index.
+ */
+ void setGPUIndex(int _iGPUIndex);
+
+protected:
+
+ int m_iGPUIndex;
+ int m_iVoxelSuperSampling;
+ bool m_bShortScan;
+};
+
+// inline functions
+inline std::string CCudaFDKAlgorithm3D::description() const { return CCudaFDKAlgorithm3D::type; };
+
+} // end namespace
+
+#endif
+
+#endif
diff --git a/include/astra/CudaFilteredBackProjectionAlgorithm.h b/include/astra/CudaFilteredBackProjectionAlgorithm.h
new file mode 100644
index 0000000..4b7b904
--- /dev/null
+++ b/include/astra/CudaFilteredBackProjectionAlgorithm.h
@@ -0,0 +1,94 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef CUDAFILTEREDBACKPROJECTIONALGORITHM2_H
+#define CUDAFILTEREDBACKPROJECTIONALGORITHM2_H
+
+#include <astra/Float32ProjectionData2D.h>
+#include <astra/Float32VolumeData2D.h>
+#include <astra/ReconstructionAlgorithm2D.h>
+
+#include "../../cuda/2d/astra.h"
+
+namespace astra
+{
+
+class _AstraExport CCudaFilteredBackProjectionAlgorithm : public CReconstructionAlgorithm2D
+{
+public:
+ static std::string type;
+
+private:
+ CFloat32ProjectionData2D * m_pSinogram;
+ CFloat32VolumeData2D * m_pReconstruction;
+ int m_iGPUIndex;
+ int m_iPixelSuperSampling;
+ E_FBPFILTER m_eFilter;
+ float * m_pfFilter;
+ int m_iFilterWidth; // number of elements per projection direction in filter
+ float m_fFilterParameter; // some filters allow for parameterization (value < 0.0f -> no parameter)
+ float m_fFilterD; // frequency cut-off
+
+ static E_FBPFILTER _convertStringToFilter(const char * _filterType);
+
+public:
+ CCudaFilteredBackProjectionAlgorithm();
+ virtual ~CCudaFilteredBackProjectionAlgorithm();
+
+ virtual bool initialize(const Config& _cfg);
+ bool initialize(CFloat32ProjectionData2D * _pSinogram, CFloat32VolumeData2D * _pReconstruction, E_FBPFILTER _eFilter, const float * _pfFilter = NULL, int _iFilterWidth = 0, int _iGPUIndex = 0, float _fFilterParameter = -1.0f);
+
+ virtual void run(int _iNrIterations = 0);
+
+ static int calcIdealRealFilterWidth(int _iDetectorCount);
+ static int calcIdealFourierFilterWidth(int _iDetectorCount);
+
+ //debug
+ static void testGenFilter(E_FBPFILTER _eFilter, float _fD, int _iProjectionCount, cufftComplex * _pFilter, int _iFFTRealDetectorCount, int _iFFTFourierDetectorCount);
+ static int getGPUCount();
+
+ /** Get a description of the class.
+ *
+ * @return description string
+ */
+ virtual std::string description() const;
+
+protected:
+ bool check();
+
+ AstraFBP* m_pFBP;
+
+ bool m_bAstraFBPInit;
+};
+
+// inline functions
+inline std::string CCudaFilteredBackProjectionAlgorithm::description() const { return CCudaFilteredBackProjectionAlgorithm::type; };
+
+}
+
+#endif /* CUDAFILTEREDBACKPROJECTIONALGORITHM2_H */
diff --git a/include/astra/CudaForwardProjectionAlgorithm.h b/include/astra/CudaForwardProjectionAlgorithm.h
new file mode 100644
index 0000000..53b6c8e
--- /dev/null
+++ b/include/astra/CudaForwardProjectionAlgorithm.h
@@ -0,0 +1,169 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_CUDAFORWARDPROJECTIONALGORITHM2
+#define _INC_ASTRA_CUDAFORWARDPROJECTIONALGORITHM2
+
+#include "Globals.h"
+
+#include "Algorithm.h"
+
+#include "ParallelProjectionGeometry2D.h"
+#include "VolumeGeometry2D.h"
+
+#include "Float32ProjectionData2D.h"
+#include "Float32VolumeData2D.h"
+
+#ifdef ASTRA_CUDA
+
+namespace astra {
+
+/**
+ * \brief
+ * This class contains a GPU implementation of an algorithm that creates a forward projection
+ * of a volume object and stores it into a sinogram.
+ *
+ * \par XML Configuration
+ * \astra_xml_item{VolumeGeometry, integer, Geometry of the volume data.}
+ * \astra_xml_item{ProjectionGeometry, integer, Geometry of the projection data.}
+ * \astra_xml_item{VolumeDataId, integer, Identifier of the volume data object as it is stored in the DataManager.}
+ * \astra_xml_item{ProjectionDataId, integer, Identifier of the resulting projection data object as it is stored in the DataManager.}
+ *
+ * \par MATLAB example
+ * \astra_code{
+ * cfg = astra_struct('FP_CUDA2');\n
+ * cfg.VolumeGeometry = vol_geom;\n
+ * cfg.ProjectionGeometry = proj_geom;\n
+ * cfg.VolumeDataId = vol_id;\n
+ * cfg.ProjectionDataId = sino_id;\n
+ * alg_id = astra_mex_algorithm('create'\, cfg);\n
+ * astra_mex_algorithm('run'\, alg_id);\n
+ * astra_mex_algorithm('delete'\, alg_id);\n
+ * }
+ *
+ */
+class _AstraExport CCudaForwardProjectionAlgorithm : public CAlgorithm
+{
+public:
+
+ // type of the algorithm, needed to register with CAlgorithmFactory
+ static std::string type;
+
+ /** Default constructor, containing no code.
+ */
+ CCudaForwardProjectionAlgorithm();
+
+ /** Destructor.
+ */
+ virtual ~CCudaForwardProjectionAlgorithm();
+
+ /** Initialize the algorithm with a config object.
+ *
+ * @param _cfg Configuration Object
+ * @return initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ /** Initialize class.
+ *
+ * @param _pVolumeGeometry Geometry of the volume.
+ * @param _pProjectionGeometry Geometry of the projection.
+ * @param _pVolume VolumeData2D object containing the phantom to compute sinogram from
+ * @param _pSinogram ProjectionData2D object to store sinogram data in.
+ * @param _iGPUindex Index of GPU to use. (Starting at 0.)
+ * @param _iDetectorSuperSampling Number of samples per detector element, used to compute the forward projection
+ * @return success
+ */
+ bool initialize(CProjectionGeometry2D* _pProjectionGeometry,
+ CVolumeGeometry2D* _pVolumeGeometry,
+ CFloat32VolumeData2D* _pVolume,
+ CFloat32ProjectionData2D* _pSinogram,
+ int _iGPUindex = 0, int _iDetectorSuperSampling = 1);
+
+ /** Get all information parameters
+ *
+ * @return map with all boost::any object
+ */
+ virtual map<string,boost::any> getInformation();
+
+ /** Get a single piece of information represented as a boost::any
+ *
+ * @param _sIdentifier identifier string to specify which piece of information you want
+ * @return boost::any object
+ */
+ virtual boost::any getInformation(std::string _sIdentifier);
+
+ /** Perform a number of iterations.
+ *
+ * @param _iNrIterations amount of iterations to perform.
+ */
+ virtual void run(int _iNrIterations = 0);
+
+ /** Get a description of the class.
+ *
+ * @return description string
+ */
+ virtual std::string description() const;
+
+ /** Check this object.
+ *
+ * @return object initialized
+ */
+ bool check();
+
+ CFloat32VolumeData2D* getVolume() { return m_pVolume; }
+ CFloat32ProjectionData2D* getSinogram() { return m_pSinogram; }
+
+ /**
+ * Sets the index of the used GPU index: first GPU has index 0
+ *
+ * @param _iGPUIndex New GPU index.
+ */
+ void setGPUIndex(int _iGPUIndex);
+
+protected:
+ //< ProjectionData2D object containing the sinogram.
+ CFloat32ProjectionData2D* m_pSinogram;
+ //< VolumeData2D object containing the phantom.
+ CFloat32VolumeData2D* m_pVolume;
+
+ //< Index of GPU to use
+ int m_iGPUIndex;
+ //< Number of rays per detector element
+ int m_iDetectorSuperSampling;
+
+};
+
+// inline functions
+inline std::string CCudaForwardProjectionAlgorithm::description() const { return CCudaForwardProjectionAlgorithm::type; };
+
+} // end namespace
+
+#endif // ASTRA_CUDA
+
+#endif
diff --git a/include/astra/CudaForwardProjectionAlgorithm3D.h b/include/astra/CudaForwardProjectionAlgorithm3D.h
new file mode 100644
index 0000000..72c6a00
--- /dev/null
+++ b/include/astra/CudaForwardProjectionAlgorithm3D.h
@@ -0,0 +1,135 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_CUDAFORWARDPROJECTIONALGORITHM3D
+#define _INC_ASTRA_CUDAFORWARDPROJECTIONALGORITHM3D
+
+#include "Globals.h"
+
+#include "Algorithm.h"
+
+#include "Float32ProjectionData3DMemory.h"
+#include "Float32VolumeData3DMemory.h"
+
+#ifdef ASTRA_CUDA
+
+namespace astra {
+
+class CProjector3D;
+
+class _AstraExport CCudaForwardProjectionAlgorithm3D : public CAlgorithm
+{
+public:
+
+ // type of the algorithm, needed to register with CAlgorithmFactory
+ static std::string type;
+
+ /** Default constructor, containing no code.
+ */
+ CCudaForwardProjectionAlgorithm3D();
+
+ /** Destructor.
+ */
+ virtual ~CCudaForwardProjectionAlgorithm3D();
+
+ /** Initialize the algorithm with a config object.
+ *
+ * @param _cfg Configuration Object
+ * @return initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ /** Initialize class.
+ *
+ * @param _pProjector Projector Object.
+ * @param _pProjectionData ProjectionData3D object for storing the projection data.
+ * @param _pReconstruction VolumeData3D object containing the volume.
+ * @return initialization successful?
+ */
+ bool initialize(CProjector3D* _pProjector,
+ CFloat32ProjectionData3DMemory* _pSinogram,
+ CFloat32VolumeData3DMemory* _pReconstruction,
+ int _iGPUindex = 0, int _iDetectorSuperSampling = 1);
+
+
+ /** Get all information parameters
+ *
+ * @return map with all boost::any object
+ */
+ virtual map<string,boost::any> getInformation();
+
+ /** Get a single piece of information represented as a boost::any
+ *
+ * @param _sIdentifier identifier string to specify which piece of information you want
+ * @return boost::any object
+ */
+ virtual boost::any getInformation(std::string _sIdentifier);
+
+ /** Perform a number of iterations.
+ *
+ * @param _iNrIterations amount of iterations to perform.
+ */
+ virtual void run(int _iNrIterations = 0);
+
+ /** Get a description of the class.
+ *
+ * @return description string
+ */
+ virtual std::string description() const;
+
+ /** Check this object.
+ *
+ * @return object initialized
+ */
+ bool check();
+
+ /**
+ * Sets the index of the used GPU index: first GPU has index 0
+ *
+ * @param _iGPUIndex New GPU index.
+ */
+ void setGPUIndex(int _iGPUIndex);
+
+protected:
+ CProjector3D* m_pProjector;
+ CFloat32ProjectionData3DMemory* m_pProjections;
+ CFloat32VolumeData3DMemory* m_pVolume;
+ int m_iGPUIndex;
+ int m_iDetectorSuperSampling;
+
+};
+
+// inline functions
+inline std::string CCudaForwardProjectionAlgorithm3D::description() const { return CCudaForwardProjectionAlgorithm3D::type; };
+
+
+}
+
+#endif
+
+#endif
diff --git a/include/astra/CudaProjector2D.h b/include/astra/CudaProjector2D.h
new file mode 100644
index 0000000..073b299
--- /dev/null
+++ b/include/astra/CudaProjector2D.h
@@ -0,0 +1,122 @@
+/*
+-----------------------------------------------------------------------
+This file is part of the
+All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA-Toolbox")
+
+Copyright: IBBT-Vision Lab, University of Antwerp
+Contact: mailto:wim.vanaarle@ua.ac.be
+Website: http://astra.ua.ac.be
+-----------------------------------------------------------------------
+$Id$
+*/
+#ifndef _INC_ASTRA_CUDAPROJECTOR2D
+#define _INC_ASTRA_CUDAPROJECTOR2D
+
+#include "ParallelProjectionGeometry2D.h"
+#include "Float32Data2D.h"
+#include "Projector2D.h"
+#include "../../cuda/2d/astra.h"
+
+namespace astra
+{
+
+
+/** This is a two-dimensional CUDA-projector.
+ * It is essentially a fake projector, containing settings relevant for the
+ * actual CUDA code.
+ */
+class _AstraExport CCudaProjector2D : public CProjector2D {
+
+protected:
+
+ /** Initial clearing. Only to be used by constructors.
+ */
+ virtual void _clear();
+
+ /** Check the values of this object. If everything is ok, the object can be set to the initialized state.
+ * The following statements are then guaranteed to hold:
+ * - no NULL pointers
+ * - all sub-objects are initialized properly
+ * - blobvalues are ok
+ */
+ virtual bool _check();
+
+public:
+
+ // type of the projector, needed to register with CProjectorFactory
+ static std::string type;
+
+ /** Default constructor.
+ */
+ CCudaProjector2D();
+
+ /** Constructor.
+ *
+ * @param _pProjectionGeometry Information class about the geometry of the projection. Will be HARDCOPIED.
+ * @param _pReconstructionGeometry Information class about the geometry of the reconstruction volume. Will be HARDCOPIED.
+ */
+ CCudaProjector2D(CParallelProjectionGeometry2D* _pProjectionGeometry,
+ CVolumeGeometry2D* _pReconstructionGeometry);
+
+ ~CCudaProjector2D();
+
+ /** Initialize the projector with a config object.
+ *
+ * @param _cfg Configuration Object
+ * @return initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ /** Clear this class.
+ */
+ virtual void clear();
+
+
+ virtual int getProjectionWeightsCount(int _iProjectionIndex) { return 0; }
+
+ virtual void computeSingleRayWeights(int _iProjectionIndex,
+ int _iDetectorIndex,
+ SPixelWeight* _pWeightedPixels,
+ int _iMaxPixelCount,
+ int& _iStoredPixelCount) {}
+
+ virtual std::vector<SDetector2D> projectPoint(int _iRow, int _iCol)
+ { std::vector<SDetector2D> x; return x; }
+
+ template <typename Policy>
+ void project(Policy& _policy) {}
+ template <typename Policy>
+ void projectSingleProjection(int _iProjection, Policy& _policy) {}
+ template <typename Policy>
+ void projectSingleRay(int _iProjection, int _iDetector, Policy& _policy) {}
+
+
+ /** Return the type of this projector.
+ *
+ * @return identification type of this projector
+ */
+ virtual std::string getType();
+
+ /** get a description of the class
+ *
+ * @return description string
+ */
+ virtual std::string description() const;
+
+
+protected:
+
+ Cuda2DProjectionKernel m_projectionKernel;
+};
+
+//----------------------------------------------------------------------------------------
+
+inline std::string CCudaProjector2D::getType()
+{
+ return type;
+}
+
+} // namespace astra
+
+#endif
+
diff --git a/include/astra/CudaProjector3D.h b/include/astra/CudaProjector3D.h
new file mode 100644
index 0000000..66071f0
--- /dev/null
+++ b/include/astra/CudaProjector3D.h
@@ -0,0 +1,131 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef INC_ASTRA_CUDAPROJECTOR3D
+#define INC_ASTRA_CUDAPROJECTOR3D
+
+#ifdef ASTRA_CUDA
+
+#include <cmath>
+#include <vector>
+
+#include "Globals.h"
+#include "Config.h"
+#include "Projector3D.h"
+#include "../../cuda/3d/astra3d.h"
+
+namespace astra
+{
+
+/** This is a three-dimensional CUDA-projector.
+ * It is essentially a fake projector, containing settings relevant for the
+ * actual CUDA code.
+ */
+class _AstraExport CCudaProjector3D : public CProjector3D
+{
+
+protected:
+
+ /** Check variable values.
+ */
+ bool _check();
+
+ /** 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 _clear();
+
+public:
+
+ // type of the projector, needed to register with CProjectorFactory
+ static std::string type;
+
+ /**
+ * Default Constructor.
+ */
+ CCudaProjector3D();
+
+ /** Destructor, is virtual to show that we are aware subclass destructor is called.
+ */
+ virtual ~CCudaProjector3D();
+
+ /** Clear all member variables, setting all numeric variables to 0 and all pointers to NULL.
+ */
+ void clear();
+
+ /** Initialize the projector with a config object.
+ *
+ * @param _cfg Configuration Object
+ * @return initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ virtual void computeSingleRayWeights(int _iProjectionIndex,
+ int _iSliceIndex,
+ int _iDetectorIndex,
+ SPixelWeight* _pWeightedPixels,
+ int _iMaxPixelCount,
+ int& _iStoredPixelCount) {}
+ virtual int getProjectionWeightsCount(int _iProjectionIndex) { return 0; }
+ template <typename Policy>
+ void project(Policy& _policy) {}
+ template <typename Policy>
+ void projectSingleProjection(int _iProjection, Policy& _policy) {}
+ template <typename Policy>
+ void projectSingleRay(int _iProjection, int _iSlice, int _iDetector, Policy& _policy) {}
+
+
+
+ /** Return the type of this projector.
+ *
+ * @return identification type of this projector
+ */
+ virtual std::string getType() { return type; }
+
+ /** get a description of the class
+ *
+ * @return description string
+ */
+ virtual std::string description() const;
+
+
+ Cuda3DProjectionKernel getProjectionKernel() const { return m_projectionKernel; }
+
+protected:
+
+ Cuda3DProjectionKernel m_projectionKernel;
+
+
+};
+
+
+} // namespace astra
+
+#endif // ASTRA_CUDA
+
+#endif /* INC_ASTRA_CUDAPROJECTOR3D */
diff --git a/include/astra/CudaReconstructionAlgorithm2D.h b/include/astra/CudaReconstructionAlgorithm2D.h
new file mode 100644
index 0000000..88fc344
--- /dev/null
+++ b/include/astra/CudaReconstructionAlgorithm2D.h
@@ -0,0 +1,176 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_CUDARECONSTRUCTIONALGORITHM2D
+#define _INC_ASTRA_CUDARECONSTRUCTIONALGORITHM2D
+
+#include "Globals.h"
+#include "Config.h"
+
+#include "ReconstructionAlgorithm2D.h"
+
+#include "Projector2D.h"
+#include "Float32ProjectionData2D.h"
+#include "Float32VolumeData2D.h"
+
+namespace astraCUDA {
+class ReconAlgo;
+}
+
+namespace astra {
+
+/**
+ * This is a base class for the different CUDA implementations of 2D reconstruction algorithms.
+ * They don't use a Projector, and share GPUIndex and DetectorSuperSampling options.
+ *
+ */
+class _AstraExport CCudaReconstructionAlgorithm2D : public CReconstructionAlgorithm2D {
+
+public:
+
+ /** Default constructor, containing no code.
+ */
+ CCudaReconstructionAlgorithm2D();
+
+ /** Destructor.
+ */
+ virtual ~CCudaReconstructionAlgorithm2D();
+
+ /** Initialize the algorithm with a config object.
+ *
+ * @param _cfg Configuration Object
+ * @return initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ /** Initialize class.
+ *
+ * @param _pProjector Projector Object. (Ignored)
+ * @param _pSinogram ProjectionData2D object containing the sinogram data.
+ * @param _pReconstruction VolumeData2D object for storing the reconstructed volume.
+ */
+ bool initialize(CProjector2D* _pProjector,
+ CFloat32ProjectionData2D* _pSinogram,
+ CFloat32VolumeData2D* _pReconstruction);
+
+ /** Initialize class.
+ *
+ * @param _pProjector Projector Object. (Ignored)
+ * @param _pSinogram ProjectionData2D object containing the sinogram data.
+ * @param _pReconstruction VolumeData2D object for storing the reconstructed volume.
+ * @param _iGPUindex GPU to use.
+ * @param _iDetectorSuperSampling Supersampling factor for the FP.
+ * @param _iPixelSuperSampling Square root of number of samples per voxel, used to compute the backprojection
+ */
+ virtual bool initialize(CProjector2D* _pProjector,
+ CFloat32ProjectionData2D* _pSinogram,
+ CFloat32VolumeData2D* _pReconstruction,
+ int _iGPUindex = 0, int _iDetectorSuperSampling = 1,
+ int _iPixelSuperSampling = 1);
+
+
+ /** Clear this class.
+ */
+ virtual void clear();
+
+ /** Get all information parameters.
+ *
+ * @return map with all boost::any object
+ */
+ virtual map<string,boost::any> getInformation();
+
+ /** Get a single piece of information.
+ *
+ * @param _sIdentifier identifier string to specify which piece of information you want
+ * @return boost::any object
+ */
+ virtual boost::any getInformation(std::string _sIdentifier);
+
+ /** Get a description of the class.
+ *
+ * @return description string
+ */
+ virtual std::string description() const;
+
+ /** Get the norm of the residual image.
+ * Only a few algorithms support this method.
+ *
+ * @param _fNorm if supported, the norm is returned here
+ * @return true if this operation is supported
+ */
+ virtual bool getResidualNorm(float32& _fNorm);
+
+ /**
+ * Sets the index of the used GPU index: first GPU has index 0
+ *
+ * @param _iGPUIndex New GPU index.
+ */
+ void setGPUIndex(int _iGPUIndex);
+
+ /** Perform a number of iterations.
+ *
+ * @param _iNrIterations amount of iterations to perform.
+ */
+ virtual void run(int _iNrIterations = 0);
+
+ virtual void signalAbort();
+
+protected:
+
+ /** Check this object.
+ *
+ * @return object initialized
+ */
+ bool _check();
+
+ /** Initial clearing. Only to be used by constructors.
+ */
+ void _clear();
+
+ /** Set up geometry. For internal use only.
+ */
+ bool setupGeometry();
+
+
+ /** The internally used CUDA algorithm object
+ */
+ astraCUDA::ReconAlgo *m_pAlgo;
+
+ int m_iDetectorSuperSampling;
+ int m_iPixelSuperSampling;
+ int m_iGPUIndex;
+
+ bool m_bAlgoInit;
+};
+
+// inline functions
+inline std::string CCudaReconstructionAlgorithm2D::description() const { return "2D CUDA Reconstruction Algorithm"; };
+
+} // end namespace
+
+#endif
diff --git a/include/astra/CudaRoiSelectAlgorithm.h b/include/astra/CudaRoiSelectAlgorithm.h
new file mode 100644
index 0000000..1ee9c32
--- /dev/null
+++ b/include/astra/CudaRoiSelectAlgorithm.h
@@ -0,0 +1,123 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_CUDAROISELECTALGORITHM
+#define _INC_ASTRA_CUDAROISELECTALGORITHM
+
+#include "Globals.h"
+#include "Config.h"
+#include "Algorithm.h"
+#include "Float32VolumeData2D.h"
+
+
+#ifdef ASTRA_CUDA
+
+namespace astraCUDA {
+class PDART;
+}
+
+namespace astra {
+
+ class _AstraExport CCudaRoiSelectAlgorithm : public CAlgorithm
+{
+
+public:
+
+ // type of the algorithm, needed to register with CAlgorithmFactory
+ static std::string type;
+
+ /** Default constructor, containing no code.
+ */
+ CCudaRoiSelectAlgorithm();
+
+ /** Destructor.
+ */
+ virtual ~CCudaRoiSelectAlgorithm();
+
+ /** Initialize the algorithm with a config object.
+ *
+ * @param _cfg Configuration Object
+ * @return initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ /** Initialize class, use sequential order.
+ *
+ * @param _pSegmentation ...
+ * @param iConn ...
+ */
+ //bool initialize(CFloat32VolumeData2D* _pSegmentation, int _iConn);
+
+ /** Get all information parameters
+ *
+ * @return map with all boost::any object
+ */
+ virtual map<string,boost::any> getInformation();
+
+ /** Get a single piece of information represented as a boost::any
+ *
+ * @param _sIdentifier identifier string to specify which piece of information you want
+ * @return boost::any object
+ */
+ virtual boost::any getInformation(std::string _sIdentifier);
+
+ /** Get a description of the class.
+ *
+ * @return description string
+ */
+ virtual std::string description() const;
+
+ /** Perform a number of iterations.
+ *
+ * @param _iNrIterations amount of iterations to perform.
+ */
+ virtual void run(int _iNrIterations = 0);
+
+
+protected:
+ /** Check this object.
+ *
+ * @return object initialized
+ */
+ bool _check();
+
+ float32 m_fRadius;
+ int m_iGPUIndex;
+
+ CFloat32VolumeData2D* m_pData;
+
+};
+
+// inline functions
+inline std::string CCudaRoiSelectAlgorithm::description() const { return CCudaRoiSelectAlgorithm::type; };
+
+} // end namespace
+
+#endif // ASTRA_CUDA
+
+#endif
diff --git a/include/astra/CudaSartAlgorithm.h b/include/astra/CudaSartAlgorithm.h
new file mode 100644
index 0000000..319e1e9
--- /dev/null
+++ b/include/astra/CudaSartAlgorithm.h
@@ -0,0 +1,112 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_CUDASARTALGORITHM
+#define _INC_ASTRA_CUDASARTALGORITHM
+
+#include "Globals.h"
+#include "Config.h"
+
+#include "CudaReconstructionAlgorithm2D.h"
+
+#ifdef ASTRA_CUDA
+
+namespace astra {
+
+/**
+ * \brief
+ * This class contains a GPU implementation of the SART algorithm.
+ *
+ * \par XML Configuration
+ * \astra_xml_item{ProjectionDataId, integer, Identifier of a projection data object as it is stored in the DataManager.}
+ * \astra_xml_item{ReconstructionDataId, integer, Identifier of a volume data object as it is stored in the DataManager.}
+ * \astra_xml_item_option{ReconstructionMaskId, integer, not used, Identifier of a volume data object that acts as a reconstruction mask. 0 = reconstruct on this pixel. 1 = don't reconstruct on this pixel.}
+ *
+ * \par MATLAB example
+ * \astra_code{
+ * cfg = astra_struct('SART_CUDA');\n
+ * cfg.ProjectionDataId = sino_id;\n
+ * cfg.ReconstructionDataId = recon_id;\n
+ * cfg.option.ReconstructionMaskId = mask_id;\n
+ * alg_id = astra_mex_algorithm('create'\, cfg);\n
+ * astra_mex_algorithm('iterate'\, alg_id\, 10);\n
+ * astra_mex_algorithm('delete'\, alg_id);\n
+ * }
+ *
+ */
+class _AstraExport CCudaSartAlgorithm : public CCudaReconstructionAlgorithm2D
+{
+
+public:
+
+ // type of the algorithm, needed to register with CAlgorithmFactory
+ static std::string type;
+
+ /** Default constructor, containing no code.
+ */
+ CCudaSartAlgorithm();
+
+ /** Destructor.
+ */
+ virtual ~CCudaSartAlgorithm();
+
+ /** Initialize the algorithm with a config object.
+ *
+ * @param _cfg Configuration Object
+ * @return initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ /** Initialize class.
+ *
+ * @param _pProjector Projector Object. (Ignored)
+ * @param _pSinogram ProjectionData2D object containing the sinogram data.
+ * @param _pReconstruction VolumeData2D object for storing the reconstructed volume.
+ * @param _iGPUindex GPU to use.
+ * @param _iDetectorSuperSampling Supersampling factor for the FP.
+ */
+ bool initialize(CProjector2D* _pProjector,
+ CFloat32ProjectionData2D* _pSinogram,
+ CFloat32VolumeData2D* _pReconstruction,
+ int _iGPUindex = 0, int _iDetectorSuperSampling = 1);
+
+ /** Get a description of the class.
+ *
+ * @return description string
+ */
+ virtual std::string description() const;
+};
+
+// inline functions
+inline std::string CCudaSartAlgorithm::description() const { return CCudaSartAlgorithm::type; };
+
+} // end namespace
+
+#endif // ASTRA_CUDA
+
+#endif
diff --git a/include/astra/CudaSirtAlgorithm.h b/include/astra/CudaSirtAlgorithm.h
new file mode 100644
index 0000000..7f3d67b
--- /dev/null
+++ b/include/astra/CudaSirtAlgorithm.h
@@ -0,0 +1,131 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_CUDASIRTALGORITHM2
+#define _INC_ASTRA_CUDASIRTALGORITHM2
+
+#include "Globals.h"
+#include "Config.h"
+
+#include "CudaReconstructionAlgorithm2D.h"
+
+#ifdef ASTRA_CUDA
+
+namespace astra {
+
+/**
+ * \brief
+ * This class contains a GPU implementation of the SIRT (Simultaneous Iterative Reconstruction Technique) algorithm.
+ *
+ * The update step of pixel \f$v_j\f$ for iteration \f$k\f$ is given by:
+ * \f[
+ * v_j^{(k+1)} = v_j^{(k)} + \alpha \sum_{i=1}^{M} \left( \frac{w_{ij}\left( p_i - \sum_{r=1}^{N} w_{ir}v_r^{(k)}\right)}{\sum_{k=1}^{N} w_{ik}} \right) \frac{1}{\sum_{l=1}^{M}w_{lj}}
+ * \f]
+ *
+ * \par XML Configuration
+ * \astra_xml_item{ProjectionGeometry, integer, Geometry of the projection data.}
+ * \astra_xml_item{VolumeGeometry, integer, Geometry of the volume data.}
+ * \astra_xml_item{ProjectionDataId, integer, Identifier of a projection data object as it is stored in the DataManager.}
+ * \astra_xml_item{ReconstructionDataId, integer, Identifier of a volume data object as it is stored in the DataManager.}
+ * \astra_xml_item_option{ReconstructionMaskId, integer, not used, Identifier of a volume data object that acts as a reconstruction mask. 0 = reconstruct on this pixel. 1 = don't reconstruct on this pixel.}
+ *
+ * \par MATLAB example
+ * \astra_code{
+ * cfg = astra_struct('SIRT_CUDA2');\n
+ * cfg.ProjectionGeometry = proj_geom;\n
+ * cfg.VolumeGeometry = vol_geom;\n
+ * cfg.ProjectionDataId = sino_id;\n
+ * cfg.ReconstructionDataId = recon_id;\n
+ * cfg.option.ReconstructionMaskId = mask_id;\n
+ * alg_id = astra_mex_algorithm('create'\, cfg);\n
+ * astra_mex_algorithm('iterate'\, alg_id\, 10);\n
+ * astra_mex_algorithm('delete'\, alg_id);\n
+ * }
+ *
+ * \par References
+ * [1] "Computational Analysis and Improvement of SIRT", J. Gregor, T. Benson, IEEE Transactions on Medical Imaging, Vol. 22, No. 7, July 2008.
+ */
+class _AstraExport CCudaSirtAlgorithm : public CCudaReconstructionAlgorithm2D
+{
+
+public:
+
+ // type of the algorithm, needed to register with CAlgorithmFactory
+ static std::string type;
+
+ /** Default constructor, containing no code.
+ */
+ CCudaSirtAlgorithm();
+
+ /** Destructor.
+ */
+ virtual ~CCudaSirtAlgorithm();
+
+ /** Initialize the algorithm with a config object.
+ *
+ * @param _cfg Configuration Object
+ * @return initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ virtual void run(int _iNrIterations);
+
+ /** Initialize class.
+ *
+ * @param _pProjector Projector Object. (Ignored)
+ * @param _pSinogram ProjectionData2D object containing the sinogram data.
+ * @param _pReconstruction VolumeData2D object for storing the reconstructed volume.
+ * @param _iGPUindex GPU to use.
+ * @param _iDetectorSuperSampling Supersampling factor for the FP.
+ * @param _iPixelSuperSampling Square root of number of samples per voxel, used to compute the backprojection
+ */
+ bool initialize(CProjector2D* _pProjector,
+ CFloat32ProjectionData2D* _pSinogram,
+ CFloat32VolumeData2D* _pReconstruction,
+ int _iGPUindex = 0, int _iDetectorSuperSampling = 1,
+ int _iPixelSuperSampling = 1);
+
+ /** Get a description of the class.
+ *
+ * @return description string
+ */
+ virtual std::string description() const;
+
+protected:
+ CFloat32VolumeData2D* m_pMinMask;
+ CFloat32VolumeData2D* m_pMaxMask;
+};
+
+// inline functions
+inline std::string CCudaSirtAlgorithm::description() const { return CCudaSirtAlgorithm::type; };
+
+} // end namespace
+
+#endif // ASTRA_CUDA
+
+#endif
diff --git a/include/astra/CudaSirtAlgorithm3D.h b/include/astra/CudaSirtAlgorithm3D.h
new file mode 100644
index 0000000..c2c794d
--- /dev/null
+++ b/include/astra/CudaSirtAlgorithm3D.h
@@ -0,0 +1,187 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_CUDASIRTALGORITHM3D
+#define _INC_ASTRA_CUDASIRTALGORITHM3D
+
+#include "Globals.h"
+#include "Config.h"
+
+#include "Algorithm.h"
+
+#include "Float32ProjectionData3DMemory.h"
+#include "Float32VolumeData3DMemory.h"
+#include "ReconstructionAlgorithm3D.h"
+
+#ifdef ASTRA_CUDA
+
+namespace astra {
+
+class AstraSIRT3d;
+
+/**
+ * \brief
+ * This class contains the 3D implementation of the SIRT (Simultaneous Iterative Reconstruction Technique) algorithm.
+ *
+ * The update step of pixel \f$v_j\f$ for iteration \f$k\f$ is given by:
+ * \f[
+ * v_j^{(k+1)} = v_j^{(k)} + \alpha \sum_{i=1}^{M} \left( \frac{w_{ij}\left( p_i - \sum_{r=1}^{N} w_{ir}v_r^{(k)}\right)}{\sum_{k=1}^{N} w_{ik}} \right) \frac{1}{\sum_{l=1}^{M}w_{lj}}
+ * \f]
+ *
+ * \par XML Configuration
+ *
+ * \par MATLAB example
+ * \astra_code{
+ *
+ * }
+ *
+ * \par References
+ * [1] "Computational Analysis and Improvement of SIRT", J. Gregor, T. Benson, IEEE Transactions on Medical Imaging, Vol. 22, No. 7, July 2008.
+ */
+class _AstraExport CCudaSirtAlgorithm3D : public CReconstructionAlgorithm3D {
+
+protected:
+
+ /** Check the values of this object. If everything is ok, the object can be set to the initialized state.
+ * The following statements are then guaranteed to hold:
+ * - no NULL pointers
+ * - all sub-objects are initialized properly
+ * - the projector is compatible with both data objects
+ */
+ virtual bool _check();
+
+public:
+
+ // type of the algorithm, needed to register with CAlgorithmFactory
+ static std::string type;
+
+ /** Default constructor, does not initialize the object.
+ */
+ CCudaSirtAlgorithm3D();
+
+ /** Constructor with initialization.
+ *
+ * @param _pProjector Projector Object.
+ * @param _pProjectionData ProjectionData3D object containing the projection data.
+ * @param _pReconstruction VolumeData3D object for storing the reconstructed volume.
+ */
+ CCudaSirtAlgorithm3D(CProjector3D* _pProjector,
+ CFloat32ProjectionData3DMemory* _pProjectionData,
+ CFloat32VolumeData3DMemory* _pReconstruction);
+
+ /** Copy constructor.
+ */
+ CCudaSirtAlgorithm3D(const CCudaSirtAlgorithm3D&);
+
+ /** Destructor.
+ */
+ virtual ~CCudaSirtAlgorithm3D();
+
+ /** Clear this class.
+ */
+/* virtual void clear();*/
+
+ /** Initialize the algorithm with a config object.
+ *
+ * @param _cfg Configuration Object
+ * @return initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ /** Initialize class.
+ *
+ * @param _pProjector Projector Object.
+ * @param _pProjectionData ProjectionData3D object containing the projection data.
+ * @param _pReconstruction VolumeData3D object for storing the reconstructed volume.
+ * @return initialization successful?
+ */
+ bool initialize(CProjector3D* _pProjector,
+ CFloat32ProjectionData3DMemory* _pSinogram,
+ CFloat32VolumeData3DMemory* _pReconstruction);
+
+ /** Get all information parameters
+ *
+ * @return map with all boost::any object
+ */
+ virtual map<string,boost::any> getInformation();
+
+ /** Get a single piece of information represented as a boost::any
+ *
+ * @param _sIdentifier identifier string to specify which piece of information you want
+ * @return boost::any object
+ */
+ virtual boost::any getInformation(std::string _sIdentifier);
+
+ /** Perform a number of iterations.
+ *
+ * @param _iNrIterations amount of iterations to perform.
+ */
+ virtual void run(int _iNrIterations = 0);
+
+ /** Get a description of the class.
+ *
+ * @return description string
+ */
+ virtual std::string description() const;
+
+ /**
+ * Sets the index of the used GPU index: first GPU has index 0
+ *
+ * @param _iGPUIndex New GPU index.
+ */
+ void setGPUIndex(int _iGPUIndex);
+
+
+ virtual void signalAbort();
+
+ /** Get the norm of the residual image.
+ * Only a few algorithms support this method.
+ *
+ * @param _fNorm if supported, the norm is returned here
+ * @return true if this operation is supported
+ */
+ virtual bool getResidualNorm(float32& _fNorm);
+
+protected:
+
+ AstraSIRT3d* m_pSirt;
+
+ int m_iGPUIndex;
+ bool m_bAstraSIRTInit;
+ int m_iDetectorSuperSampling;
+ int m_iVoxelSuperSampling;
+};
+
+// inline functions
+inline std::string CCudaSirtAlgorithm3D::description() const { return CCudaSirtAlgorithm3D::type; };
+
+} // end namespace
+
+#endif
+
+#endif
diff --git a/include/astra/DataProjector.h b/include/astra/DataProjector.h
new file mode 100644
index 0000000..a324625
--- /dev/null
+++ b/include/astra/DataProjector.h
@@ -0,0 +1,327 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_DATAPROJECTOR
+#define _INC_ASTRA_DATAPROJECTOR
+
+#include "Projector2D.h"
+
+#include "TypeList.h"
+
+#include "ProjectorTypelist.h"
+
+#include "DataProjectorPolicies.h"
+
+namespace astra
+{
+
+
+/**
+ * Interface class for the Data Projector. The sole purpose of this class is to force child classes to implement a series of methods
+ */
+class CDataProjectorInterface {
+public:
+ CDataProjectorInterface() { }
+ virtual ~CDataProjectorInterface() { }
+ virtual void project() = 0;
+ virtual void projectSingleProjection(int _iProjection) = 0;
+ virtual void projectSingleRay(int _iProjection, int _iDetector) = 0;
+// virtual void projectSingleVoxel(int _iRow, int _iCol) = 0;
+// virtual void projectAllVoxels() = 0;
+};
+
+/**
+ * Templated Data Projector Class. In this class a specific projector and policies are combined.
+ */
+template <typename Projector, typename Policy>
+class CDataProjector: public CDataProjectorInterface {
+
+private:
+
+ Projector* m_pProjector;
+ Policy m_pPolicy;
+
+public:
+
+ CDataProjector() {};
+
+ CDataProjector(Projector* _p, Policy _a);
+ ~CDataProjector();
+
+ virtual void project();
+
+ virtual void projectSingleProjection(int _iProjection);
+
+ virtual void projectSingleRay(int _iProjection, int _iDetector);
+
+// virtual void projectSingleVoxel(int _iRow, int _iCol);
+
+// virtual void projectAllVoxels();
+};
+
+//----------------------------------------------------------------------------------------
+/**
+ * Constructor
+*/
+template <typename Projector, typename Policy>
+CDataProjector<Projector,Policy>::CDataProjector(Projector* _p, Policy _a)
+{
+ m_pProjector = _p;
+ m_pPolicy = _a;
+}
+
+//----------------------------------------------------------------------------------------
+/**
+ * Destructor
+*/
+template <typename Projector, typename Policy>
+CDataProjector<Projector,Policy>::~CDataProjector()
+{
+ // does nothing
+}
+
+//----------------------------------------------------------------------------------------
+/**
+ * Compute projection using the algorithm specific to the projector type
+*/
+template <typename Projector, typename Policy>
+void CDataProjector<Projector,Policy>::project()
+{
+ m_pProjector->project(m_pPolicy);
+}
+
+//----------------------------------------------------------------------------------------
+/**
+ * Compute just one projection using the algorithm specific to the projector type
+*/
+template <typename Projector, typename Policy>
+void CDataProjector<Projector,Policy>::projectSingleProjection(int _iProjection)
+{
+ m_pProjector->projectSingleProjection(_iProjection, m_pPolicy);
+}
+
+//----------------------------------------------------------------------------------------
+/**
+ * Compute projection of one ray using the algorithm specific to the projector type
+*/
+template <typename Projector, typename Policy>
+void CDataProjector<Projector,Policy>::projectSingleRay(int _iProjection, int _iDetector)
+{
+ m_pProjector->projectSingleRay(_iProjection, _iDetector, m_pPolicy);
+}
+
+//----------------------------------------------------------------------------------------
+//template <typename Projector, typename Policy>
+//void CDataProjector<Projector,Policy>::projectSingleVoxel(int _iRow, int _iCol)
+//{
+// m_pProjector->projectSingleVoxel(_iRow, _iCol, m_pPolicy);
+//}
+
+//----------------------------------------------------------------------------------------
+//template <typename Projector, typename Policy>
+//void CDataProjector<Projector,Policy>::projectAllVoxels()
+//{
+// m_pProjector->projectAllVoxels(m_pPolicy);
+//}
+//----------------------------------------------------------------------------------------
+
+
+
+
+//-----------------------------------------------------------------------------------------
+// Create a new datainterface from the projector TypeList
+namespace typelist {
+ template <class TList>
+ struct CreateDataProjector {
+ template <class U, typename Policy>
+ static void find (U& functor, CProjector2D* _pProjector, const Policy& _pPolicy) {
+ if (functor(TList::Head::type)) {
+ functor.res = new CDataProjector<typename TList::Head, Policy>(static_cast<typename TList::Head*>(_pProjector), _pPolicy);
+ }
+ CreateDataProjector<typename TList::Tail>::find(functor, _pProjector, _pPolicy);
+ }
+ };
+ template <>
+ struct CreateDataProjector<NullType> {
+ template <class U, typename Policy>
+ static void find(U& functor, CProjector2D* _pProjector, const Policy& _pPolicy) {}
+ };
+
+ struct functor_find_datainterface {
+ functor_find_datainterface() { res = NULL; }
+ bool operator() (std::string name) {
+ return strcmp(tofind.c_str(), name.c_str()) == 0;
+ }
+ std::string tofind;
+ CDataProjectorInterface* res;
+ };
+}
+//-----------------------------------------------------------------------------------------
+
+/**
+ * Data Projector Dispatcher - 1 Policy
+ */
+template <typename Policy>
+static CDataProjectorInterface* dispatchDataProjector(CProjector2D* _pProjector, const Policy& _policy)
+{
+ typelist::functor_find_datainterface finder = typelist::functor_find_datainterface();
+ finder.tofind = _pProjector->getType();
+ typelist::CreateDataProjector<Projector2DTypeList>::find(finder, _pProjector, _policy);
+ return finder.res;
+}
+
+
+
+/**
+ * Data Projector Dispatcher - 2 Policies
+ */
+template <typename Policy1, typename Policy2>
+static CDataProjectorInterface* dispatchDataProjector(CProjector2D* _pProjector,
+ const Policy1& _policy,
+ const Policy2& _policy2,
+ bool _bUsePolicy1 = true,
+ bool _bUsePolicy2 = true)
+{
+ if (!_bUsePolicy1 && !_bUsePolicy2) {
+ return dispatchDataProjector(_pProjector, EmptyPolicy());
+ } else if (!_bUsePolicy1) {
+ return dispatchDataProjector(_pProjector, _policy2);
+ } else if (!_bUsePolicy2) {
+ return dispatchDataProjector(_pProjector, _policy);
+ } else {
+ return dispatchDataProjector(_pProjector, CombinePolicy<Policy1, Policy2>(_policy, _policy2));
+ }
+
+}
+
+/**
+ * Data Projector Dispatcher - 3 Policies
+ */
+
+template <typename Policy1, typename Policy2, typename Policy3>
+static CDataProjectorInterface* dispatchDataProjector(CProjector2D* _pProjector,
+ const Policy1& _policy1,
+ const Policy2& _policy2,
+ const Policy3& _policy3,
+ bool _bUsePolicy1 = true,
+ bool _bUsePolicy2 = true,
+ bool _bUsePolicy3 = true)
+{
+ if (!_bUsePolicy1) {
+ return dispatchDataProjector(_pProjector, _policy2, _policy3, _bUsePolicy2, _bUsePolicy3);
+ } else if (!_bUsePolicy2) {
+ return dispatchDataProjector(_pProjector, _policy1, _policy3, _bUsePolicy1, _bUsePolicy3);
+ } else if (!_bUsePolicy3) {
+ return dispatchDataProjector(_pProjector, _policy1, _policy2, _bUsePolicy1, _bUsePolicy2);
+ } else {
+ return dispatchDataProjector(_pProjector, Combine3Policy<Policy1, Policy2, Policy3>(_policy1, _policy2, _policy3));
+ }
+}
+
+/**
+ * Data Projector Dispatcher - 4 Policies
+ */
+template <typename Policy1, typename Policy2, typename Policy3, typename Policy4>
+static CDataProjectorInterface* dispatchDataProjector(CProjector2D* _pProjector,
+ const Policy1& _policy1,
+ const Policy2& _policy2,
+ const Policy3& _policy3,
+ const Policy4& _policy4,
+ bool _bUsePolicy1 = true,
+ bool _bUsePolicy2 = true,
+ bool _bUsePolicy3 = true,
+ bool _bUsePolicy4 = true)
+{
+ if (!_bUsePolicy1) {
+ return dispatchDataProjector(_pProjector, _policy2, _policy3, _policy4, _bUsePolicy2, _bUsePolicy3, _bUsePolicy4);
+ } else if (!_bUsePolicy2) {
+ return dispatchDataProjector(_pProjector, _policy1, _policy3, _policy4, _bUsePolicy1, _bUsePolicy3, _bUsePolicy4);
+ } else if (!_bUsePolicy3) {
+ return dispatchDataProjector(_pProjector, _policy1, _policy2, _policy4, _bUsePolicy1, _bUsePolicy2, _bUsePolicy4);
+ } else if (!_bUsePolicy4) {
+ return dispatchDataProjector(_pProjector, _policy1, _policy2, _policy3, _bUsePolicy1, _bUsePolicy2, _bUsePolicy3);
+ } else {
+ return dispatchDataProjector(_pProjector, Combine4Policy<Policy1, Policy2, Policy3, Policy4>(_policy1, _policy2, _policy3, _policy4));
+ }
+}
+
+/**
+ * Data Projector Dispatcher - 5 Policies
+ */
+template <typename Policy1, typename Policy2, typename Policy3, typename Policy4, typename Policy5>
+static CDataProjectorInterface* dispatchDataProjector(CProjector2D* _pProjector,
+ const Policy1& _policy1,
+ const Policy2& _policy2,
+ const Policy3& _policy3,
+ const Policy4& _policy4,
+ const Policy5& _policy5,
+ bool _bUsePolicy1 = true,
+ bool _bUsePolicy2 = true,
+ bool _bUsePolicy3 = true,
+ bool _bUsePolicy4 = true,
+ bool _bUsePolicy5 = true)
+{
+ if (!_bUsePolicy1) {
+ return dispatchDataProjector(_pProjector, _policy2, _policy3, _policy4, _policy5, _bUsePolicy2, _bUsePolicy3, _bUsePolicy4, _bUsePolicy5);
+ } else if (!_bUsePolicy2) {
+ return dispatchDataProjector(_pProjector, _policy1, _policy3, _policy4, _policy5, _bUsePolicy1, _bUsePolicy3, _bUsePolicy4, _bUsePolicy5);
+ } else if (!_bUsePolicy3) {
+ return dispatchDataProjector(_pProjector, _policy1, _policy2, _policy4, _policy5, _bUsePolicy1, _bUsePolicy2, _bUsePolicy4, _bUsePolicy5);
+ } else if (!_bUsePolicy4) {
+ return dispatchDataProjector(_pProjector, _policy1, _policy2, _policy3, _policy5, _bUsePolicy1, _bUsePolicy2, _bUsePolicy3, _bUsePolicy5);
+ } else if (!_bUsePolicy5) {
+ return dispatchDataProjector(_pProjector, _policy1, _policy2, _policy3, _policy4, _bUsePolicy1, _bUsePolicy2, _bUsePolicy3, _bUsePolicy4);
+ } else {
+ return dispatchDataProjector(_pProjector, CombinePolicy< Combine4Policy<Policy1, Policy2, Policy3, Policy4>, Policy5>(
+ Combine4Policy<Policy1, Policy2, Policy3, Policy4>(_policy1, _policy2, _policy3, _policy4),
+ _policy5)
+ );
+ }
+}
+
+
+
+
+//-----------------------------------------------------------------------------------------
+/**
+ * Data Projector Project
+ */
+template <typename Policy>
+static void projectData(CProjector2D* _pProjector, const Policy& _policy)
+{
+ CDataProjectorInterface* dp = dispatchDataProjector(_pProjector, _policy);
+ dp->project();
+ delete dp;
+}
+
+
+
+
+} // namespace astra
+
+#endif
diff --git a/include/astra/DataProjectorPolicies.h b/include/astra/DataProjectorPolicies.h
new file mode 100644
index 0000000..5ec08bd
--- /dev/null
+++ b/include/astra/DataProjectorPolicies.h
@@ -0,0 +1,382 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_DATAPROJECTORPOLICIES
+#define _INC_ASTRA_DATAPROJECTORPOLICIES
+
+#include "Globals.h"
+#include "Config.h"
+
+#include <list>
+
+#include "Float32ProjectionData2D.h"
+#include "Float32VolumeData2D.h"
+
+namespace astra {
+
+//enum {PixelDrivenPolicy, RayDrivenPolicy, AllPolicy} PolicyType;
+
+
+//----------------------------------------------------------------------------------------
+/** Policy for Default Forward Projection (Ray Driven)
+ */
+class DefaultFPPolicy {
+
+ //< Projection Data
+ CFloat32ProjectionData2D* m_pProjectionData;
+ //< Volume Data
+ CFloat32VolumeData2D* m_pVolumeData;
+
+public:
+ FORCEINLINE DefaultFPPolicy();
+ FORCEINLINE DefaultFPPolicy(CFloat32VolumeData2D* _pVolumeData, CFloat32ProjectionData2D* _pProjectionData);
+ FORCEINLINE ~DefaultFPPolicy();
+
+ FORCEINLINE bool rayPrior(int _iRayIndex);
+ FORCEINLINE bool pixelPrior(int _iVolumeIndex);
+ FORCEINLINE void addWeight(int _iRayIndex, int _iVolumeIndex, float32 weight);
+ FORCEINLINE void rayPosterior(int _iRayIndex);
+ FORCEINLINE void pixelPosterior(int _iVolumeIndex);
+};
+
+
+//----------------------------------------------------------------------------------------
+/** Policy for Default Back Projection. (Ray+Pixel Driven)
+ * This does VolumeData += transpose(ProjectionMap) * ProjectionData.
+ */
+class DefaultBPPolicy {
+
+ //< Projection Data
+ CFloat32ProjectionData2D* m_pProjectionData;
+ //< Volume Data
+ CFloat32VolumeData2D* m_pVolumeData;
+
+public:
+ FORCEINLINE DefaultBPPolicy();
+ FORCEINLINE DefaultBPPolicy(CFloat32VolumeData2D* _pVolumeData, CFloat32ProjectionData2D* _pProjectionData);
+ FORCEINLINE ~DefaultBPPolicy();
+
+ FORCEINLINE bool rayPrior(int _iRayIndex);
+ FORCEINLINE bool pixelPrior(int _iVolumeIndex);
+ FORCEINLINE void addWeight(int _iRayIndex, int _iVolumeIndex, float32 weight);
+ FORCEINLINE void rayPosterior(int _iRayIndex);
+ FORCEINLINE void pixelPosterior(int _iVolumeIndex);
+};
+
+
+
+//----------------------------------------------------------------------------------------
+/** Policy For Calculating the Projection Difference between Volume Data and Projection Data (Ray Driven)
+ */
+class DiffFPPolicy {
+
+ CFloat32ProjectionData2D* m_pDiffProjectionData;
+ CFloat32ProjectionData2D* m_pBaseProjectionData;
+ CFloat32VolumeData2D* m_pVolumeData;
+public:
+
+ FORCEINLINE DiffFPPolicy();
+ FORCEINLINE DiffFPPolicy(CFloat32VolumeData2D* _vol_data, CFloat32ProjectionData2D* _proj_data, CFloat32ProjectionData2D* _proj_data_base);
+ FORCEINLINE ~DiffFPPolicy();
+
+ FORCEINLINE bool rayPrior(int _iRayIndex);
+ FORCEINLINE bool pixelPrior(int _iVolumeIndex);
+ FORCEINLINE void addWeight(int _iRayIndex, int _iVolumeIndex, float32 weight);
+ FORCEINLINE void rayPosterior(int _iRayIndex);
+ FORCEINLINE void pixelPosterior(int _iVolumeIndex);
+};
+
+//----------------------------------------------------------------------------------------
+/** Store Pixel Weights (Ray+Pixel Driven)
+ */
+class StorePixelWeightsPolicy {
+
+ SPixelWeight* m_pPixelWeights;
+ int m_iMaxPixelCount;
+ int m_iStoredPixelCount;
+
+public:
+
+ FORCEINLINE StorePixelWeightsPolicy();
+ FORCEINLINE StorePixelWeightsPolicy(SPixelWeight* _pPixelWeights, int _iMaxPixelCount);
+ FORCEINLINE ~StorePixelWeightsPolicy();
+
+ FORCEINLINE bool rayPrior(int _iRayIndex);
+ FORCEINLINE bool pixelPrior(int _iVolumeIndex);
+ FORCEINLINE void addWeight(int _iRayIndex, int _iVolumeIndex, float32 _fWeight);
+ FORCEINLINE void rayPosterior(int _iRayIndex);
+ FORCEINLINE void pixelPosterior(int _iVolumeIndex);
+
+ FORCEINLINE int getStoredPixelCount();
+};
+
+
+//----------------------------------------------------------------------------------------
+/** Policy For Calculating the Total Pixel Weight Multiplied by Sinogram
+ */
+class TotalPixelWeightBySinogramPolicy {
+
+ CFloat32VolumeData2D* m_pPixelWeight;
+ CFloat32ProjectionData2D* m_pSinogram;
+
+public:
+
+ FORCEINLINE TotalPixelWeightBySinogramPolicy();
+ FORCEINLINE TotalPixelWeightBySinogramPolicy(CFloat32ProjectionData2D* _pSinogram, CFloat32VolumeData2D* _pPixelWeight);
+ FORCEINLINE ~TotalPixelWeightBySinogramPolicy();
+
+ FORCEINLINE bool rayPrior(int _iRayIndex);
+ FORCEINLINE bool pixelPrior(int _iVolumeIndex);
+ FORCEINLINE void addWeight(int _iRayIndex, int _iVolumeIndex, float32 weight);
+ FORCEINLINE void rayPosterior(int _iRayIndex);
+ FORCEINLINE void pixelPosterior(int _iVolumeIndex);
+};
+
+//----------------------------------------------------------------------------------------
+/** Policy For Calculating the Total Pixel Weight
+ */
+class TotalPixelWeightPolicy {
+
+ CFloat32VolumeData2D* m_pPixelWeight;
+
+public:
+
+ FORCEINLINE TotalPixelWeightPolicy();
+ FORCEINLINE TotalPixelWeightPolicy(CFloat32VolumeData2D* _pPixelWeight);
+ FORCEINLINE ~TotalPixelWeightPolicy();
+
+ FORCEINLINE bool rayPrior(int _iRayIndex);
+ FORCEINLINE bool pixelPrior(int _iVolumeIndex);
+ FORCEINLINE void addWeight(int _iRayIndex, int _iVolumeIndex, float32 weight);
+ FORCEINLINE void rayPosterior(int _iRayIndex);
+ FORCEINLINE void pixelPosterior(int _iVolumeIndex);
+};
+
+//----------------------------------------------------------------------------------------
+/** Policy For Calculating the the Total Ray Length
+ */
+class TotalRayLengthPolicy {
+
+ CFloat32ProjectionData2D* m_pRayLength;
+
+public:
+
+ FORCEINLINE TotalRayLengthPolicy();
+ FORCEINLINE TotalRayLengthPolicy(CFloat32ProjectionData2D* _pRayLength);
+ FORCEINLINE ~TotalRayLengthPolicy();
+
+ FORCEINLINE bool rayPrior(int _iRayIndex);
+ FORCEINLINE bool pixelPrior(int _iVolumeIndex);
+ FORCEINLINE void addWeight(int _iRayIndex, int _iVolumeIndex, float32 weight);
+ FORCEINLINE void rayPosterior(int _iRayIndex);
+ FORCEINLINE void pixelPosterior(int _iVolumeIndex);
+};
+
+
+//----------------------------------------------------------------------------------------
+/** Policy For Combining Two Policies
+ */
+template<typename P1, typename P2>
+class CombinePolicy {
+
+ P1 policy1;
+ P2 policy2;
+
+public:
+
+ FORCEINLINE CombinePolicy();
+ FORCEINLINE CombinePolicy(P1 _policy1, P2 _policy2);
+ FORCEINLINE ~CombinePolicy();
+
+ FORCEINLINE bool rayPrior(int _iRayIndex);
+ FORCEINLINE bool pixelPrior(int _iVolumeIndex);
+ FORCEINLINE void addWeight(int _iRayIndex, int _iVolumeIndex, float32 weight);
+ FORCEINLINE void rayPosterior(int _iRayIndex);
+ FORCEINLINE void pixelPosterior(int _iVolumeIndex);
+};
+
+//----------------------------------------------------------------------------------------
+/** Policy For Combining Three Policies
+ */
+template<typename P1, typename P2, typename P3>
+class Combine3Policy {
+
+ P1 policy1;
+ P2 policy2;
+ P3 policy3;
+
+public:
+
+ FORCEINLINE Combine3Policy();
+ FORCEINLINE Combine3Policy(P1 _policy1, P2 _policy2, P3 _policy3);
+ FORCEINLINE ~Combine3Policy();
+
+ FORCEINLINE bool rayPrior(int _iRayIndex);
+ FORCEINLINE bool pixelPrior(int _iVolumeIndex);
+ FORCEINLINE void addWeight(int _iRayIndex, int _iVolumeIndex, float32 weight);
+ FORCEINLINE void rayPosterior(int _iRayIndex);
+ FORCEINLINE void pixelPosterior(int _iVolumeIndex);
+};
+
+//----------------------------------------------------------------------------------------
+/** Policy For Combining Four Policies
+ */
+template<typename P1, typename P2, typename P3, typename P4>
+class Combine4Policy {
+
+ P1 policy1;
+ P2 policy2;
+ P3 policy3;
+ P4 policy4;
+
+public:
+
+ FORCEINLINE Combine4Policy();
+ FORCEINLINE Combine4Policy(P1 _policy1, P2 _policy2, P3 _policy3, P4 _policy4);
+ FORCEINLINE ~Combine4Policy();
+
+ FORCEINLINE bool rayPrior(int _iRayIndex);
+ FORCEINLINE bool pixelPrior(int _iVolumeIndex);
+ FORCEINLINE void addWeight(int _iRayIndex, int _iVolumeIndex, float32 weight);
+ FORCEINLINE void rayPosterior(int _iRayIndex);
+ FORCEINLINE void pixelPosterior(int _iVolumeIndex);
+};
+
+//----------------------------------------------------------------------------------------
+/** Policy For Combining a List of the same Policies
+ */
+template<typename P>
+class CombineListPolicy {
+
+ std::vector<P> policyList;
+ unsigned int size;
+
+public:
+
+ FORCEINLINE CombineListPolicy();
+ FORCEINLINE CombineListPolicy(std::vector<P> _policyList);
+ FORCEINLINE ~CombineListPolicy();
+
+ FORCEINLINE void addPolicy(P _policy);
+
+ FORCEINLINE bool rayPrior(int _iRayIndex);
+ FORCEINLINE bool pixelPrior(int _iVolumeIndex);
+ FORCEINLINE void addWeight(int _iRayIndex, int _iVolumeIndex, float32 weight);
+ FORCEINLINE void rayPosterior(int _iRayIndex);
+ FORCEINLINE void pixelPosterior(int _iVolumeIndex);
+};
+
+//----------------------------------------------------------------------------------------
+/** Empty Policy
+ */
+class EmptyPolicy {
+
+public:
+
+ FORCEINLINE EmptyPolicy();
+ FORCEINLINE ~EmptyPolicy();
+
+ FORCEINLINE bool rayPrior(int _iRayIndex);
+ FORCEINLINE bool pixelPrior(int _iVolumeIndex);
+ FORCEINLINE void addWeight(int _iRayIndex, int _iVolumeIndex, float32 weight);
+ FORCEINLINE void rayPosterior(int _iRayIndex);
+ FORCEINLINE void pixelPosterior(int _iVolumeIndex);
+};
+
+//----------------------------------------------------------------------------------------
+/** Policy For SIRT Backprojection
+ */
+class SIRTBPPolicy {
+
+ CFloat32ProjectionData2D* m_pSinogram;
+ CFloat32VolumeData2D* m_pReconstruction;
+
+ CFloat32ProjectionData2D* m_pTotalRayLength;
+ CFloat32VolumeData2D* m_pTotalPixelWeight;
+
+public:
+
+ FORCEINLINE SIRTBPPolicy();
+ FORCEINLINE SIRTBPPolicy(CFloat32VolumeData2D* _pReconstruction, CFloat32ProjectionData2D* _pSinogram, CFloat32VolumeData2D* _pTotalPixelWeight, CFloat32ProjectionData2D* _pTotalRayLength);
+ FORCEINLINE ~SIRTBPPolicy();
+
+ FORCEINLINE bool rayPrior(int _iRayIndex);
+ FORCEINLINE bool pixelPrior(int _iVolumeIndex);
+ FORCEINLINE void addWeight(int _iRayIndex, int _iVolumeIndex, float32 weight);
+ FORCEINLINE void rayPosterior(int _iRayIndex);
+ FORCEINLINE void pixelPosterior(int _iVolumeIndex);
+};
+
+
+//----------------------------------------------------------------------------------------
+/** Policy For Sinogram Mask
+ */
+class SinogramMaskPolicy {
+
+ CFloat32ProjectionData2D* m_pSinogramMask;
+
+public:
+
+ FORCEINLINE SinogramMaskPolicy();
+ FORCEINLINE SinogramMaskPolicy(CFloat32ProjectionData2D* _pSinogramMask);
+ FORCEINLINE ~SinogramMaskPolicy();
+
+ FORCEINLINE bool rayPrior(int _iRayIndex);
+ FORCEINLINE bool pixelPrior(int _iVolumeIndex);
+ FORCEINLINE void addWeight(int _iRayIndex, int _iVolumeIndex, float32 weight);
+ FORCEINLINE void rayPosterior(int _iRayIndex);
+ FORCEINLINE void pixelPosterior(int _iVolumeIndex);
+};
+
+//----------------------------------------------------------------------------------------
+/** Policy For Reconstruction Mask
+ */
+class ReconstructionMaskPolicy {
+
+ CFloat32VolumeData2D* m_pReconstructionMask;
+
+public:
+
+ FORCEINLINE ReconstructionMaskPolicy();
+ FORCEINLINE ReconstructionMaskPolicy(CFloat32VolumeData2D* _pReconstructionMask);
+ FORCEINLINE ~ReconstructionMaskPolicy();
+
+ FORCEINLINE bool rayPrior(int _iRayIndex);
+ FORCEINLINE bool pixelPrior(int _iVolumeIndex);
+ FORCEINLINE void addWeight(int _iRayIndex, int _iVolumeIndex, float32 weight);
+ FORCEINLINE void rayPosterior(int _iRayIndex);
+ FORCEINLINE void pixelPosterior(int _iVolumeIndex);
+};
+
+//----------------------------------------------------------------------------------------
+
+#include "DataProjectorPolicies.inl"
+
+} // end namespace
+
+#endif
diff --git a/include/astra/DataProjectorPolicies.inl b/include/astra/DataProjectorPolicies.inl
new file mode 100644
index 0000000..b2166c3
--- /dev/null
+++ b/include/astra/DataProjectorPolicies.inl
@@ -0,0 +1,855 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_DATAPROJECTORPOLICIES_INLINE
+#define _INC_ASTRA_DATAPROJECTORPOLICIES_INLINE
+
+
+
+//----------------------------------------------------------------------------------------
+// DEFAULT FORWARD PROJECTION (Ray Driven)
+//----------------------------------------------------------------------------------------
+DefaultFPPolicy::DefaultFPPolicy()
+{
+
+}
+//----------------------------------------------------------------------------------------
+DefaultFPPolicy::DefaultFPPolicy(CFloat32VolumeData2D* _pVolumeData,
+ CFloat32ProjectionData2D* _pProjectionData)
+{
+ m_pProjectionData = _pProjectionData;
+ m_pVolumeData = _pVolumeData;
+}
+//----------------------------------------------------------------------------------------
+DefaultFPPolicy::~DefaultFPPolicy()
+{
+
+}
+//----------------------------------------------------------------------------------------
+bool DefaultFPPolicy::rayPrior(int _iRayIndex)
+{
+ m_pProjectionData->getData()[_iRayIndex] = 0.0f;
+ return true;
+}
+//----------------------------------------------------------------------------------------
+bool DefaultFPPolicy::pixelPrior(int _iVolumeIndex)
+{
+ // do nothing
+ return true;
+}
+//----------------------------------------------------------------------------------------
+void DefaultFPPolicy::addWeight(int _iRayIndex, int _iVolumeIndex, float32 _fWeight)
+{
+ m_pProjectionData->getData()[_iRayIndex] += m_pVolumeData->getData()[_iVolumeIndex] * _fWeight;
+}
+//----------------------------------------------------------------------------------------
+void DefaultFPPolicy::rayPosterior(int _iRayIndex)
+{
+ // nothing
+}
+//----------------------------------------------------------------------------------------
+void DefaultFPPolicy::pixelPosterior(int _iVolumeIndex)
+{
+ // nothing
+}
+//----------------------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------------------
+// DEFAULT BACK PROJECTION (Ray+Pixel Driven)
+//----------------------------------------------------------------------------------------
+DefaultBPPolicy::DefaultBPPolicy()
+{
+
+}
+//----------------------------------------------------------------------------------------
+DefaultBPPolicy::DefaultBPPolicy(CFloat32VolumeData2D* _pVolumeData,
+ CFloat32ProjectionData2D* _pProjectionData)
+{
+ m_pProjectionData = _pProjectionData;
+ m_pVolumeData = _pVolumeData;
+}
+//----------------------------------------------------------------------------------------
+DefaultBPPolicy::~DefaultBPPolicy()
+{
+
+}
+//----------------------------------------------------------------------------------------
+bool DefaultBPPolicy::rayPrior(int _iRayIndex)
+{
+ // do nothing
+ return true;
+}
+//----------------------------------------------------------------------------------------
+bool DefaultBPPolicy::pixelPrior(int _iVolumeIndex)
+{
+ // do nothing
+ return true;
+}
+//----------------------------------------------------------------------------------------
+void DefaultBPPolicy::addWeight(int _iRayIndex, int _iVolumeIndex, float32 _fWeight)
+{
+ m_pVolumeData->getData()[_iVolumeIndex] += m_pProjectionData->getData()[_iRayIndex] * _fWeight;
+}
+//----------------------------------------------------------------------------------------
+void DefaultBPPolicy::rayPosterior(int _iRayIndex)
+{
+ // nothing
+}
+//----------------------------------------------------------------------------------------
+void DefaultBPPolicy::pixelPosterior(int _iVolumeIndex)
+{
+ // nothing
+}
+//----------------------------------------------------------------------------------------
+
+
+
+
+//----------------------------------------------------------------------------------------
+// FORWARD PROJECTION DIFFERENCE CALCULATION (Ray Driven)
+//----------------------------------------------------------------------------------------
+DiffFPPolicy::DiffFPPolicy()
+{
+
+}
+//----------------------------------------------------------------------------------------
+DiffFPPolicy::DiffFPPolicy(CFloat32VolumeData2D* _pVolumeData,
+ CFloat32ProjectionData2D* _pDiffProjectionData,
+ CFloat32ProjectionData2D* _pBaseProjectionData)
+{
+ m_pDiffProjectionData = _pDiffProjectionData;
+ m_pBaseProjectionData = _pBaseProjectionData;
+ m_pVolumeData = _pVolumeData;
+}
+//----------------------------------------------------------------------------------------
+DiffFPPolicy::~DiffFPPolicy()
+{
+
+}
+//----------------------------------------------------------------------------------------
+ bool DiffFPPolicy::rayPrior(int _iRayIndex)
+{
+ m_pDiffProjectionData->getData()[_iRayIndex] = m_pBaseProjectionData->getData()[_iRayIndex];
+ return true;
+}
+//----------------------------------------------------------------------------------------
+bool DiffFPPolicy::pixelPrior(int _iVolumeIndex)
+{
+ return true;
+}
+//----------------------------------------------------------------------------------------
+void DiffFPPolicy::addWeight(int _iRayIndex, int _iVolumeIndex, float32 _fWeight)
+{
+ m_pDiffProjectionData->getData()[_iRayIndex] -= m_pVolumeData->getData()[_iVolumeIndex] * _fWeight;
+}
+//----------------------------------------------------------------------------------------
+void DiffFPPolicy::rayPosterior(int _iRayIndex)
+{
+ // nothing
+}
+//----------------------------------------------------------------------------------------
+void DiffFPPolicy::pixelPosterior(int _iVolumeIndex)
+{
+ // nothing
+}
+//----------------------------------------------------------------------------------------
+
+
+
+//----------------------------------------------------------------------------------------
+// STORE PIXEL WEIGHT (Ray+Pixel Driven)
+//----------------------------------------------------------------------------------------
+StorePixelWeightsPolicy::StorePixelWeightsPolicy()
+{
+
+}
+//----------------------------------------------------------------------------------------
+StorePixelWeightsPolicy::StorePixelWeightsPolicy(SPixelWeight* _pPixelWeights, int _iMaxPixelCount)
+{
+ m_iStoredPixelCount = 0;
+ m_pPixelWeights = _pPixelWeights;
+ m_iMaxPixelCount = _iMaxPixelCount;
+}
+//----------------------------------------------------------------------------------------
+StorePixelWeightsPolicy::~StorePixelWeightsPolicy()
+{
+
+}
+//----------------------------------------------------------------------------------------
+bool StorePixelWeightsPolicy::rayPrior(int _iRayIndex)
+{
+ return (m_iStoredPixelCount < m_iMaxPixelCount);
+}
+//----------------------------------------------------------------------------------------
+bool StorePixelWeightsPolicy::pixelPrior(int _iVolumeIndex)
+{
+ return (m_iStoredPixelCount < m_iMaxPixelCount);
+}
+//----------------------------------------------------------------------------------------
+void StorePixelWeightsPolicy::addWeight(int _iRayIndex, int _iVolumeIndex, float32 _fWeight)
+{
+ m_pPixelWeights[m_iStoredPixelCount].m_fWeight = _fWeight;
+ m_pPixelWeights[m_iStoredPixelCount].m_iIndex = _iVolumeIndex;
+ ++m_iStoredPixelCount;
+}
+//----------------------------------------------------------------------------------------
+void StorePixelWeightsPolicy::rayPosterior(int _iRayIndex)
+{
+ // nothing
+}
+//----------------------------------------------------------------------------------------
+void StorePixelWeightsPolicy::pixelPosterior(int _iVolumeIndex)
+{
+ // nothing
+}
+//----------------------------------------------------------------------------------------
+int StorePixelWeightsPolicy::getStoredPixelCount()
+{
+ return m_iStoredPixelCount;
+}
+//----------------------------------------------------------------------------------------
+
+
+
+//----------------------------------------------------------------------------------------
+// TOTAL PIXEL WEIGHT MULTIPLIED BY SINOGRAM (Ray+Pixel Driven)
+//----------------------------------------------------------------------------------------
+TotalPixelWeightBySinogramPolicy::TotalPixelWeightBySinogramPolicy()
+{
+
+}
+//----------------------------------------------------------------------------------------
+TotalPixelWeightBySinogramPolicy::TotalPixelWeightBySinogramPolicy(CFloat32ProjectionData2D* _pSinogram,
+ CFloat32VolumeData2D* _pPixelWeight)
+{
+ m_pPixelWeight = _pPixelWeight;
+ m_pSinogram = _pSinogram;
+}
+//----------------------------------------------------------------------------------------
+TotalPixelWeightBySinogramPolicy::~TotalPixelWeightBySinogramPolicy()
+{
+
+}
+//----------------------------------------------------------------------------------------
+bool TotalPixelWeightBySinogramPolicy::rayPrior(int _iRayIndex)
+{
+ return true;
+}
+//----------------------------------------------------------------------------------------
+bool TotalPixelWeightBySinogramPolicy::pixelPrior(int _iVolumeIndex)
+{
+ return true;
+}
+//----------------------------------------------------------------------------------------
+void TotalPixelWeightBySinogramPolicy::addWeight(int _iRayIndex, int _iVolumeIndex, float32 _fWeight)
+{
+ m_pPixelWeight->getData()[_iVolumeIndex] += _fWeight * m_pSinogram->getData()[_iRayIndex];
+}
+//----------------------------------------------------------------------------------------
+void TotalPixelWeightBySinogramPolicy::rayPosterior(int _iRayIndex)
+{
+ // nothing
+}
+//----------------------------------------------------------------------------------------
+void TotalPixelWeightBySinogramPolicy::pixelPosterior(int _iVolumeIndex)
+{
+ // nothing
+}
+//----------------------------------------------------------------------------------------
+
+
+
+
+
+//----------------------------------------------------------------------------------------
+// TOTAL PIXEL WEIGHT (Ray+Pixel Driven)
+//----------------------------------------------------------------------------------------
+TotalPixelWeightPolicy::TotalPixelWeightPolicy()
+{
+
+}
+//----------------------------------------------------------------------------------------
+TotalPixelWeightPolicy::TotalPixelWeightPolicy(CFloat32VolumeData2D* _pPixelWeight)
+{
+ m_pPixelWeight = _pPixelWeight;
+}
+//----------------------------------------------------------------------------------------
+TotalPixelWeightPolicy::~TotalPixelWeightPolicy()
+{
+
+}
+//----------------------------------------------------------------------------------------
+bool TotalPixelWeightPolicy::rayPrior(int _iRayIndex)
+{
+ return true;
+}
+//----------------------------------------------------------------------------------------
+bool TotalPixelWeightPolicy::pixelPrior(int _iVolumeIndex)
+{
+ return true;
+}
+//----------------------------------------------------------------------------------------
+void TotalPixelWeightPolicy::addWeight(int _iRayIndex, int _iVolumeIndex, float32 _fWeight)
+{
+ m_pPixelWeight->getData()[_iVolumeIndex] += _fWeight;
+}
+//----------------------------------------------------------------------------------------
+void TotalPixelWeightPolicy::rayPosterior(int _iRayIndex)
+{
+ // nothing
+}
+//----------------------------------------------------------------------------------------
+void TotalPixelWeightPolicy::pixelPosterior(int _iVolumeIndex)
+{
+ // nothing
+}
+//----------------------------------------------------------------------------------------
+
+
+
+
+//----------------------------------------------------------------------------------------
+// TOTAL RAY LENGTH (Ray+Pixel Driven)
+//----------------------------------------------------------------------------------------
+TotalRayLengthPolicy::TotalRayLengthPolicy()
+{
+
+}
+//----------------------------------------------------------------------------------------
+TotalRayLengthPolicy::TotalRayLengthPolicy(CFloat32ProjectionData2D* _pRayLength)
+{
+ m_pRayLength = _pRayLength;
+}
+//----------------------------------------------------------------------------------------
+TotalRayLengthPolicy::~TotalRayLengthPolicy()
+{
+
+}
+//----------------------------------------------------------------------------------------
+bool TotalRayLengthPolicy::rayPrior(int _iRayIndex)
+{
+ return true;
+}
+//----------------------------------------------------------------------------------------
+bool TotalRayLengthPolicy::pixelPrior(int _iVolumeIndex)
+{
+ return true;
+}
+//----------------------------------------------------------------------------------------
+void TotalRayLengthPolicy::addWeight(int _iRayIndex, int _iVolumeIndex, float32 _fWeight)
+{
+ m_pRayLength->getData()[_iRayIndex] += _fWeight;
+}
+//----------------------------------------------------------------------------------------
+void TotalRayLengthPolicy::rayPosterior(int _iRayIndex)
+{
+ // nothing
+}
+//----------------------------------------------------------------------------------------
+void TotalRayLengthPolicy::pixelPosterior(int _iVolumeIndex)
+{
+ // nothing
+}
+//----------------------------------------------------------------------------------------
+
+
+
+
+
+//----------------------------------------------------------------------------------------
+// COMBINE TWO POLICIES (Ray+Pixel Driven)
+//----------------------------------------------------------------------------------------
+template<typename P1, typename P2>
+CombinePolicy<P1,P2>::CombinePolicy()
+{
+
+}
+//----------------------------------------------------------------------------------------
+template<typename P1, typename P2>
+CombinePolicy<P1,P2>::CombinePolicy(P1 _policy1, P2 _policy2)
+{
+ policy1 = _policy1;
+ policy2 = _policy2;
+}
+//----------------------------------------------------------------------------------------
+template<typename P1, typename P2>
+CombinePolicy<P1,P2>::~CombinePolicy()
+{
+
+}
+//----------------------------------------------------------------------------------------
+template<typename P1, typename P2>
+bool CombinePolicy<P1,P2>::rayPrior(int _iRayIndex)
+{
+ if (!policy1.rayPrior(_iRayIndex)) return false;
+ return policy2.rayPrior(_iRayIndex);
+}
+//----------------------------------------------------------------------------------------
+template<typename P1, typename P2>
+bool CombinePolicy<P1,P2>::pixelPrior(int _iVolumeIndex)
+{
+ if (!policy1.pixelPrior(_iVolumeIndex)) return false;
+ return policy2.pixelPrior(_iVolumeIndex);
+}
+//----------------------------------------------------------------------------------------
+template<typename P1, typename P2>
+void CombinePolicy<P1,P2>::addWeight(int _iRayIndex, int _iVolumeIndex, float32 _fWeight)
+{
+ policy1.addWeight(_iRayIndex, _iVolumeIndex, _fWeight);
+ policy2.addWeight(_iRayIndex, _iVolumeIndex, _fWeight);
+}
+//----------------------------------------------------------------------------------------
+template<typename P1, typename P2>
+void CombinePolicy<P1,P2>::rayPosterior(int _iRayIndex)
+{
+ policy1.rayPosterior(_iRayIndex);
+ policy2.rayPosterior(_iRayIndex);
+}
+//----------------------------------------------------------------------------------------
+template<typename P1, typename P2>
+void CombinePolicy<P1,P2>::pixelPosterior(int _iVolumeIndex)
+{
+ policy1.pixelPosterior(_iVolumeIndex);
+ policy2.pixelPosterior(_iVolumeIndex);
+}
+//----------------------------------------------------------------------------------------
+
+
+
+
+//----------------------------------------------------------------------------------------
+// COMBINE THREE POLICIES (Ray+Pixel Driven)
+//----------------------------------------------------------------------------------------
+template<typename P1, typename P2, typename P3>
+Combine3Policy<P1,P2,P3>::Combine3Policy()
+{
+
+}
+//----------------------------------------------------------------------------------------
+template<typename P1, typename P2, typename P3>
+Combine3Policy<P1,P2,P3>::Combine3Policy(P1 _policy1, P2 _policy2, P3 _policy3)
+{
+ policy1 = _policy1;
+ policy2 = _policy2;
+ policy3 = _policy3;
+}
+//----------------------------------------------------------------------------------------
+template<typename P1, typename P2, typename P3>
+Combine3Policy<P1,P2,P3>::~Combine3Policy()
+{
+
+}
+//----------------------------------------------------------------------------------------
+template<typename P1, typename P2, typename P3>
+bool Combine3Policy<P1,P2,P3>::rayPrior(int _iRayIndex)
+{
+ if (!policy1.rayPrior(_iRayIndex)) return false;
+ if (!policy2.rayPrior(_iRayIndex)) return false;
+ return policy3.rayPrior(_iRayIndex);
+}
+//----------------------------------------------------------------------------------------
+template<typename P1, typename P2, typename P3>
+bool Combine3Policy<P1,P2,P3>::pixelPrior(int _iVolumeIndex)
+{
+ if (!policy1.pixelPrior(_iVolumeIndex)) return false;
+ if (!policy2.pixelPrior(_iVolumeIndex)) return false;
+ return policy3.pixelPrior(_iVolumeIndex);
+}
+//----------------------------------------------------------------------------------------
+template<typename P1, typename P2, typename P3>
+void Combine3Policy<P1,P2,P3>::addWeight(int _iRayIndex, int _iVolumeIndex, float32 _fWeight)
+{
+ policy1.addWeight(_iRayIndex, _iVolumeIndex, _fWeight);
+ policy2.addWeight(_iRayIndex, _iVolumeIndex, _fWeight);
+ policy3.addWeight(_iRayIndex, _iVolumeIndex, _fWeight);
+}
+//----------------------------------------------------------------------------------------
+template<typename P1, typename P2, typename P3>
+void Combine3Policy<P1,P2,P3>::rayPosterior(int _iRayIndex)
+{
+ policy1.rayPosterior(_iRayIndex);
+ policy2.rayPosterior(_iRayIndex);
+ policy3.rayPosterior(_iRayIndex);
+}
+//----------------------------------------------------------------------------------------
+template<typename P1, typename P2, typename P3>
+void Combine3Policy<P1,P2,P3>::pixelPosterior(int _iVolumeIndex)
+{
+ policy1.pixelPosterior(_iVolumeIndex);
+ policy2.pixelPosterior(_iVolumeIndex);
+ policy3.pixelPosterior(_iVolumeIndex);
+}
+//----------------------------------------------------------------------------------------
+
+
+
+
+
+
+//----------------------------------------------------------------------------------------
+// COMBINE FOUR POLICIES (Ray+Pixel Driven)
+//----------------------------------------------------------------------------------------
+template<typename P1, typename P2, typename P3, typename P4>
+Combine4Policy<P1,P2,P3,P4>::Combine4Policy()
+{
+
+}
+//----------------------------------------------------------------------------------------
+template<typename P1, typename P2, typename P3, typename P4>
+Combine4Policy<P1,P2,P3,P4>::Combine4Policy(P1 _policy1, P2 _policy2, P3 _policy3, P4 _policy4)
+{
+ policy1 = _policy1;
+ policy2 = _policy2;
+ policy3 = _policy3;
+ policy4 = _policy4;
+}
+//----------------------------------------------------------------------------------------
+template<typename P1, typename P2, typename P3, typename P4>
+Combine4Policy<P1,P2,P3,P4>::~Combine4Policy()
+{
+
+}
+//----------------------------------------------------------------------------------------
+template<typename P1, typename P2, typename P3, typename P4>
+bool Combine4Policy<P1,P2,P3,P4>::rayPrior(int _iRayIndex)
+{
+ if (!policy1.rayPrior(_iRayIndex)) return false;
+ if (!policy2.rayPrior(_iRayIndex)) return false;
+ if (!policy3.rayPrior(_iRayIndex)) return false;
+ return policy4.rayPrior(_iRayIndex);
+}
+//----------------------------------------------------------------------------------------
+template<typename P1, typename P2, typename P3, typename P4>
+bool Combine4Policy<P1,P2,P3,P4>::pixelPrior(int _iVolumeIndex)
+{
+ if (!policy1.pixelPrior(_iVolumeIndex)) return false;
+ if (!policy2.pixelPrior(_iVolumeIndex)) return false;
+ if (!policy3.pixelPrior(_iVolumeIndex)) return false;
+ return policy4.pixelPrior(_iVolumeIndex);
+}
+//----------------------------------------------------------------------------------------
+template<typename P1, typename P2, typename P3, typename P4>
+void Combine4Policy<P1,P2,P3,P4>::addWeight(int _iRayIndex, int _iVolumeIndex, float32 _fWeight)
+{
+ policy1.addWeight(_iRayIndex, _iVolumeIndex, _fWeight);
+ policy2.addWeight(_iRayIndex, _iVolumeIndex, _fWeight);
+ policy3.addWeight(_iRayIndex, _iVolumeIndex, _fWeight);
+ policy4.addWeight(_iRayIndex, _iVolumeIndex, _fWeight);
+}
+//----------------------------------------------------------------------------------------
+template<typename P1, typename P2, typename P3, typename P4>
+void Combine4Policy<P1,P2,P3,P4>::rayPosterior(int _iRayIndex)
+{
+ policy1.rayPosterior(_iRayIndex);
+ policy2.rayPosterior(_iRayIndex);
+ policy3.rayPosterior(_iRayIndex);
+ policy4.rayPosterior(_iRayIndex);
+}
+//----------------------------------------------------------------------------------------
+template<typename P1, typename P2, typename P3, typename P4>
+void Combine4Policy<P1,P2,P3,P4>::pixelPosterior(int _iVolumeIndex)
+{
+ policy1.pixelPosterior(_iVolumeIndex);
+ policy2.pixelPosterior(_iVolumeIndex);
+ policy3.pixelPosterior(_iVolumeIndex);
+ policy4.pixelPosterior(_iVolumeIndex);
+}
+//----------------------------------------------------------------------------------------
+
+
+
+//----------------------------------------------------------------------------------------
+// COMBINE LIST OF EQUAL POLICIES (Ray+Pixel Driven)
+//----------------------------------------------------------------------------------------
+template<typename P>
+CombineListPolicy<P>::CombineListPolicy()
+{
+ size = 0;
+}
+//----------------------------------------------------------------------------------------
+template<typename P>
+CombineListPolicy<P>::CombineListPolicy(std::vector<P> _policyList)
+{
+ policyList = _policyList;
+ size = policyList.size();
+}
+//----------------------------------------------------------------------------------------
+template<typename P>
+CombineListPolicy<P>::~CombineListPolicy()
+{
+
+}
+//----------------------------------------------------------------------------------------
+template<typename P>
+void CombineListPolicy<P>::addPolicy(P _policy)
+{
+ policyList.push_back(_policy);
+ size = policyList.size();
+}
+//----------------------------------------------------------------------------------------
+template<typename P>
+bool CombineListPolicy<P>::rayPrior(int _iRayIndex)
+{
+ for(unsigned int i = 0; i < size; ++i) {
+ if (!policyList[i].rayPrior(_iRayIndex)) return false;
+ }
+ return true;
+}
+//----------------------------------------------------------------------------------------
+template<typename P>
+bool CombineListPolicy<P>::pixelPrior(int _iVolumeIndex)
+{
+ for(unsigned int i = 0; i < size; ++i) {
+ if (!policyList[i].pixelPrior(_iVolumeIndex)) return false;
+ }
+ return true;
+}
+//----------------------------------------------------------------------------------------
+template<typename P>
+void CombineListPolicy<P>::addWeight(int _iRayIndex, int _iVolumeIndex, float32 _fWeight)
+{
+ for(unsigned int i = 0; i < size; ++i) {
+ policyList[i].addWeight(_iRayIndex, _iVolumeIndex, _fWeight);
+ }
+}
+//----------------------------------------------------------------------------------------
+template<typename P>
+void CombineListPolicy<P>::rayPosterior(int _iRayIndex)
+{
+ for(unsigned int i = 0; i < size; ++i) {
+ policyList[i].rayPosterior(_iRayIndex);
+ }
+}
+//----------------------------------------------------------------------------------------
+template<typename P>
+void CombineListPolicy<P>::pixelPosterior(int _iVolumeIndex)
+{
+ for(unsigned int i = 0; i < size; ++i) {
+ policyList[i].pixelPosterior(_iVolumeIndex);
+ }
+}
+//----------------------------------------------------------------------------------------
+
+
+
+
+
+//----------------------------------------------------------------------------------------
+// EMPTY POLICY (Ray+Pixel Driven)
+//----------------------------------------------------------------------------------------
+EmptyPolicy::EmptyPolicy()
+{
+
+}
+//----------------------------------------------------------------------------------------
+EmptyPolicy::~EmptyPolicy()
+{
+
+}
+//----------------------------------------------------------------------------------------
+bool EmptyPolicy::rayPrior(int _iRayIndex)
+{
+ return true;
+}
+//----------------------------------------------------------------------------------------
+bool EmptyPolicy::pixelPrior(int _iVolumeIndex)
+{
+ return true;
+}
+//----------------------------------------------------------------------------------------
+void EmptyPolicy::addWeight(int _iRayIndex, int _iVolumeIndex, float32 _fWeight)
+{
+ // nothing
+}
+//----------------------------------------------------------------------------------------
+void EmptyPolicy::rayPosterior(int _iRayIndex)
+{
+ // nothing
+}
+//----------------------------------------------------------------------------------------
+void EmptyPolicy::pixelPosterior(int _iVolumeIndex)
+{
+ // nothing
+}
+//----------------------------------------------------------------------------------------
+
+
+
+//----------------------------------------------------------------------------------------
+// SIRT BACKPROJECTION (Ray+Pixel Driven)
+//----------------------------------------------------------------------------------------
+SIRTBPPolicy::SIRTBPPolicy()
+{
+
+}
+//----------------------------------------------------------------------------------------
+SIRTBPPolicy::SIRTBPPolicy(CFloat32VolumeData2D* _pReconstruction,
+ CFloat32ProjectionData2D* _pSinogram,
+ CFloat32VolumeData2D* _pTotalPixelWeight,
+ CFloat32ProjectionData2D* _pTotalRayLength)
+{
+ m_pReconstruction = _pReconstruction;
+ m_pSinogram = _pSinogram;
+ m_pTotalPixelWeight = _pTotalPixelWeight;
+ m_pTotalRayLength = _pTotalRayLength;
+}
+//----------------------------------------------------------------------------------------
+SIRTBPPolicy::~SIRTBPPolicy()
+{
+
+}
+//----------------------------------------------------------------------------------------
+bool SIRTBPPolicy::rayPrior(int _iRayIndex)
+{
+ return true;
+}
+//----------------------------------------------------------------------------------------
+bool SIRTBPPolicy::pixelPrior(int _iVolumeIndex)
+{
+ return true;
+}
+//----------------------------------------------------------------------------------------
+void SIRTBPPolicy::addWeight(int _iRayIndex, int _iVolumeIndex, float32 _fWeight)
+{
+ float32 fGammaBeta = m_pTotalPixelWeight->getData()[_iVolumeIndex] * m_pTotalRayLength->getData()[_iRayIndex];
+ if ((fGammaBeta > 0.001f) || (fGammaBeta < -0.001f)) {
+ m_pReconstruction->getData()[_iVolumeIndex] += _fWeight * m_pSinogram->getData()[_iRayIndex] / fGammaBeta;
+ }
+}
+//----------------------------------------------------------------------------------------
+void SIRTBPPolicy::rayPosterior(int _iRayIndex)
+{
+ // nothing
+}
+//----------------------------------------------------------------------------------------
+void SIRTBPPolicy::pixelPosterior(int _iVolumeIndex)
+{
+ // nothing
+}
+//----------------------------------------------------------------------------------------
+
+
+
+
+
+//----------------------------------------------------------------------------------------
+// SINOGRAM MASK (Ray+Pixel Driven)
+//----------------------------------------------------------------------------------------
+SinogramMaskPolicy::SinogramMaskPolicy()
+{
+
+}
+//----------------------------------------------------------------------------------------
+SinogramMaskPolicy::SinogramMaskPolicy(CFloat32ProjectionData2D* _pSinogramMask)
+{
+ m_pSinogramMask = _pSinogramMask;
+}
+//----------------------------------------------------------------------------------------
+SinogramMaskPolicy::~SinogramMaskPolicy()
+{
+
+}
+//----------------------------------------------------------------------------------------
+bool SinogramMaskPolicy::rayPrior(int _iRayIndex)
+{
+ return (m_pSinogramMask->getData()[_iRayIndex] != 0);
+}
+//----------------------------------------------------------------------------------------
+bool SinogramMaskPolicy::pixelPrior(int _iVolumeIndex)
+{
+ return true;
+}
+//----------------------------------------------------------------------------------------
+void SinogramMaskPolicy::addWeight(int _iRayIndex, int _iVolumeIndex, float32 _fWeight)
+{
+ // nothing
+}
+//----------------------------------------------------------------------------------------
+void SinogramMaskPolicy::rayPosterior(int _iRayIndex)
+{
+ // nothing
+}
+//----------------------------------------------------------------------------------------
+void SinogramMaskPolicy::pixelPosterior(int _iVolumeIndex)
+{
+ // nothing
+}
+//----------------------------------------------------------------------------------------
+
+
+
+
+
+//----------------------------------------------------------------------------------------
+// RECONSTRUCTION MASK (Ray+Pixel Driven)
+//----------------------------------------------------------------------------------------
+ReconstructionMaskPolicy::ReconstructionMaskPolicy()
+{
+
+}
+//----------------------------------------------------------------------------------------
+ReconstructionMaskPolicy::ReconstructionMaskPolicy(CFloat32VolumeData2D* _pReconstructionMask)
+{
+ m_pReconstructionMask = _pReconstructionMask;
+}
+//----------------------------------------------------------------------------------------
+ReconstructionMaskPolicy::~ReconstructionMaskPolicy()
+{
+
+}
+//----------------------------------------------------------------------------------------
+bool ReconstructionMaskPolicy::rayPrior(int _iRayIndex)
+{
+ return true;
+}
+//----------------------------------------------------------------------------------------
+bool ReconstructionMaskPolicy::pixelPrior(int _iVolumeIndex)
+{
+ return (m_pReconstructionMask->getData()[_iVolumeIndex] != 0);
+}
+//----------------------------------------------------------------------------------------
+void ReconstructionMaskPolicy::addWeight(int _iRayIndex, int _iVolumeIndex, float32 _fWeight)
+{
+ // nothing
+}
+//----------------------------------------------------------------------------------------
+void ReconstructionMaskPolicy::rayPosterior(int _iRayIndex)
+{
+ // nothing
+}
+//----------------------------------------------------------------------------------------
+void ReconstructionMaskPolicy::pixelPosterior(int _iVolumeIndex)
+{
+ // nothing
+}
+//----------------------------------------------------------------------------------------
+
+
+
+#endif
diff --git a/include/astra/FanFlatBeamLineKernelProjector2D.h b/include/astra/FanFlatBeamLineKernelProjector2D.h
new file mode 100644
index 0000000..154504a
--- /dev/null
+++ b/include/astra/FanFlatBeamLineKernelProjector2D.h
@@ -0,0 +1,194 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_FANFLATBEAMLINEKERNELPROJECTOR
+#define _INC_ASTRA_FANFLATBEAMLINEKERNELPROJECTOR
+
+#include "FanFlatProjectionGeometry2D.h"
+#include "FanFlatVecProjectionGeometry2D.h"
+#include "Float32Data2D.h"
+#include "Projector2D.h"
+
+namespace astra
+{
+
+
+/** This class implements a two-dimensional projector based on a line based kernel
+ * with a fan flat projection geometry.
+ *
+ * \par XML Configuration
+ * \astra_xml_item{ProjectionGeometry, xml node, The geometry of the projection.}
+ * \astra_xml_item{VolumeGeometry, xml node, The geometry of the volume.}
+ *
+ * \par MATLAB example
+ * \astra_code{
+ * cfg = astra_struct('fanflat_line');\n
+ * cfg.ProjectionGeometry = proj_geom;\n
+ * cfg.VolumeGeometry = vol_geom;\n
+ * proj_id = astra_mex_projector('create'\, cfg);\n
+ * }
+ */
+class _AstraExport CFanFlatBeamLineKernelProjector2D : public CProjector2D {
+
+protected:
+
+ /** Initial clearing. Only to be used by constructors.
+ */
+ virtual void _clear();
+
+ /** Check the values of this object. If everything is ok, the object can be set to the initialized state.
+ * The following statements are then guaranteed to hold:
+ * - no NULL pointers
+ * - all sub-objects are initialized properly
+ * - blobvalues are ok
+ */
+ virtual bool _check();
+
+public:
+
+ // type of the projector, needed to register with CProjectorFactory
+ static std::string type;
+
+ /** Default constructor.
+ */
+ CFanFlatBeamLineKernelProjector2D();
+
+ /** Constructor.
+ *
+ * @param _pProjectionGeometry Information class about the geometry of the projection. Will be HARDCOPIED.
+ * @param _pReconstructionGeometry Information class about the geometry of the reconstruction volume. Will be HARDCOPIED.
+ */
+ CFanFlatBeamLineKernelProjector2D(CFanFlatProjectionGeometry2D* _pProjectionGeometry,
+ CVolumeGeometry2D* _pReconstructionGeometry);
+
+ /** Destructor, is virtual to show that we are aware subclass destructor are called.
+ */
+ ~CFanFlatBeamLineKernelProjector2D();
+
+ /** Initialize the projector with a config object.
+ *
+ * @param _cfg Configuration Object
+ * @return initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ /** Initialize the projector.
+ *
+ * @param _pProjectionGeometry Information class about the geometry of the projection. Will be HARDCOPIED.
+ * @param _pReconstructionGeometry Information class about the geometry of the reconstruction volume. Will be HARDCOPIED.
+ * @return initialization successful?
+ */
+ virtual bool initialize(CFanFlatProjectionGeometry2D* _pProjectionGeometry,
+ CVolumeGeometry2D* _pReconstructionGeometry);
+
+ /** Clear this class.
+ */
+ virtual void clear();
+
+ /** Returns the number of weights required for storage of all weights of one projection.
+ *
+ * @param _iProjectionIndex Index of the projection (zero-based).
+ * @return Size of buffer (given in SPixelWeight elements) needed to store weighted pixels.
+ */
+ virtual int getProjectionWeightsCount(int _iProjectionIndex);
+
+ /** Compute the pixel weights for a single ray, from the source to a detector pixel.
+ *
+ * @param _iProjectionIndex Index of the projection
+ * @param _iDetectorIndex Index of the detector pixel
+ * @param _pWeightedPixels Pointer to a pre-allocated array, consisting of _iMaxPixelCount elements
+ * of type SPixelWeight. On return, this array contains a list of the index
+ * and weight for all pixels on the ray.
+ * @param _iMaxPixelCount Maximum number of pixels (and corresponding weights) that can be stored in _pWeightedPixels.
+ * This number MUST be greater than the total number of pixels on the ray.
+ * @param _iStoredPixelCount On return, this variable contains the total number of pixels on the
+ * ray (that have been stored in the list _pWeightedPixels).
+ */
+ virtual void computeSingleRayWeights(int _iProjectionIndex,
+ int _iDetectorIndex,
+ SPixelWeight* _pWeightedPixels,
+ int _iMaxPixelCount,
+ int& _iStoredPixelCount);
+
+ /** Create a list of detectors that are influenced by point [_iRow, _iCol].
+ *
+ * @param _iRow row of the point
+ * @param _iCol column of the point
+ * @return list of SDetector2D structs
+ */
+ virtual std::vector<SDetector2D> projectPoint(int _iRow, int _iCol);
+
+ /** Policy-based projection of all rays. This function will calculate each non-zero projection
+ * weight and use this value for a task provided by the policy object.
+ *
+ * @param _policy Policy object. Should contain prior, addWeight and posterior function.
+ */
+ template <typename Policy>
+ void project(Policy& _policy);
+
+ /** Policy-based projection of all rays of a single projection. This function will calculate
+ * each non-zero projection weight and use this value for a task provided by the policy object.
+ *
+ * @param _iProjection Wwhich projection should be projected?
+ * @param _policy Policy object. Should contain prior, addWeight and posterior function.
+ */
+ template <typename Policy>
+ void projectSingleProjection(int _iProjection, Policy& _policy);
+
+ /** Policy-based projection of a single ray. This function will calculate each non-zero
+ * projection weight and use this value for a task provided by the policy object.
+ *
+ * @param _iProjection Which projection should be projected?
+ * @param _iDetector Which detector should be projected?
+ * @param _policy Policy object. Should contain prior, addWeight and posterior function.
+ */
+ template <typename Policy>
+ void projectSingleRay(int _iProjection, int _iDetector, Policy& _policy);
+
+ /** Return the type of this projector.
+ *
+ * @return identification type of this projector
+ */
+ virtual std::string getType();
+
+ float32 angleBetweenVectors(float32 _fAX, float32 _fAY, float32 _fBX, float32 _fBY);
+
+};
+
+//----------------------------------------------------------------------------------------
+
+inline std::string CFanFlatBeamLineKernelProjector2D::getType()
+{
+ return type;
+}
+
+
+} // namespace astra
+
+#endif
+
diff --git a/include/astra/FanFlatBeamLineKernelProjector2D.inl b/include/astra/FanFlatBeamLineKernelProjector2D.inl
new file mode 100644
index 0000000..e686532
--- /dev/null
+++ b/include/astra/FanFlatBeamLineKernelProjector2D.inl
@@ -0,0 +1,740 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+
+using namespace astra;
+
+//----------------------------------------------------------------------------------------
+// PROJECT ALL
+template <typename Policy>
+void CFanFlatBeamLineKernelProjector2D::project(Policy& p)
+{
+ // variables
+ float32 sin_theta, cos_theta, inv_sin_theta, inv_cos_theta, S, T, t, I, P, x, x2;
+ float32 lengthPerRow, updatePerRow, inv_pixelLengthX, lengthPerCol, updatePerCol, inv_pixelLengthY;
+ int iVolumeIndex, iRayIndex, row, col, iAngle, iDetector, x1;
+ bool switch_t;
+
+ const CFanFlatProjectionGeometry2D* pProjectionGeometry = dynamic_cast<CFanFlatProjectionGeometry2D*>(m_pProjectionGeometry);
+ const CFanFlatVecProjectionGeometry2D* pVecProjectionGeometry = dynamic_cast<CFanFlatVecProjectionGeometry2D*>(m_pProjectionGeometry);
+
+ float32 old_theta, theta, alpha;
+ const SFanProjection * proj = 0;
+
+ // loop angles
+ for (iAngle = 0; iAngle < m_pProjectionGeometry->getProjectionAngleCount(); ++iAngle) {
+
+ // get theta
+ if (pProjectionGeometry) {
+ old_theta = pProjectionGeometry->getProjectionAngle(iAngle);
+ }
+ else if (pVecProjectionGeometry) {
+ proj = &pVecProjectionGeometry->getProjectionVectors()[iAngle];
+ old_theta = atan2(-proj->fSrcX, proj->fSrcY);
+ if (old_theta < 0) old_theta += 2*PI;
+ } else {
+ assert(false);
+ }
+
+ switch_t = false;
+ if (old_theta >= 7*PIdiv4) old_theta -= 2*PI;
+ if (old_theta >= 3*PIdiv4) {
+ old_theta -= PI;
+ switch_t = true;
+ }
+
+ // loop detectors
+ for (iDetector = 0; iDetector < m_pProjectionGeometry->getDetectorCount(); ++iDetector) {
+
+ iRayIndex = iAngle * m_pProjectionGeometry->getDetectorCount() + iDetector;
+
+ // POLICY: RAY PRIOR
+ if (!p.rayPrior(iRayIndex)) continue;
+
+ // get values
+ if (pProjectionGeometry) {
+ t = -pProjectionGeometry->indexToDetectorOffset(iDetector);
+ alpha = atan(t / pProjectionGeometry->getSourceDetectorDistance());
+ t = sin(alpha) * pProjectionGeometry->getOriginSourceDistance();
+ }
+ else if (pVecProjectionGeometry) {
+ float32 detX = proj->fDetSX + proj->fDetUX*(0.5f + iDetector);
+ float32 detY = proj->fDetSY + proj->fDetUY*(0.5f + iDetector);
+ alpha = angleBetweenVectors(-proj->fSrcX, -proj->fSrcY, detX - proj->fSrcX, detY - proj->fSrcY);
+ t = sin(alpha) * sqrt(proj->fSrcX*proj->fSrcX + proj->fSrcY*proj->fSrcY);
+ } else {
+ assert(false);
+ }
+
+ if (switch_t) t = -t;
+ theta = old_theta + alpha;
+
+ // precalculate sin, cos, 1/cos
+ sin_theta = sin(theta);
+ cos_theta = cos(theta);
+ inv_sin_theta = 1.0f / sin_theta;
+ inv_cos_theta = 1.0f / cos_theta;
+
+ // precalculate kernel limits
+ lengthPerRow = m_pVolumeGeometry->getPixelLengthY() * inv_cos_theta;
+ updatePerRow = sin_theta * inv_cos_theta;
+ inv_pixelLengthX = 1.0f / m_pVolumeGeometry->getPixelLengthX();
+
+ // precalculate kernel limits
+ lengthPerCol = m_pVolumeGeometry->getPixelLengthX() * inv_sin_theta;
+ updatePerCol = cos_theta * inv_sin_theta;
+ inv_pixelLengthY = 1.0f / m_pVolumeGeometry->getPixelLengthY();
+
+ // precalculate S and T
+ S = 0.5f - 0.5f * ((updatePerRow < 0) ? -updatePerRow : updatePerRow);
+ T = 0.5f - 0.5f * ((updatePerCol < 0) ? -updatePerCol : updatePerCol);
+
+ // vertically
+ if (old_theta <= PIdiv4) {
+
+ // calculate x for row 0
+ P = (t - sin_theta * m_pVolumeGeometry->pixelRowToCenterY(0)) * inv_cos_theta;
+ x = (P - m_pVolumeGeometry->getWindowMinX()) * inv_pixelLengthX;
+
+ // for each row
+ for (row = 0; row < m_pVolumeGeometry->getGridRowCount(); ++row) {
+
+ // get coords
+ x1 = int((x > 0.0f) ? x : x-1.0f);
+ x2 = x - x1;
+ x += updatePerRow;
+
+ if (x1 < -1 || x1 > m_pVolumeGeometry->getGridColCount()) continue;
+
+ // left
+ if (x2 < 0.5f-S) {
+ I = (0.5f - S + x2) / (1.0f - 2.0f*S) * lengthPerRow;
+
+ if (x1-1 >= 0 /*&& x1-1 < m_pVolumeGeometry->getGridColCount()*/) {//x1 is always less than or equal to gridColCount because of the "continue" in the beginning of the for-loop
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1-1);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, lengthPerRow-I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+
+ if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridColCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ }
+
+ // center
+ else if (x2 <= 0.5f+S) {
+ if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridColCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, lengthPerRow);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ }
+
+ // right
+ else if (x2 <= 1.0f) {
+ I = (1.5f - S - x2) / (1.0f - 2.0f*S) * lengthPerRow;
+
+ if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridColCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ if (/*x1+1 >= 0 &&*/ x1+1 < m_pVolumeGeometry->getGridColCount()) {//x1 is always greater than or equal to -1 because of the "continue" in the beginning of the for-loop
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1+1);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, lengthPerRow-I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ }
+ }
+ }
+
+ // horizontally
+ //else if (PIdiv4 <= old_theta && old_theta <= 3*PIdiv4) {
+ else {
+
+ // calculate point P
+ P = (t - cos_theta * m_pVolumeGeometry->pixelColToCenterX(0)) * inv_sin_theta;
+ x = (m_pVolumeGeometry->getWindowMaxY() - P) * inv_pixelLengthY;
+
+ // for each col
+ for (col = 0; col < m_pVolumeGeometry->getGridColCount(); ++col) {
+
+ // get coords
+ x1 = int((x > 0.0f) ? x : x-1.0f);
+ x2 = x - x1;
+ x += updatePerCol;
+
+ if (x1 < -1 || x1 > m_pVolumeGeometry->getGridRowCount()) continue;
+
+ // up
+ if (x2 < 0.5f-T) {
+ I = (0.5f - T + x2) / (1.0f - 2.0f*T) * lengthPerCol;
+
+ if (x1-1 >= 0 /*&& x1-1 < m_pVolumeGeometry->getGridRowCount()*/) {//x1 is always less than or equal to gridRowCount because of the "continue" in the beginning of the for-loop
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1-1, col);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, lengthPerCol-I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+
+ if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridRowCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1, col);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ }
+
+ // center
+ else if (x2 <= 0.5f+T) {
+ if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridRowCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1, col);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, lengthPerCol);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ }
+
+ // down
+ else if (x2 <= 1.0f) {
+ I = (1.5f - T - x2) / (1.0f - 2.0f*T) * lengthPerCol;
+
+ if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridRowCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1, col);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ if (/*x1+1 >= 0 &&*/ x1+1 < m_pVolumeGeometry->getGridRowCount()) {//x1 is always greater than or equal to -1 because of the "continue" in the beginning of the for-loop
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1+1, col);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, lengthPerCol-I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ }
+ }
+ } // end loop col
+
+ // POLICY: RAY POSTERIOR
+ p.rayPosterior(iRayIndex);
+
+ } // end loop detector
+ } // end loop angles
+}
+
+
+//----------------------------------------------------------------------------------------
+// PROJECT SINGLE PROJECTION
+template <typename Policy>
+void CFanFlatBeamLineKernelProjector2D::projectSingleProjection(int _iProjection, Policy& p)
+{
+ // variables
+ float32 sin_theta, cos_theta, inv_sin_theta, inv_cos_theta, S, T, t, I, P, x, x2;
+ float32 lengthPerRow, updatePerRow, inv_pixelLengthX, lengthPerCol, updatePerCol, inv_pixelLengthY;
+ int iVolumeIndex, iRayIndex, row, col, iDetector, x1;
+ bool switch_t;
+
+ const CFanFlatProjectionGeometry2D* pProjectionGeometry = dynamic_cast<CFanFlatProjectionGeometry2D*>(m_pProjectionGeometry);
+ const CFanFlatVecProjectionGeometry2D* pVecProjectionGeometry = dynamic_cast<CFanFlatVecProjectionGeometry2D*>(m_pProjectionGeometry);
+
+ float32 old_theta, theta, alpha;
+ const SFanProjection * proj = 0;
+
+ //get theta
+ if (pProjectionGeometry) {
+ old_theta = pProjectionGeometry->getProjectionAngle(_iProjection);
+ }
+ else if (pVecProjectionGeometry) {
+ proj = &pVecProjectionGeometry->getProjectionVectors()[_iProjection];
+ old_theta = atan2(-proj->fSrcX, proj->fSrcY);
+ if (old_theta < 0) old_theta += 2*PI;
+ } else {
+ assert(false);
+ }
+
+ switch_t = false;
+ if (old_theta >= 7*PIdiv4) old_theta -= 2*PI;
+ if (old_theta >= 3*PIdiv4) {
+ old_theta -= PI;
+ switch_t = true;
+ }
+
+ // loop detectors
+ for (iDetector = 0; iDetector < m_pProjectionGeometry->getDetectorCount(); ++iDetector) {
+
+ iRayIndex = _iProjection * m_pProjectionGeometry->getDetectorCount() + iDetector;
+
+ // POLICY: RAY PRIOR
+ if (!p.rayPrior(iRayIndex)) continue;
+
+ if (pProjectionGeometry) {
+ t = -pProjectionGeometry->indexToDetectorOffset(iDetector);
+ alpha = atan(t / pProjectionGeometry->getSourceDetectorDistance());
+ t = sin(alpha) * pProjectionGeometry->getOriginSourceDistance();
+ }
+ else if (pVecProjectionGeometry) {
+ float32 detX = proj->fDetSX + proj->fDetUX*(0.5f + iDetector);
+ float32 detY = proj->fDetSY + proj->fDetUY*(0.5f + iDetector);
+ alpha = angleBetweenVectors(-proj->fSrcX, -proj->fSrcY, detX - proj->fSrcX, detY - proj->fSrcY);
+ t = sin(alpha) * sqrt(proj->fSrcX*proj->fSrcX + proj->fSrcY*proj->fSrcY);
+ } else {
+ assert(false);
+ }
+
+ if (switch_t) t = -t;
+ theta = old_theta + alpha;
+
+ // precalculate sin, cos, 1/cos
+ sin_theta = sin(theta);
+ cos_theta = cos(theta);
+ inv_sin_theta = 1.0f / sin_theta;
+ inv_cos_theta = 1.0f / cos_theta;
+
+ // precalculate kernel limits
+ lengthPerRow = m_pVolumeGeometry->getPixelLengthY() * inv_cos_theta;
+ updatePerRow = sin_theta * inv_cos_theta;
+ inv_pixelLengthX = 1.0f / m_pVolumeGeometry->getPixelLengthX();
+
+ // precalculate kernel limits
+ lengthPerCol = m_pVolumeGeometry->getPixelLengthX() * inv_sin_theta;
+ updatePerCol = cos_theta * inv_sin_theta;
+ inv_pixelLengthY = 1.0f / m_pVolumeGeometry->getPixelLengthY();
+
+ // precalculate S and T
+ S = 0.5f - 0.5f * ((updatePerRow < 0) ? -updatePerRow : updatePerRow);
+ T = 0.5f - 0.5f * ((updatePerCol < 0) ? -updatePerCol : updatePerCol);
+
+ // vertically
+ if (old_theta <= PIdiv4) {
+
+ // calculate x for row 0
+ P = (t - sin_theta * m_pVolumeGeometry->pixelRowToCenterY(0)) * inv_cos_theta;
+ x = (P - m_pVolumeGeometry->getWindowMinX()) * inv_pixelLengthX;
+
+ // for each row
+ for (row = 0; row < m_pVolumeGeometry->getGridRowCount(); ++row) {
+
+ // get coords
+ x1 = int((x > 0.0f) ? x : x-1.0f);
+ x2 = x - x1;
+ x += updatePerRow;
+
+ if (x1 < -1 || x1 > m_pVolumeGeometry->getGridColCount()) continue;
+
+ // left
+ if (x2 < 0.5f-S) {
+ I = (0.5f - S + x2) / (1.0f - 2.0f*S) * lengthPerRow;
+
+ if (x1-1 >= 0 /*&& x1-1 < m_pVolumeGeometry->getGridColCount()*/) {//x1 is always less than or equal to gridColCount because of the "continue" in the beginning of the for-loop
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1-1);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, lengthPerRow-I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+
+ if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridColCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ }
+
+ // center
+ else if (x2 <= 0.5f+S) {
+ if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridColCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, lengthPerRow);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ }
+
+ // right
+ else if (x2 <= 1.0f) {
+ I = (1.5f - S - x2) / (1.0f - 2.0f*S) * lengthPerRow;
+
+ if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridColCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ if (/*x1+1 >= 0 &&*/ x1+1 < m_pVolumeGeometry->getGridColCount()) {//x1 is always greater than or equal to -1 because of the "continue" in the beginning of the for-loop
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1+1);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, lengthPerRow-I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ }
+ }
+ }
+
+ // horizontally
+ else {
+
+ // calculate point P
+ P = (t - cos_theta * m_pVolumeGeometry->pixelColToCenterX(0)) * inv_sin_theta;
+ x = (m_pVolumeGeometry->getWindowMaxY() - P) * inv_pixelLengthY;
+
+ // for each col
+ for (col = 0; col < m_pVolumeGeometry->getGridColCount(); ++col) {
+
+ // get coords
+ x1 = int((x > 0.0f) ? x : x-1.0f);
+ x2 = x - x1;
+ x += updatePerCol;
+
+ if (x1 < -1 || x1 > m_pVolumeGeometry->getGridRowCount()) continue;
+
+ // up
+ if (x2 < 0.5f-T) {
+ I = (0.5f - T + x2) / (1.0f - 2.0f*T) * lengthPerCol;
+
+ if (x1-1 >= 0 /*&& x1-1 < m_pVolumeGeometry->getGridRowCount()*/) {//x1 is always less than or equal to gridRowCount because of the "continue" in the beginning of the for-loop
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1-1, col);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, lengthPerCol-I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+
+ if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridRowCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1, col);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ }
+
+ // center
+ else if (x2 <= 0.5f+T) {
+ if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridRowCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1, col);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, lengthPerCol);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ }
+
+ // down
+ else if (x2 <= 1.0f) {
+ I = (1.5f - T - x2) / (1.0f - 2.0f*T) * lengthPerCol;
+
+ if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridRowCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1, col);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ if (/*x1+1 >= 0 &&*/ x1+1 < m_pVolumeGeometry->getGridRowCount()) {//x1 is always greater than or equal to -1 because of the "continue" in the beginning of the for-loop
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1+1, col);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, lengthPerCol-I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ }
+ }
+ } // end loop col
+
+ // POLICY: RAY POSTERIOR
+ p.rayPosterior(iRayIndex);
+
+ } // end loop detector
+
+}
+
+//----------------------------------------------------------------------------------------
+// PROJECT SINGLE RAY
+template <typename Policy>
+void CFanFlatBeamLineKernelProjector2D::projectSingleRay(int _iProjection, int _iDetector, Policy& p)
+{
+ // variables
+ float32 sin_theta, cos_theta, inv_sin_theta, inv_cos_theta, S, T, t, I, P, x, x2;
+ float32 lengthPerRow, updatePerRow, inv_pixelLengthX, lengthPerCol, updatePerCol, inv_pixelLengthY;
+ int iVolumeIndex, iRayIndex, row, col, x1;
+ bool switch_t;
+
+ const CFanFlatProjectionGeometry2D* pProjectionGeometry = dynamic_cast<CFanFlatProjectionGeometry2D*>(m_pProjectionGeometry);
+ const CFanFlatVecProjectionGeometry2D* pVecProjectionGeometry = dynamic_cast<CFanFlatVecProjectionGeometry2D*>(m_pProjectionGeometry);
+
+ iRayIndex = _iProjection * m_pProjectionGeometry->getDetectorCount() + _iDetector;
+
+ // POLICY: RAY PRIOR
+ if (!p.rayPrior(iRayIndex)) return;
+
+ float32 old_theta, theta, alpha;
+ if (pProjectionGeometry) {
+ old_theta = pProjectionGeometry->getProjectionAngle(_iProjection);
+ t = -pProjectionGeometry->indexToDetectorOffset(_iDetector);
+ alpha = atan(t / pProjectionGeometry->getSourceDetectorDistance());
+ t = sin(alpha) * pProjectionGeometry->getOriginSourceDistance();
+ }
+ else if (pVecProjectionGeometry) {
+ const SFanProjection * proj = &pVecProjectionGeometry->getProjectionVectors()[_iProjection];
+ old_theta = atan2(-proj->fSrcX, proj->fSrcY);
+ if (old_theta < 0) old_theta += 2*PI;
+
+ float32 detX = proj->fDetSX + proj->fDetUX*(0.5f + _iDetector);
+ float32 detY = proj->fDetSY + proj->fDetUY*(0.5f + _iDetector);
+ alpha = angleBetweenVectors(-proj->fSrcX, -proj->fSrcY, detX - proj->fSrcX, detY - proj->fSrcY);
+ t = sin(alpha) * sqrt(proj->fSrcX*proj->fSrcX + proj->fSrcY*proj->fSrcY);
+ } else {
+ assert(false);
+ }
+
+ switch_t = false;
+ if (old_theta >= 7*PIdiv4) old_theta -= 2*PI;
+ if (old_theta >= 3*PIdiv4) {
+ old_theta -= PI;
+ switch_t = true;
+ }
+ if (switch_t) t = -t;
+ theta = old_theta + alpha;
+
+ // precalculate sin, cos, 1/cos
+ sin_theta = sin(theta);
+ cos_theta = cos(theta);
+ inv_sin_theta = 1.0f / sin_theta;
+ inv_cos_theta = 1.0f / cos_theta;
+
+ // precalculate kernel limits
+ lengthPerRow = m_pVolumeGeometry->getPixelLengthY() * inv_cos_theta;
+ updatePerRow = sin_theta * inv_cos_theta;
+ inv_pixelLengthX = 1.0f / m_pVolumeGeometry->getPixelLengthX();
+
+ // precalculate kernel limits
+ lengthPerCol = m_pVolumeGeometry->getPixelLengthX() * inv_sin_theta;
+ updatePerCol = cos_theta * inv_sin_theta;
+ inv_pixelLengthY = 1.0f / m_pVolumeGeometry->getPixelLengthY();
+
+ // precalculate S and T
+ S = 0.5f - 0.5f * ((updatePerRow < 0) ? -updatePerRow : updatePerRow);
+ T = 0.5f - 0.5f * ((updatePerCol < 0) ? -updatePerCol : updatePerCol);
+
+ // vertically
+ if (old_theta <= PIdiv4) {
+
+ // calculate x for row 0
+ P = (t - sin_theta * m_pVolumeGeometry->pixelRowToCenterY(0)) * inv_cos_theta;
+ x = (P - m_pVolumeGeometry->getWindowMinX()) * inv_pixelLengthX;
+
+ // for each row
+ for (row = 0; row < m_pVolumeGeometry->getGridRowCount(); ++row) {
+
+ // get coords
+ x1 = int((x > 0.0f) ? x : x-1.0f);
+ x2 = x - x1;
+ x += updatePerRow;
+
+ if (x1 < -1 || x1 > m_pVolumeGeometry->getGridColCount()) continue;
+
+ // left
+ if (x2 < 0.5f-S) {
+ I = (0.5f - S + x2) / (1.0f - 2.0f*S) * lengthPerRow;
+
+ if (x1-1 >= 0 /*&& x1-1 < m_pVolumeGeometry->getGridColCount()*/) {//x1 is always less than or equal to gridColCount because of the "continue" in the beginning of the for-loop
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1-1);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, lengthPerRow-I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+
+ if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridColCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ }
+
+ // center
+ else if (x2 <= 0.5f+S) {
+ if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridColCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, lengthPerRow);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ }
+
+ // right
+ else if (x2 <= 1.0f) {
+ I = (1.5f - S - x2) / (1.0f - 2.0f*S) * lengthPerRow;
+
+ if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridColCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ if (/*x1+1 >= 0 &&*/ x1+1 < m_pVolumeGeometry->getGridColCount()) {//x1 is always greater than or equal to -1 because of the "continue" in the beginning of the for-loop
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1+1);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, lengthPerRow-I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ }
+ }
+ }
+
+ // horizontally
+ else {
+
+ // calculate point P
+ P = (t - cos_theta * m_pVolumeGeometry->pixelColToCenterX(0)) * inv_sin_theta;
+ x = (m_pVolumeGeometry->getWindowMaxY() - P) * inv_pixelLengthY;
+
+ // for each col
+ for (col = 0; col < m_pVolumeGeometry->getGridColCount(); ++col) {
+
+ // get coords
+ x1 = int((x > 0.0f) ? x : x-1.0f);
+ x2 = x - x1;
+ x += updatePerCol;
+
+ if (x1 < -1 || x1 > m_pVolumeGeometry->getGridRowCount()) continue;
+
+ // up
+ if (x2 < 0.5f-T) {
+ I = (0.5f - T + x2) / (1.0f - 2.0f*T) * lengthPerCol;
+
+ if (x1-1 >= 0 /*&& x1-1 < m_pVolumeGeometry->getGridRowCount()*/) {//x1 is always less than or equal to gridRowCount because of the "continue" in the beginning of the for-loop
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1-1, col);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, lengthPerCol-I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+
+ if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridRowCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1, col);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ }
+
+ // center
+ else if (x2 <= 0.5f+T) {
+ if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridRowCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1, col);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, lengthPerCol);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ }
+
+ // down
+ else if (x2 <= 1.0f) {
+ I = (1.5f - T - x2) / (1.0f - 2.0f*T) * lengthPerCol;
+
+ if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridRowCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1, col);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ if (/*x1+1 >= 0 &&*/ x1+1 < m_pVolumeGeometry->getGridRowCount()) {//x1 is always greater than or equal to -1 because of the "continue" in the beginning of the for-loop
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1+1, col);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, lengthPerCol-I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ }
+ }
+ } // end loop col
+
+ // POLICY: RAY POSTERIOR
+ p.rayPosterior(iRayIndex);
+}
diff --git a/include/astra/FanFlatBeamStripKernelProjector2D.h b/include/astra/FanFlatBeamStripKernelProjector2D.h
new file mode 100644
index 0000000..7fed4c8
--- /dev/null
+++ b/include/astra/FanFlatBeamStripKernelProjector2D.h
@@ -0,0 +1,191 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_FANFLATBEAMSTRIPKERNELPROJECTOR
+#define _INC_ASTRA_FANFLATBEAMSTRIPKERNELPROJECTOR
+
+#include "FanFlatProjectionGeometry2D.h"
+#include "Float32Data2D.h"
+#include "Projector2D.h"
+
+namespace astra
+{
+
+
+/** This class implements a two-dimensional fan-flat-beam projector based on a strip based kernel.
+ *
+ * \par XML Configuration
+ * \astra_xml_item{ProjectionGeometry, xml node, The geometry of the projection.}
+ * \astra_xml_item{VolumeGeometry, xml node, The geometry of the volume.}
+ *
+ * \par MATLAB example
+ * \astra_code{
+ * cfg = astra_struct('strip_fanflat');\n
+ * cfg.ProjectionGeometry = proj_geom;\n
+ * cfg.VolumeGeometry = vol_geom;\n
+ * proj_id = astra_mex_projector('create'\, cfg);\n
+ * }
+ */
+class _AstraExport CFanFlatBeamStripKernelProjector2D : public CProjector2D {
+
+protected:
+
+ /** Initial clearing. Only to be used by constructors.
+ */
+ virtual void _clear();
+
+ /** Check the values of this object. If everything is ok, the object can be set to the initialized state.
+ * The following statements are then guaranteed to hold:
+ * - no NULL pointers
+ * - all sub-objects are initialized properly
+ * - blobvalues are ok
+ */
+ virtual bool _check();
+
+public:
+
+ // type of the projector, needed to register with CProjectorFactory
+ static std::string type;
+
+ /** Default constructor.
+ */
+ CFanFlatBeamStripKernelProjector2D();
+
+ /** Constructor.
+ *
+ * @param _pProjectionGeometry Information class about the geometry of the projection. Will be HARDCOPIED.
+ * @param _pReconstructionGeometry Information class about the geometry of the reconstruction volume. Will be HARDCOPIED.
+ */
+ CFanFlatBeamStripKernelProjector2D(CFanFlatProjectionGeometry2D* _pProjectionGeometry,
+ CVolumeGeometry2D* _pReconstructionGeometry);
+
+ /** Destructor, is virtual to show that we are aware subclass destructor are called.
+ */
+ ~CFanFlatBeamStripKernelProjector2D();
+
+ /** Initialize the projector with a config object.
+ *
+ * @param _cfg Configuration Object
+ * @return initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ /** Initialize the projector.
+ *
+ * @param _pProjectionGeometry Information class about the geometry of the projection. Will be HARDCOPIED.
+ * @param _pReconstructionGeometry Information class about the geometry of the reconstruction volume. Will be HARDCOPIED.
+ * @return initialization successful?
+ */
+ virtual bool initialize(CFanFlatProjectionGeometry2D* _pProjectionGeometry,
+ CVolumeGeometry2D* _pReconstructionGeometry);
+
+ /** Clear this class.
+ */
+ virtual void clear();
+
+ /** Returns the number of weights required for storage of all weights of one projection.
+ *
+ * @param _iProjectionIndex Index of the projection (zero-based).
+ * @return Size of buffer (given in SPixelWeight elements) needed to store weighted pixels.
+ */
+ virtual int getProjectionWeightsCount(int _iProjectionIndex);
+
+ /** Compute the pixel weights for a single ray, from the source to a detector pixel.
+ *
+ * @param _iProjectionIndex Index of the projection
+ * @param _iDetectorIndex Index of the detector pixel
+ * @param _pWeightedPixels Pointer to a pre-allocated array, consisting of _iMaxPixelCount elements
+ * of type SPixelWeight. On return, this array contains a list of the index
+ * and weight for all pixels on the ray.
+ * @param _iMaxPixelCount Maximum number of pixels (and corresponding weights) that can be stored in _pWeightedPixels.
+ * This number MUST be greater than the total number of pixels on the ray.
+ * @param _iStoredPixelCount On return, this variable contains the total number of pixels on the
+ * ray (that have been stored in the list _pWeightedPixels).
+ */
+ virtual void computeSingleRayWeights(int _iProjectionIndex,
+ int _iDetectorIndex,
+ SPixelWeight* _pWeightedPixels,
+ int _iMaxPixelCount,
+ int& _iStoredPixelCount);
+
+ /** Create a list of detectors that are influenced by point [_iRow, _iCol].
+ *
+ * @param _iRow row of the point
+ * @param _iCol column of the point
+ * @return list of SDetector2D structs
+ */
+ virtual std::vector<SDetector2D> projectPoint(int _iRow, int _iCol);
+
+ /** Policy-based projection of all rays. This function will calculate each non-zero projection
+ * weight and use this value for a task provided by the policy object.
+ *
+ * @param _policy Policy object. Should contain prior, addWeight and posterior function.
+ */
+ template <typename Policy>
+ void project(Policy& _policy);
+
+ /** Policy-based projection of all rays of a single projection. This function will calculate
+ * each non-zero projection weight and use this value for a task provided by the policy object.
+ *
+ * @param _iProjection Wwhich projection should be projected?
+ * @param _policy Policy object. Should contain prior, addWeight and posterior function.
+ */
+ template <typename Policy>
+ void projectSingleProjection(int _iProjection, Policy& _policy);
+
+ /** Policy-based projection of a single ray. This function will calculate each non-zero
+ * projection weight and use this value for a task provided by the policy object.
+ *
+ * @param _iProjection Which projection should be projected?
+ * @param _iDetector Which detector should be projected?
+ * @param _policy Policy object. Should contain prior, addWeight and posterior function.
+ */
+ template <typename Policy>
+ void projectSingleRay(int _iProjection, int _iDetector, Policy& _policy);
+
+ /** Return the type of this projector.
+ *
+ * @return identification type of this projector
+ */
+ virtual std::string getType();
+
+};
+
+//----------------------------------------------------------------------------------------
+
+inline std::string CFanFlatBeamStripKernelProjector2D::getType()
+{
+ return type;
+}
+
+} // namespace astra
+
+
+
+#endif
+
diff --git a/include/astra/FanFlatBeamStripKernelProjector2D.inl b/include/astra/FanFlatBeamStripKernelProjector2D.inl
new file mode 100644
index 0000000..e3f8b29
--- /dev/null
+++ b/include/astra/FanFlatBeamStripKernelProjector2D.inl
@@ -0,0 +1,961 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+
+using namespace astra;
+
+//----------------------------------------------------------------------------------------
+// PROJECT ALL
+template <typename Policy>
+void CFanFlatBeamStripKernelProjector2D::project(Policy& p)
+{
+ ASTRA_ASSERT(m_bIsInitialized);
+
+ // Some variables
+ float32 theta;
+ int row, col;
+ int iAngle, iDetector;
+ float32 res;
+ int x1L, x1R;
+ float32 x2L, x2R;
+ int iVolumeIndex, iRayIndex;
+
+ CFanFlatProjectionGeometry2D* projgeom = static_cast<CFanFlatProjectionGeometry2D*>(m_pProjectionGeometry);
+
+ // Other precalculations
+ float32 PW = m_pVolumeGeometry->getPixelLengthX();
+ float32 PH = m_pVolumeGeometry->getPixelLengthY();
+ float32 DW = m_pProjectionGeometry->getDetectorWidth();
+ float32 inv_PW = 1.0f / PW;
+ float32 inv_PH = 1.0f / PH;
+
+ // calculate alpha's
+ float32 alpha;
+ float32* cos_alpha = new float32[m_pProjectionGeometry->getDetectorCount() + 1];
+ float32* sin_alpha = new float32[m_pProjectionGeometry->getDetectorCount() + 1];
+ for (int i = 0; i < m_pProjectionGeometry->getDetectorCount() + 1; ++i) {
+ alpha = -atan((i - m_pProjectionGeometry->getDetectorCount()*0.5f) * DW / projgeom->getSourceDetectorDistance());
+ cos_alpha[i] = cos(alpha);
+ sin_alpha[i] = sin(alpha);
+ }
+
+ // loop angles
+ for (iAngle = 0; iAngle < m_pProjectionGeometry->getProjectionAngleCount(); ++iAngle) {
+
+ // get values
+ theta = m_pProjectionGeometry->getProjectionAngle(iAngle);
+ bool switch_t = false;
+ if (theta >= 7*PIdiv4) theta -= 2*PI;
+ if (theta >= 3*PIdiv4) {
+ theta -= PI;
+ switch_t = true;
+ }
+
+ // Precalculate sin, cos, 1/cos
+ float32 sin_theta = sin(theta);
+ float32 cos_theta = cos(theta);
+
+ // [-45?,45?] and [135?,225?]
+ if (theta < PIdiv4) {
+
+ // loop detectors
+ for (iDetector = 0; iDetector < m_pProjectionGeometry->getDetectorCount(); ++iDetector) {
+
+ iRayIndex = iAngle * m_pProjectionGeometry->getDetectorCount() + iDetector;
+
+ // POLICY: RAY PRIOR
+ if (!p.rayPrior(iRayIndex)) continue;
+
+ float32 sin_theta_left, cos_theta_left;
+ float32 sin_theta_right, cos_theta_right;
+
+ // get theta_l = alpha_left + theta and theta_r = alpha_right + theta
+ float32 t_l, t_r;
+ if (!switch_t) {
+ sin_theta_left = sin_theta * cos_alpha[iDetector+1] + cos_theta * sin_alpha[iDetector+1];
+ sin_theta_right = sin_theta * cos_alpha[iDetector] + cos_theta * sin_alpha[iDetector];
+
+ cos_theta_left = cos_theta * cos_alpha[iDetector+1] - sin_theta * sin_alpha[iDetector+1];
+ cos_theta_right = cos_theta * cos_alpha[iDetector] - sin_theta * sin_alpha[iDetector];
+
+ t_l = sin_alpha[iDetector+1] * projgeom->getOriginSourceDistance();
+ t_r = sin_alpha[iDetector] * projgeom->getOriginSourceDistance();
+
+ } else {
+ sin_theta_left = sin_theta * cos_alpha[iDetector] + cos_theta * sin_alpha[iDetector];
+ sin_theta_right = sin_theta * cos_alpha[iDetector+1] + cos_theta * sin_alpha[iDetector+1];
+
+ cos_theta_left = cos_theta * cos_alpha[iDetector] - sin_theta * sin_alpha[iDetector];
+ cos_theta_right = cos_theta * cos_alpha[iDetector+1] - sin_theta * sin_alpha[iDetector+1];
+
+ t_l = -sin_alpha[iDetector] * projgeom->getOriginSourceDistance();
+ t_r = -sin_alpha[iDetector+1] * projgeom->getOriginSourceDistance();
+ }
+
+ float32 inv_cos_theta_left = 1.0f / cos_theta_left;
+ float32 inv_cos_theta_right = 1.0f / cos_theta_right;
+
+ float32 updateX_left = sin_theta_left * inv_cos_theta_left;
+ float32 updateX_right = sin_theta_right * inv_cos_theta_right;
+
+ // Precalculate kernel limits
+ float32 S_l = -0.5f * updateX_left;
+ if (S_l > 0) {S_l = -S_l;}
+ float32 T_l = -S_l;
+ float32 U_l = 1.0f + S_l;
+ float32 V_l = 1.0f - S_l;
+ float32 inv_4T_l = 0.25f / T_l;
+
+ float32 S_r = -0.5f * updateX_right;
+ if (S_r > 0) {S_r = -S_r;}
+ float32 T_r = -S_r;
+ float32 U_r = 1.0f + S_r;
+ float32 V_r = 1.0f - S_r;
+ float32 inv_4T_r = 0.25f / T_r;
+
+ // calculate strip extremes (volume coordinates)
+ float32 PL = (t_l - sin_theta_left * m_pVolumeGeometry->pixelRowToCenterY(0)) * inv_cos_theta_left;
+ float32 PR = (t_r - sin_theta_right * m_pVolumeGeometry->pixelRowToCenterY(0)) * inv_cos_theta_right;
+ float32 PLimitL = PL + S_l * PH;
+ float32 PLimitR = PR - S_r * PH;
+
+ // calculate strip extremes (pixel coordinates)
+ float32 XLimitL = (PLimitL - m_pVolumeGeometry->getWindowMinX()) * inv_PW;
+ float32 XLimitR = (PLimitR - m_pVolumeGeometry->getWindowMinX()) * inv_PW;
+ float32 xL = (PL - m_pVolumeGeometry->getWindowMinX()) * inv_PW;
+ float32 xR = (PR - m_pVolumeGeometry->getWindowMinX()) * inv_PW;
+
+ // for each row
+ for (row = 0; row < m_pVolumeGeometry->getGridRowCount(); ++row) {
+
+ // get strip extremes in column indices
+ x1L = int((XLimitL > 0.0f) ? XLimitL : XLimitL-1.0f);
+ x1R = int((XLimitR > 0.0f) ? XLimitR : XLimitR-1.0f);
+
+ // get coords w.r.t leftmost column hit by strip
+ x2L = xL - x1L;
+ x2R = xR - x1L;
+
+ // update strip extremes for the next row
+ XLimitL += updateX_left;
+ XLimitR += updateX_right;
+ xL += updateX_left;
+ xR += updateX_right;
+
+ // for each affected col
+ for (col = x1L; col <= x1R; ++col) {
+
+ if (col < 0 || col >= m_pVolumeGeometry->getGridColCount()) { x2L -= 1.0f; x2R -= 1.0f; continue; }
+
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, col);
+ // POLICY: PIXEL PRIOR
+ if (!p.pixelPrior(iVolumeIndex)) { x2L -= 1.0f; x2R -= 1.0f; continue; }
+
+ // right
+ if (x2R >= V_r) res = 1.0f;
+ else if (x2R > U_r) res = x2R - (x2R-U_r)*(x2R-U_r)*inv_4T_r;
+ else if (x2R >= T_r) res = x2R;
+ else if (x2R > S_r) res = (x2R-S_r)*(x2R-S_r) * inv_4T_r;
+ else { x2L -= 1.0f; x2R -= 1.0f; continue; }
+
+ // left
+ if (x2L <= S_l) {}
+ else if (x2L < T_l) res -= (x2L-S_l)*(x2L-S_l) * inv_4T_l;
+ else if (x2L <= U_l) res -= x2L;
+ else if (x2L < V_l) res -= x2L - (x2L-U_l)*(x2L-U_l)*inv_4T_l;
+ else { x2L -= 1.0f; x2R -= 1.0f; continue; }
+
+ // POLICY: ADD
+ p.addWeight(iRayIndex, iVolumeIndex, PW*PH * res);
+
+ // POLICY: PIXEL POSTERIOR
+ p.pixelPosterior(iVolumeIndex);
+
+ x2L -= 1.0f;
+ x2R -= 1.0f;
+
+ } // end col loop
+
+ } // end row loop
+
+ // POLICY: RAY POSTERIOR
+ p.rayPosterior(iRayIndex);
+
+ } // end detector loop
+
+ // [45?,135?] and [225?,315?]
+ // horizontaly
+ } else {
+
+ // loop detectors
+ for (iDetector = 0; iDetector < m_pProjectionGeometry->getDetectorCount(); ++iDetector) {
+
+ iRayIndex = iAngle * m_pProjectionGeometry->getDetectorCount() + iDetector;
+
+ // POLICY: RAY PRIOR
+ if (!p.rayPrior(iRayIndex)) continue;
+
+ // get theta_l = alpha_left + theta and theta_r = alpha_right + theta
+ float32 sin_theta_left, cos_theta_left;
+ float32 sin_theta_right, cos_theta_right;
+ float32 t_l, t_r;
+ if (!switch_t) {
+ sin_theta_left = sin_theta * cos_alpha[iDetector] + cos_theta * sin_alpha[iDetector];
+ sin_theta_right = sin_theta * cos_alpha[iDetector+1] + cos_theta * sin_alpha[iDetector+1];
+
+ cos_theta_left = cos_theta * cos_alpha[iDetector] - sin_theta * sin_alpha[iDetector];
+ cos_theta_right = cos_theta * cos_alpha[iDetector+1] - sin_theta * sin_alpha[iDetector+1];
+
+ t_l = sin_alpha[iDetector] * projgeom->getOriginSourceDistance();
+ t_r = sin_alpha[iDetector+1] * projgeom->getOriginSourceDistance();
+
+ } else {
+ sin_theta_left = sin_theta * cos_alpha[iDetector+1] + cos_theta * sin_alpha[iDetector+1];
+ sin_theta_right = sin_theta * cos_alpha[iDetector] + cos_theta * sin_alpha[iDetector];
+
+ cos_theta_left = cos_theta * cos_alpha[iDetector+1] - sin_theta * sin_alpha[iDetector+1];
+ cos_theta_right = cos_theta * cos_alpha[iDetector] - sin_theta * sin_alpha[iDetector];
+
+ t_l = -sin_alpha[iDetector+1] * projgeom->getOriginSourceDistance();
+ t_r = -sin_alpha[iDetector] * projgeom->getOriginSourceDistance();
+ }
+
+ float32 inv_sin_theta_left = 1.0f / sin_theta_left;
+ float32 inv_sin_theta_right = 1.0f / sin_theta_right;
+
+ float32 updateX_left = cos_theta_left * inv_sin_theta_left;
+ float32 updateX_right = cos_theta_right * inv_sin_theta_right;
+
+ // Precalculate kernel limits
+ float32 S_l = -0.5f * updateX_left;
+ if (S_l > 0) { S_l = -S_l; }
+ float32 T_l = -S_l;
+ float32 U_l = 1.0f + S_l;
+ float32 V_l = 1.0f - S_l;
+ float32 inv_4T_l = 0.25f / T_l;
+
+ float32 S_r = -0.5f * updateX_right;
+ if (S_r > 0) { S_r = -S_r; }
+ float32 T_r = -S_r;
+ float32 U_r = 1.0f + S_r;
+ float32 V_r = 1.0f - S_r;
+ float32 inv_4T_r = 0.25f / T_r;
+
+ // calculate strip extremes (volume coordinates)
+ float32 PL = (t_l - cos_theta_left * m_pVolumeGeometry->pixelColToCenterX(0)) * inv_sin_theta_left;
+ float32 PR = (t_r - cos_theta_right * m_pVolumeGeometry->pixelColToCenterX(0)) * inv_sin_theta_right;
+ float32 PLimitL = PL - S_l * PW;
+ float32 PLimitR = PR + S_r * PW;
+
+ // calculate strip extremes (pixel coordinates)
+ float32 XLimitL = (m_pVolumeGeometry->getWindowMaxY() - PLimitL) * inv_PH;
+ float32 XLimitR = (m_pVolumeGeometry->getWindowMaxY() - PLimitR) * inv_PH;
+ float32 xL = (m_pVolumeGeometry->getWindowMaxY() - PL) * inv_PH;
+ float32 xR = (m_pVolumeGeometry->getWindowMaxY() - PR) * inv_PH;
+
+ // for each col
+ for (col = 0; col < m_pVolumeGeometry->getGridColCount(); ++col) {
+
+ // get strip extremes in column indices
+ x1L = int((XLimitL > 0.0f) ? XLimitL : XLimitL-1.0f);
+ x1R = int((XLimitR > 0.0f) ? XLimitR : XLimitR-1.0f);
+
+ // get coords w.r.t leftmost column hit by strip
+ x2L = xL - x1L;
+ x2R = xR - x1L;
+
+ // update strip extremes for the next row
+ XLimitL += updateX_left;
+ XLimitR += updateX_right;
+ xL += updateX_left;
+ xR += updateX_right;
+
+ // for each affected row
+ for (row = x1L; row <= x1R; ++row) {
+
+ if (row < 0 || row >= m_pVolumeGeometry->getGridRowCount()) { x2L -= 1.0f; x2R -= 1.0f; continue; }
+
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, col);
+
+ // POLICY: PIXEL PRIOR
+ if (!p.pixelPrior(iVolumeIndex)) { x2L -= 1.0f; x2R -= 1.0f; continue; }
+
+ // right
+ if (x2R >= V_r) res = 1.0f;
+ else if (x2R > U_r) res = x2R - (x2R-U_r)*(x2R-U_r)*inv_4T_r;
+ else if (x2R >= T_r) res = x2R;
+ else if (x2R > S_r) res = (x2R-S_r)*(x2R-S_r) * inv_4T_r;
+ else { x2L -= 1.0f; x2R -= 1.0f; continue; }
+
+ // left
+ if (x2L <= S_l) {}
+ else if (x2L < T_l) res -= (x2L-S_l)*(x2L-S_l) * inv_4T_l;
+ else if (x2L <= U_l) res -= x2L;
+ else if (x2L < V_l) res -= x2L - (x2L-U_l)*(x2L-U_l)*inv_4T_l;
+ else { x2L -= 1.0f; x2R -= 1.0f; continue; }
+
+ // POLICY: ADD
+ p.addWeight(iRayIndex, iVolumeIndex, PW*PH * res);
+
+ // POLICY: PIXEL POSTERIOR
+ p.pixelPosterior(iVolumeIndex);
+
+ x2L -= 1.0f;
+ x2R -= 1.0f;
+
+ } // end col loop
+
+ } // end row loop
+
+ // POLICY: RAY POSTERIOR
+ p.rayPosterior(iRayIndex);
+
+ } // end detector loop
+
+ } // end theta switch
+
+ } // end angle loop
+
+ delete[] cos_alpha;
+ delete[] sin_alpha;
+}
+
+
+//----------------------------------------------------------------------------------------
+// PROJECT SINGLE PROJECTION
+template <typename Policy>
+void CFanFlatBeamStripKernelProjector2D::projectSingleProjection(int _iProjection, Policy& p)
+{
+ ASTRA_ASSERT(m_bIsInitialized);
+
+ // Some variables
+ float32 theta;
+ int row, col;
+ int iDetector;
+ float32 res;
+ int x1L, x1R;
+ float32 x2L, x2R;
+ int iVolumeIndex, iRayIndex;
+
+ CFanFlatProjectionGeometry2D* projgeom = static_cast<CFanFlatProjectionGeometry2D*>(m_pProjectionGeometry);
+
+ // Other precalculations
+ float32 PW = m_pVolumeGeometry->getPixelLengthX();
+ float32 PH = m_pVolumeGeometry->getPixelLengthY();
+ float32 DW = m_pProjectionGeometry->getDetectorWidth();
+ float32 inv_PW = 1.0f / PW;
+ float32 inv_PH = 1.0f / PH;
+
+ // calculate alpha's
+ float32 alpha;
+ float32* cos_alpha = new float32[m_pProjectionGeometry->getDetectorCount() + 1];
+ float32* sin_alpha = new float32[m_pProjectionGeometry->getDetectorCount() + 1];
+ for (int i = 0; i < m_pProjectionGeometry->getDetectorCount() + 1; ++i) {
+ alpha = -atan((i - m_pProjectionGeometry->getDetectorCount()*0.5f) * DW / projgeom->getSourceDetectorDistance());
+ cos_alpha[i] = cos(alpha);
+ sin_alpha[i] = sin(alpha);
+ }
+
+
+ // get values
+ theta = m_pProjectionGeometry->getProjectionAngle(_iProjection);
+ bool switch_t = false;
+ if (theta >= 7*PIdiv4) theta -= 2*PI;
+ if (theta >= 3*PIdiv4) {
+ theta -= PI;
+ switch_t = true;
+ }
+
+ // Precalculate sin, cos, 1/cos
+ float32 sin_theta = sin(theta);
+ float32 cos_theta = cos(theta);
+
+ // [-45?,45?] and [135?,225?]
+ if (theta < PIdiv4) {
+
+ // loop detectors
+ for (iDetector = 0; iDetector < m_pProjectionGeometry->getDetectorCount(); ++iDetector) {
+
+ iRayIndex = _iProjection * m_pProjectionGeometry->getDetectorCount() + iDetector;
+
+ // POLICY: RAY PRIOR
+ if (!p.rayPrior(iRayIndex)) continue;
+
+ float32 sin_theta_left, cos_theta_left;
+ float32 sin_theta_right, cos_theta_right;
+
+ // get theta_l = alpha_left + theta and theta_r = alpha_right + theta
+ float32 t_l, t_r;
+ if (!switch_t) {
+ sin_theta_left = sin_theta * cos_alpha[iDetector+1] + cos_theta * sin_alpha[iDetector+1];
+ sin_theta_right = sin_theta * cos_alpha[iDetector] + cos_theta * sin_alpha[iDetector];
+
+ cos_theta_left = cos_theta * cos_alpha[iDetector+1] - sin_theta * sin_alpha[iDetector+1];
+ cos_theta_right = cos_theta * cos_alpha[iDetector] - sin_theta * sin_alpha[iDetector];
+
+ t_l = sin_alpha[iDetector+1] * projgeom->getOriginSourceDistance();
+ t_r = sin_alpha[iDetector] * projgeom->getOriginSourceDistance();
+
+ } else {
+ sin_theta_left = sin_theta * cos_alpha[iDetector] + cos_theta * sin_alpha[iDetector];
+ sin_theta_right = sin_theta * cos_alpha[iDetector+1] + cos_theta * sin_alpha[iDetector+1];
+
+ cos_theta_left = cos_theta * cos_alpha[iDetector] - sin_theta * sin_alpha[iDetector];
+ cos_theta_right = cos_theta * cos_alpha[iDetector+1] - sin_theta * sin_alpha[iDetector+1];
+
+ t_l = -sin_alpha[iDetector] * projgeom->getOriginSourceDistance();
+ t_r = -sin_alpha[iDetector+1] * projgeom->getOriginSourceDistance();
+ }
+
+ float32 inv_cos_theta_left = 1.0f / cos_theta_left;
+ float32 inv_cos_theta_right = 1.0f / cos_theta_right;
+
+ float32 updateX_left = sin_theta_left * inv_cos_theta_left;
+ float32 updateX_right = sin_theta_right * inv_cos_theta_right;
+
+ // Precalculate kernel limits
+ float32 S_l = -0.5f * updateX_left;
+ if (S_l > 0) {S_l = -S_l;}
+ float32 T_l = -S_l;
+ float32 U_l = 1.0f + S_l;
+ float32 V_l = 1.0f - S_l;
+ float32 inv_4T_l = 0.25f / T_l;
+
+ float32 S_r = -0.5f * updateX_right;
+ if (S_r > 0) {S_r = -S_r;}
+ float32 T_r = -S_r;
+ float32 U_r = 1.0f + S_r;
+ float32 V_r = 1.0f - S_r;
+ float32 inv_4T_r = 0.25f / T_r;
+
+ // calculate strip extremes (volume coordinates)
+ float32 PL = (t_l - sin_theta_left * m_pVolumeGeometry->pixelRowToCenterY(0)) * inv_cos_theta_left;
+ float32 PR = (t_r - sin_theta_right * m_pVolumeGeometry->pixelRowToCenterY(0)) * inv_cos_theta_right;
+ float32 PLimitL = PL + S_l * PH;
+ float32 PLimitR = PR - S_r * PH;
+
+ // calculate strip extremes (pixel coordinates)
+ float32 XLimitL = (PLimitL - m_pVolumeGeometry->getWindowMinX()) * inv_PW;
+ float32 XLimitR = (PLimitR - m_pVolumeGeometry->getWindowMinX()) * inv_PW;
+ float32 xL = (PL - m_pVolumeGeometry->getWindowMinX()) * inv_PW;
+ float32 xR = (PR - m_pVolumeGeometry->getWindowMinX()) * inv_PW;
+
+ // for each row
+ for (row = 0; row < m_pVolumeGeometry->getGridRowCount(); ++row) {
+
+ // get strip extremes in column indices
+ x1L = int((XLimitL > 0.0f) ? XLimitL : XLimitL-1.0f);
+ x1R = int((XLimitR > 0.0f) ? XLimitR : XLimitR-1.0f);
+
+ // get coords w.r.t leftmost column hit by strip
+ x2L = xL - x1L;
+ x2R = xR - x1L;
+
+ // update strip extremes for the next row
+ XLimitL += updateX_left;
+ XLimitR += updateX_right;
+ xL += updateX_left;
+ xR += updateX_right;
+
+ // for each affected col
+ for (col = x1L; col <= x1R; ++col) {
+
+ if (col < 0 || col >= m_pVolumeGeometry->getGridColCount()) { x2L -= 1.0f; x2R -= 1.0f; continue; }
+
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, col);
+ // POLICY: PIXEL PRIOR
+ if (!p.pixelPrior(iVolumeIndex)) { x2L -= 1.0f; x2R -= 1.0f; continue; }
+
+ // right
+ if (x2R >= V_r) res = 1.0f;
+ else if (x2R > U_r) res = x2R - (x2R-U_r)*(x2R-U_r)*inv_4T_r;
+ else if (x2R >= T_r) res = x2R;
+ else if (x2R > S_r) res = (x2R-S_r)*(x2R-S_r) * inv_4T_r;
+ else { x2L -= 1.0f; x2R -= 1.0f; continue; }
+
+ // left
+ if (x2L <= S_l) {}
+ else if (x2L < T_l) res -= (x2L-S_l)*(x2L-S_l) * inv_4T_l;
+ else if (x2L <= U_l) res -= x2L;
+ else if (x2L < V_l) res -= x2L - (x2L-U_l)*(x2L-U_l)*inv_4T_l;
+ else { x2L -= 1.0f; x2R -= 1.0f; continue; }
+
+ // POLICY: ADD
+ p.addWeight(iRayIndex, iVolumeIndex, PW*PH * res);
+
+ // POLICY: PIXEL POSTERIOR
+ p.pixelPosterior(iVolumeIndex);
+
+ x2L -= 1.0f;
+ x2R -= 1.0f;
+
+ } // end col loop
+
+ } // end row loop
+
+ // POLICY: RAY POSTERIOR
+ p.rayPosterior(iRayIndex);
+
+ } // end detector loop
+
+ // [45?,135?] and [225?,315?]
+ // horizontaly
+ } else {
+
+ // loop detectors
+ for (iDetector = 0; iDetector < m_pProjectionGeometry->getDetectorCount(); ++iDetector) {
+
+ iRayIndex = _iProjection * m_pProjectionGeometry->getDetectorCount() + iDetector;
+
+ // POLICY: RAY PRIOR
+ if (!p.rayPrior(iRayIndex)) continue;
+
+ // get theta_l = alpha_left + theta and theta_r = alpha_right + theta
+ float32 sin_theta_left, cos_theta_left;
+ float32 sin_theta_right, cos_theta_right;
+ float32 t_l, t_r;
+ if (!switch_t) {
+ sin_theta_left = sin_theta * cos_alpha[iDetector] + cos_theta * sin_alpha[iDetector];
+ sin_theta_right = sin_theta * cos_alpha[iDetector+1] + cos_theta * sin_alpha[iDetector+1];
+
+ cos_theta_left = cos_theta * cos_alpha[iDetector] - sin_theta * sin_alpha[iDetector];
+ cos_theta_right = cos_theta * cos_alpha[iDetector+1] - sin_theta * sin_alpha[iDetector+1];
+
+ t_l = sin_alpha[iDetector] * projgeom->getOriginSourceDistance();
+ t_r = sin_alpha[iDetector+1] * projgeom->getOriginSourceDistance();
+
+ } else {
+ sin_theta_left = sin_theta * cos_alpha[iDetector+1] + cos_theta * sin_alpha[iDetector+1];
+ sin_theta_right = sin_theta * cos_alpha[iDetector] + cos_theta * sin_alpha[iDetector];
+
+ cos_theta_left = cos_theta * cos_alpha[iDetector+1] - sin_theta * sin_alpha[iDetector+1];
+ cos_theta_right = cos_theta * cos_alpha[iDetector] - sin_theta * sin_alpha[iDetector];
+
+ t_l = -sin_alpha[iDetector+1] * projgeom->getOriginSourceDistance();
+ t_r = -sin_alpha[iDetector] * projgeom->getOriginSourceDistance();
+ }
+
+ float32 inv_sin_theta_left = 1.0f / sin_theta_left;
+ float32 inv_sin_theta_right = 1.0f / sin_theta_right;
+
+ float32 updateX_left = cos_theta_left * inv_sin_theta_left;
+ float32 updateX_right = cos_theta_right * inv_sin_theta_right;
+
+ // Precalculate kernel limits
+ float32 S_l = -0.5f * updateX_left;
+ if (S_l > 0) { S_l = -S_l; }
+ float32 T_l = -S_l;
+ float32 U_l = 1.0f + S_l;
+ float32 V_l = 1.0f - S_l;
+ float32 inv_4T_l = 0.25f / T_l;
+
+ float32 S_r = -0.5f * updateX_right;
+ if (S_r > 0) { S_r = -S_r; }
+ float32 T_r = -S_r;
+ float32 U_r = 1.0f + S_r;
+ float32 V_r = 1.0f - S_r;
+ float32 inv_4T_r = 0.25f / T_r;
+
+ // calculate strip extremes (volume coordinates)
+ float32 PL = (t_l - cos_theta_left * m_pVolumeGeometry->pixelColToCenterX(0)) * inv_sin_theta_left;
+ float32 PR = (t_r - cos_theta_right * m_pVolumeGeometry->pixelColToCenterX(0)) * inv_sin_theta_right;
+ float32 PLimitL = PL - S_l * PW;
+ float32 PLimitR = PR + S_r * PW;
+
+ // calculate strip extremes (pixel coordinates)
+ float32 XLimitL = (m_pVolumeGeometry->getWindowMaxY() - PLimitL) * inv_PH;
+ float32 XLimitR = (m_pVolumeGeometry->getWindowMaxY() - PLimitR) * inv_PH;
+ float32 xL = (m_pVolumeGeometry->getWindowMaxY() - PL) * inv_PH;
+ float32 xR = (m_pVolumeGeometry->getWindowMaxY() - PR) * inv_PH;
+
+ // for each col
+ for (col = 0; col < m_pVolumeGeometry->getGridColCount(); ++col) {
+
+ // get strip extremes in column indices
+ x1L = int((XLimitL > 0.0f) ? XLimitL : XLimitL-1.0f);
+ x1R = int((XLimitR > 0.0f) ? XLimitR : XLimitR-1.0f);
+
+ // get coords w.r.t leftmost column hit by strip
+ x2L = xL - x1L;
+ x2R = xR - x1L;
+
+ // update strip extremes for the next row
+ XLimitL += updateX_left;
+ XLimitR += updateX_right;
+ xL += updateX_left;
+ xR += updateX_right;
+
+ // for each affected row
+ for (row = x1L; row <= x1R; ++row) {
+
+ if (row < 0 || row >= m_pVolumeGeometry->getGridRowCount()) { x2L -= 1.0f; x2R -= 1.0f; continue; }
+
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, col);
+
+ // POLICY: PIXEL PRIOR
+ if (!p.pixelPrior(iVolumeIndex)) { x2L -= 1.0f; x2R -= 1.0f; continue; }
+
+ // right
+ if (x2R >= V_r) res = 1.0f;
+ else if (x2R > U_r) res = x2R - (x2R-U_r)*(x2R-U_r)*inv_4T_r;
+ else if (x2R >= T_r) res = x2R;
+ else if (x2R > S_r) res = (x2R-S_r)*(x2R-S_r) * inv_4T_r;
+ else { x2L -= 1.0f; x2R -= 1.0f; continue; }
+
+ // left
+ if (x2L <= S_l) {}
+ else if (x2L < T_l) res -= (x2L-S_l)*(x2L-S_l) * inv_4T_l;
+ else if (x2L <= U_l) res -= x2L;
+ else if (x2L < V_l) res -= x2L - (x2L-U_l)*(x2L-U_l)*inv_4T_l;
+ else { x2L -= 1.0f; x2R -= 1.0f; continue; }
+
+ // POLICY: ADD
+ p.addWeight(iRayIndex, iVolumeIndex, PW*PH * res);
+
+ // POLICY: PIXEL POSTERIOR
+ p.pixelPosterior(iVolumeIndex);
+
+ x2L -= 1.0f;
+ x2R -= 1.0f;
+
+ } // end col loop
+
+ } // end row loop
+
+ // POLICY: RAY POSTERIOR
+ p.rayPosterior(iRayIndex);
+
+ } // end detector loop
+
+ } // end theta switch
+
+ delete[] cos_alpha;
+ delete[] sin_alpha;
+}
+
+
+//----------------------------------------------------------------------------------------
+// PROJECT SINGLE RAY
+template <typename Policy>
+void CFanFlatBeamStripKernelProjector2D::projectSingleRay(int _iProjection, int _iDetector, Policy& p)
+{
+ ASTRA_ASSERT(m_bIsInitialized);
+
+ // Some variables
+ float32 theta;
+ int row, col;
+ float32 res;
+ int x1L, x1R;
+ float32 x2L, x2R;
+ int iVolumeIndex, iRayIndex;
+
+ CFanFlatProjectionGeometry2D* projgeom = static_cast<CFanFlatProjectionGeometry2D*>(m_pProjectionGeometry);
+
+ // Other precalculations
+ float32 PW = m_pVolumeGeometry->getPixelLengthX();
+ float32 PH = m_pVolumeGeometry->getPixelLengthY();
+ float32 DW = m_pProjectionGeometry->getDetectorWidth();
+ float32 inv_PW = 1.0f / PW;
+ float32 inv_PH = 1.0f / PH;
+
+ // calculate alpha's
+ float32 alpha;
+ float32* cos_alpha = new float32[m_pProjectionGeometry->getDetectorCount() + 1];
+ float32* sin_alpha = new float32[m_pProjectionGeometry->getDetectorCount() + 1];
+ for (int i = 0; i < m_pProjectionGeometry->getDetectorCount() + 1; ++i) {
+ alpha = -atan((i - m_pProjectionGeometry->getDetectorCount()*0.5f) * DW / projgeom->getSourceDetectorDistance());
+ cos_alpha[i] = cos(alpha);
+ sin_alpha[i] = sin(alpha);
+ }
+
+
+ // get values
+ theta = m_pProjectionGeometry->getProjectionAngle(_iProjection);
+ bool switch_t = false;
+ if (theta >= 7*PIdiv4) theta -= 2*PI;
+ if (theta >= 3*PIdiv4) {
+ theta -= PI;
+ switch_t = true;
+ }
+
+ // Precalculate sin, cos, 1/cos
+ float32 sin_theta = sin(theta);
+ float32 cos_theta = cos(theta);
+
+ // [-45?,45?] and [135?,225?]
+ if (theta < PIdiv4) {
+
+ iRayIndex = _iProjection * m_pProjectionGeometry->getDetectorCount() + _iDetector;
+
+ // POLICY: RAY PRIOR
+ if (!p.rayPrior(iRayIndex)) { delete[] cos_alpha; delete[] sin_alpha; return; }
+
+ float32 sin_theta_left, cos_theta_left;
+ float32 sin_theta_right, cos_theta_right;
+
+ // get theta_l = alpha_left + theta and theta_r = alpha_right + theta
+ float32 t_l, t_r;
+ if (!switch_t) {
+ sin_theta_left = sin_theta * cos_alpha[_iDetector+1] + cos_theta * sin_alpha[_iDetector+1];
+ sin_theta_right = sin_theta * cos_alpha[_iDetector] + cos_theta * sin_alpha[_iDetector];
+
+ cos_theta_left = cos_theta * cos_alpha[_iDetector+1] - sin_theta * sin_alpha[_iDetector+1];
+ cos_theta_right = cos_theta * cos_alpha[_iDetector] - sin_theta * sin_alpha[_iDetector];
+
+ t_l = sin_alpha[_iDetector+1] * projgeom->getOriginSourceDistance();
+ t_r = sin_alpha[_iDetector] * projgeom->getOriginSourceDistance();
+
+ } else {
+ sin_theta_left = sin_theta * cos_alpha[_iDetector] + cos_theta * sin_alpha[_iDetector];
+ sin_theta_right = sin_theta * cos_alpha[_iDetector+1] + cos_theta * sin_alpha[_iDetector+1];
+
+ cos_theta_left = cos_theta * cos_alpha[_iDetector] - sin_theta * sin_alpha[_iDetector];
+ cos_theta_right = cos_theta * cos_alpha[_iDetector+1] - sin_theta * sin_alpha[_iDetector+1];
+
+ t_l = -sin_alpha[_iDetector] * projgeom->getOriginSourceDistance();
+ t_r = -sin_alpha[_iDetector+1] * projgeom->getOriginSourceDistance();
+ }
+
+ float32 inv_cos_theta_left = 1.0f / cos_theta_left;
+ float32 inv_cos_theta_right = 1.0f / cos_theta_right;
+
+ float32 updateX_left = sin_theta_left * inv_cos_theta_left;
+ float32 updateX_right = sin_theta_right * inv_cos_theta_right;
+
+ // Precalculate kernel limits
+ float32 S_l = -0.5f * updateX_left;
+ if (S_l > 0) {S_l = -S_l;}
+ float32 T_l = -S_l;
+ float32 U_l = 1.0f + S_l;
+ float32 V_l = 1.0f - S_l;
+ float32 inv_4T_l = 0.25f / T_l;
+
+ float32 S_r = -0.5f * updateX_right;
+ if (S_r > 0) {S_r = -S_r;}
+ float32 T_r = -S_r;
+ float32 U_r = 1.0f + S_r;
+ float32 V_r = 1.0f - S_r;
+ float32 inv_4T_r = 0.25f / T_r;
+
+ // calculate strip extremes (volume coordinates)
+ float32 PL = (t_l - sin_theta_left * m_pVolumeGeometry->pixelRowToCenterY(0)) * inv_cos_theta_left;
+ float32 PR = (t_r - sin_theta_right * m_pVolumeGeometry->pixelRowToCenterY(0)) * inv_cos_theta_right;
+ float32 PLimitL = PL + S_l * PH;
+ float32 PLimitR = PR - S_r * PH;
+
+ // calculate strip extremes (pixel coordinates)
+ float32 XLimitL = (PLimitL - m_pVolumeGeometry->getWindowMinX()) * inv_PW;
+ float32 XLimitR = (PLimitR - m_pVolumeGeometry->getWindowMinX()) * inv_PW;
+ float32 xL = (PL - m_pVolumeGeometry->getWindowMinX()) * inv_PW;
+ float32 xR = (PR - m_pVolumeGeometry->getWindowMinX()) * inv_PW;
+
+ // for each row
+ for (row = 0; row < m_pVolumeGeometry->getGridRowCount(); ++row) {
+
+ // get strip extremes in column indices
+ x1L = int((XLimitL > 0.0f) ? XLimitL : XLimitL-1.0f);
+ x1R = int((XLimitR > 0.0f) ? XLimitR : XLimitR-1.0f);
+
+ // get coords w.r.t leftmost column hit by strip
+ x2L = xL - x1L;
+ x2R = xR - x1L;
+
+ // update strip extremes for the next row
+ XLimitL += updateX_left;
+ XLimitR += updateX_right;
+ xL += updateX_left;
+ xR += updateX_right;
+
+ // for each affected col
+ for (col = x1L; col <= x1R; ++col) {
+
+ if (col < 0 || col >= m_pVolumeGeometry->getGridColCount()) { x2L -= 1.0f; x2R -= 1.0f; continue; }
+
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, col);
+ // POLICY: PIXEL PRIOR
+ if (!p.pixelPrior(iVolumeIndex)) { x2L -= 1.0f; x2R -= 1.0f; continue; }
+
+ // right
+ if (x2R >= V_r) res = 1.0f;
+ else if (x2R > U_r) res = x2R - (x2R-U_r)*(x2R-U_r)*inv_4T_r;
+ else if (x2R >= T_r) res = x2R;
+ else if (x2R > S_r) res = (x2R-S_r)*(x2R-S_r) * inv_4T_r;
+ else { x2L -= 1.0f; x2R -= 1.0f; continue; }
+
+ // left
+ if (x2L <= S_l) {}
+ else if (x2L < T_l) res -= (x2L-S_l)*(x2L-S_l) * inv_4T_l;
+ else if (x2L <= U_l) res -= x2L;
+ else if (x2L < V_l) res -= x2L - (x2L-U_l)*(x2L-U_l)*inv_4T_l;
+ else { x2L -= 1.0f; x2R -= 1.0f; continue; }
+
+ // POLICY: ADD
+ p.addWeight(iRayIndex, iVolumeIndex, PW*PH * res);
+
+ // POLICY: PIXEL POSTERIOR
+ p.pixelPosterior(iVolumeIndex);
+
+ x2L -= 1.0f;
+ x2R -= 1.0f;
+
+ } // end col loop
+
+ } // end row loop
+
+ // POLICY: RAY POSTERIOR
+ p.rayPosterior(iRayIndex);
+
+ // [45?,135?] and [225?,315?]
+ // horizontaly
+ } else {
+
+ iRayIndex = _iProjection * m_pProjectionGeometry->getDetectorCount() + _iDetector;
+
+ // POLICY: RAY PRIOR
+ if (!p.rayPrior(iRayIndex)) { delete[] cos_alpha; delete[] sin_alpha; return; }
+
+ // get theta_l = alpha_left + theta and theta_r = alpha_right + theta
+ float32 sin_theta_left, cos_theta_left;
+ float32 sin_theta_right, cos_theta_right;
+ float32 t_l, t_r;
+ if (!switch_t) {
+ sin_theta_left = sin_theta * cos_alpha[_iDetector] + cos_theta * sin_alpha[_iDetector];
+ sin_theta_right = sin_theta * cos_alpha[_iDetector+1] + cos_theta * sin_alpha[_iDetector+1];
+
+ cos_theta_left = cos_theta * cos_alpha[_iDetector] - sin_theta * sin_alpha[_iDetector];
+ cos_theta_right = cos_theta * cos_alpha[_iDetector+1] - sin_theta * sin_alpha[_iDetector+1];
+
+ t_l = sin_alpha[_iDetector] * projgeom->getOriginSourceDistance();
+ t_r = sin_alpha[_iDetector+1] * projgeom->getOriginSourceDistance();
+
+ } else {
+ sin_theta_left = sin_theta * cos_alpha[_iDetector+1] + cos_theta * sin_alpha[_iDetector+1];
+ sin_theta_right = sin_theta * cos_alpha[_iDetector] + cos_theta * sin_alpha[_iDetector];
+
+ cos_theta_left = cos_theta * cos_alpha[_iDetector+1] - sin_theta * sin_alpha[_iDetector+1];
+ cos_theta_right = cos_theta * cos_alpha[_iDetector] - sin_theta * sin_alpha[_iDetector];
+
+ t_l = -sin_alpha[_iDetector+1] * projgeom->getOriginSourceDistance();
+ t_r = -sin_alpha[_iDetector] * projgeom->getOriginSourceDistance();
+ }
+
+ float32 inv_sin_theta_left = 1.0f / sin_theta_left;
+ float32 inv_sin_theta_right = 1.0f / sin_theta_right;
+
+ float32 updateX_left = cos_theta_left * inv_sin_theta_left;
+ float32 updateX_right = cos_theta_right * inv_sin_theta_right;
+
+ // Precalculate kernel limits
+ float32 S_l = -0.5f * updateX_left;
+ if (S_l > 0) { S_l = -S_l; }
+ float32 T_l = -S_l;
+ float32 U_l = 1.0f + S_l;
+ float32 V_l = 1.0f - S_l;
+ float32 inv_4T_l = 0.25f / T_l;
+
+ float32 S_r = -0.5f * updateX_right;
+ if (S_r > 0) { S_r = -S_r; }
+ float32 T_r = -S_r;
+ float32 U_r = 1.0f + S_r;
+ float32 V_r = 1.0f - S_r;
+ float32 inv_4T_r = 0.25f / T_r;
+
+ // calculate strip extremes (volume coordinates)
+ float32 PL = (t_l - cos_theta_left * m_pVolumeGeometry->pixelColToCenterX(0)) * inv_sin_theta_left;
+ float32 PR = (t_r - cos_theta_right * m_pVolumeGeometry->pixelColToCenterX(0)) * inv_sin_theta_right;
+ float32 PLimitL = PL - S_l * PW;
+ float32 PLimitR = PR + S_r * PW;
+
+ // calculate strip extremes (pixel coordinates)
+ float32 XLimitL = (m_pVolumeGeometry->getWindowMaxY() - PLimitL) * inv_PH;
+ float32 XLimitR = (m_pVolumeGeometry->getWindowMaxY() - PLimitR) * inv_PH;
+ float32 xL = (m_pVolumeGeometry->getWindowMaxY() - PL) * inv_PH;
+ float32 xR = (m_pVolumeGeometry->getWindowMaxY() - PR) * inv_PH;
+
+ // for each col
+ for (col = 0; col < m_pVolumeGeometry->getGridColCount(); ++col) {
+
+ // get strip extremes in column indices
+ x1L = int((XLimitL > 0.0f) ? XLimitL : XLimitL-1.0f);
+ x1R = int((XLimitR > 0.0f) ? XLimitR : XLimitR-1.0f);
+
+ // get coords w.r.t leftmost column hit by strip
+ x2L = xL - x1L;
+ x2R = xR - x1L;
+
+ // update strip extremes for the next row
+ XLimitL += updateX_left;
+ XLimitR += updateX_right;
+ xL += updateX_left;
+ xR += updateX_right;
+
+ // for each affected row
+ for (row = x1L; row <= x1R; ++row) {
+
+ if (row < 0 || row >= m_pVolumeGeometry->getGridRowCount()) { x2L -= 1.0f; x2R -= 1.0f; continue; }
+
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, col);
+
+ // POLICY: PIXEL PRIOR
+ if (!p.pixelPrior(iVolumeIndex)) { x2L -= 1.0f; x2R -= 1.0f; continue; }
+
+ // right
+ if (x2R >= V_r) res = 1.0f;
+ else if (x2R > U_r) res = x2R - (x2R-U_r)*(x2R-U_r)*inv_4T_r;
+ else if (x2R >= T_r) res = x2R;
+ else if (x2R > S_r) res = (x2R-S_r)*(x2R-S_r) * inv_4T_r;
+ else { x2L -= 1.0f; x2R -= 1.0f; continue; }
+
+ // left
+ if (x2L <= S_l) {}
+ else if (x2L < T_l) res -= (x2L-S_l)*(x2L-S_l) * inv_4T_l;
+ else if (x2L <= U_l) res -= x2L;
+ else if (x2L < V_l) res -= x2L - (x2L-U_l)*(x2L-U_l)*inv_4T_l;
+ else { x2L -= 1.0f; x2R -= 1.0f; continue; }
+
+ // POLICY: ADD
+ p.addWeight(iRayIndex, iVolumeIndex, PW*PH * res);
+
+ // POLICY: PIXEL POSTERIOR
+ p.pixelPosterior(iVolumeIndex);
+
+ x2L -= 1.0f;
+ x2R -= 1.0f;
+
+ } // end col loop
+
+ } // end row loop
+
+ // POLICY: RAY POSTERIOR
+ p.rayPosterior(iRayIndex);
+
+ } // end theta switch
+
+ delete[] cos_alpha;
+ delete[] sin_alpha;
+}
diff --git a/include/astra/FanFlatProjectionGeometry2D.h b/include/astra/FanFlatProjectionGeometry2D.h
new file mode 100644
index 0000000..0e790ae
--- /dev/null
+++ b/include/astra/FanFlatProjectionGeometry2D.h
@@ -0,0 +1,244 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_FANFLATPROJECTIONGEOMETRY2D
+#define _INC_ASTRA_FANFLATPROJECTIONGEOMETRY2D
+
+#include "ProjectionGeometry2D.h"
+
+#include <cmath>
+
+namespace astra
+{
+
+/**
+ * This class defines a 2D fan beam geometry with a flat detector that has equally spaced detector cells.
+ *
+ * \par XML Configuration
+ * \astra_xml_item{DetectorCount, int, Number of detectors for each projection.}
+ * \astra_xml_item{DetectorWidth, float, Width of each detector.}
+ * \astra_xml_item{ProjectionAngles, vector of float, projection angles in radians.}
+ * \astra_xml_item{DistanceOriginDetector, float, Distance between the center of rotation and the detectorarray.}
+ * \astra_xml_item{DistanceOriginSource, float, Distance between the center of rotation the the x-ray source.}
+ *
+ * \par MATLAB example
+ * \astra_code{
+ * proj_geom = astra_struct('fanflat');\n
+ * proj_geom.DetectorCount = 512;\n
+ * proj_geom.DetectorWidth = 1.0;\n
+ * proj_geom.ProjectionAngles = linspace(0,pi,100);\n
+ * proj_geom.DistanceOriginDetector = 300;\n
+ * proj_geom.DistanceOriginSource = 300;\n
+ * }
+ */
+class _AstraExport CFanFlatProjectionGeometry2D : public CProjectionGeometry2D
+{
+ /**
+ * Distance from the origin of the coordinate system to the source.
+ */
+ float32 m_fOriginSourceDistance;
+
+ /**
+ * Distance from the origin of the coordinate system to the detector (i.e., the distance between the origin and its orthogonal projection
+ * onto the detector array).
+ */
+ float32 m_fOriginDetectorDistance;
+
+public:
+
+ /** Default constructor. Sets all variables to zero. Note that this constructor leaves the object in an unusable state and must
+ * be followed by a call to init().
+ */
+ CFanFlatProjectionGeometry2D();
+
+ /** Constructor.
+ *
+ * @param _iProjectionAngleCount Number of projection angles.
+ * @param _iDetectorCount Number of detectors, i.e., the number of detector measurements for each projection angle.
+ * @param _fDetectorWidth Width of a detector cell, in unit lengths. All detector cells are assumed to have equal width.
+ * @param _pfProjectionAngles Pointer to an array of projection angles. The angles will be copied from this array.
+ * All angles are represented in radians.
+ * @param _fOriginSourceDistance Distance from the origin of the coordinate system to the source
+ * @param _fOriginDetectorDistance Distance from the origin of the coordinate system to the detector
+ */
+ CFanFlatProjectionGeometry2D(int _iProjectionAngleCount,
+ int _iDetectorCount,
+ float32 _fDetectorWidth,
+ const float32* _pfProjectionAngles,
+ float32 _fOriginSourceDistance,
+ float32 _fOriginDetectorDistance);
+
+ /** Copy constructor.
+ */
+ CFanFlatProjectionGeometry2D(const CFanFlatProjectionGeometry2D& _projGeom);
+
+ /** Assignment operator.
+ */
+ CFanFlatProjectionGeometry2D& operator=(const CFanFlatProjectionGeometry2D& _other);
+
+ /** Destructor.
+ */
+ virtual ~CFanFlatProjectionGeometry2D();
+
+ /** Initialize the geometry with a config object.
+ *
+ * @param _cfg Configuration Object
+ * @return initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ /** Initialization. This function MUST be called after using the default constructor and MAY be called to
+ * reset a previously initialized object.
+ *
+ * @param _iProjectionAngleCount Number of projection angles.
+ * @param _iDetectorCount Number of detectors, i.e., the number of detector measurements for each projection angle.
+ * @param _fDetectorWidth Width of a detector cell, in unit lengths. All detector cells are assumed to have equal width.
+ * @param _pfProjectionAngles Pointer to an array of projection angles. The angles will be copied from this array.
+ * @param _fOriginSourceDistance Distance from the origin of the coordinate system to the source
+ * @param _fOriginDetectorDistance Distance from the origin of the coordinate system to the detector
+ */
+ bool initialize(int _iProjectionAngleCount,
+ int _iDetectorCount,
+ float32 _fDetectorWidth,
+ const float32* _pfProjectionAngles,
+ float32 _fOriginSourceDistance,
+ float32 _fOriginDetectorDistance);
+
+ /** Create a hard copy.
+ */
+ virtual CProjectionGeometry2D* clone();
+
+ /** Returns true if the type of geometry defined in this class is the one specified in _sType.
+ *
+ * @param _sType geometry type to compare to.
+ * @return true if _sType == "fanflat".
+ */
+ virtual bool isOfType(const std::string& _sType);
+
+ /** Return true if this geometry instance is the same as the one specified.
+ *
+ * @return true if this geometry instance is the same as the one specified.
+ */
+ virtual bool isEqual(CProjectionGeometry2D*) const;
+
+ /** Returns the distance from the origin of the coordinate system to the source.
+ *
+ * @return Distance from the origin of the coordinate system to the source
+ */
+ float32 getOriginSourceDistance() const;
+
+ /** Returns the distance from the origin of the coordinate system to the detector
+ * (i.e., the distance between the origin and its orthogonal projection onto the detector array).
+ *
+ * @return Distance from the origin of the coordinate system to the detector
+ */
+ float32 getOriginDetectorDistance() const;
+
+ /** Returns the distance from the source to the detector
+ * (i.e., the distance between the source and its orthogonal projection onto the detector array).
+ *
+ * @return Distance from the source to the detector
+ */
+ float32 getSourceDetectorDistance() const;
+
+ /** Get the value for t and theta, based upon the row and column index.
+ *
+ * @param _iRow row index
+ * @param _iColumn column index
+ * @param _fT output: value of t
+ * @param _fTheta output: value of theta, always lies within the [0,pi[ interval.
+ */
+ virtual void getRayParams(int _iRow, int _iColumn, float32& _fT, float32& _fTheta) const;
+
+ /**
+ * Returns a vector describing the direction of a ray belonging to a certain detector
+ *
+ * @param _iProjectionIndex index of projection
+ * @param _iProjectionIndex index of detector
+ *
+ * @return a unit vector describing the direction
+ */
+ virtual CVector3D getProjectionDirection(int _iProjectionIndex, int _iDetectorIndex);
+};
+
+
+
+// Returns the distance from the origin of the coordinate system to the source.
+inline float32 CFanFlatProjectionGeometry2D::getOriginSourceDistance() const
+{
+ return m_fOriginSourceDistance;
+}
+
+
+// Returns the distance from the origin of the coordinate system to the detector.
+inline float32 CFanFlatProjectionGeometry2D::getOriginDetectorDistance() const
+{
+ return m_fOriginDetectorDistance;
+}
+
+
+// Returns the distance from the source to the detector.
+inline float32 CFanFlatProjectionGeometry2D::getSourceDetectorDistance() const
+{
+ return (m_fOriginSourceDistance + m_fOriginDetectorDistance);
+}
+
+
+// Get T and Theta
+inline void CFanFlatProjectionGeometry2D::getRayParams(int _iRow, int _iColumn, float32& _fT, float32& _fTheta) const
+{
+ assert(m_bInitialized);
+
+ // get the distance between the center of the detector array and the detector.
+ float32 det_offset = indexToDetectorOffset(_iColumn);
+
+ // get the angle between the center ray of the projection and the projection.
+ float32 alpha = atan(det_offset / getSourceDetectorDistance());
+
+ // calculate t and theta
+ _fT = m_fOriginSourceDistance * sin(alpha);
+ _fTheta = getProjectionAngle(_iRow) + alpha;
+
+ // if theta is larger than pi, flip of the origin
+ if (PI <= _fTheta) {
+ _fTheta -= PI;
+ _fT = -_fT;
+ }
+ // if theta is below 0, flip
+ if (_fTheta < 0) {
+ _fTheta += PI;
+ _fT = -_fT;
+ }
+}
+
+
+
+} // namespace astra
+
+#endif /* _INC_ASTRA_FANFLATPROJECTIONGEOMETRY2D */
+
diff --git a/include/astra/FanFlatVecProjectionGeometry2D.h b/include/astra/FanFlatVecProjectionGeometry2D.h
new file mode 100644
index 0000000..d370b24
--- /dev/null
+++ b/include/astra/FanFlatVecProjectionGeometry2D.h
@@ -0,0 +1,155 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_FANFLATVECPROJECTIONGEOMETRY2D
+#define _INC_ASTRA_FANFLATVECPROJECTIONGEOMETRY2D
+
+#include "ProjectionGeometry2D.h"
+#include "../cuda/2d/dims.h"
+
+#include <cmath>
+
+// FIXME: Avoid using
+using astraCUDA::SFanProjection;
+
+namespace astra
+{
+
+/**
+ * This class defines a 2D fan beam geometry.
+ *
+ * \par XML Configuration
+ * \astra_xml_item{DetectorCount, int, Number of detectors for each projection.}
+ * \astra_xml_item{Vectors, matrix defining the 2D position of source and detector.}
+ *
+ * \par MATLAB example
+ * \astra_code{
+ * proj_geom = astra_struct('fanflat_vec');\n
+ * proj_geom.DetectorCount = 512;\n
+ * proj_geom.Vectors = V;\n
+ * }
+ */
+class _AstraExport CFanFlatVecProjectionGeometry2D : public CProjectionGeometry2D
+{
+protected:
+
+ SFanProjection *m_pProjectionAngles;
+
+public:
+
+ /** Default constructor. Sets all variables to zero. Note that this constructor leaves the object in an unusable state and must
+ * be followed by a call to init().
+ */
+ CFanFlatVecProjectionGeometry2D();
+
+ /** Constructor.
+ *
+ * @param _iProjectionAngleCount Number of projection angles.
+ * @param _iDetectorCount Number of detectors, i.e., the number of detector measurements for each projection angle.
+ * @param _pfProjectionAngles Pointer to an array of projection angles. The angles will be copied from this array.
+ */
+ CFanFlatVecProjectionGeometry2D(int _iProjectionAngleCount,
+ int _iDetectorCount,
+ const SFanProjection* _pfProjectionAngles);
+
+ /** Copy constructor.
+ */
+ CFanFlatVecProjectionGeometry2D(const CFanFlatVecProjectionGeometry2D& _projGeom);
+
+ /** Assignment operator.
+ */
+ CFanFlatVecProjectionGeometry2D& operator=(const CFanFlatVecProjectionGeometry2D& _other);
+
+ /** Destructor.
+ */
+ virtual ~CFanFlatVecProjectionGeometry2D();
+
+ /** Initialize the geometry with a config object.
+ *
+ * @param _cfg Configuration Object
+ * @return initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ /** Initialization. This function MUST be called after using the default constructor and MAY be called to
+ * reset a previously initialized object.
+ *
+ * @param _iProjectionAngleCount Number of projection angles.
+ * @param _iDetectorCount Number of detectors, i.e., the number of detector measurements for each projection angle.
+ * @param _pfProjectionAngles Pointer to an array of projection angles. The angles will be copied from this array.
+ */
+ bool initialize(int _iProjectionAngleCount,
+ int _iDetectorCount,
+ const SFanProjection* _pfProjectionAngles);
+
+ virtual bool _check();
+
+ /** Create a hard copy.
+ */
+ virtual CProjectionGeometry2D* clone();
+
+ /** Returns true if the type of geometry defined in this class is the one specified in _sType.
+ *
+ * @param _sType geometry type to compare to.
+ * @return true if _sType == "fanflat_vec".
+ */
+ virtual bool isOfType(const std::string& _sType);
+
+ /** Return true if this geometry instance is the same as the one specified.
+ *
+ * @return true if this geometry instance is the same as the one specified.
+ */
+ virtual bool isEqual(CProjectionGeometry2D*) const;
+
+ /** Get the value for t and theta, based upon the row and column index.
+ *
+ * @param _iRow row index
+ * @param _iColumn column index
+ * @param _fT output: value of t
+ * @param _fTheta output: value of theta, always lies within the [0,pi[ interval.
+ */
+ virtual void getRayParams(int _iRow, int _iColumn, float32& _fT, float32& _fTheta) const;
+
+ /**
+ * Returns a vector describing the direction of a ray belonging to a certain detector
+ *
+ * @param _iProjectionIndex index of projection
+ * @param _iProjectionIndex index of detector
+ *
+ * @return a unit vector describing the direction
+ */
+ virtual CVector3D getProjectionDirection(int _iProjectionIndex, int _iDetectorIndex);
+
+ const SFanProjection* getProjectionVectors() const { return m_pProjectionAngles; }
+};
+
+
+} // namespace astra
+
+#endif /* _INC_ASTRA_FANFLATVECPROJECTIONGEOMETRY2D */
+
diff --git a/include/astra/FilteredBackProjectionAlgorithm.h b/include/astra/FilteredBackProjectionAlgorithm.h
new file mode 100644
index 0000000..cda7962
--- /dev/null
+++ b/include/astra/FilteredBackProjectionAlgorithm.h
@@ -0,0 +1,155 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_FILTEREDBACKPROJECTION
+#define _INC_ASTRA_FILTEREDBACKPROJECTION
+
+#include "ReconstructionAlgorithm2D.h"
+
+#include "Globals.h"
+
+#include "Projector2D.h"
+#include "Float32ProjectionData2D.h"
+#include "Float32VolumeData2D.h"
+
+
+namespace astra {
+
+/**
+ * \brief
+ * This class contains the implementation of the filtered back projection (FBP)
+ * reconstruction algorithm.
+ *
+ * \par XML Configuration
+ * \astra_xml_item{ProjectorId, integer, Identifier of a projector as it is stored in the ProjectorManager.}
+ * \astra_xml_item{VolumeDataId, integer, Identifier of the volume data object as it is stored in the DataManager.}
+ * \astra_xml_item{ReconstructionDataId, integer, Identifier of the resulting projection data object as it is stored in the DataManager.}
+ * \astra_xml_item_option{ProjectionIndex, integer, 0, Only reconstruct this specific projection angle. }
+
+ * \par MATLAB example
+ * \astra_code{
+ * cfg = astra_struct('FP');\n
+ * cfg.ProjectorId = proj_id;\n
+ * cfg.ReconstructionDataId = vol_id;\n
+ * cfg.ProjectionDataId = sino_id;\n
+ * alg_id = astra_mex_algorithm('create'\, cfg);\n
+ * astra_mex_algorithm('run'\, alg_id);\n
+ * astra_mex_algorithm('delete'\, alg_id);\n
+ * }
+ *
+ */
+class _AstraExport CFilteredBackProjectionAlgorithm : public CReconstructionAlgorithm2D {
+
+protected:
+
+ /** Initial clearing. Only to be used by constructors.
+ */
+ virtual void _clear();
+
+ /** Check the values of this object. If everything is ok, the object can be set to the initialized state.
+ * The following statements are then guaranteed to hold:
+ * - valid projector
+ * - valid data objects
+ * - projection order all within range
+ */
+ virtual bool _check();
+
+public:
+
+ // type of the algorithm, needed to register with CAlgorithmFactory
+ static std::string type;
+
+ /** Default constructor, containing no code.
+ */
+ CFilteredBackProjectionAlgorithm();
+
+ /** Destructor.
+ */
+ virtual ~CFilteredBackProjectionAlgorithm();
+
+ /** Initialize class.
+ *
+ * @param _pProjector Projector to use.
+ * @param _pSinogram ProjectionData2D object containing the sinogram data.
+ * @param _pReconstruction VolumeData2D object for storing the reconstructed volume.
+ * @return success
+ */
+ bool initialize(CProjector2D* _pProjector,
+ CFloat32VolumeData2D* _pReconstruction,
+ CFloat32ProjectionData2D* _pSinogram);
+
+ /** Initialize the algorithm with a config object.
+ *
+ * @param _cfg Configuration Object
+ * @return initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ /** Clear this class.
+ */
+ virtual void clear();
+
+ /** Get all information parameters
+ *
+ * @return map with all boost::any object
+ */
+ virtual map<string,boost::any> getInformation();
+
+ /** Get a single piece of information represented as a boost::any
+ *
+ * @param _sIdentifier identifier string to specify which piece of information you want
+ * @return boost::any object
+ */
+ virtual boost::any getInformation(std::string _sIdentifier);
+
+ /** Perform a number of iterations.
+ *
+ * @param _iNrIterations amount of iterations to perform.
+ */
+ virtual void run(int _iNrIterations = 0);
+
+ /** Performs the filtering of the projection data.
+ *
+ * @param _pFilteredSinogram will contain filtered sinogram afterwards
+ */
+ void performFiltering(CFloat32ProjectionData2D * _pFilteredSinogram);
+
+ /** Get a description of the class.
+ *
+ * @return description string
+ */
+ virtual std::string description() const;
+
+};
+
+// inline functions
+inline std::string CFilteredBackProjectionAlgorithm::description() const { return CFilteredBackProjectionAlgorithm::type; };
+
+} // end namespace
+
+#endif
diff --git a/include/astra/Float32Data.h b/include/astra/Float32Data.h
new file mode 100644
index 0000000..99bbaf3
--- /dev/null
+++ b/include/astra/Float32Data.h
@@ -0,0 +1,88 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_FLOAT32DATA
+#define _INC_ASTRA_FLOAT32DATA
+
+#include "Globals.h"
+
+namespace astra {
+
+/**
+ * This is a virtual base class for floating point data classes.
+ */
+class _AstraExport CFloat32Data {
+
+protected:
+
+ // Protected Member Variables
+ bool m_bInitialized; ///< has the object been initialized?
+ int m_iDimensions; ///< the number of dimensions
+
+public:
+
+ /**
+ * Default constructor.
+ */
+ CFloat32Data();
+
+ /**
+ * Destructor. Free allocated memory
+ */
+ virtual ~CFloat32Data();
+
+ /**
+ * Get the initialization state of the object.
+ *
+ * @return true iff the object has been initialized
+ */
+ bool isInitialized() const;
+
+ /**
+ * Get the number of dimensions of this object.
+ *
+ * @return number of dimensions
+ */
+ virtual int getDimensionCount() const = 0;
+
+};
+
+//----------------------------------------------------------------------------------------
+// Inline member functions
+//----------------------------------------------------------------------------------------
+
+// Get the initialization state of the object.
+inline bool CFloat32Data::isInitialized() const
+{
+ return m_bInitialized;
+}
+//----------------------------------------------------------------------------------------
+
+} // end namespace
+
+#endif
diff --git a/include/astra/Float32Data2D.h b/include/astra/Float32Data2D.h
new file mode 100644
index 0000000..c89e9f8
--- /dev/null
+++ b/include/astra/Float32Data2D.h
@@ -0,0 +1,544 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_FLOAT32DATA2D
+#define _INC_ASTRA_FLOAT32DATA2D
+
+#include "Globals.h"
+#include "Float32Data.h"
+
+#include <sstream>
+
+namespace astra {
+
+/**
+ * This class represents a two-dimensional block of float32ing point data.
+ * It contains member functions for accessing this data and for performing
+ * elementary computations on the data.
+ * The data block is "owned" by the class, meaning that the class is
+ * responsible for deallocation of the memory involved.
+ */
+class _AstraExport CFloat32Data2D : public CFloat32Data {
+
+protected:
+
+ int m_iWidth; ///< width of the data (x)
+ int m_iHeight; ///< height of the data (y)
+ int m_iSize; ///< total size of the data
+
+ /** Pointer to the data block, represented as a 1-dimensional array.
+ * Note that the data memory is "owned" by this class, meaning that the
+ * class is responsible for deallocation of the memory involved.
+ * To access element (ix, iy) internally, use
+ * m_pData[iy * m_iWidth + ix]
+ */
+ float32* m_pfData;
+
+ /** Array of float32 pointers, each pointing to a single horizontal
+ * line in the m_pfData memory block.
+ * To access element (ix, iy) internally, use m_ppfData2D[iy][ix]
+ */
+ float32** m_ppfData2D;
+
+ float32 m_fGlobalMin; ///< minimum value of the data
+ float32 m_fGlobalMax; ///< maximum value of the data
+ float32 m_fGlobalMean; ///< mean value of the data
+
+ /** Allocate memory for m_pfData and m_ppfData2D arrays.
+ *
+ * The allocated block consists of m_iSize float32s. The block is
+ * not cleared after allocation and its contents is undefined.
+ * This function may NOT be called if memory has already been allocated.
+ */
+ void _allocateData();
+
+ /** Free memory for m_pfData and m_ppfData2D arrays.
+ *
+ * This function may ONLY be called if the memory for both blocks has been
+ * allocated before.
+ */
+ void _freeData();
+
+ /** Clear all member variables, setting all numeric variables to 0 and all pointers to NULL.
+ */
+ void _clear();
+
+ /** Un-initialize the object, bringing it back in the uninitialized state.
+ */
+ void _unInit();
+
+ /** Find the minimum and maximum data value and store them in
+ * m_fGlobalMin and m_fGlobalMax
+ */
+ void _computeGlobalMinMax();
+
+ /** Initialization. Initializes an instance of the CFloat32Data2D class, without filling the data block.
+ * Can only be called by derived classes.
+ *
+ * Initializes an instance of the CFloat32Data2D class. Memory is allocated for the
+ * data block. The allocated memory is not cleared and its contents after
+ * construction is undefined. Initialization may be followed by a call to
+ * copyData() to fill the memory block. If the object has been initialized before, the
+ * object is reinitialized and memory is freed and reallocated if necessary.
+ * This function does not set m_bInitialized to true if everything is ok.
+ *
+ * @param _iWidth width of the 2D data (x-axis), must be > 0
+ * @param _iHeight height of the 2D data (y-axis), must be > 0
+ * @return initialization of the base class successfull
+ */
+ bool _initialize(int _iWidth, int _iHeight);
+
+ /** Initialization. Initializes an instance of the CFloat32Data2D class with initialization of the data block.
+ * Can only be called by derived classes.
+ *
+ * Initializes an instance of the CFloat32Data2D class. Memory
+ * is allocated for the data block and the contents of the memory pointed to by
+ * _pfData is copied into the allocated memory. If the object has been initialized before, the
+ * object is reinitialized and memory is freed and reallocated if necessary.
+ * This function does not set m_bInitialized to true if everything is ok.
+ *
+ * @param _iWidth width of the 2D data (x-axis), must be > 0
+ * @param _iHeight height of the 2D data (y-axis), must be > 0
+ * @param _pfData pointer to a one-dimensional float32 data block
+ */
+ bool _initialize(int _iWidth, int _iHeight, const float32* _pfData);
+
+ /** Initialization. Initializes an instance of the CFloat32Data2D class with initialization of the data
+ * block with a scalar value. Can only be called by derived classes.
+ *
+ * Initializes an instance of the CFloat32Data2D class. Memory
+ * is allocated for the data block and the contents of the memory pointed to by
+ * _pfData is copied into the allocated memory. If the object has been initialized before, the
+ * object is reinitialized and memory is freed and reallocated if necessary.
+ * This function does not set m_bInitialized to true if everything is ok.
+ *
+ * @param _iWidth width of the 2D data (x-axis), must be > 0
+ * @param _iHeight height of the 2D data (y-axis), must be > 0
+ * @param _fScalar scalar value to put at each index
+ */
+ bool _initialize(int _iWidth, int _iHeight, float32 _fScalar);
+
+ /** Constructor. Create an instance of the CFloat32Data2D class without initializing the data block.
+ * Can only be called by derived classes.
+ *
+ * Creates an instance of the CFloat32Data2D class. Memory is allocated for the
+ * data block. The allocated memory is not cleared and its contents after
+ * construction is undefined. Construction may be followed by a call to
+ * copyData() to fill the memory block.
+ *
+ * @param _iWidth width of the 2D data (x-axis), must be > 0
+ * @param _iHeight height of the 2D data (y-axis), must be > 0
+ */
+ CFloat32Data2D(int _iWidth, int _iHeight);
+
+ /** Constructor. Create an instance of the CFloat32Data2D class with initialization of the data block.
+ * Can only be called by derived classes.
+ *
+ * Creates an instance of the CFloat32Data2D class. Memory
+ * is allocated for the data block and the contents of the memory pointed to by
+ * _pfData is copied into the allocated memory.
+ *
+ * @param _iWidth width of the 2D data (x-axis), must be > 0
+ * @param _iHeight height of the 2D data (y-axis), must be > 0
+ * @param _pfData pointer to a one-dimensional float32 data block
+ */
+ CFloat32Data2D(int _iWidth, int _iHeight, const float32* _pfData);
+
+ /** Constructor. Create an instance of the CFloat32Data2D class with initialization of the data block
+ * with a scalar value. Can only be called by derived classes.
+ *
+ * Creates an instance of the CFloat32Data2D class. Memory
+ * is allocated for the data block and the contents of the memory pointed to by
+ * _pfData is copied into the allocated memory.
+ *
+ * @param _iWidth width of the 2D data (x-axis), must be > 0
+ * @param _iHeight height of the 2D data (y-axis), must be > 0
+ * @param _fScalar scalar value to put at each index
+ */
+ CFloat32Data2D(int _iWidth, int _iHeight, float32 _fScalar);
+
+ /** Copy constructor.
+ */
+ CFloat32Data2D(const CFloat32Data2D&);
+
+public:
+
+ /** Typedef with available datatypes: BASE, PROJECTION, VOLUME.
+ */
+ typedef enum {BASE,
+ PROJECTION,
+ VOLUME} EDataType;
+
+ /** Default constructor. Sets all numeric member variables to 0 and all pointer member variables to NULL.
+ *
+ * If an object is constructed using this default constructor, it must always be followed by a call
+ * to one of the initialize() methods before the object can be used. Any use before calling init() is not allowed,
+ * except calling the member function isInitialized().
+ *
+ */
+ CFloat32Data2D();
+
+ /** Destructor. Free allocated memory
+ */
+ virtual ~CFloat32Data2D();
+
+ /** Copy the data block pointed to by _pfData to the data block pointed to by m_pfData.
+ * The pointer _pfData must point to a block of m_iSize float32s.
+ *
+ * @param _pfData source data block
+ */
+ void copyData(const float32* _pfData);
+
+ /** scale the grey value of the data from 0-255.
+ *
+ */
+ void scale();
+
+ /** Set each element of the data to a specified scalar value.
+ *
+ * @param _fScalar scalar value
+ */
+ void setData(float32 _fScalar);
+
+ /** Set all data to zero
+ */
+ void clearData();
+
+ /** Get a pointer to the data block, represented as a 1-dimensional
+ * array of float32 values. The data memory is still "owned" by the
+ * CFloat32Data2D instance; this memory may NEVER be freed by the
+ * caller of this function. If changes are made to this data, the
+ * function updateStatistics() should be called after completion of
+ * all changes.
+ *
+ * @return pointer to the 1-dimensional 32-bit floating point data block
+ */
+ float32* getData();
+
+ /** Get a const pointer to the data block, represented as a 1-dimensional
+ * array of float32 values. The data memory is still "owned" by the
+ * CFloat32Data2D instance; this memory may NEVER be freed by the
+ * caller of this function. If changes are made to this data, the
+ * function updateStatistics() should be called after completion of
+ * all changes.
+ *
+ * @return pointer to the 1-dimensional 32-bit floating point data block
+ */
+ const float32* getDataConst() const;
+
+ /** Get a float32** to the data block, represented as a 2-dimensional array of float32 values.
+ *
+ * After the call p = getData2D(), use p[iy][ix] to access element (ix, iy).
+ * The data memory and pointer array are still "owned" by the CFloat32Data2D
+ * instance; this memory may NEVER be freed by the caller of this function.
+ * If changes are made to this data, the function updateStatistics()
+ * should be called after completion of all changes.
+ *
+ * @return pointer to the 2-dimensional 32-bit floating point data block
+ */
+ float32** getData2D();
+
+ /** Get a const float32** to the data block, represented as a 2-dimensional array of float32 values.
+ *
+ * After the call p = getData2D(), use p[iy][ix] to access element (ix, iy).
+ * The data memory and pointer array are still "owned" by the CFloat32Data2D
+ * instance; this memory may NEVER be freed by the caller of this function.
+ * If changes are made to this data, the function updateStatistics()
+ * should be called after completion of all changes.
+ *
+ * @return pointer to the 2-dimensional 32-bit floating point data block
+ */
+ const float32** getData2DConst() const;
+
+ /** Update data statistics, such as minimum and maximum value, after the data has been modified.
+ */
+ virtual void updateStatistics();
+
+ /** Get the minimum value in the data block.
+ * If the data has been changed after construction, the function
+ * updateStatistics() must be called at least once before
+ * a query can be made on this value.
+ *
+ * @return minimum value in the data block
+ */
+ virtual float32 getGlobalMin() const;
+
+ /** Get the maximum value in the data block
+ * If the data has been changed after construction, the function
+ * updateStatistics() must be called at least once before
+ * a query can be made on this value.
+ *
+ * @return maximum value in the data block
+ */
+ virtual float32 getGlobalMax() const;
+
+ /** Get the mean value in the data block
+ * If the data has been changed after construction, the function
+ * updateStatistics() must be called at least once before
+ * a query can be made on this value.
+ *
+ * @return maximum value in the data block
+ */
+ virtual float32 getGlobalMean() const;
+
+
+ /** Get the width of the data block.
+ *
+ * @return width of the data block
+ */
+ int getWidth() const;
+
+ /** Get the height of the data block.
+ *
+ * @return height of the data block
+ */
+ int getHeight() const;
+
+ /** Get the total size (width*height) of the data block.
+ *
+ * @return size of the data block
+ */
+ int getSize() const;
+
+ /** which type is this class?
+ *
+ * @return DataType: ASTRA_DATATYPE_FLOAT32_PROJECTION or
+ * ASTRA_DATATYPE_FLOAT32_VOLUME
+ */
+ virtual EDataType getType() const;
+
+ /** get a description of the class
+ *
+ * @return description string
+ */
+ virtual std::string description() const;
+
+ /** Get the number of dimensions of this object.
+ *
+ * @return number of dimensions
+ */
+ int getDimensionCount() const;
+
+ /**
+ * Clamp data to minimum value
+ *
+ * @param _fMin minimum value
+ * @return l-value
+ */
+ CFloat32Data2D& clampMin(float32& _fMin);
+
+ /**
+ * Clamp data to maximum value
+ *
+ * @param _fMax maximum value
+ * @return l-value
+ */
+ CFloat32Data2D& clampMax(float32& _fMax);
+
+ /**
+ * Overloaded Operator: data += data (pointwise)
+ *
+ * @param _data r-value
+ * @return l-value
+ */
+ CFloat32Data2D& operator+=(const CFloat32Data2D& _data);
+
+ /**
+ * Overloaded Operator: data -= data (pointwise)
+ *
+ * @param _data r-value
+ * @return l-value
+ */
+ CFloat32Data2D& operator-=(const CFloat32Data2D& _data);
+
+ /**
+ * Overloaded Operator: data *= data (pointwise)
+ *
+ * @param _data r-value
+ * @return l-value
+ */
+ CFloat32Data2D& operator*=(const CFloat32Data2D& _data);
+
+ /**
+ * Overloaded Operator: data *= scalar (pointwise)
+ *
+ * @param _fScalar r-value
+ * @return l-value
+ */
+ CFloat32Data2D& operator*=(const float32& _fScalar);
+
+ /**
+ * Overloaded Operator: data /= scalar (pointwise)
+ *
+ * @param _fScalar r-value
+ * @return l-value
+ */
+ CFloat32Data2D& operator/=(const float32& _fScalar);
+
+ /**
+ * Overloaded Operator: data += scalar (pointwise)
+ *
+ * @param _fScalar r-value
+ * @return l-value
+ */
+ CFloat32Data2D& operator+=(const float32& _fScalar);
+
+ /**
+ * Overloaded Operator: data -= scalar (pointwise)
+ *
+ * @param _fScalar r-value
+ * @return l-value
+ */
+ CFloat32Data2D& operator-=(const float32& _fScalar);
+
+ CFloat32Data2D& operator=(const CFloat32Data2D& _dataIn);
+
+ float32& getData(int _index);
+
+};
+
+
+//----------------------------------------------------------------------------------------
+// Inline member functions
+//----------------------------------------------------------------------------------------
+
+// Get the number of dimensions of this object.
+inline int CFloat32Data2D::getDimensionCount() const
+{
+ return 2;
+}
+
+//----------------------------------------------------------------------------------------
+inline std::string CFloat32Data2D::description() const
+{
+ std::stringstream res;
+ res << m_iWidth << "x" << m_iHeight;
+ if (getType() == CFloat32Data2D::PROJECTION) res << " sinogram data \t";
+ if (getType() == CFloat32Data2D::VOLUME) res << " volume data \t";
+ return res.str();
+}
+
+//----------------------------------------------------------------------------------------
+// Get the type of this object.
+inline CFloat32Data2D::EDataType CFloat32Data2D::getType() const
+{
+ return BASE;
+}
+
+//----------------------------------------------------------------------------------------
+// Get the width of the data block.
+inline int CFloat32Data2D::getWidth() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_iWidth;
+}
+
+//----------------------------------------------------------------------------------------
+// Get the height of the data block.
+inline int CFloat32Data2D::getHeight() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_iHeight;
+}
+
+//----------------------------------------------------------------------------------------
+// Get the total size (width*height*depth) of the data block.
+inline int CFloat32Data2D::getSize() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_iSize;
+}
+
+//----------------------------------------------------------------------------------------
+// Get a pointer to the data block, represented as a 1-dimensional array of float32 values.
+inline float32* CFloat32Data2D::getData()
+{
+ //ASTRA_ASSERT(m_bInitialized);
+ return m_pfData;
+}
+
+//----------------------------------------------------------------------------------------
+// Get a pointer to the data block, represented as a 1-dimensional array of float32 values.
+inline float32& CFloat32Data2D::getData(int _index)
+{
+ //ASTRA_ASSERT(m_bInitialized);
+ return m_pfData[_index];
+}
+
+//----------------------------------------------------------------------------------------
+// Get a const pointer to the data block, represented as a 1-dimensional array of float32 values.
+inline const float32* CFloat32Data2D::getDataConst() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return (const float32*)m_pfData;
+}
+
+//----------------------------------------------------------------------------------------
+// Get a float32** to the data block, represented as a 2-dimensional array of float32 values.
+inline float32** CFloat32Data2D::getData2D()
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_ppfData2D;
+}
+
+//----------------------------------------------------------------------------------------
+// Get a const float32** to the data block, represented as a 2-dimensional array of float32 values.
+inline const float32** CFloat32Data2D::getData2DConst() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return (const float32**)m_ppfData2D;
+}
+
+//----------------------------------------------------------------------------------------
+// Get the minimum value in the data block.
+inline float32 CFloat32Data2D::getGlobalMin() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_fGlobalMin;
+}
+
+//----------------------------------------------------------------------------------------
+// Get the maximum value in the data block
+inline float32 CFloat32Data2D::getGlobalMax() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_fGlobalMax;
+}
+
+//----------------------------------------------------------------------------------------
+// Get the mean value in the data block
+inline float32 CFloat32Data2D::getGlobalMean() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_fGlobalMean;
+}
+
+
+} // end namespace astra
+
+#endif // _INC_ASTRA_FLOAT32DATA2D
diff --git a/include/astra/Float32Data3D.h b/include/astra/Float32Data3D.h
new file mode 100644
index 0000000..8666890
--- /dev/null
+++ b/include/astra/Float32Data3D.h
@@ -0,0 +1,199 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_FLOAT32DATA3D
+#define _INC_ASTRA_FLOAT32DATA3D
+
+#include "Globals.h"
+#include "Float32Data.h"
+#include "Float32Data2D.h"
+
+namespace astra {
+
+/**
+ * This class represents a three-dimensional block of float32ing point data.
+ */
+class _AstraExport CFloat32Data3D : public CFloat32Data {
+
+protected:
+
+ int m_iWidth; ///< width of the data (x)
+ int m_iHeight; ///< height of the data (y)
+ int m_iDepth; ///< depth of the data (z)
+ size_t m_iSize; ///< size of the data (width*height*depth)
+
+ /**
+ * Compares the size of two CFloat32Data instances.
+ *
+ * @param _pA CFloat32Data3D instance A
+ * @param _pB CFloat32Data3D instance B
+ * @return True if they have the same size
+ */
+ static bool _data3DSizesEqual(const CFloat32Data3D * _pA, const CFloat32Data3D * _pB);
+
+public:
+
+ typedef enum {BASE, PROJECTION, VOLUME} EDataType;
+
+ /** Default constructor. Sets all numeric member variables to 0 and all pointer member variables to NULL.
+ *
+ * If an object is constructed using this default constructor, it must always be followed by a call
+ * to one of the init() methods before the object can be used. Any use before calling init() is not allowed,
+ * except calling the member function isInitialized().
+ */
+ CFloat32Data3D();
+
+ /** Destructor.
+ */
+ virtual ~CFloat32Data3D();
+
+ /** Get the width of the data block.
+ *
+ * @return width of the data block
+ */
+ int getWidth() const;
+
+ /** Get the height of the data block.
+ *
+ * @return height of the data block
+ */
+ int getHeight() const;
+
+ /** Get the depth of the data block.
+ *
+ * @return depth of the data block
+ */
+ int getDepth() const;
+
+ /** Get the size of the data block.
+ *
+ * @return size of the data block
+ */
+ int getSize() const;
+
+ /** Which type is this class?
+ *
+ * @return DataType: PROJECTION or VOLUME
+ */
+ virtual EDataType getType() const;
+
+ /** Get the number of dimensions of this object.
+ *
+ * @return number of dimensions
+ */
+ int getDimensionCount() const;
+
+ /**
+ * Clamp data to minimum value
+ *
+ * @param _fMin minimum value
+ * @return l-value
+ */
+ virtual CFloat32Data3D& clampMin(float32& _fMin) = 0;
+
+ /**
+ * Clamp data to maximum value
+ *
+ * @param _fMax maximum value
+ * @return l-value
+ */
+ virtual CFloat32Data3D& clampMax(float32& _fMax) = 0;
+
+ /** get a description of the class
+ *
+ * @return description string
+ */
+ virtual std::string description() const;
+
+};
+//----------------------------------------------------------------------------------------
+
+
+
+//----------------------------------------------------------------------------------------
+// Get dimension count.
+inline int CFloat32Data3D::getDimensionCount() const
+{
+ return 3;
+}
+
+//----------------------------------------------------------------------------------------
+// Get the width of the data block.
+inline int CFloat32Data3D::getWidth() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_iWidth;
+}
+
+//----------------------------------------------------------------------------------------
+// Get the height of the data block.
+inline int CFloat32Data3D::getHeight() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_iHeight;
+}
+
+//----------------------------------------------------------------------------------------
+// Get the height of the data block.
+inline int CFloat32Data3D::getDepth() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_iDepth;
+}
+
+//----------------------------------------------------------------------------------------
+// Get the size of the data block.
+inline int CFloat32Data3D::getSize() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_iSize;
+}
+
+
+//----------------------------------------------------------------------------------------
+// get type
+inline CFloat32Data3D::EDataType CFloat32Data3D::getType() const
+{
+ return BASE;
+}
+
+//----------------------------------------------------------------------------------------
+// To String
+inline std::string CFloat32Data3D::description() const
+{
+ std::stringstream res;
+ res << m_iWidth << "x" << m_iHeight << "x" << m_iDepth;
+ if (getType() == CFloat32Data3D::PROJECTION) res << " sinogram data \t";
+ if (getType() == CFloat32Data3D::VOLUME) res << " volume data \t";
+ return res.str();
+}
+//----------------------------------------------------------------------------------------
+
+} // end namespace astra
+
+#endif // _INC_ASTRA_FLOAT32DATA2D
diff --git a/include/astra/Float32Data3DMemory.h b/include/astra/Float32Data3DMemory.h
new file mode 100644
index 0000000..3a445b6
--- /dev/null
+++ b/include/astra/Float32Data3DMemory.h
@@ -0,0 +1,338 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_FLOAT32DATA3DMEMORY
+#define _INC_ASTRA_FLOAT32DATA3DMEMORY
+
+#include "Globals.h"
+#include "Float32Data3D.h"
+
+namespace astra {
+
+/**
+ * This class represents a three-dimensional block of float32ing point data.
+ * It contains member functions for accessing this data and for performing
+ * elementary computations on the data.
+ * The data block is "owned" by the class, meaning that the class is
+ * responsible for deallocation of the memory involved.
+ */
+class _AstraExport CFloat32Data3DMemory : public virtual CFloat32Data3D {
+
+protected:
+
+ /** Pointer to the data block, represented as a 1-dimensional array.
+ * Note that the data memory is "owned" by this class, meaning that the
+ * class is responsible for deallocation of the memory involved.
+ * To access element (ix, iy, iz) internally, use
+ * m_pData[iz * m_iWidth * m_iHeight + iy * m_iWidth + ix]
+ */
+ float32* m_pfData;
+
+ /** Array of float32 pointers, each pointing to a single row
+ * in the m_pfData memory block.
+ * To access element (ix, iy, iz) internally, use m_ppfDataRowInd[iz * m_iHeight + iy][ix]
+ */
+ float32** m_ppfDataRowInd;
+
+ /** Array of float32 pointers, each pointing to a single slice
+ * in the m_pfData memory block.
+ * To access element (ix, iy, iz) internally, use m_pppfDataSliceInd[iz][iy][ix]
+ */
+ float32*** m_pppfDataSliceInd;
+
+ float32 m_fGlobalMin; ///< minimum value of the data
+ float32 m_fGlobalMax; ///< maximum value of the data
+
+ /** Allocate memory for m_pfData, m_ppfDataRowInd and m_pppfDataSliceInd arrays.
+ *
+ * The allocated block consists of m_iSize float32s. The block is
+ * not cleared after allocation and its contents is undefined.
+ * This function may NOT be called if memory has already been allocated.
+ */
+ void _allocateData();
+
+ /** Free memory for m_pfData, m_ppfDataRowInd and m_pppfDataSliceInd arrays.
+ *
+ * This function may ONLY be called if the memory for both blocks has been
+ * allocated before.
+ */
+ void _freeData();
+
+ /** Clear all member variables, setting all numeric variables to 0 and all pointers to NULL.
+ */
+ void _clear();
+
+ /** Un-initialize the object, bringing it back in the unitialized state.
+ */
+ void _unInit();
+
+ /** Find the minimum and maximum data value and store them in
+ * m_fGlobalMin and m_fGlobalMax
+ */
+ void _computeGlobalMinMax();
+
+ /** Initialization. Initializes an instance of the CFloat32Data3DMemory class, without filling the data block.
+ * Can only be called by derived classes.
+ *
+ * Initializes an instance of the CFloat32Data3DMemory class. Memory is allocated for the
+ * data block. The allocated memory is not cleared and its contents after
+ * construction is undefined. Initialization may be followed by a call to
+ * copyData() to fill the memory block. If the object has been initialized before, the
+ * object is reinitialized and memory is freed and reallocated if necessary.
+ * This function does not set m_bInitialized to true if everything is ok.
+ *
+ * @param _iWidth width of the 3D data (x-axis), must be > 0
+ * @param _iHeight height of the 3D data (y-axis), must be > 0
+ * @param _iDepth depth of the 3D data (z-axis), must be > 0
+ * @return initialization of the base class successfull
+ */
+ bool _initialize(int _iWidth, int _iHeight, int _iDepth);
+
+ /** Initialization. Initializes an instance of the CFloat32Data3DMemory class with initialization of the data block.
+ * Can only be called by derived classes.
+ *
+ * Initializes an instance of the CFloat32Data3DMemory class. Memory
+ * is allocated for the data block and the contents of the memory pointed to by
+ * _pfData is copied into the allocated memory. If the object has been initialized before, the
+ * object is reinitialized and memory is freed and reallocated if necessary.
+ * This function does not set m_bInitialized to true if everything is ok.
+ *
+ * @param _iWidth width of the 2D data (x-axis), must be > 0
+ * @param _iHeight height of the 2D data (y-axis), must be > 0
+ * @param _iDepth depth of the 2D data (z-axis), must be > 0
+ * @param _pfData pointer to a one-dimensional float32 data block
+ * @return initialization of the base class successfull
+ */
+ bool _initialize(int _iWidth, int _iHeight, int _iDepth, const float32* _pfData);
+
+ /** Initialization. Initializes an instance of the CFloat32Data3DMemory class with initialization of the data block.
+ * Can only be called by derived classes.
+ *
+ * Initializes an instance of the CFloat32Data3DMemory class. Memory
+ * is allocated for the data block and the contents of the memory pointed to by
+ * _pfData is copied into the allocated memory. If the object has been initialized before, the
+ * object is reinitialized and memory is freed and reallocated if necessary.
+ * This function does not set m_bInitialized to true if everything is ok.
+ *
+ * @param _iWidth width of the 2D data (x-axis), must be > 0
+ * @param _iHeight height of the 2D data (y-axis), must be > 0
+ * @param _iDepth depth of the 2D data (z-axis), must be > 0
+ * @param _fScalar scalar value to fill the data
+ * @return initialization of the base class successfull
+ */
+ bool _initialize(int _iWidth, int _iHeight, int _iDepth, float32 _fScalar);
+
+public:
+
+ /** Default constructor. Sets all numeric member variables to 0 and all pointer member variables to NULL.
+ *
+ * If an object is constructed using this default constructor, it must always be followed by a call
+ * to one of the initialize() methods before the object can be used. Any use before calling init() is not allowed,
+ * except calling the member function isInitialized().
+ *
+ */
+ CFloat32Data3DMemory();
+
+ /** Destructor. Free allocated memory
+ */
+ virtual ~CFloat32Data3DMemory();
+
+ /** Copy the data block pointed to by _pfData to the data block pointed to by m_pfData.
+ * The pointer _pfData must point to a block of m_iSize float32s.
+ *
+ * @param _pfData source data block
+ * @param _iSize total number of data elements, must be equal to the allocated size of the object.
+ */
+ void copyData(const float32* _pfData, size_t _iSize);
+
+ /** Set each element of the data to a specified scalar value.
+ *
+ * @param _fScalar scalar value
+ */
+ void setData(float32 _fScalar);
+
+ /** Set all data to zero
+ */
+ void clearData();
+
+ /** Get a pointer to the data block, represented as a 1-dimensional
+ * array of float32 values. The data memory is still "owned" by the
+ * CFloat32Data3DMemory instance; this memory may NEVER be freed by the
+ * caller of this function. If changes are made to this data, the
+ * function updateStatistics() should be called after completion of
+ * all changes.
+ *
+ * @return pointer to the 1-dimensional 32-bit floating point data block
+ */
+ float32* getData();
+
+ /** Get a const pointer to the data block, represented as a 1-dimensional
+ * array of float32 values. The data memory is still "owned" by the
+ * CFloat32Data3DMemory instance; this memory may NEVER be freed by the
+ * caller of this function. If changes are made to this data, the
+ * function updateStatistics() should be called after completion of
+ * all changes.
+ *
+ * @return pointer to the 1-dimensional 32-bit floating point data block
+ */
+ const float32* getDataConst() const;
+
+ /** Get a float32*** to the data block, represented as a 3-dimensional array of float32 values.
+ *
+ * After the call p = getData3D(), use p[iz][iy][ix] to access element (ix, iy, iz).
+ * The data memory and pointer array are still "owned" by the CFloat32Data3DMemory
+ * instance; this memory may NEVER be freed by the caller of this function.
+ * If changes are made to this data, the function updateStatistics()
+ * should be called after completion of all changes.
+ *
+ * @return pointer to the 3-dimensional 32-bit floating point data block
+ */
+ float32*** getData3D();
+
+ /** Get a const float32*** to the data block, represented as a 3-dimensional array of float32 values.
+ *
+ * After the call p = getData3D(), use p[iy][ix] to access element (ix, iy, iz).
+ * The data memory and pointer array are still "owned" by the CFloat32Data3DMemory
+ * instance; this memory may NEVER be freed by the caller of this function.
+ * If changes are made to this data, the function updateStatistics()
+ * should be called after completion of all changes.
+ *
+ * @return pointer to the 3-dimensional 32-bit floating point data block
+ */
+ const float32*** getData3DConst() const;
+
+ /** Update data statistics, such as minimum and maximum value, after the data has been modified.
+ */
+ virtual void updateStatistics();
+
+ /** Get the minimum value in the data block.
+ * If the data has been changed after construction, the function
+ * updateStatistics() must be called at least once before
+ * a query can be made on this value.
+ *
+ * @return minimum value in the data block
+ */
+ virtual float32 getGlobalMin() const;
+
+ /** Get the maximum value in the data block
+ * If the data has been changed after construction, the function
+ * updateStatistics() must be called at least once before
+ * a query can be made on this value.
+ *
+ * @return maximum value in the data block
+ */
+ virtual float32 getGlobalMax() const;
+
+ /** which type is this class?
+ *
+ * @return DataType: ASTRA_DATATYPE_FLOAT32_PROJECTION or
+ * ASTRA_DATATYPE_FLOAT32_VOLUME
+ */
+ virtual EDataType getType() const;
+
+ /**
+ * Clamp data to minimum value
+ *
+ * @param _fMin minimum value
+ * @return l-value
+ */
+ virtual CFloat32Data3D& clampMin(float32& _fMin);
+
+ /**
+ * Clamp data to maximum value
+ *
+ * @param _fMax maximum value
+ * @return l-value
+ */
+ virtual CFloat32Data3D& clampMax(float32& _fMax);
+};
+
+
+//----------------------------------------------------------------------------------------
+// Inline member functions
+//----------------------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------------------
+// Get the type of this object.
+inline CFloat32Data3DMemory::EDataType CFloat32Data3DMemory::getType() const
+{
+ return BASE;
+}
+
+//----------------------------------------------------------------------------------------
+// Get the minimum value in the data block.
+inline float32 CFloat32Data3DMemory::getGlobalMin() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_fGlobalMin;
+}
+
+//----------------------------------------------------------------------------------------
+// Get the maximum value in the data block
+inline float32 CFloat32Data3DMemory::getGlobalMax() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_fGlobalMax;
+}
+
+//----------------------------------------------------------------------------------------
+// Get a pointer to the data block, represented as a 1-dimensional array of float32 values.
+inline float32* CFloat32Data3DMemory::getData()
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_pfData;
+}
+
+//----------------------------------------------------------------------------------------
+// Get a const pointer to the data block, represented as a 1-dimensional array of float32 values.
+inline const float32* CFloat32Data3DMemory::getDataConst() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return (const float32*)m_pfData;
+}
+
+//----------------------------------------------------------------------------------------
+// Get a float32** to the data block, represented as a 3-dimensional array of float32 values.
+inline float32*** CFloat32Data3DMemory::getData3D()
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_pppfDataSliceInd;
+}
+
+//----------------------------------------------------------------------------------------
+// Get a const float32** to the data block, represented as a 3-dimensional array of float32 values.
+inline const float32*** CFloat32Data3DMemory::getData3DConst() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return (const float32***)m_pppfDataSliceInd;
+}
+//----------------------------------------------------------------------------------------
+
+} // end namespace astra
+
+#endif // _INC_ASTRA_FLOAT32DATA2D
diff --git a/include/astra/Float32ProjectionData2D.h b/include/astra/Float32ProjectionData2D.h
new file mode 100644
index 0000000..d9fe51a
--- /dev/null
+++ b/include/astra/Float32ProjectionData2D.h
@@ -0,0 +1,247 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_FLOAT32PROJECTIONDATA2D
+#define _INC_ASTRA_FLOAT32PROJECTIONDATA2D
+
+#include "Float32Data2D.h"
+#include "ProjectionGeometry2D.h"
+
+namespace astra {
+
+/**
+ * This class represents two-dimensional Projection Data.
+ *
+ * It contains member functions for accessing this data and for performing
+ * elementary computations on the data.
+ * The data block is "owned" by the class, meaning that the class is
+ * responsible for deallocation of the memory involved.
+ *
+ * The projection data is stored as a series of consecutive rows, where
+ * each row contains the data for a single projection.
+ */
+class _AstraExport CFloat32ProjectionData2D : public CFloat32Data2D {
+
+public:
+
+ /**
+ * Default constructor. Sets all numeric member variables to 0 and all pointer member variables to NULL.
+ *
+ * If an object is constructed using this default constructor, it must always be followed by a call
+ * to one of the init() methods before the object can be used. Any use before calling init() is not allowed,
+ * except calling the member function isInitialized().
+ *
+ */
+ CFloat32ProjectionData2D();
+
+ /**
+ * Constructor. Create an instance of the CFloat32ProjectionData2D class without initializing the data.
+ *
+ * Memory is allocated for the data block. The allocated memory is not cleared and
+ * its contents after construction is undefined. Construction may be followed by a
+ * call to copyData() to fill the memory block.
+ * The size of the data is determined by the specified projection geometry object.
+ *
+ * @param _pGeometry Projection Geometry object. This object will be HARDCOPIED into this class.
+ */
+ CFloat32ProjectionData2D(CProjectionGeometry2D* _pGeometry);
+
+ /**
+ * Constructor. Create an instance of the CFloat32ProjectionData2D class with initialization of the data.
+ *
+ * Creates an instance of the CFloat32ProjectionData2D class. Memory
+ * is allocated for the data block and the contents of the memory pointed to by
+ * _pfData is copied into the allocated memory.
+ * The size of the data is determined by the specified projection geometry object.
+ *
+ * @param _pGeometry Projection Geometry object. This object will be HARDCOPIED into this class.
+ * @param _pfData pointer to a one-dimensional float32 data block
+ */
+ CFloat32ProjectionData2D(CProjectionGeometry2D* _pGeometry, float32* _pfData);
+
+ /**
+ * Constructor. Create an instance of the CFloat32ProjectionData2D class with initialization of the data.
+ *
+ * Creates an instance of the CFloat32ProjectionData2D class. Memory
+ * is allocated for the data block and the contents of the memory pointed to by
+ * _pfData is copied into the allocated memory.
+ * The size of the data is determined by the specified projection geometry object.
+ *
+ * @param _pGeometry Projection Geometry object. This object will be HARDCOPIED into this class.
+ * @param _fScalar scalar value to be put at each index.
+ */
+ CFloat32ProjectionData2D(CProjectionGeometry2D* _pGeometry, float32 _fScalar);
+
+ /**
+ * Copy constructor
+ */
+ CFloat32ProjectionData2D(const CFloat32ProjectionData2D& _other);
+
+ /**
+ * Assignment operator
+ */
+ CFloat32ProjectionData2D& operator=(const CFloat32ProjectionData2D& _other);
+
+ /**
+ * Destructor.
+ */
+ virtual ~CFloat32ProjectionData2D();
+
+ /** Initialization. Initializes an instance of the CFloat32ProjectionData2D class, without filling the data block.
+ *
+ * Initializes an instance of the CFloat32Data2D class. Memory is allocated for the
+ * data block. The allocated memory is not cleared and its contents after
+ * construction is undefined. Initialization may be followed by a call to
+ * copyData() to fill the memory block. If the object has been initialized before, the
+ * object is reinitialized and memory is freed and reallocated if necessary.
+ *
+ * @param _pGeometry Projection Geometry of the data. This object will be HARDCOPIED into this class.
+ * @return Initialization of the base class successfull.
+ */
+ bool initialize(CProjectionGeometry2D* _pGeometry);
+
+ /** Initialization. Initializes an instance of the CFloat32Data2D class with initialization of the data block.
+ *
+ * Initializes an instance of the CFloat32Data2D class. Memory
+ * is allocated for the data block and the contents of the memory pointed to by
+ * _pfData is copied into the allocated memory. If the object has been initialized before, the
+ * object is reinitialized and memory is freed and reallocated if necessary.
+ *
+ * @param _pGeometry Projection Geometry of the data. This object will be HARDCOPIED into this class.
+ * @param _pfData pointer to a one-dimensional float32 data block
+ */
+ bool initialize(CProjectionGeometry2D* _pGeometry, const float32* _pfData);
+
+ /** Initialization. Initializes an instance of the CFloat32Data2D class with initialization of the data block.
+ *
+ * Initializes an instance of the CFloat32Data2D class. Memory
+ * is allocated for the data block and the contents of the memory pointed to by
+ * _pfData is copied into the allocated memory. If the object has been initialized before, the
+ * object is reinitialized and memory is freed and reallocated if necessary.
+ *
+ * @param _pGeometry Projection Geometry of the data. This object will be HARDCOPIED into this class.
+ * @param _fScalar scalar value to be put at each index.
+ */
+ bool initialize(CProjectionGeometry2D* _pGeometry, float32 _fScalar);
+
+ /** Get the number of detectors.
+ *
+ * @return number of detectors
+ */
+ int getDetectorCount() const;
+
+ /** Get the number of projection angles.
+ *
+ * @return number of projection angles
+ */
+ int getAngleCount() const;
+
+ /** Get a pointer to the data of a single projection angle.
+ *
+ * The data memory is still "owned" by the
+ * CFloat32ProjectionData2D instance; this memory may NEVER be freed by the
+ * caller of this function. If changes are made to this data, the
+ * function updateStatistics() should be called after completion of
+ * all changes.
+ *
+ * @return pointer to the data
+ */
+ float32* getSingleProjectionData(int _iAngleIndex);
+
+ /** Get a const pointer to the data of a single projection angle.
+ *
+ * The data memory is still "owned" by the
+ * CFloat32ProjectionData2D instance; this memory may NEVER be freed by the
+ * caller of this function.
+ *
+ * @return pointer to the data
+ */
+ const float32* getSingleProjectionDataConst(int _iAngleIndex) const;
+
+ /** Which type is this class?
+ *
+ * @return DataType: PROJECTION
+ */
+ virtual EDataType getType() const;
+
+ /** Get the projection geometry.
+ *
+ * @return pointer to projection geometry.
+ */
+ virtual CProjectionGeometry2D* getGeometry() const;
+
+ /** Change the projection geometry.
+ * Note that this can't change the dimensions of the data.
+ */
+ virtual void changeGeometry(CProjectionGeometry2D* pGeometry);
+
+protected:
+
+ /** The projection geometry for this data.
+ */
+ CProjectionGeometry2D* m_pGeometry;
+
+};
+//----------------------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------------------
+// Get the number of detectors.
+inline int CFloat32ProjectionData2D::getDetectorCount() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_iWidth;
+}
+
+//----------------------------------------------------------------------------------------
+// Get the number of projection angles.
+inline int CFloat32ProjectionData2D::getAngleCount() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_iHeight;
+}
+
+//----------------------------------------------------------------------------------------
+// Get the projection geometry.
+inline CProjectionGeometry2D* CFloat32ProjectionData2D::getGeometry() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_pGeometry;
+}
+
+//----------------------------------------------------------------------------------------
+// Get type.
+inline CFloat32Data2D::EDataType CFloat32ProjectionData2D::getType() const
+{
+ return PROJECTION;
+}
+//----------------------------------------------------------------------------------------
+
+} // end namespace astra
+
+#endif // _INC_ASTRA_FLOAT32PROJECTIONDATA2D
diff --git a/include/astra/Float32ProjectionData3D.h b/include/astra/Float32ProjectionData3D.h
new file mode 100644
index 0000000..92122a7
--- /dev/null
+++ b/include/astra/Float32ProjectionData3D.h
@@ -0,0 +1,257 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_FLOAT32PROJECTIONDATA3D
+#define _INC_ASTRA_FLOAT32PROJECTIONDATA3D
+
+#include "Float32Data3D.h"
+#include "Float32ProjectionData2D.h"
+#include "Float32VolumeData2D.h"
+#include "ProjectionGeometry3D.h"
+
+namespace astra {
+
+/**
+ * This asbtract class represents three-dimensional Projection Data.
+ */
+class _AstraExport CFloat32ProjectionData3D : public virtual CFloat32Data3D
+{
+protected:
+ /** The projection geometry for this data.
+ */
+ CProjectionGeometry3D* m_pGeometry;
+
+public:
+
+ /** Default constructor.
+ */
+ CFloat32ProjectionData3D();
+
+ /** Destructor.
+ */
+ virtual ~CFloat32ProjectionData3D();
+
+ /** Get the number of detectors in one detector column.
+ *
+ * @return number of detectors
+ */
+ int getDetectorRowCount() const;
+
+ /** Get the number of detectors in one detector row.
+ *
+ * @return number of detectors
+ */
+ int getDetectorColCount() const;
+
+ /** Get the total number of detectors.
+ *
+ * @return number of detectors
+ */
+ int getDetectorTotCount() const;
+
+ /** Get the number of projection angles.
+ *
+ * @return number of projection angles
+ */
+ int getAngleCount() const;
+
+ /** Which type is this class?
+ *
+ * @return DataType: ASTRA_DATATYPE_FLOAT32_PROJECTION
+ */
+ virtual CFloat32Data3D::EDataType getType() const;
+
+ /** Fetch a COPY of a projection of the data. Note that if you update the 2D data slice, the data in the
+ * 3d data object will remain unaltered. To copy the data back in the 3D-volume you must return the data by calling 'returnProjection'.
+ *
+ * @param _iProjectionNr projection number
+ * @return Volume data object
+ */
+ virtual CFloat32VolumeData2D* fetchProjection(int _iProjectionNr) const = 0;
+
+ /** Return a projection slice to the 3d data. The data will be deleted. If the slice was fetched with
+ * 'fetchProjection', the data will be stored first.
+ *
+ * @param _iProjectionNr projection number
+ * @param _pProjection 2D Projection Data
+ */
+ virtual void returnProjection(int _iProjectionNr, CFloat32VolumeData2D* _pProjection) = 0;
+
+ /** Fetch a COPY of a sinogram slice of the data. Note that if you update the 2D data slice, the data in the
+ * 3d data object will remain unaltered. To copy the data back in the 3D-volume you must return the data by calling 'returnSlice'.
+ *
+ * @param _iSliceNr slice number
+ * @return Sinogram data object
+ */
+ virtual CFloat32ProjectionData2D* fetchSinogram(int _iSliceNr) const = 0;
+
+ /** Return a sinogram slice to the 3d data. The data will be stored in the 3D Data object.
+ *
+ * @param _iSliceNr slice number
+ * @param _pSinogram2D 2D Sinogram Object.
+ */
+ virtual void returnSinogram(int _iSliceNr, CFloat32ProjectionData2D* _pSinogram2D) = 0;
+
+ /** This SLOW function returns a detector value stored a specific index in the array.
+ * Reading values in this way might cause a lot of unnecessar__y memory operations, don't
+ * use it in time-critical code.
+ *
+ * @param _iIndex Index in the array if the data were stored completely in main memory
+ * @return The value the location specified by _iIndex
+ */
+ virtual float32 getDetectorValue(int _iIndex) = 0;
+
+ /** This SLOW function stores a detector value at a specific index in the array.
+ * Writing values in this way might cause a lot of unnecessary memory operations, don't
+ * use it in time-critical code.
+ *
+ * @param _iIndex Index in the array if the data were stored completely in main memory
+ * @param _fValue The value to be stored at the location specified by _iIndex
+ */
+ virtual void setDetectorValue(int _iIndex, float32 _fValue) = 0;
+
+ /**
+ * Overloaded Operator: data += data (pointwise)
+ *
+ * @param _data r-value
+ * @return l-value
+ */
+ CFloat32ProjectionData3D& operator+=(const CFloat32ProjectionData3D& _data);
+
+ /**
+ * Overloaded Operator: data -= data (pointwise)
+ *
+ * @param _data r-value
+ * @return l-value
+ */
+ CFloat32ProjectionData3D& operator-=(const CFloat32ProjectionData3D& _data);
+
+ /**
+ * Overloaded Operator: data *= data (pointwise)
+ *
+ * @param _data r-value
+ * @return l-value
+ */
+ CFloat32ProjectionData3D& operator*=(const CFloat32ProjectionData3D& _data);
+
+ /**
+ * Overloaded Operator: data *= scalar (pointwise)
+ *
+ * @param _fScalar r-value
+ * @return l-value
+ */
+ CFloat32ProjectionData3D& operator*=(const float32& _fScalar);
+
+ /**
+ * Overloaded Operator: data /= scalar (pointwise)
+ *
+ * @param _fScalar r-value
+ * @return l-value
+ */
+ CFloat32ProjectionData3D& operator/=(const float32& _fScalar);
+
+ /**
+ * Overloaded Operator: data += scalar (pointwise)
+ *
+ * @param _fScalar r-value
+ * @return l-value
+ */
+ CFloat32ProjectionData3D& operator+=(const float32& _fScalar);
+
+ /**
+ * Overloaded Operator: data -= scalar (pointwise)
+ *
+ * @param _fScalar r-value
+ * @return l-value
+ */
+ CFloat32ProjectionData3D& operator-=(const float32& _fScalar);
+
+ /** Get the projection geometry.
+ *
+ * @return pointer to projection geometry.
+ */
+ virtual CProjectionGeometry3D* getGeometry() const;
+};
+
+
+//----------------------------------------------------------------------------------------
+// Inline member functions
+//----------------------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------------------
+// Get the number of detectors.
+inline int CFloat32ProjectionData3D::getDetectorColCount() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_iWidth;
+}
+
+//----------------------------------------------------------------------------------------
+// Get the number of detectors.
+inline int CFloat32ProjectionData3D::getDetectorRowCount() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_iDepth;
+}
+
+//----------------------------------------------------------------------------------------
+// Get the number of detectors.
+inline int CFloat32ProjectionData3D::getDetectorTotCount() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_iWidth * m_iDepth;
+}
+
+//----------------------------------------------------------------------------------------
+// Get the number of projection angles.
+inline int CFloat32ProjectionData3D::getAngleCount() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_iHeight;
+}
+
+//----------------------------------------------------------------------------------------
+// Get type
+inline CFloat32Data3D::EDataType CFloat32ProjectionData3D::getType() const
+{
+ return PROJECTION;
+}
+//----------------------------------------------------------------------------------------
+// Get the projection geometry.
+inline CProjectionGeometry3D* CFloat32ProjectionData3D::getGeometry() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_pGeometry;
+}
+//----------------------------------------------------------------------------------------
+
+
+} // end namespace astra
+
+#endif // _INC_ASTRA_FLOAT32PROJECTIONDATA3D
diff --git a/include/astra/Float32ProjectionData3DMemory.h b/include/astra/Float32ProjectionData3DMemory.h
new file mode 100644
index 0000000..8b61d45
--- /dev/null
+++ b/include/astra/Float32ProjectionData3DMemory.h
@@ -0,0 +1,218 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_FLOAT32PROJECTIONDATA3DMEMORY
+#define _INC_ASTRA_FLOAT32PROJECTIONDATA3DMEMORY
+
+#include "Float32Data3DMemory.h"
+#include "Float32ProjectionData3D.h"
+#include "ParallelProjectionGeometry2D.h" // TEMP
+
+namespace astra {
+
+/**
+ * This class represents three-dimensional Projection Data.
+ *
+ * It contains member functions for accessing this data and for performing
+ * elementary computations on the data.
+ * The data block is "owned" by the class, meaning that the class is
+ * responsible for deallocation of the memory involved.
+ *
+ * The projection data is stored as a series of consecutive rows, where
+ * each row contains the data for a single projection.
+ */
+class _AstraExport CFloat32ProjectionData3DMemory : public CFloat32Data3DMemory, public CFloat32ProjectionData3D {
+
+public:
+
+ /**
+ * Default constructor. Sets all numeric member variables to 0 and all pointer member variables to NULL.
+ *
+ * If an object is constructed using this default constructor, it must always be followed by a call
+ * to one of the init() methods before the object can be used. Any use before calling init() is not allowed,
+ * except calling the member function isInitialized().
+ *
+ */
+ CFloat32ProjectionData3DMemory();
+
+ /**
+ * Constructor. Create an instance of the CFloat32ProjectionData3DMemory class without initializing the data.
+ *
+ * Memory is allocated for the data block. The allocated memory is not cleared and
+ * its contents after construction is undefined. Construction may be followed by a
+ * call to copyData() to fill the memory block.
+ * The size of the data is determined by the specified projection geometry object.
+ *
+ * @param _pGeometry Projection Geometry object. This object will be HARDCOPIED into this class.
+ */
+ CFloat32ProjectionData3DMemory(CProjectionGeometry3D* _pGeometry);
+
+ /**
+ * Constructor. Create an instance of the CFloat32ProjectionData3DMemory class with initialization of the data.
+ *
+ * Creates an instance of the CFloat32ProjectionData3DMemory class. Memory
+ * is allocated for the data block and the contents of the memory pointed to by
+ * _pfData is copied into the allocated memory.
+ * The size of the data is determined by the specified projection geometry object.
+ *
+ * @param _pGeometry Projection Geometry object. This object will be HARDCOPIED into this class.
+ * @param _pfData pointer to a one-dimensional float32 data block
+ */
+ CFloat32ProjectionData3DMemory(CProjectionGeometry3D* _pGeometry, float32* _pfData);
+
+ /**
+ * Constructor. Create an instance of the CFloat32ProjectionData3DMemory class filled with scalar data.
+ *
+ * Creates an instance of the CFloat32ProjectionData3DMemory class. Memory
+ * is allocated for the data block and the contents of the memory pointed to by
+ * _pfData is copied into the allocated memory.
+ * The size of the data is determined by the specified projection geometry object.
+ *
+ * @param _pGeometry Projection Geometry object. This object will be HARDCOPIED into this class.
+ * @param _fScalar scalar data
+ */
+ CFloat32ProjectionData3DMemory(CProjectionGeometry3D* _pGeometry, float32 _fScalar);
+
+ /**
+ * Destructor.
+ */
+ virtual ~CFloat32ProjectionData3DMemory();
+
+ /** Initialization. Initializes an instance of the CFloat32ProjectionData3DMemory class, without filling the data block.
+ *
+ * Initializes an instance of the CFloat32ProjectionData3DMemory class. Memory is allocated for the
+ * data block. The allocated memory is not cleared and its contents after
+ * construction is undefined. Initialization may be followed by a call to
+ * copyData() to fill the memory block. If the object has been initialized before, the
+ * object is reinitialized and memory is freed and reallocated if necessary.
+ *
+ * @param _pGeometry Projection Geometry of the data. This object will be HARDCOPIED into this class.
+ * @return Initialization of the base class successfull.
+ */
+ bool initialize(CProjectionGeometry3D* _pGeometry);
+
+ /** Initialization. Initializes an instance of the CFloat32ProjectionData3DMemory class with scalar initialization.
+ *
+ * Initializes an instance of the CFloat32ProjectionData3DMemory class. Memory
+ * is allocated for the data block and the contents of the memory pointed to by
+ * _pfData is copied into the allocated memory. If the object has been initialized before, the
+ * object is reinitialized and memory is freed and reallocated if necessary.
+ *
+ * @param _pGeometry Projection Geometry of the data. This object will be HARDCOPIED into this class.
+ * @param _fScalar scalar value
+ */
+ bool initialize(CProjectionGeometry3D* _pGeometry, float32 _fScalar);
+
+ /** Initialization. Initializes an instance of the CFloat32ProjectionData3DMemory class with initialization of the data block.
+ *
+ * Initializes an instance of the CFloat32ProjectionData3DMemory class. Memory
+ * is allocated for the data block and the contents of the memory pointed to by
+ * _pfData is copied into the allocated memory. If the object has been initialized before, the
+ * object is reinitialized and memory is freed and reallocated if necessary.
+ *
+ * @param _pGeometry Projection Geometry of the data. This object will be HARDCOPIED into this class.
+ * @param _pfData pointer to a one-dimensional float32 data block
+ */
+ bool initialize(CProjectionGeometry3D* _pGeometry, const float32* _pfData);
+
+ /** Fetch a COPY of a projection of the data. Note that if you update the 2D data slice, the data in the
+ * 3D data object will remain unaltered. To copy the data back in the 3D-volume you must return the data by calling 'returnProjection'.
+ *
+ * @param _iProjectionNr projection number
+ * @return Volume data object
+ */
+ virtual CFloat32VolumeData2D* fetchProjection(int _iProjectionNr) const;
+
+ /** Return a projection slice to the 3D data. The data will be deleted. If the slice was fetched with
+ * 'fetchProjection', the data will be stored first.
+ *
+ * @param _iProjectionNr projection number
+ * @param _pProjection 2D Projection image
+ */
+ virtual void returnProjection(int _iProjectionNr, CFloat32VolumeData2D* _pProjection);
+
+ /** Fetch a COPY of a sinogram slice of the data. Note that if you update the 2D data slice, the data in the
+ * 3D data object will remain unaltered. To copy the data back in the 3D-volume you must return the data by calling 'returnSlice'.
+ *
+ * @param _iSliceNr slice number
+ * @return Sinogram data object
+ */
+ virtual CFloat32ProjectionData2D* fetchSinogram(int _iSliceNr) const;
+
+ /** This SLOW function returns a detector value stored a specific index in the array.
+ * Reading values in this way might cause a lot of unnecessary memory operations, don't
+ * use it in time-critical code.
+ *
+ * @param _iIndex Index in the array if the data were stored completely in main memory
+ * @return The value the location specified by _iIndex
+ */
+ virtual float32 getDetectorValue(int _iIndex);
+
+ /** This SLOW function stores a detector value at a specific index in the array.
+ * Writing values in this way might cause a lot of unnecessary memory operations, don't
+ * use it in time-critical code.
+ *
+ * @param _iIndex Index in the array if the data were stored completely in main memory
+ * @param _fValue The value to be stored at the location specified by _iIndex
+ */
+ virtual void setDetectorValue(int _iIndex, float32 _fValue);
+
+ /** Return a sinogram slice to the 3d data. The data will be stored in the 3D Data object.
+ *
+ * @param _iSliceNr slice number
+ * @param _pSinogram2D 2D Sinogram Object.
+ */
+ virtual void returnSinogram(int _iSliceNr, CFloat32ProjectionData2D* _pSinogram2D);
+
+ /** Which type is this class?
+ *
+ * @return DataType: PROJECTION
+ */
+ virtual EDataType getType() const;
+
+ /**
+ * Overloaded Operator: data = data (pointwise)
+ *
+ * @param _dataIn r-value
+ * @return l-value
+ */
+ CFloat32ProjectionData3DMemory& operator=(const CFloat32ProjectionData3DMemory& _dataIn);
+};
+//----------------------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------------------
+// Get type.
+inline CFloat32Data3D::EDataType CFloat32ProjectionData3DMemory::getType() const
+{
+ return PROJECTION;
+}
+//----------------------------------------------------------------------------------------
+
+} // end namespace astra
+
+#endif // _INC_ASTRA_FLOAT32PROJECTIONDATA3DMEMORY
diff --git a/include/astra/Float32VolumeData2D.h b/include/astra/Float32VolumeData2D.h
new file mode 100644
index 0000000..d7bf2f6
--- /dev/null
+++ b/include/astra/Float32VolumeData2D.h
@@ -0,0 +1,183 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_FLOAT32VOLUMEDATA2D
+#define _INC_ASTRA_FLOAT32VOLUMEDATA2D
+
+#include "Float32Data2D.h"
+#include "VolumeGeometry2D.h"
+
+namespace astra {
+
+/**
+ * This class represents two-dimensional Volume Data.
+ *
+ * It contains member functions for accessing this data and for performing
+ * elementary computations on the data.
+ * The data block is "owned" by the class, meaning that the class is
+ * responsible for deallocation of the memory involved.
+ */
+class _AstraExport CFloat32VolumeData2D : public CFloat32Data2D {
+
+public:
+
+ /** Default constructor. Sets all numeric member variables to 0 and all pointer member variables to NULL.
+ *
+ * If an object is constructed using this default constructor, it must always be followed by a call
+ * to one of the init() methods before the object can be used. Any use before calling init() is not allowed,
+ * except calling the member function isInitialized().
+ *
+ */
+ CFloat32VolumeData2D();
+
+ /** Constructor. Create an instance of the CFloat32VolumeData2D class without initializing the data.
+ *
+ * Memory is allocated for the data block. The allocated memory is not cleared and
+ * its contents after construction is undefined. Construction may be followed by a
+ * call to copyData() to fill the memory block.
+ * The size of the data is determined by the specified volume geometry object.
+ *
+ * @param _pGeometry Volume Geometry object. This object will be HARDCOPIED into this class.
+ */
+ CFloat32VolumeData2D(CVolumeGeometry2D* _pGeometry);
+
+ /** Constructor. Create an instance of the CFloat32VolumeData2D class with initialization of the data.
+ *
+ * Memory is allocated for the data block and the contents of the memory pointed to by
+ * _pfData is copied into the allocated memory.
+ * The size of the data is determined by the specified volume geometry object.
+ *
+ * @param _pGeometry Volume Geometry object. This object will be HARDCOPIED into this class.
+ * @param _pfData pointer to a one-dimensional float32 data block
+ */
+ CFloat32VolumeData2D(CVolumeGeometry2D* _pGeometry, float32* _pfData);
+
+ /** Constructor. Create an instance of the CFloat32VolumeData2D class with a scalar initialization of the data.
+ *
+ * Memory is allocated for the data block and the contents of the memory pointed to by
+ * _pfData is copied into the allocated memory.
+ * The size of the data is determined by the specified volume geometry object.
+ *
+ * @param _pGeometry Volume Geometry object. This object will be HARDCOPIED into this class.
+ * @param _fScalar scalar value to be put at each index.
+ */
+ CFloat32VolumeData2D(CVolumeGeometry2D* _pGeometry, float32 _fScalar);
+
+ /**
+ * Copy constructor
+ */
+ CFloat32VolumeData2D(const CFloat32VolumeData2D& _other);
+
+ /**
+ * Assignment operator
+ */
+ CFloat32VolumeData2D& operator=(const CFloat32VolumeData2D& _other);
+
+ /** Initialization. Initializes of the CFloat32VolumeData2D class without initializing the data.
+ *
+ * Memory is allocated for the data block. The allocated memory is not cleared and
+ * its contents after construction is undefined. Construction may be followed by a
+ * call to copyData() to fill the memory block.
+ * The size of the data is determined by the specified volume geometry object.
+ *
+ * @param _pGeometry Volume Geometry of the data. This object will be HARDCOPIED into this class.
+ * @return Initialization of the base class successfull.
+ */
+ bool initialize(CVolumeGeometry2D* _pGeometry);
+
+ /** Initialization. Initializes an instance of the CFloat32VolumeData2D class with initialization of the data.
+ *
+ * Memory is allocated for the data block and the contents of the memory pointed to by
+ * _pfData is copied into the allocated memory.
+ * The size of the data is determined by the specified volume geometry object.
+ *
+ * @param _pGeometry Volume Geometry of the data. This object will be HARDCOPIED into this class.
+ * @param _pfData pointer to a one-dimensional float32 data block
+ */
+ bool initialize(CVolumeGeometry2D* _pGeometry, const float32* _pfData);
+
+
+ /** Initialization. Initializes an instance of the CFloat32VolumeData2D class with scalar initialization of the data.
+ *
+ * Memory is allocated for the data block and the contents of the memory pointed to by
+ * _pfData is copied into the allocated memory.
+ * The size of the data is determined by the specified volume geometry object.
+ *
+ * @param _pGeometry Volume Geometry of the data. This object will be HARDCOPIED into this class.
+ * @param _fScalar scalar value to be put at each index.
+ */
+ bool initialize(CVolumeGeometry2D* _pGeometry, float32 _fScalar);
+
+ /** Destructor.
+ */
+ virtual ~CFloat32VolumeData2D();
+
+ /** Which type is this class?
+ *
+ * @return DataType: VOLUME
+ */
+ virtual EDataType getType() const;
+
+ /** Get the volume geometry.
+ *
+ * @return pointer to volume geometry.
+ */
+ virtual CVolumeGeometry2D* getGeometry() const;
+
+ /** Change the projection geometry.
+ * Note that this can't change the dimensions of the data.
+ */
+ virtual void changeGeometry(CVolumeGeometry2D* pGeometry);
+
+protected:
+
+ /** The projection geometry for this data.
+ */
+ CVolumeGeometry2D* m_pGeometry;
+
+};
+
+//----------------------------------------------------------------------------------------
+// Get the projection geometry.
+inline CVolumeGeometry2D* CFloat32VolumeData2D::getGeometry() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_pGeometry;
+}
+
+//----------------------------------------------------------------------------------------
+// Get type
+inline CFloat32Data2D::EDataType CFloat32VolumeData2D::getType() const
+{
+ return VOLUME;
+}
+
+
+} // end namespace astra
+
+#endif // _INC_ASTRA_FLOAT32VOLUMEDATA2D
diff --git a/include/astra/Float32VolumeData3D.h b/include/astra/Float32VolumeData3D.h
new file mode 100644
index 0000000..0b1bd96
--- /dev/null
+++ b/include/astra/Float32VolumeData3D.h
@@ -0,0 +1,265 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_FLOAT32VOLUMEDATA3D
+#define _INC_ASTRA_FLOAT32VOLUMEDATA3D
+
+#include "Float32Data3D.h"
+#include "Float32VolumeData2D.h"
+#include "VolumeGeometry3D.h"
+
+namespace astra {
+
+/**
+ * This asbtract class represents three-dimensional Volume Data.
+ */
+class _AstraExport CFloat32VolumeData3D : public virtual CFloat32Data3D
+{
+protected:
+ CVolumeGeometry3D * m_pGeometry;
+
+public:
+ /** Default constructor.
+ */
+ CFloat32VolumeData3D();
+
+ /** Destructor.
+ */
+ virtual ~CFloat32VolumeData3D();
+
+ /**
+ * Returns number of rows
+ *
+ * @return number of rows
+ */
+ int getRowCount() const;
+
+ /**
+ * Returns number of columns
+ *
+ * @return number of columns
+ */
+ int getColCount() const;
+
+ /**
+ * Returns number of slices
+ *
+ * @return number of slices
+ */
+ int getSliceCount() const;
+
+ /**
+ * Returns total number of volumes
+ *
+ * @return total number of volumes
+ */
+ int getVoxelTotCount() const;
+
+ /** Which type is this class?
+ *
+ * @return DataType: VOLUME
+ */
+ virtual CFloat32Data3D::EDataType getType() const;
+
+ /** Fetch a slice from the data in the x direction. Note that if you update the 2D data slice, the data in the
+ * 3d data object will remain unaltered. To copy the data you must return the data by calling 'returnSliceX'.
+ * You should not delete data fetched with this function yourself, instead call the 'returnSliceX' function.
+ *
+ * @param _iColumnIndex slice number
+ * @return Volume data object
+ */
+ virtual CFloat32VolumeData2D* fetchSliceX(int _iColumnIndex) const = 0;
+
+ /** Fetch a slice from the data in the y direction. Note that if you update the 2D data slice, the data in the
+ * 3d data object will remain unaltered. To copy the data you must return the data by calling 'returnSliceY'.
+ * You should not delete data fetched with this function yourself, instead call the 'returnSliceY' function.
+ *
+ * @param _iRowIndex slice number
+ * @return Volume data object
+ */
+ virtual CFloat32VolumeData2D* fetchSliceY(int _iRowIndex) const = 0;
+
+ /** Fetch a slice from the data in the z direction. Note that if you update the 2D data slice, the data in the
+ * 3d data object will remain unaltered. To copy the data you must return the data by calling 'returnSliceZ'.
+ * You should not delete data fetched with this function yourself, instead call the 'returnSliceZ' function.
+ *
+ * @param _iSliceIndex slice number
+ * @return Volume data object
+ */
+ virtual CFloat32VolumeData2D* fetchSliceZ(int _iSliceIndex) const = 0;
+
+ /** Return a slice from the data in the x direction to the 3d data. The data will be deleted. If the slice was
+ * fetched with 'fetchSliceX', the data will be stored first.
+ *
+ * @param _iColumnIndex slice number
+ */
+ virtual void returnSliceX(int _iColumnIndex, CFloat32VolumeData2D * _pSlice) = 0;
+
+ /** Return a slice from the data in the y direction to the 3d data. The data will be deleted. If the slice was
+ * fetched with 'fetchSliceY', the data will be stored first.
+ *
+ * @param _iRowIndex slice number
+ */
+ virtual void returnSliceY(int _iRowIndex, CFloat32VolumeData2D * _pSlice) = 0;
+
+ /** Return a slice from the data in the z direction to the 3d data. The data will be deleted. If the slice was
+ * fetched with 'fetchSliceZ', the data will be stored first.
+ *
+ * @param _iSliceIndex slice number
+ */
+ virtual void returnSliceZ(int _iSliceIndex, CFloat32VolumeData2D * _pSlice) = 0;
+
+ /** This SLOW function returns a voxel value stored at a specific index in the array.
+ * Reading values in this way might cause a lot of unnecessary memory operations, don't
+ * use it in time-critical code.
+ *
+ * @param _iIndex Index in the array if the data were stored completely in main memory
+ * @return The value stored at the location specified by _iIndex
+ */
+ virtual float32 getVoxelValue(int _iIndex) = 0;
+
+ /** This SLOW function stores a voxel value at a specific index in the array.
+ * Writing values in this way might cause a lot of unnecessary memory operations, don't
+ * use it in time-critical code.
+ *
+ * @param _iIndex Index in the array if the data were stored completely in main memory
+ * @param _fValue The value to be stored at the location specified by _iIndex
+ */
+ virtual void setVoxelValue(int _iIndex, float32 _fValue) = 0;
+
+ /**
+ * Overloaded Operator: data += data (pointwise)
+ *
+ * @param _data r-value
+ * @return l-value
+ */
+ CFloat32VolumeData3D& operator+=(const CFloat32VolumeData3D& _data);
+
+ /**
+ * Overloaded Operator: data -= data (pointwise)
+ *
+ * @param _data r-value
+ * @return l-value
+ */
+ CFloat32VolumeData3D& operator-=(const CFloat32VolumeData3D& _data);
+
+ /**
+ * Overloaded Operator: data *= data (pointwise)
+ *
+ * @param _data r-value
+ * @return l-value
+ */
+ CFloat32VolumeData3D& operator*=(const CFloat32VolumeData3D& _data);
+
+ /**
+ * Overloaded Operator: data *= scalar (pointwise)
+ *
+ * @param _fScalar r-value
+ * @return l-value
+ */
+ CFloat32VolumeData3D& operator*=(const float32& _fScalar);
+
+ /**
+ * Overloaded Operator: data /= scalar (pointwise)
+ *
+ * @param _fScalar r-value
+ * @return l-value
+ */
+ CFloat32VolumeData3D& operator/=(const float32& _fScalar);
+
+ /**
+ * Overloaded Operator: data += scalar (pointwise)
+ *
+ * @param _fScalar r-value
+ * @return l-value
+ */
+ CFloat32VolumeData3D& operator+=(const float32& _fScalar);
+
+ /**
+ * Overloaded Operator: data -= scalar (pointwise)
+ *
+ * @param _fScalar r-value
+ * @return l-value
+ */
+ CFloat32VolumeData3D& operator-=(const float32& _fScalar);
+
+ /**
+ * Gives access to the geometry stored in this class
+ *
+ * @return The geometry describing the data stored in this volume
+ */
+ virtual CVolumeGeometry3D* getGeometry() const;
+};
+
+//----------------------------------------------------------------------------------------
+// get row count
+inline int CFloat32VolumeData3D::getRowCount() const
+{
+ return m_iHeight;
+}
+
+//----------------------------------------------------------------------------------------
+// get column count
+inline int CFloat32VolumeData3D::getColCount() const
+{
+ return m_iWidth;
+}
+
+//----------------------------------------------------------------------------------------
+// get slice count
+inline int CFloat32VolumeData3D::getSliceCount() const
+{
+ return m_iDepth;
+}
+
+//----------------------------------------------------------------------------------------
+// get total voxel count
+inline int CFloat32VolumeData3D::getVoxelTotCount() const
+{
+ return m_iHeight * m_iWidth * m_iDepth;
+}
+
+//----------------------------------------------------------------------------------------
+// get type
+inline CFloat32Data3D::EDataType CFloat32VolumeData3D::getType() const
+{
+ return CFloat32Data3D::VOLUME;
+}
+
+//----------------------------------------------------------------------------------------
+// Get the volume geometry.
+inline CVolumeGeometry3D* CFloat32VolumeData3D::getGeometry() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_pGeometry;
+}
+//----------------------------------------------------------------------------------------
+
+} // end namespace astra
+
+#endif // _INC_ASTRA_FLOAT32VOLUMEDATA2D
diff --git a/include/astra/Float32VolumeData3DMemory.h b/include/astra/Float32VolumeData3DMemory.h
new file mode 100644
index 0000000..51df93e
--- /dev/null
+++ b/include/astra/Float32VolumeData3DMemory.h
@@ -0,0 +1,213 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_FLOAT32VOLUMEDATA3DMEMORY
+#define _INC_ASTRA_FLOAT32VOLUMEDATA3DMEMORY
+
+#include "Float32Data3DMemory.h"
+#include "VolumeGeometry3D.h"
+#include "Float32VolumeData3D.h"
+
+namespace astra {
+
+/**
+ * This class represents three-dimensional Volume Data where the entire data block is stored in memory.
+ */
+class _AstraExport CFloat32VolumeData3DMemory : public CFloat32Data3DMemory, public CFloat32VolumeData3D
+{
+public:
+
+ /** Default constructor. Sets all numeric member variables to 0 and all pointer member variables to NULL.
+ *
+ * If an object is constructed using this default constructor, it must always be followed by a call
+ * to one of the init() methods before the object can be used. Any use before calling init() is not allowed,
+ * except calling the member function isInitialized().
+ *
+ */
+ CFloat32VolumeData3DMemory();
+
+ /** Constructor. Create an instance of the CFloat32VolumeData3DMemory class without initializing the data.
+ *
+ * Memory is allocated for the data block. The allocated memory is not cleared and
+ * its contents after construction is undefined. Construction may be followed by a
+ * call to copyData() to fill the memory block.
+ * The size of the data is determined by the specified volume geometry object.
+ *
+ * @param _pGeometry Volume Geometry object. This object will be HARDCOPIED into this class.
+ */
+ CFloat32VolumeData3DMemory(CVolumeGeometry3D* _pGeometry);
+
+ /** Constructor. Create an instance of the CFloat32VolumeData3DMemory class with initialization of the data.
+ *
+ * Memory is allocated for the data block and the contents of the memory pointed to by
+ * _pfData is copied into the allocated memory.
+ * The size of the data is determined by the specified volume geometry object.
+ *
+ * @param _pGeometry Volume Geometry object. This object will be HARDCOPIED into this class.
+ * @param _pfData pointer to a one-dimensional float32 data block
+ */
+ CFloat32VolumeData3DMemory(CVolumeGeometry3D* _pGeometry, const float32* _pfData);
+
+ /** Constructor. Create an instance of the CFloat32VolumeData3DMemory class with scalar initialization of the data.
+ *
+ * Memory is allocated for the data block and the contents of the memory pointed to by
+ * _pfData is copied into the allocated memory.
+ * The size of the data is determined by the specified volume geometry object.
+ *
+ * @param _pGeometry Volume Geometry object. This object will be HARDCOPIED into this class.
+ * @param _fScalar scalar value
+ */
+ CFloat32VolumeData3DMemory(CVolumeGeometry3D* _pGeometry, float32 _fScalar);
+
+ /** Destructor.
+ */
+ virtual ~CFloat32VolumeData3DMemory();
+
+ /** Initialization. Initializes of the CFloat32VolumeData3DMemory class without initializing the data.
+ *
+ * Memory is allocated for the data block. The allocated memory is not cleared and
+ * its contents after construction is undefined. Construction may be followed by a
+ * call to copyData() to fill the memory block.
+ * The size of the data is determined by the specified volume geometry object.
+ *
+ * @param _pGeometry Volume Geometry of the data. This object will be HARDCOPIED into this class.
+ * @return Initialization of the base class successful.
+ */
+ bool initialize(CVolumeGeometry3D* _pGeometry);
+
+ /** Initialization. Initializes an instance of the CFloat32VolumeData3DMemory class with initialization of the data.
+ *
+ * Memory is allocated for the data block and the contents of the memory pointed to by
+ * _pfData is copied into the allocated memory.
+ * The size of the data is determined by the specified volume geometry object.
+ *
+ * @param _pGeometry Volume Geometry of the data. This object will be HARDCOPIED into this class.
+ * @param _pfData pointer to a one-dimensional float32 data block
+ */
+ bool initialize(CVolumeGeometry3D* _pGeometry, const float32* _pfData);
+
+ /** Initialization. Initializes an instance of the CFloat32VolumeData3DMemory class with scalar initialization of the data.
+ *
+ * Memory is allocated for the data block and the contents of the memory pointed to by
+ * _pfData is copied into the allocated memory.
+ * The size of the data is determined by the specified volume geometry object.
+ *
+ * @param _pGeometry Volume Geometry of the data. This object will be HARDCOPIED into this class.
+ * @param _fScalar scalar value
+ */
+ bool initialize(CVolumeGeometry3D* _pGeometry, float32 _fScalar);
+
+ /** Which type is this class?
+ *
+ * @return DataType: VOLUME
+ */
+ virtual CFloat32Data3D::EDataType getType() const;
+
+ /** Get the volume geometry.
+ *
+ * @return pointer to volume geometry.
+ */
+ CVolumeGeometry3D* getGeometry();
+
+ /**
+ * Gets a slice, containing all voxels with a given x (= column) index.
+ */
+ CFloat32VolumeData2D * fetchSliceX(int _iColumnIndex) const;
+
+ /**
+ * Gets a slice, containing all voxels with a given y (= row) index.
+ */
+ CFloat32VolumeData2D * fetchSliceY(int _iRowIndex) const;
+
+ /**
+ * Gets a slice, containing all voxels with a given z (= slice) index.
+ */
+ CFloat32VolumeData2D * fetchSliceZ(int _iSliceIndex) const;
+
+ /**
+ * Gets a slice, containing all voxels with a given x (= column) index.
+ */
+ void returnSliceX(int _iColumnIndex, CFloat32VolumeData2D * _pSliceData);
+
+ /**
+ * Gets a slice, containing all voxels with a given y (= row) index.
+ */
+ void returnSliceY(int _iRowIndex, CFloat32VolumeData2D * _pSliceData);
+
+ /**
+ * Copies data from a 2D slice containing all voxels with a given z (= slice) index to the
+ * 3D memory stored in this class.
+ */
+ void returnSliceZ(int _iSliceIndex, CFloat32VolumeData2D * _pSliceData);
+
+ /** This SLOW function returns a volume value stored a specific index in the array.
+ * Reading values in this way might cause a lot of unnecessary memory operations, don't
+ * use it in time-critical code.
+ *
+ * @param _iIndex Index in the array if the data were stored completely in main memory
+ * @return The value the location specified by _iIndex
+ */
+ virtual float32 getVoxelValue(int _iIndex);
+
+ /** This SLOW function stores a voxel value at a specific index in the array.
+ * Writing values in this way might cause a lot of unnecessary memory operations, don't
+ * use it in time-critical code.
+ *
+ * @param _iIndex Index in the array if the data were stored completely in main memory
+ * @param _fValue The value to be stored at the location specified by _iIndex
+ */
+ virtual void setVoxelValue(int _iIndex, float32 _fValue);
+
+ /**
+ * Overloaded Operator: data = data (pointwise)
+ *
+ * @param _dataIn r-value
+ * @return l-value
+ */
+ CFloat32VolumeData3DMemory& operator=(const CFloat32VolumeData3DMemory& _dataIn);
+};
+
+//----------------------------------------------------------------------------------------
+// Get the projection geometry.
+inline CVolumeGeometry3D* CFloat32VolumeData3DMemory::getGeometry()
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_pGeometry;
+}
+
+//----------------------------------------------------------------------------------------
+// Get type
+inline CFloat32Data3D::EDataType CFloat32VolumeData3DMemory::getType() const
+{
+ return VOLUME;
+}
+
+
+} // end namespace astra
+
+#endif // _INC_ASTRA_FLOAT32VOLUMEDATA3DMEMORY
diff --git a/include/astra/ForwardProjectionAlgorithm.h b/include/astra/ForwardProjectionAlgorithm.h
new file mode 100644
index 0000000..147002b
--- /dev/null
+++ b/include/astra/ForwardProjectionAlgorithm.h
@@ -0,0 +1,225 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_FORWARDPROJECTIONALGORITHM
+#define _INC_ASTRA_FORWARDPROJECTIONALGORITHM
+
+#include "Algorithm.h"
+
+#include "Globals.h"
+
+#include "Projector2D.h"
+#include "Float32ProjectionData2D.h"
+#include "Float32VolumeData2D.h"
+
+#include "DataProjector.h"
+
+namespace astra {
+
+/**
+ * \brief
+ * This class contains the implementation of an algorithm that creates a forward projection
+ * of a volume object and stores it into a sinogram.
+ *
+ * \par XML Configuration
+ * \astra_xml_item{ProjectorId, integer, Identifier of a projector as it is stored in the ProjectorManager.}
+ * \astra_xml_item{VolumeDataId, integer, Identifier of the volume data object as it is stored in the DataManager.}
+ * \astra_xml_item{ProjectionDataId, integer, Identifier of the resulting projection data object as it is stored in the DataManager.}
+ * \astra_xml_item_option{VolumeMaskId, integer, not used, Identifier of a volume data object that acts as a volume mask. 0 = don't use this pixel. 1 = use this pixel. }
+ * \astra_xml_item_option{SinogramMaskId, integer, not used, Identifier of a projection data object that acts as a projection mask. 0 = don't use this ray. 1 = use this ray.}
+ *
+ * \par MATLAB example
+ * \astra_code{
+ * cfg = astra_struct('FP');\n
+ * cfg.ProjectorId = proj_id;\n
+ * cfg.VolumeDataId = vol_id;\n
+ * cfg.ProjectionDataId = sino_id;\n
+ * alg_id = astra_mex_algorithm('create'\, cfg);\n
+ * astra_mex_algorithm('run'\, alg_id);\n
+ * astra_mex_algorithm('delete'\, alg_id);\n
+ * }
+ *
+ */
+class _AstraExport CForwardProjectionAlgorithm : public CAlgorithm {
+
+protected:
+
+ /** Init stuff
+ */
+ virtual void _init();
+
+ /** Initial clearing. Only to be used by constructors.
+ */
+ virtual void _clear();
+
+ /** Check the values of this object. If everything is ok, the object can be set to the initialized state.
+ * The following statements are then guaranteed to hold:
+ * - valid projector
+ * - valid data objects
+ */
+ virtual bool _check();
+
+ //< Projector object.
+ CProjector2D* m_pProjector;
+ //< ProjectionData2D object containing the sinogram.
+ CFloat32ProjectionData2D* m_pSinogram;
+ //< VolumeData2D object containing the phantom.
+ CFloat32VolumeData2D* m_pVolume;
+
+ // data projector
+ astra::CDataProjectorInterface* m_pForwardProjector;
+
+ // ray or voxel-driven projector code?
+ bool m_bUseVoxelProjector;
+
+ //< Dataobject containing fixed volume mask (0 = don't project)
+ CFloat32VolumeData2D* m_pVolumeMask;
+ //< Use the fixed reconstruction mask?
+ bool m_bUseVolumeMask;
+
+ //< Dataobject containing fixed reconstruction mask (0 = don't project)
+ CFloat32ProjectionData2D* m_pSinogramMask;
+ //< Use the fixed reconstruction mask?
+ bool m_bUseSinogramMask;
+
+public:
+
+ // type of the algorithm, needed to register with CAlgorithmFactory
+ static std::string type;
+
+ /** Default constructor, containing no code.
+ */
+ CForwardProjectionAlgorithm();
+
+ /** Initializing constructor.
+ *
+ * @param _pProjector Projector to use.
+ * @param _pVolume VolumeData2D object containing the phantom to compute sinogram from
+ * @param _pSinogram ProjectionData2D object to store sinogram data in.
+ */
+ CForwardProjectionAlgorithm(CProjector2D* _pProjector,
+ CFloat32VolumeData2D* _pVolume,
+ CFloat32ProjectionData2D* _pSinogram);
+
+ /** Destructor.
+ */
+ virtual ~CForwardProjectionAlgorithm();
+
+ /** Clear this class.
+ */
+ virtual void clear();
+
+ /** Initialize class.
+ *
+ * @param _pProjector Projector to use.
+ * @param _pVolume VolumeData2D object containing the phantom to compute sinogram from
+ * @param _pSinogram ProjectionData2D object to store sinogram data in.
+ * @return success
+ */
+ bool initialize(CProjector2D* _pProjector,
+ CFloat32VolumeData2D* _pVolume,
+ CFloat32ProjectionData2D* _pSinogram);
+
+ /** Initialize the algorithm with a config object.
+ *
+ * @param _cfg Configuration Object
+ * @return initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ /** Get all information parameters
+ *
+ * @return map with all boost::any object
+ */
+ virtual map<string,boost::any> getInformation();
+
+ /** Get a single piece of information represented as a boost::any
+ *
+ * @param _sIdentifier identifier string to specify which piece of information you want
+ * @return boost::any object
+ */
+ virtual boost::any getInformation(std::string _sIdentifier);
+
+ /** Set a fixed reconstruction mask. A pixel will only be used in the reconstruction if the
+ * corresponding value in the mask is 1.
+ *
+ * @param _pMask Volume Data object containing fixed reconstruction mask
+ * @param _bEnable enable the use of this mask
+ */
+ void setVolumeMask(CFloat32VolumeData2D* _pMask, bool _bEnable = true);
+
+ /** Set a fixed sinogram mask. A detector value will only be used in the reconstruction if the
+ * corresponding value in the mask is 1.
+ *
+ * @param _pMask Projection Data object containing fixed sinogram mask
+ * @param _bEnable enable the use of this mask
+ */
+ void setSinogramMask(CFloat32ProjectionData2D* _pMask, bool _bEnable = true);
+
+ /** Get projector object
+ *
+ * @return projector
+ */
+ CProjector2D* getProjector() const;
+
+ /** Get sinogram data object
+ *
+ * @return sinogram data object
+ */
+ CFloat32ProjectionData2D* getSinogram() const;
+
+ /** Get volume data object
+ *
+ * @return volume data object
+ */
+ CFloat32VolumeData2D* getVolume() const;
+
+ /** Perform a number of iterations.
+ *
+ * @param _iNrIterations amount of iterations to perform.
+ */
+ virtual void run(int _iNrIterations = 0);
+
+ /** Get a description of the class.
+ *
+ * @return description string
+ */
+ virtual std::string description() const;
+
+
+};
+
+// inline functions
+inline std::string CForwardProjectionAlgorithm::description() const { return CForwardProjectionAlgorithm::type; };
+inline CProjector2D* CForwardProjectionAlgorithm::getProjector() const { return m_pProjector; }
+inline CFloat32ProjectionData2D* CForwardProjectionAlgorithm::getSinogram() const { return m_pSinogram; }
+inline CFloat32VolumeData2D* CForwardProjectionAlgorithm::getVolume() const { return m_pVolume; }
+
+} // end namespace
+
+#endif
diff --git a/include/astra/Fourier.h b/include/astra/Fourier.h
new file mode 100644
index 0000000..290c094
--- /dev/null
+++ b/include/astra/Fourier.h
@@ -0,0 +1,127 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_FOURIER
+#define _INC_ASTRA_FOURIER
+
+#include "Globals.h"
+
+namespace astra {
+
+
+/**
+ * Perform a 1D DFT or inverse DFT.
+ *
+ * @param iLength number of elements
+ * @param pfRealIn real part of input
+ * @param pfImaginaryIn imaginary part of input
+ * @param pfRealOut real part of output
+ * @param pfImaginaryOut imaginary part of output
+ * @param iStrideIn distance between elements in pf*In
+ * @param iStrideOut distance between elements in pf*Out
+ * @param bInverse if true, perform an inverse DFT
+ */
+
+void _AstraExport discreteFourierTransform1D(unsigned int iLength,
+ const float32* pfRealIn,
+ const float32* pfImaginaryIn,
+ float32* pfRealOut,
+ float32* pfImaginaryOut,
+ unsigned int iStrideIn,
+ unsigned int iStrideOut,
+ bool bInverse);
+
+/**
+ * Perform a 2D DFT or inverse DFT.
+ *
+ * @param iHeight number of rows
+ * @param iWidth number of columns
+ * @param pfRealIn real part of input
+ * @param pfImaginaryIn imaginary part of input
+ * @param pfRealOut real part of output
+ * @param pfImaginaryOut imaginary part of output
+ * @param bInverse if true, perform an inverse DFT
+ */
+
+void _AstraExport discreteFourierTransform2D(unsigned int iHeight, unsigned int iWidth,
+ const float32* pfRealIn,
+ const float32* pfImaginaryIn,
+ float32* pfRealOut,
+ float32* pfImaginaryOut,
+ bool bInverse);
+
+/**
+ * Perform a 1D FFT or inverse FFT. The size must be a power of two.
+ * This transform can be done in-place, so the input and output pointers
+ * may point to the same data.
+ *
+ * @param iLength number of elements, must be a power of two
+ * @param pfRealIn real part of input
+ * @param pfImaginaryIn imaginary part of input
+ * @param pfRealOut real part of output
+ * @param pfImaginaryOut imaginary part of output
+ * @param iStrideIn distance between elements in pf*In
+ * @param iStrideOut distance between elements in pf*Out
+ * @param bInverse if true, perform an inverse DFT
+ */
+
+void _AstraExport fastTwoPowerFourierTransform1D(unsigned int iLength,
+ const float32* pfRealIn,
+ const float32* pfImaginaryIn,
+ float32* pfRealOut,
+ float32* pfImaginaryOut,
+ unsigned int iStrideIn,
+ unsigned int iStrideOut,
+ bool bInverse);
+
+/**
+ * Perform a 2D FFT or inverse FFT. The size must be a power of two.
+ * This transform can be done in-place, so the input and output pointers
+ * may point to the same data.
+ *
+ * @param iHeight number of rows, must be a power of two
+ * @param iWidth number of columns, must be a power of two
+ * @param pfRealIn real part of input
+ * @param pfImaginaryIn imaginary part of input
+ * @param pfRealOut real part of output
+ * @param pfImaginaryOut imaginary part of output
+ * @param bInverse if true, perform an inverse DFT
+ */
+
+void _AstraExport fastTwoPowerFourierTransform2D(unsigned int iHeight,
+ unsigned int iWidth,
+ const float32* pfRealIn,
+ const float32* pfImaginaryIn,
+ float32* pfRealOut,
+ float32* pfImaginaryOut,
+ bool bInverse);
+
+
+}
+
+#endif
diff --git a/include/astra/Globals.h b/include/astra/Globals.h
new file mode 100644
index 0000000..9407ef9
--- /dev/null
+++ b/include/astra/Globals.h
@@ -0,0 +1,309 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_GLOBALS
+#define _INC_ASTRA_GLOBALS
+
+/*! \mainpage The ASTRA-toolbox
+ *
+ * <img src="../images/logo_big.png"/>
+ */
+
+
+//----------------------------------------------------------------------------------------
+
+#ifdef _MSC_VER
+
+// disable warning: 'fopen' was declared deprecated
+#pragma warning (disable : 4996)
+// disable warning: C++ exception handler used, but unwind semantics are not enables
+#pragma warning (disable : 4530)
+// disable warning: no suitable definition provided for explicit template instantiation request
+#pragma warning (disable : 4661)
+
+#endif
+
+//----------------------------------------------------------------------------------------
+// standard includes
+#include <cassert>
+#include <iostream>
+#include <fstream>
+#include <math.h>
+#include <boost/static_assert.hpp>
+#include <boost/throw_exception.hpp>
+
+//----------------------------------------------------------------------------------------
+// macro's
+
+#define ASTRA_TOOLBOXVERSION_MAJOR 1
+#define ASTRA_TOOLBOXVERSION_MINOR 1
+#define ASTRA_TOOLBOXVERSION ((ASTRA_TOOLBOXVERSION_MAJOR)*100 + (ASTRA_TOOLBOXVERSION_MINOR))
+#define ASTRA_TOOLBOXVERSION_STRING "1.1"
+
+
+#define ASTRA_ASSERT(a) assert(a)
+
+#define ASTRA_CONFIG_CHECK(value, type, msg) if (!(value)) { cout << "Configuration Error in " << type << ": " << msg << endl; return false; }
+
+#define ASTRA_CONFIG_WARNING(type, msg) { cout << "Warning in " << type << ": " << msg << endl; }
+
+
+#define ASTRA_DELETE(a) if (a) { delete a; a = NULL; }
+#define ASTRA_DELETE_ARRAY(a) if (a) { delete[] a; a = NULL; }
+
+#ifdef _MSC_VER
+
+#ifdef DLL_EXPORTS
+#define _AstraExport __declspec(dllexport)
+#define EXPIMP_TEMPLATE
+#else
+#define _AstraExport __declspec(dllimport)
+#define EXPIMP_TEMPLATE extern
+#endif
+
+#else
+
+#define _AstraExport
+
+#endif
+
+
+//----------------------------------------------------------------------------------------
+// typedefs
+namespace astra {
+ typedef float float32;
+ typedef double float64;
+ typedef unsigned short int uint16;
+ typedef signed short int sint16;
+ typedef unsigned char uchar8;
+ typedef signed char schar8;
+
+ typedef int int32;
+ typedef short int int16;
+}
+
+//----------------------------------------------------------------------------------------
+// globals vars & functions
+//namespace astra {
+//#define ToolboxVersion 0.1f;
+
+//float32 getVersion() { return ToolboxVersion; }
+
+//_AstraExport bool cudaEnabled() {
+//#ifdef ASTRA_CUDA
+// return true;
+//#else
+// return false;
+//#endif
+//}
+//}
+
+//----------------------------------------------------------------------------------------
+// errors
+namespace astra {
+
+typedef enum {ASTRA_SUCCESS,
+ ASTRA_ERROR_NOT_INITIALIZED,
+ ASTRA_ERROR_INVALID_FILE,
+ ASTRA_ERROR_OUT_OF_RANGE,
+ ASTRA_ERROR_DIMENSION_MISMATCH,
+ ASTRA_ERROR_EXTERNAL_LIBRARY,
+ ASTRA_ERROR_ALLOCATION,
+ ASTRA_ERROR_NOT_IMPLEMENTED} AstraError;
+}
+
+
+//----------------------------------------------------------------------------------------
+// variables
+namespace astra {
+ const float32 PI = 3.14159265358979323846264338328f;
+ const float32 PI32 = 3.14159265358979323846264338328f;
+ const float32 PIdiv2 = PI / 2;
+ const float32 PIdiv4 = PI / 4;
+ const float32 eps = 1e-7f;
+}
+
+//----------------------------------------------------------------------------------------
+// math
+namespace astra {
+
+ inline float32 cos_73s(float32 x)
+ {
+ /*
+ const float32 c1 = 0.999999953464f;
+ const float32 c2 = -0.4999999053455f;
+ const float32 c3 = 0.0416635846769f;
+ const float32 c4 = -0.0013853704264f;
+ const float32 c5 = 0.000023233f;
+ */
+ const float c1= (float)0.99940307;
+ const float c2= (float)-0.49558072;
+ const float c3= (float)0.03679168;
+
+ float32 x2;
+ x2 = x * x;
+ //return (c1 + x2*(c2 + x2*(c3 + x2*(c4 + c5*x2))));
+ return (c1 + x2*(c2 + c3 * x2));
+ }
+
+ inline float32 fast_cos(float32 x)
+ {
+ int quad;
+
+ //x = fmod(x, 2*PI); // Get rid of values > 2* pi
+ if (x < 0) x =- x; // cos(-x) = cos(x)
+ quad = int(x/PIdiv2); // Get quadrant # (0 to 3)
+ switch (quad) {
+ case 0: return cos_73s(x);
+ case 1: return -cos_73s(PI-x);
+ case 2: return -cos_73s(x-PI);
+ case 3: return cos_73s(2*PI-x);
+ }
+ return 0.0f;
+ }
+
+ inline float32 fast_sin(float32 x){
+ return fast_cos(PIdiv2-x);
+ }
+
+}
+
+//----------------------------------------------------------------------------------------
+// structs
+namespace astra {
+ /**
+ * Struct for storing pixel weigths
+ **/
+ struct SPixelWeight
+ {
+ int m_iIndex;
+ float32 m_fWeight;
+ };
+
+ /**
+ * Struct combining some properties of a detector in 1D detector row
+ **/
+ struct SDetector2D
+ {
+ int m_iIndex;
+ int m_iAngleIndex;
+ int m_iDetectorIndex;
+ };
+
+ /**
+ * Struct combining some properties of a detector in 2D detector array
+ **/
+ struct SDetector3D
+ {
+ int m_iIndex;
+ int m_iAngleIndex;
+ int m_iDetectorIndex;
+ int m_iSliceIndex;
+ };
+}
+//----------------------------------------------------------------------------------------
+// some toys
+
+// safe reinterpret cast
+template <class To, class From>
+To safe_reinterpret_cast(From from)
+{
+ BOOST_STATIC_ASSERT(sizeof(From) <= sizeof(To));
+ return reinterpret_cast<To>(from);
+}
+
+//----------------------------------------------------------------------------------------
+// functions for testing
+template<typename T>
+inline void writeArray(T*** arr, int dim1, int dim2, int dim3, const std::string& filename)
+{
+ std::ofstream out(filename.c_str());
+ int i1, i2, i3;
+ for (i1 = 0; i1 < dim1; ++i1) {
+ for (i2 = 0; i2 < dim2; ++i2) {
+ for (i3 = 0; i3 < dim3; ++i3) {
+ out << arr[i1][i2][i3] << " ";
+ }
+ out << std::endl;
+ }
+ out << std::endl;
+ }
+ out.close();
+}
+
+template<typename T>
+inline void writeArray(T** arr, int dim1, int dim2, const std::string& filename)
+{
+ std::ofstream out(filename.c_str());
+ for (int i1 = 0; i1 < dim1; i1++) {
+ for (int i2 = 0; i2 < dim2; i2++) {
+ out << arr[i1][i2] << " ";
+ }
+ out << std::endl;
+ }
+ out.close();
+}
+
+template<typename T>
+inline void writeArray(T* arr, int dim1, const std::string& filename)
+{
+ std::ofstream out(filename.c_str());
+ for (int i1 = 0; i1 < dim1; i1++) {
+ out << arr[i1] << " ";
+ }
+ out.close();
+}
+namespace astra {
+_AstraExport inline int getVersion() { return ASTRA_TOOLBOXVERSION; }
+_AstraExport inline const char* getVersionString() { return ASTRA_TOOLBOXVERSION_STRING; }
+#ifdef ASTRA_CUDA
+_AstraExport inline bool cudaEnabled() { return true; }
+#else
+_AstraExport inline bool cudaEnabled() { return false; }
+#endif
+}
+//----------------------------------------------------------------------------------------
+// portability between MSVC and Linux/gcc
+
+#ifndef _MSC_VER
+#include "swrap.h"
+#define EXPIMP_TEMPLATE
+
+#if !defined(FORCEINLINE) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
+#define FORCEINLINE inline __attribute__((__always_inline__))
+#else
+#define FORCEINLINE inline
+#endif
+
+#else
+
+#define FORCEINLINE __forceinline
+
+#endif
+
+#endif
diff --git a/include/astra/Logger.h b/include/astra/Logger.h
new file mode 100644
index 0000000..ae064fe
--- /dev/null
+++ b/include/astra/Logger.h
@@ -0,0 +1,72 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_LOGGER
+#define _INC_ASTRA_LOGGER
+
+#include <cstdio>
+
+namespace astra
+{
+
+/**
+ * This is the first stab at a decent logger. If the file "astra_logger.txt", it will be replaced
+ * with the text sent to this logger. If the file doesn't exist when the app starts, nothing is written.
+ */
+class CLogger
+{
+ static std::FILE * m_pOutFile;
+ static bool m_bInitialized;
+
+ static void _assureIsInitialized();
+
+ CLogger();
+
+public:
+
+ /**
+ * Writes a line to the log file (newline is added). Ignored if logging is turned off.
+ *
+ * @param _text char pointer to text in line
+ */
+ static void writeLine(const char * _text);
+
+ /**
+ * Formats and writes a CUDA error to the log file. Ignored if logging is turned off.
+ *
+ * @param _fileName filename where error occurred (typically __FILE__)
+ * @param _line line in file (typically __LINE__)
+ * @param _errString string describing the error, can be output of cudaGetErrorString
+ */
+ static void writeTerminalCUDAError(const char * _fileName, int _iLine, const char * _errString);
+};
+
+}
+
+#endif /* _INC_ASTRA_LOGGER */
+
diff --git a/include/astra/ParallelBeamBlobKernelProjector2D.h b/include/astra/ParallelBeamBlobKernelProjector2D.h
new file mode 100644
index 0000000..38b209c
--- /dev/null
+++ b/include/astra/ParallelBeamBlobKernelProjector2D.h
@@ -0,0 +1,232 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_PARALLELBEAMBLOBPROJECTOR
+#define _INC_ASTRA_PARALLELBEAMBLOBPROJECTOR
+
+#include "ParallelProjectionGeometry2D.h"
+#include "Float32Data2D.h"
+#include "Projector2D.h"
+
+namespace astra
+{
+
+/** This class implements a two-dimensional projector based on a blob-kernel.
+ * A more detailed description (in dutch) is available at
+ * http://www.astra.ua.ac.be/wiki/images/6/6e/Uitleg_blob_projector.pdf
+ *
+ * \par XML Configuration
+ * type = "blob"
+ * \astra_xml_item{ProjectionGeometry, xml node, The geometry of the projection.}
+ * \astra_xml_item{VolumeGeometry, xml node, The geometry of the volume.}
+ * \astra_xml_item{Kernel, xml node, Kernel details. See below.}
+ *
+ * \par XML Configuration of the Kernel
+ * \astra_xml_item{KernelSize, float, Radius of the kernel.}
+ * \astra_xml_item{SampleRate, float, Sample rate of the kernel.}
+ * \astra_xml_item{SampleCount, integer, Number of samples.}
+ * \astra_xml_item{KernelValues, vector of float, Samples of the kernels starting at distance 0.}
+ *
+ * \par MATLAB example
+ * \astra_code{
+ * cfg = astra_struct('blob');\n
+ * cfg.ProjectionGeometry = proj_geom;\n
+ * cfg.VolumeGeometry = vol_geom;\n
+ * cfg.Kernel.KernelSize = 2;\n
+ * cfg.Kernel.SampleRate = 0.01;\n
+ * cfg.Kernel.SampleCount = length(0:0.01:2);\n
+ * cfg.Kernel.KernelValues = kaiserBessel(2\, 10.4\, 2\, 0:0.01:2);\n
+ * proj_id = astra_mex_projector('create'\, cfg);\n
+ * }
+ */
+class _AstraExport CParallelBeamBlobKernelProjector2D : public CProjector2D {
+
+protected:
+
+ /** Initial clearing. Only to be used by constructors.
+ */
+ virtual void _clear();
+
+ /** Check the values of this object. If everything is ok, the object can be set to the initialized state.
+ * The following statements are then guaranteed to hold:
+ * - no NULL pointers
+ * - all sub-objects are initialized properly
+ * - blobvalues are ok
+ */
+ virtual bool _check();
+
+public:
+
+ // type of the projector, needed to register with CProjectorFactory
+ static std::string type;
+
+ /** Default constructor.
+ */
+ CParallelBeamBlobKernelProjector2D();
+
+ /** Constructor.
+ *
+ * @param _pProjectionGeometry Information class about the geometry of the projection. Will be HARDCOPIED.
+ * @param _pReconstructionGeometry Information class about the geometry of the reconstruction volume. Will be HARDCOPIED.
+ * @param _fBlobSize Width of the blob. In units of PixelSize.
+ * @param _fBlobSampleRate Spacing between two blob samples. (= _fBlobSize/_iBlobSampleCount)
+ * @param _iBlobSampleCount Number of samples.
+ * @param _pfBlobValues Array of _iBlobSampleCount blob evaluations.
+ */
+ CParallelBeamBlobKernelProjector2D(CParallelProjectionGeometry2D* _pProjectionGeometry,
+ CVolumeGeometry2D* _pReconstructionGeometry,
+ float32 _fBlobSize,
+ float32 _fBlobSampleRate,
+ int _iBlobSampleCount,
+ float32* _pfBlobValues);
+
+ /** Destructor, is virtual to show that we are aware subclass destructor are called.
+ */
+ ~CParallelBeamBlobKernelProjector2D();
+
+ /** Initialize the projector with a config object.
+ *
+ * @param _cfg Configuration Object
+ * @return initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ /** Initialize the projector.
+ *
+ * @param _pProjectionGeometry Information class about the geometry of the projection. Will be HARDCOPIED.
+ * @param _pReconstructionGeometry Information class about the geometry of the reconstruction volume. Will be HARDCOPIED.
+ * @param _fBlobSize Width of the blob. In units of PixelSize.
+ * @param _fBlobSampleRate Spacing between two blob samples. (= _fBlobSize/_iBlobSampleCount)
+ * @param _iBlobSampleCount Number of samples.
+ * @param _pfBlobValues Array of _iBlobSampleCount blob evaluations. Will be HARDCOPIED.
+ */
+ bool initialize(CParallelProjectionGeometry2D* _pProjectionGeometry,
+ CVolumeGeometry2D* _pReconstructionGeometry,
+ float32 _fBlobSize,
+ float32 _fBlobSampleRate,
+ int _iBlobSampleCount,
+ float32* _pfBlobValues);
+
+ /** Clear this class.
+ */
+ virtual void clear();
+
+ /** Returns the number of weights required for storage of all weights of one projection.
+ *
+ * @param _iProjectionIndex Index of the projection (zero-based).
+ * @return Size of buffer (given in SPixelWeight elements) needed to store weighted pixels.
+ */
+ virtual int getProjectionWeightsCount(int _iProjectionIndex);
+
+ /** Compute the pixel weights for a single ray, from the source to a detector pixel.
+ *
+ * @param _iProjectionIndex Index of the projection
+ * @param _iDetectorIndex Index of the detector pixel
+ * @param _pWeightedPixels Pointer to a pre-allocated array, consisting of _iMaxPixelCount elements
+ * of type SPixelWeight. On return, this array contains a list of the index
+ * and weight for all pixels on the ray.
+ * @param _iMaxPixelCount Maximum number of pixels (and corresponding weights) that can be stored in _pWeightedPixels.
+ * This number MUST be greater than the total number of pixels on the ray.
+ * @param _iStoredPixelCount On return, this variable contains the total number of pixels on the
+ * ray (that have been stored in the list _pWeightedPixels).
+ */
+ virtual void computeSingleRayWeights(int _iProjectionIndex,
+ int _iDetectorIndex,
+ SPixelWeight* _pWeightedPixels,
+ int _iMaxPixelCount,
+ int& _iStoredPixelCount);
+
+ /** Create a list of detectors that are influenced by point [_iRow, _iCol].
+ *
+ * @param _iRow row of the point
+ * @param _iCol column of the point
+ * @return list of SDetector2D structs
+ */
+ virtual std::vector<SDetector2D> projectPoint(int _iRow, int _iCol);
+
+ /** Policy-based projection of all rays. This function will calculate each non-zero projection
+ * weight and use this value for a task provided by the policy object.
+ *
+ * @param _policy Policy object. Should contain prior, addWeight and posterior function.
+ */
+ template <typename Policy>
+ void project(Policy& _policy);
+
+ /** Policy-based projection of all rays of a single projection. This function will calculate
+ * each non-zero projection weight and use this value for a task provided by the policy object.
+ *
+ * @param _iProjection Wwhich projection should be projected?
+ * @param _policy Policy object. Should contain prior, addWeight and posterior function.
+ */
+ template <typename Policy>
+ void projectSingleProjection(int _iProjection, Policy& _policy);
+
+ /** Policy-based projection of a single ray. This function will calculate each non-zero
+ * projection weight and use this value for a task provided by the policy object.
+ *
+ * @param _iProjection Which projection should be projected?
+ * @param _iDetector Which detector should be projected?
+ * @param _policy Policy object. Should contain prior, addWeight and posterior function.
+ */
+ template <typename Policy>
+ void projectSingleRay(int _iProjection, int _iDetector, Policy& _policy);
+
+ /** Return the type of this projector.
+ *
+ * @return identification type of this projector
+ */
+ virtual std::string getType();
+
+protected:
+
+ /** Evaluate the blob kernel for a given distance from its center.
+ *
+ * @param _fDiff distance between hit point and blob center
+ * @return blob value
+ */
+ float32 _getBlobValue(float32 _fDiff);
+
+ float32 m_fBlobSize; //< Width of the blob
+ float32 m_fBlobSampleRate; //< At which interval are the inserted blob values evaluated?
+ int m_iBlobSampleCount; //< Number of evaluated blob samples
+ float32* m_pfBlobValues; //< Evaluated blob values
+ float32* m_pfBlobValuesNeg; //< Evaluated blob values
+
+};
+
+//----------------------------------------------------------------------------------------
+
+inline std::string CParallelBeamBlobKernelProjector2D::getType()
+{
+ return type;
+}
+
+} // namespace astra
+
+#endif
+
diff --git a/include/astra/ParallelBeamBlobKernelProjector2D.inl b/include/astra/ParallelBeamBlobKernelProjector2D.inl
new file mode 100644
index 0000000..70764b1
--- /dev/null
+++ b/include/astra/ParallelBeamBlobKernelProjector2D.inl
@@ -0,0 +1,212 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+
+
+//----------------------------------------------------------------------------------------
+// PROJECT ALL
+template <typename Policy>
+void CParallelBeamBlobKernelProjector2D::project(Policy& p)
+{
+ for (int iAngle = 0; iAngle < m_pProjectionGeometry->getProjectionAngleCount(); ++iAngle) {
+ for (int iDetector = 0; iDetector < m_pProjectionGeometry->getDetectorCount(); ++iDetector) {
+ projectSingleRay(iAngle, iDetector, p);
+ }
+ }
+}
+
+
+//----------------------------------------------------------------------------------------
+// PROJECT SINGLE PROJECTION
+template <typename Policy>
+void CParallelBeamBlobKernelProjector2D::projectSingleProjection(int _iProjection, Policy& p)
+{
+ for (int iDetector = 0; iDetector < m_pProjectionGeometry->getDetectorCount(); ++iDetector) {
+ projectSingleRay(_iProjection, iDetector, p);
+ }
+}
+
+
+
+//----------------------------------------------------------------------------------------
+// PROJECT SINGLE RAY
+template <typename Policy>
+void CParallelBeamBlobKernelProjector2D::projectSingleRay(int _iProjection, int _iDetector, Policy& p)
+{
+ ASTRA_ASSERT(m_bIsInitialized);
+
+ int iRayIndex = _iProjection * m_pProjectionGeometry->getDetectorCount() + _iDetector;
+
+ // POLICY: RAY PRIOR
+ if (!p.rayPrior(iRayIndex)) return;
+
+ // get values
+ float32 t = m_pProjectionGeometry->indexToDetectorOffset(_iDetector);
+ float32 theta = m_pProjectionGeometry->getProjectionAngle(_iProjection);
+ if (theta >= 7*PIdiv4) theta -= 2*PI;
+
+ bool flip = false;
+
+ if (theta >= 3*PIdiv4) {
+ theta -= PI;
+ t = -t;
+ flip = true;
+ }
+
+
+ if (theta <= PIdiv4) { // -pi/4 <= theta <= pi/4
+
+ // precalculate sin, cos, 1/cos
+ float32 sin_theta = sin(theta);
+ float32 cos_theta = cos(theta);
+ float32 inv_cos_theta = 1.0f / cos_theta;
+
+ // precalculate other stuff
+ float32 lengthPerRow = m_pVolumeGeometry->getPixelLengthY() * inv_cos_theta;
+ float32 updatePerRow = sin_theta * lengthPerRow;
+ float32 inv_pixelLengthX = 1.0f / m_pVolumeGeometry->getPixelLengthX();
+ float32 pixelLengthX_over_blobSize = m_pVolumeGeometry->getPixelLengthX() / m_fBlobSize;
+
+ // some variables
+ int row, col, xmin, xmax;
+ float32 P, x, d;
+
+ // calculate P and x for row 0
+ P = (t - sin_theta * m_pVolumeGeometry->pixelRowToCenterY(0)) * inv_cos_theta;
+ x = (P - m_pVolumeGeometry->getWindowMinX()) * inv_pixelLengthX - 0.5f;
+
+ // for each row
+ for (row = 0; row < m_pVolumeGeometry->getGridRowCount(); ++row) {
+
+ // calculate extent
+ xmin = (int)ceil((P - m_fBlobSize - m_pVolumeGeometry->getWindowMinX()) * inv_pixelLengthX - 0.5f);
+ xmax = (int)floor((P + m_fBlobSize - m_pVolumeGeometry->getWindowMinX()) * inv_pixelLengthX - 0.5f);
+
+ // add pixels
+ for (col = xmin; col <= xmax; col++) {
+ if (col >= 0 && col < m_pVolumeGeometry->getGridColCount()) {
+ //d = abs(x - col) * pixelLengthX_over_blobSize;
+ //index = (int)(d*m_iBlobSampleCount+0.5f);
+ //float32 fWeight = m_pfBlobValues[min(index,m_iBlobSampleCount-1)] * lengthPerRow;
+
+ float32 fWeight;
+ int index;
+ if ((x >= col) ^ flip) {
+ d = abs(x - col) * pixelLengthX_over_blobSize * cos_theta;
+ index = (int)(d*m_iBlobSampleCount+0.5f);
+ fWeight = m_pfBlobValues[min(index,m_iBlobSampleCount-1)];
+ } else {
+ d = abs(x - col) * pixelLengthX_over_blobSize * cos_theta;
+ index = (int)(d*m_iBlobSampleCount+0.5f);
+ fWeight = m_pfBlobValuesNeg[min(index,m_iBlobSampleCount-1)];
+ }
+
+ int iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, col);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, fWeight);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ }
+
+ // update P and x
+ P += updatePerRow;
+ x += updatePerRow * inv_pixelLengthX;
+ }
+
+ } else { // pi/4 < theta < 3pi/4
+
+ // precalculate sin cos
+ float32 sin_90_theta = sin(PIdiv2-theta);
+ float32 cos_90_theta = cos(PIdiv2-theta);
+ float32 inv_cos_90_theta = 1.0f / cos_90_theta;
+
+ // precalculate other stuff
+ float32 lengthPerCol = m_pVolumeGeometry->getPixelLengthX() * inv_cos_90_theta;
+ float32 updatePerCol = sin_90_theta * lengthPerCol;
+ float32 inv_pixelLengthY = 1.0f / m_pVolumeGeometry->getPixelLengthY();
+ float32 pixelLengthY_over_blobSize = m_pVolumeGeometry->getPixelLengthY() / m_fBlobSize;
+
+ // some variables
+ int row, col, xmin, xmax;
+ float32 P,x, d;
+
+ // calculate P and x for col 0
+ P = (sin_90_theta * m_pVolumeGeometry->pixelColToCenterX(0) - t) * inv_cos_90_theta;
+ x = (P - m_pVolumeGeometry->getWindowMinY()) * inv_pixelLengthY - 0.5f;
+
+ // for each col
+ for (col = 0; col < m_pVolumeGeometry->getGridColCount(); ++col) {
+
+ // calculate extent
+ xmin = (int)ceil((P - m_fBlobSize - m_pVolumeGeometry->getWindowMinY()) * inv_pixelLengthY - 0.5f);
+ xmax = (int)floor((P + m_fBlobSize - m_pVolumeGeometry->getWindowMinY()) * inv_pixelLengthY - 0.5f);
+
+ // add pixels
+ for (row = xmin; row <= xmax; row++) {
+ if (row >= 0 && row < m_pVolumeGeometry->getGridRowCount()) {
+ //d = abs(x - row) * pixelLengthY_over_blobSize;
+ //int index = (int)(d*m_iBlobSampleCount+0.5f);
+ //float32 fWeight = m_pfBlobValues[min(index,m_iBlobSampleCount-1)] * lengthPerCol;
+
+ float32 fWeight;
+ int index;
+ if ((x <= row) ^ flip) {
+ d = abs(x - row) * pixelLengthY_over_blobSize * cos_90_theta;
+ index = (int)(d*m_iBlobSampleCount+0.5f);
+ fWeight = m_pfBlobValues[min(index,m_iBlobSampleCount-1)];
+ } else {
+ d = abs(x - row) * pixelLengthY_over_blobSize * cos_90_theta;
+ index = (int)(d*m_iBlobSampleCount+0.5f);
+ fWeight = m_pfBlobValuesNeg[min(index,m_iBlobSampleCount-1)];
+ }
+
+
+ int iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, col);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, fWeight);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ }
+
+ // update P and x
+ P += updatePerCol;
+ x += updatePerCol * inv_pixelLengthY;
+ }
+
+ }
+
+ // POLICY: RAY POSTERIOR
+ p.rayPosterior(iRayIndex);
+
+
+
+}
diff --git a/include/astra/ParallelBeamLineKernelProjector2D.h b/include/astra/ParallelBeamLineKernelProjector2D.h
new file mode 100644
index 0000000..9e2cc5a
--- /dev/null
+++ b/include/astra/ParallelBeamLineKernelProjector2D.h
@@ -0,0 +1,186 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_PARALLELBEAMLINEKERNELPROJECTOR
+#define _INC_ASTRA_PARALLELBEAMLINEKERNELPROJECTOR
+
+#include "ParallelProjectionGeometry2D.h"
+#include "Float32Data2D.h"
+#include "Projector2D.h"
+
+namespace astra
+{
+
+/** This class implements a two-dimensional projector based on a line based kernel.
+ *
+ * \par XML Configuration
+ * \astra_xml_item{ProjectionGeometry, xml node, The geometry of the projection.}
+ * \astra_xml_item{VolumeGeometry, xml node, The geometry of the volume.}
+ *
+ * \par MATLAB example
+ * \astra_code{
+ * cfg = astra_struct('line');\n
+ * cfg.ProjectionGeometry = proj_geom;\n
+ * cfg.VolumeGeometry = vol_geom;\n
+ * proj_id = astra_mex_projector('create'\, cfg);\n
+ * }
+ */
+class _AstraExport CParallelBeamLineKernelProjector2D : public CProjector2D {
+
+protected:
+
+ /** Initial clearing. Only to be used by constructors.
+ */
+ virtual void _clear();
+
+ /** Check the values of this object. If everything is ok, the object can be set to the initialized state.
+ * The following statements are then guaranteed to hold:
+ * - no NULL pointers
+ * - all sub-objects are initialized properly
+ * - blobvalues are ok
+ */
+ virtual bool _check();
+
+public:
+
+ // type of the projector, needed to register with CProjectorFactory
+ static std::string type;
+
+ /** Default constructor.
+ */
+ CParallelBeamLineKernelProjector2D();
+
+ /** Constructor.
+ *
+ * @param _pProjectionGeometry Information class about the geometry of the projection. Will be HARDCOPIED.
+ * @param _pReconstructionGeometry Information class about the geometry of the reconstruction volume. Will be HARDCOPIED.
+ */
+ CParallelBeamLineKernelProjector2D(CParallelProjectionGeometry2D* _pProjectionGeometry,
+ CVolumeGeometry2D* _pReconstructionGeometry);
+
+ /** Destructor, is virtual to show that we are aware subclass destructor are called.
+ */
+ ~CParallelBeamLineKernelProjector2D();
+
+ /** Initialize the projector with a config object.
+ *
+ * @param _cfg Configuration Object
+ * @return initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ /** Initialize the projector.
+ *
+ * @param _pProjectionGeometry Information class about the geometry of the projection. Will be HARDCOPIED.
+ * @param _pReconstructionGeometry Information class about the geometry of the reconstruction volume. Will be HARDCOPIED.
+ * @return initialization successful?
+ */
+ virtual bool initialize(CParallelProjectionGeometry2D* _pProjectionGeometry,
+ CVolumeGeometry2D* _pReconstructionGeometry);
+
+ /** Clear this class.
+ */
+ virtual void clear();
+
+ /** Returns the number of weights required for storage of all weights of one projection.
+ *
+ * @param _iProjectionIndex Index of the projection (zero-based).
+ * @return Size of buffer (given in SPixelWeight elements) needed to store weighted pixels.
+ */
+ virtual int getProjectionWeightsCount(int _iProjectionIndex);
+
+ /** Compute the pixel weights for a single ray, from the source to a detector pixel.
+ *
+ * @param _iProjectionIndex Index of the projection
+ * @param _iDetectorIndex Index of the detector pixel
+ * @param _pWeightedPixels Pointer to a pre-allocated array, consisting of _iMaxPixelCount elements
+ * of type SPixelWeight. On return, this array contains a list of the index
+ * and weight for all pixels on the ray.
+ * @param _iMaxPixelCount Maximum number of pixels (and corresponding weights) that can be stored in _pWeightedPixels.
+ * This number MUST be greater than the total number of pixels on the ray.
+ * @param _iStoredPixelCount On return, this variable contains the total number of pixels on the
+ * ray (that have been stored in the list _pWeightedPixels).
+ */
+ virtual void computeSingleRayWeights(int _iProjectionIndex,
+ int _iDetectorIndex,
+ SPixelWeight* _pWeightedPixels,
+ int _iMaxPixelCount,
+ int& _iStoredPixelCount);
+
+ /** Create a list of detectors that are influenced by point [_iRow, _iCol].
+ *
+ * @param _iRow row of the point
+ * @param _iCol column of the point
+ * @return list of SDetector2D structs
+ */
+ virtual std::vector<SDetector2D> projectPoint(int _iRow, int _iCol);
+
+ /** Policy-based projection of all rays. This function will calculate each non-zero projection
+ * weight and use this value for a task provided by the policy object.
+ *
+ * @param _policy Policy object. Should contain prior, addWeight and posterior function.
+ */
+ template <typename Policy>
+ void project(Policy& _policy);
+
+ /** Policy-based projection of all rays of a single projection. This function will calculate
+ * each non-zero projection weight and use this value for a task provided by the policy object.
+ *
+ * @param _iProjection Wwhich projection should be projected?
+ * @param _policy Policy object. Should contain prior, addWeight and posterior function.
+ */
+ template <typename Policy>
+ void projectSingleProjection(int _iProjection, Policy& _policy);
+
+ /** Policy-based projection of a single ray. This function will calculate each non-zero
+ * projection weight and use this value for a task provided by the policy object.
+ *
+ * @param _iProjection Which projection should be projected?
+ * @param _iDetector Which detector should be projected?
+ * @param _policy Policy object. Should contain prior, addWeight and posterior function.
+ */
+ template <typename Policy>
+ void projectSingleRay(int _iProjection, int _iDetector, Policy& _policy);
+
+ /** Return the type of this projector.
+ *
+ * @return identification type of this projector
+ */
+ virtual std::string getType();
+
+};
+
+inline std::string CParallelBeamLineKernelProjector2D::getType()
+{
+ return type;
+}
+
+} // namespace astra
+
+#endif
+
diff --git a/include/astra/ParallelBeamLineKernelProjector2D.inl b/include/astra/ParallelBeamLineKernelProjector2D.inl
new file mode 100644
index 0000000..08bbe5f
--- /dev/null
+++ b/include/astra/ParallelBeamLineKernelProjector2D.inl
@@ -0,0 +1,731 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+
+
+//----------------------------------------------------------------------------------------
+// PROJECT ALL
+template <typename Policy>
+void CParallelBeamLineKernelProjector2D::project(Policy& p)
+{
+ // variables
+ float32 theta, sin_theta, cos_theta, inv_sin_theta, inv_cos_theta, S, T, t, I, P, x, x2;
+ float32 lengthPerRow, updatePerRow, inv_pixelLengthX, lengthPerCol, updatePerCol, inv_pixelLengthY;
+ int iVolumeIndex, iRayIndex, row, col, iAngle, iDetector, x1;
+ bool switch_t;
+
+ // loop angles
+ for (iAngle = 0; iAngle < m_pProjectionGeometry->getProjectionAngleCount(); ++iAngle) {
+
+ // get theta
+ theta = m_pProjectionGeometry->getProjectionAngle(iAngle);
+ switch_t = false;
+ if (theta >= 7*PIdiv4) theta -= 2*PI;
+ if (theta >= 3*PIdiv4) {
+ theta -= PI;
+ switch_t = true;
+ }
+
+ // precalculate sin, cos, 1/cos
+ sin_theta = sin(theta);
+ cos_theta = cos(theta);
+ inv_sin_theta = 1.0f / sin_theta;
+ inv_cos_theta = 1.0f / cos_theta;
+
+ // precalculate kernel limits
+ lengthPerRow = m_pVolumeGeometry->getPixelLengthY() * inv_cos_theta;
+ updatePerRow = sin_theta * inv_cos_theta;
+ inv_pixelLengthX = 1.0f / m_pVolumeGeometry->getPixelLengthX();
+
+ // precalculate kernel limits
+ lengthPerCol = m_pVolumeGeometry->getPixelLengthX() * inv_sin_theta;
+ updatePerCol = cos_theta * inv_sin_theta;
+ inv_pixelLengthY = 1.0f / m_pVolumeGeometry->getPixelLengthY();
+
+ // precalculate S and T
+ S = 0.5f - 0.5f * ((updatePerRow < 0) ? -updatePerRow : updatePerRow);
+ T = 0.5f - 0.5f * ((updatePerCol < 0) ? -updatePerCol : updatePerCol);
+
+ // loop detectors
+ for (iDetector = 0; iDetector < m_pProjectionGeometry->getDetectorCount(); ++iDetector) {
+
+ iRayIndex = iAngle * m_pProjectionGeometry->getDetectorCount() + iDetector;
+
+ // POLICY: RAY PRIOR
+ if (!p.rayPrior(iRayIndex)) continue;
+
+ // get t
+ t = m_pProjectionGeometry->indexToDetectorOffset(iDetector);
+ if (switch_t) t = -t;
+
+ // vertically
+ if (theta <= PIdiv4) {
+
+ // calculate x for row 0
+ P = (t - sin_theta * m_pVolumeGeometry->pixelRowToCenterY(0)) * inv_cos_theta;
+ x = (P - m_pVolumeGeometry->getWindowMinX()) * inv_pixelLengthX;
+
+ // get coords
+ int nextx1 = int((x > 0.0f) ? x : x-1.0f);
+ float nextx2 = x - nextx1;
+
+ // for each row
+ for (row = 0; row < m_pVolumeGeometry->getGridRowCount(); ++row) {
+
+ x1 = nextx1;
+ x2 = nextx2;
+
+ nextx2 += updatePerRow;
+ while (nextx2 >= 1.0f) {
+ nextx2 -= 1.0f;
+ nextx1++;
+ }
+ while (nextx2 < 0.0f) {
+ nextx2 += 1.0f;
+ nextx1--;
+ }
+
+ if (x1 < -1 || x1 > m_pVolumeGeometry->getGridColCount()) continue;
+
+ // left
+ if (x2 < 0.5f-S) {
+ I = (0.5f - S + x2) / (1.0f - 2.0f*S) * lengthPerRow;
+
+ if (x1-1 >= 0 && x1-1 < m_pVolumeGeometry->getGridColCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1-1);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, lengthPerRow-I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+
+ if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridColCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ }
+
+ // center
+ else if (x2 <= 0.5f+S) {
+ if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridColCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, lengthPerRow);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ }
+
+ // right
+ else {
+ I = (1.5f - S - x2) / (1.0f - 2.0f*S) * lengthPerRow;
+
+ if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridColCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ if (x1+1 >= 0 && x1+1 < m_pVolumeGeometry->getGridColCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1+1);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, lengthPerRow-I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ }
+ }
+ }
+
+ // horizontally
+ else if (PIdiv4 <= theta && theta <= 3*PIdiv4) {
+
+ // calculate point P
+ P = (t - cos_theta * m_pVolumeGeometry->pixelColToCenterX(0)) * inv_sin_theta;
+ x = (m_pVolumeGeometry->getWindowMaxY() - P) * inv_pixelLengthY;
+
+ // get coords
+ int nextx1 = int((x > 0.0f) ? x : x-1.0f);
+ float nextx2 = x - nextx1;
+
+ // for each col
+ for (col = 0; col < m_pVolumeGeometry->getGridColCount(); ++col) {
+
+ x1 = nextx1;
+ x2 = nextx2;
+
+ nextx2 += updatePerCol;
+ while (nextx2 >= 1.0f) {
+ nextx2 -= 1.0f;
+ nextx1++;
+ }
+ while (nextx2 < 0.0f) {
+ nextx2 += 1.0f;
+ nextx1--;
+ }
+
+ if (x1 < -1 || x1 > m_pVolumeGeometry->getGridRowCount()) continue;
+
+ // up
+ if (x2 < 0.5f-T) {
+ I = (0.5f - T + x2) / (1.0f - 2.0f*T) * lengthPerCol;
+
+ if (x1-1 >= 0 && x1-1 < m_pVolumeGeometry->getGridRowCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1-1, col);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, lengthPerCol-I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+
+ if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridRowCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1, col);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ }
+
+ // center
+ else if (x2 <= 0.5f+T) {
+ if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridRowCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1, col);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, lengthPerCol);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ }
+
+ // down
+ else {
+ I = (1.5f - T - x2) / (1.0f - 2.0f*T) * lengthPerCol;
+
+ if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridColCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1, col);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ if (x1+1 >= 0 && x1+1 < m_pVolumeGeometry->getGridColCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1+1, col);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, lengthPerCol-I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ }
+ }
+ } // end loop col
+
+ // POLICY: RAY POSTERIOR
+ p.rayPosterior(iRayIndex);
+
+ } // end loop detector
+ } // end loop angles
+
+}
+
+
+//----------------------------------------------------------------------------------------
+// PROJECT SINGLE PROJECTION
+template <typename Policy>
+void CParallelBeamLineKernelProjector2D::projectSingleProjection(int _iProjection, Policy& p)
+{
+ // variables
+ float32 theta, sin_theta, cos_theta, inv_sin_theta, inv_cos_theta, S, T, t, I, P, x, x2;
+ float32 lengthPerRow, updatePerRow, inv_pixelLengthX, lengthPerCol, updatePerCol, inv_pixelLengthY;
+ int iVolumeIndex, iRayIndex, row, col, iDetector, x1;
+ bool switch_t;
+
+ // get theta
+ theta = m_pProjectionGeometry->getProjectionAngle(_iProjection);
+ switch_t = false;
+ if (theta >= 7*PIdiv4) theta -= 2*PI;
+ if (theta >= 3*PIdiv4) {
+ theta -= PI;
+ switch_t = true;
+ }
+
+ // precalculate sin, cos, 1/cos
+ sin_theta = sin(theta);
+ cos_theta = cos(theta);
+ inv_sin_theta = 1.0f / sin_theta;
+ inv_cos_theta = 1.0f / cos_theta;
+
+ // precalculate kernel limits
+ lengthPerRow = m_pVolumeGeometry->getPixelLengthY() * inv_cos_theta;
+ updatePerRow = sin_theta * inv_cos_theta;
+ inv_pixelLengthX = 1.0f / m_pVolumeGeometry->getPixelLengthX();
+
+ // precalculate kernel limits
+ lengthPerCol = m_pVolumeGeometry->getPixelLengthX() * inv_sin_theta;
+ updatePerCol = cos_theta * inv_sin_theta;
+ inv_pixelLengthY = 1.0f / m_pVolumeGeometry->getPixelLengthY();
+
+ // precalculate S and T
+ S = 0.5f - 0.5f * ((updatePerRow < 0) ? -updatePerRow : updatePerRow);
+ T = 0.5f - 0.5f * ((updatePerCol < 0) ? -updatePerCol : updatePerCol);
+
+ // loop detectors
+ for (iDetector = 0; iDetector < m_pProjectionGeometry->getDetectorCount(); ++iDetector) {
+
+ iRayIndex = _iProjection * m_pProjectionGeometry->getDetectorCount() + iDetector;
+
+ // POLICY: RAY PRIOR
+ if (!p.rayPrior(iRayIndex)) continue;
+
+ // get t
+ t = m_pProjectionGeometry->indexToDetectorOffset(iDetector);
+ if (switch_t) t = -t;
+
+ // vertically
+ if (theta <= PIdiv4) {
+
+ // calculate x for row 0
+ P = (t - sin_theta * m_pVolumeGeometry->pixelRowToCenterY(0)) * inv_cos_theta;
+ x = (P - m_pVolumeGeometry->getWindowMinX()) * inv_pixelLengthX;
+
+ // get coords
+ int nextx1 = int((x > 0.0f) ? x : x-1.0f);
+ float nextx2 = x - nextx1;
+
+ // for each row
+ for (row = 0; row < m_pVolumeGeometry->getGridRowCount(); ++row) {
+
+ x1 = nextx1;
+ x2 = nextx2;
+
+ nextx2 += updatePerRow;
+ while (nextx2 >= 1.0f) {
+ nextx2 -= 1.0f;
+ nextx1++;
+ }
+ while (nextx2 < 0.0f) {
+ nextx2 += 1.0f;
+ nextx1--;
+ }
+
+ if (x1 < -1 || x1 > m_pVolumeGeometry->getGridColCount()) continue;
+
+ // left
+ if (x2 < 0.5f-S) {
+ I = (0.5f - S + x2) / (1.0f - 2.0f*S) * lengthPerRow;
+
+ if (x1-1 >= 0 && x1-1 < m_pVolumeGeometry->getGridColCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1-1);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, lengthPerRow-I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+
+ if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridColCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ }
+
+ // center
+ else if (x2 <= 0.5f+S) {
+ if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridColCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, lengthPerRow);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ }
+
+ // right
+ else {
+ I = (1.5f - S - x2) / (1.0f - 2.0f*S) * lengthPerRow;
+
+ if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridColCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ if (x1+1 >= 0 && x1+1 < m_pVolumeGeometry->getGridColCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1+1);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, lengthPerRow-I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ }
+ }
+ }
+
+ // horizontally
+ else if (PIdiv4 <= theta && theta <= 3*PIdiv4) {
+
+ // calculate point P
+ P = (t - cos_theta * m_pVolumeGeometry->pixelColToCenterX(0)) * inv_sin_theta;
+ x = (m_pVolumeGeometry->getWindowMaxY() - P) * inv_pixelLengthY;
+
+ // get coords
+ int nextx1 = int((x > 0.0f) ? x : x-1.0f);
+ float nextx2 = x - nextx1;
+
+ // for each col
+ for (col = 0; col < m_pVolumeGeometry->getGridColCount(); ++col) {
+
+ x1 = nextx1;
+ x2 = nextx2;
+
+ nextx2 += updatePerCol;
+ while (nextx2 >= 1.0f) {
+ nextx2 -= 1.0f;
+ nextx1++;
+ }
+ while (nextx2 < 0.0f) {
+ nextx2 += 1.0f;
+ nextx1--;
+ }
+
+ if (x1 < -1 || x1 > m_pVolumeGeometry->getGridRowCount()) continue;
+
+ // up
+ if (x2 < 0.5f-T) {
+ I = (0.5f - T + x2) / (1.0f - 2.0f*T) * lengthPerCol;
+
+ if (x1-1 >= 0 && x1-1 < m_pVolumeGeometry->getGridRowCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1-1, col);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, lengthPerCol-I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+
+ if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridRowCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1, col);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ }
+
+ // center
+ else if (x2 <= 0.5f+T) {
+ if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridRowCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1, col);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, lengthPerCol);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ }
+
+ // down
+ else {
+ I = (1.5f - T - x2) / (1.0f - 2.0f*T) * lengthPerCol;
+
+ if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridColCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1, col);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ if (x1+1 >= 0 && x1+1 < m_pVolumeGeometry->getGridColCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1+1, col);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, lengthPerCol-I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ }
+ }
+ } // end loop col
+
+ // POLICY: RAY POSTERIOR
+ p.rayPosterior(iRayIndex);
+
+ } // end loop detector
+}
+
+
+
+//----------------------------------------------------------------------------------------
+// PROJECT SINGLE RAY
+template <typename Policy>
+void CParallelBeamLineKernelProjector2D::projectSingleRay(int _iProjection, int _iDetector, Policy& p)
+{
+ int iRayIndex = _iProjection * m_pProjectionGeometry->getDetectorCount() + _iDetector;
+
+ // POLICY: RAY PRIOR
+ if (!p.rayPrior(iRayIndex)) return;
+
+ // variables
+ float32 t, I, P, x, x2;
+ int iVolumeIndex, row, col, x1;
+
+ // get theta
+ float32 theta = m_pProjectionGeometry->getProjectionAngle(_iProjection);
+ bool switch_t = false;
+ if (theta >= 7*PIdiv4) theta -= 2*PI;
+ if (theta >= 3*PIdiv4) {
+ theta -= PI;
+ switch_t = true;
+ }
+
+ // get t
+ t = m_pProjectionGeometry->indexToDetectorOffset(_iDetector);
+ if (switch_t) t = -t;
+
+ // vertically
+ if (theta <= PIdiv4) {
+
+ float32 sin_theta = sin(theta);
+ float32 inv_cos_theta = 1.0f / cos(theta);
+
+ // precalculate kernel limits
+ float32 lengthPerRow = m_pVolumeGeometry->getPixelLengthY() * inv_cos_theta;
+ float32 updatePerRow = sin_theta * inv_cos_theta;
+ float32 inv_pixelLengthX = 1.0f / m_pVolumeGeometry->getPixelLengthX();
+ float32 S = 0.5f - 0.5f * ((updatePerRow < 0) ? -updatePerRow : updatePerRow);
+
+ // calculate x for row 0
+ P = (t - sin_theta * m_pVolumeGeometry->pixelRowToCenterY(0)) * inv_cos_theta;
+ x = (P - m_pVolumeGeometry->getWindowMinX()) * inv_pixelLengthX;
+
+ // get coords
+ int nextx1 = int((x > 0.0f) ? x : x-1.0f);
+ float nextx2 = x - nextx1;
+
+ // for each row
+ for (row = 0; row < m_pVolumeGeometry->getGridRowCount(); ++row) {
+
+ x1 = nextx1;
+ x2 = nextx2;
+
+ nextx2 += updatePerRow;
+ while (nextx2 >= 1.0f) {
+ nextx2 -= 1.0f;
+ nextx1++;
+ }
+ while (nextx2 < 0.0f) {
+ nextx2 += 1.0f;
+ nextx1--;
+ }
+
+ if (x1 < -1 || x1 > m_pVolumeGeometry->getGridColCount()) continue;
+
+ // left
+ if (x2 < 0.5f-S) {
+ I = (0.5f - S + x2) / (1.0f - 2.0f*S) * lengthPerRow;
+
+ if (x1-1 >= 0 && x1-1 < m_pVolumeGeometry->getGridColCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1-1);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, lengthPerRow-I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+
+ if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridColCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ }
+
+ // center
+ else if (x2 <= 0.5f+S) {
+ if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridColCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, lengthPerRow);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ }
+
+ // right
+ else {
+ I = (1.5f - S - x2) / (1.0f - 2.0f*S) * lengthPerRow;
+
+ if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridColCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ if (x1+1 >= 0 && x1+1 < m_pVolumeGeometry->getGridColCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1+1);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, lengthPerRow-I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ }
+ }
+ }
+
+ // horizontally
+ else if (PIdiv4 <= theta && theta <= 3*PIdiv4) {
+
+ float32 cos_theta = cos(theta);
+ float32 inv_sin_theta = 1.0f / sin(theta);
+
+ // precalculate kernel limits
+ float32 lengthPerCol = m_pVolumeGeometry->getPixelLengthX() * inv_sin_theta;
+ float32 updatePerCol = cos_theta * inv_sin_theta;
+ float32 inv_pixelLengthY = 1.0f / m_pVolumeGeometry->getPixelLengthY();
+ float32 T = 0.5f - 0.5f * ((updatePerCol < 0) ? -updatePerCol : updatePerCol);
+
+ // calculate point P
+ P = (t - cos_theta * m_pVolumeGeometry->pixelColToCenterX(0)) * inv_sin_theta;
+ x = (m_pVolumeGeometry->getWindowMaxY() - P) * inv_pixelLengthY;
+
+ // get coords
+ int nextx1 = int((x > 0.0f) ? x : x-1.0f);
+ float nextx2 = x - nextx1;
+
+ // for each col
+ for (col = 0; col < m_pVolumeGeometry->getGridColCount(); ++col) {
+
+ x1 = nextx1;
+ x2 = nextx2;
+
+ nextx2 += updatePerCol;
+ while (nextx2 >= 1.0f) {
+ nextx2 -= 1.0f;
+ nextx1++;
+ }
+ while (nextx2 < 0.0f) {
+ nextx2 += 1.0f;
+ nextx1--;
+ }
+
+ if (x1 < -1 || x1 > m_pVolumeGeometry->getGridRowCount()) continue;
+
+ // up
+ if (x2 < 0.5f-T) {
+ I = (0.5f - T + x2) / (1.0f - 2.0f*T) * lengthPerCol;
+
+ if (x1-1 >= 0 && x1-1 < m_pVolumeGeometry->getGridRowCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1-1, col);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, lengthPerCol-I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+
+ if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridRowCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1, col);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ }
+
+ // center
+ else if (x2 <= 0.5f+T) {
+ if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridRowCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1, col);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, lengthPerCol);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ }
+
+ // down
+ else {
+ I = (1.5f - T - x2) / (1.0f - 2.0f*T) * lengthPerCol;
+
+ if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridColCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1, col);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ if (x1+1 >= 0 && x1+1 < m_pVolumeGeometry->getGridColCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1+1, col);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, lengthPerCol-I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ }
+ }
+ } // end loop col
+
+ // POLICY: RAY POSTERIOR
+ p.rayPosterior(iRayIndex);
+
+}
diff --git a/include/astra/ParallelBeamLinearKernelProjector2D.h b/include/astra/ParallelBeamLinearKernelProjector2D.h
new file mode 100644
index 0000000..ac5899e
--- /dev/null
+++ b/include/astra/ParallelBeamLinearKernelProjector2D.h
@@ -0,0 +1,194 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_PARALLELLINEARKERNELPROJECTOR
+#define _INC_ASTRA_PARALLELLINEARKERNELPROJECTOR
+
+#include "ParallelProjectionGeometry2D.h"
+#include "Float32Data2D.h"
+#include "Projector2D.h"
+
+#include "Float32ProjectionData2D.h"
+#include "Float32VolumeData2D.h"
+
+namespace astra
+{
+
+/** This class implements a two-dimensional projector based on a lineary interpolated kernel.
+ *
+ * \par XML Configuration
+ * \astra_xml_item{ProjectionGeometry, xml node, The geometry of the projection.}
+ * \astra_xml_item{VolumeGeometry, xml node, The geometry of the volume.}
+ *
+ * \par MATLAB example
+ * \astra_code{
+ * cfg = astra_struct('linear');\n
+ * cfg.ProjectionGeometry = proj_geom;\n
+ * cfg.VolumeGeometry = vol_geom;\n
+ * proj_id = astra_mex_projector('create'\, cfg);\n
+ * }
+ */
+class _AstraExport CParallelBeamLinearKernelProjector2D : public CProjector2D {
+
+protected:
+
+ /** Initial clearing. Only to be used by constructors.
+ */
+ virtual void _clear();
+
+ /** Check the values of this object. If everything is ok, the object can be set to the initialized state.
+ * The following statements are then guaranteed to hold:
+ * - no NULL pointers
+ * - all sub-objects are initialized properly
+ * - blobvalues are ok
+ */
+ virtual bool _check();
+
+public:
+
+ // type of the projector, needed to register with CProjectorFactory
+ static std::string type;
+
+ /** Default constructor.
+ */
+ CParallelBeamLinearKernelProjector2D();
+
+ /** Constructor.
+ *
+ * @param _pProjectionGeometry Information class about the geometry of the projection. Will be HARDCOPIED.
+ * @param _pReconstructionGeometry Information class about the geometry of the reconstruction volume. Will be HARDCOPIED.
+ */
+ CParallelBeamLinearKernelProjector2D(CParallelProjectionGeometry2D* _pProjectionGeometry,
+ CVolumeGeometry2D* _pReconstructionGeometry);
+
+ /** Destructor, is virtual to show that we are aware subclass destructor are called.
+ */
+ ~CParallelBeamLinearKernelProjector2D();
+
+ /** Initialize the projector with a config object.
+ *
+ * @param _cfg Configuration Object
+ * @return initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ /** Initialize the projector.
+ *
+ * @param _pProjectionGeometry Information class about the geometry of the projection. Will be HARDCOPIED.
+ * @param _pReconstructionGeometry Information class about the geometry of the reconstruction volume. Will be HARDCOPIED.
+ * @return initialization successful?
+ */
+ virtual bool initialize(CParallelProjectionGeometry2D* _pProjectionGeometry,
+ CVolumeGeometry2D* _pVolumeGeometry);
+
+ /** Clear this class.
+ */
+ virtual void clear();
+
+ /** Returns the number of weights required for storage of all weights of one projection.
+ *
+ * @param _iProjectionIndex Index of the projection (zero-based).
+ * @return Size of buffer (given in SPixelWeight elements) needed to store weighted pixels.
+ */
+ virtual int getProjectionWeightsCount(int _iProjectionIndex);
+
+ /** Compute the pixel weights for a single ray, from the source to a detector pixel.
+ *
+ * @param _iProjectionIndex Index of the projection
+ * @param _iDetectorIndex Index of the detector pixel
+ * @param _pWeightedPixels Pointer to a pre-allocated array, consisting of _iMaxPixelCount elements
+ * of type SPixelWeight. On return, this array contains a list of the index
+ * and weight for all pixels on the ray.
+ * @param _iMaxPixelCount Maximum number of pixels (and corresponding weights) that can be stored in _pWeightedPixels.
+ * This number MUST be greater than the total number of pixels on the ray.
+ * @param _iStoredPixelCount On return, this variable contains the total number of pixels on the
+ * ray (that have been stored in the list _pWeightedPixels).
+ */
+ virtual void computeSingleRayWeights(int _iProjectionIndex,
+ int _iDetectorIndex,
+ SPixelWeight* _pWeightedPixels,
+ int _iMaxPixelCount,
+ int& _iStoredPixelCount);
+
+ /** Create a list of detectors that are influenced by point [_iRow, _iCol].
+ *
+ * @param _iRow row of the point
+ * @param _iCol column of the point
+ * @return list of SDetector2D structs
+ */
+ virtual std::vector<SDetector2D> projectPoint(int _iRow, int _iCol);
+
+
+ /** Policy-based projection of all rays. This function will calculate each non-zero projection
+ * weight and use this value for a task provided by the policy object.
+ *
+ * @param _policy Policy object. Should contain prior, addWeight and posterior function.
+ */
+ template <typename Policy>
+ void project(Policy& _policy);
+
+ /** Policy-based projection of all rays of a single projection. This function will calculate
+ * each non-zero projection weight and use this value for a task provided by the policy object.
+ *
+ * @param _iProjection Which projection should be projected?
+ * @param _policy Policy object. Should contain prior, addWeight and posterior function.
+ */
+ template <typename Policy>
+ void projectSingleProjection(int _iProjection, Policy& _policy);
+
+ /** Policy-based projection of a single ray. This function will calculate each non-zero
+ * projection weight and use this value for a task provided by the policy object.
+ *
+ * @param _iProjection Which projection should be projected?
+ * @param _iDetector Which detector should be projected?
+ * @param _policy Policy object. Should contain prior, addWeight and posterior function.
+ */
+ template <typename Policy>
+ void projectSingleRay(int _iProjection, int _iDetector, Policy& _policy);
+
+ /** Return the type of this projector.
+ *
+ * @return identification type of this projector
+ */
+ virtual std::string getType();
+
+};
+
+//----------------------------------------------------------------------------------------
+
+inline std::string CParallelBeamLinearKernelProjector2D::getType()
+{
+ return type;
+}
+
+
+} // namespace astra
+
+
+#endif
+
diff --git a/include/astra/ParallelBeamLinearKernelProjector2D.inl b/include/astra/ParallelBeamLinearKernelProjector2D.inl
new file mode 100644
index 0000000..66b1cb2
--- /dev/null
+++ b/include/astra/ParallelBeamLinearKernelProjector2D.inl
@@ -0,0 +1,416 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+
+
+//----------------------------------------------------------------------------------------
+// PROJECT ALL
+template <typename Policy>
+void CParallelBeamLinearKernelProjector2D::project(Policy& p)
+{
+ // variables
+ float32 theta, sin_theta, cos_theta, inv_sin_theta, inv_cos_theta, t;
+ float32 lengthPerRow, updatePerRow, inv_pixelLengthX;
+ float32 lengthPerCol, updatePerCol, inv_pixelLengthY;
+ bool switch_t;
+ int iAngle, iDetector, iVolumeIndex, iRayIndex;
+ int row, col, x1;
+ float32 P,x,x2;
+
+ // loop angles
+ for (iAngle = 0; iAngle < m_pProjectionGeometry->getProjectionAngleCount(); ++iAngle) {
+
+ // get theta
+ theta = m_pProjectionGeometry->getProjectionAngle(iAngle);
+ switch_t = false;
+ if (theta >= 7*PIdiv4) theta -= 2*PI;
+ if (theta >= 3*PIdiv4) {
+ theta -= PI;
+ switch_t = true;
+ }
+
+ // precalculate sin, cos, 1/cos
+ sin_theta = sin(theta);
+ cos_theta = cos(theta);
+ inv_cos_theta = 1.0f / cos_theta;
+ inv_sin_theta = 1.0f / sin_theta;
+
+ // precalculate kernel limits
+ lengthPerRow = m_pVolumeGeometry->getPixelLengthY() * inv_cos_theta;
+ updatePerRow = sin_theta * inv_cos_theta;
+ inv_pixelLengthX = 1.0f / m_pVolumeGeometry->getPixelLengthX();
+
+ // precalculate kernel limits
+ lengthPerCol = m_pVolumeGeometry->getPixelLengthX() * inv_sin_theta;
+ updatePerCol = cos_theta * inv_sin_theta;
+ inv_pixelLengthY = 1.0f / m_pVolumeGeometry->getPixelLengthY();
+
+ // loop detectors
+ for (iDetector = 0; iDetector < m_pProjectionGeometry->getDetectorCount(); ++iDetector) {
+
+ iRayIndex = iAngle * m_pProjectionGeometry->getDetectorCount() + iDetector;
+
+ // POLICY: RAY PRIOR
+ if (!p.rayPrior(iRayIndex)) continue;
+
+ // get t
+ t = m_pProjectionGeometry->indexToDetectorOffset(iDetector);
+ if (switch_t) {
+ t = -t;
+ }
+
+ // vertically
+ if (theta <= PIdiv4) {
+
+ // calculate x for row 0
+ P = (t - sin_theta * m_pVolumeGeometry->pixelRowToCenterY(0)) * inv_cos_theta;
+ x = m_pVolumeGeometry->coordXToColF(P) - 0.5f;
+
+ // for each row
+ for (row = 0; row < m_pVolumeGeometry->getGridRowCount(); ++row) {
+
+ // get coords
+ x1 = int((x > 0.0f) ? x : x-1.0f);
+ x2 = x - x1;
+ x += updatePerRow;
+
+ // add weights
+ if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridColCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, (1.0f - x2) * lengthPerRow);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ if (x1+1 >= 0 && x1+1 < m_pVolumeGeometry->getGridColCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1+1);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, (x2) * lengthPerRow);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ }
+ }
+
+ // horizontally
+ else if (PIdiv4 <= theta && theta <= 3*PIdiv4) {
+
+ // calculate point P
+ P = (t - cos_theta * m_pVolumeGeometry->pixelColToCenterX(0)) * inv_sin_theta;
+ x = m_pVolumeGeometry->coordYToRowF(P) - 0.5f;
+
+ // for each row
+ for (col = 0; col < m_pVolumeGeometry->getGridColCount(); ++col) {
+
+ // get coords
+ x1 = int((x > 0.0f) ? x : x-1.0f);
+ x2 = x - x1;
+ x += updatePerCol;
+
+ // add weights
+ if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridRowCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1, col);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, (1.0f - x2) * lengthPerCol);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ if (x1+1 >= 0 && x1+1 < m_pVolumeGeometry->getGridRowCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1+1, col);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, x2 * lengthPerCol);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ }
+ }
+
+ // POLICY: RAY POSTERIOR
+ p.rayPosterior(iRayIndex);
+
+ } // end loop detector
+ } // end loop angles
+
+}
+
+
+//----------------------------------------------------------------------------------------
+// PROJECT SINGLE PROJECTION
+template <typename Policy>
+void CParallelBeamLinearKernelProjector2D::projectSingleProjection(int _iProjection, Policy& p)
+{
+ // variables
+ float32 theta, sin_theta, cos_theta, inv_sin_theta, inv_cos_theta, t;
+ float32 lengthPerRow, updatePerRow, inv_pixelLengthX;
+ float32 lengthPerCol, updatePerCol, inv_pixelLengthY;
+ bool switch_t;
+ int iDetector, iVolumeIndex, iRayIndex;
+ int row, col, x1;
+ float32 P,x,x2;
+
+ // get theta
+ theta = m_pProjectionGeometry->getProjectionAngle(_iProjection);
+ switch_t = false;
+ if (theta >= 7*PIdiv4) theta -= 2*PI;
+ if (theta >= 3*PIdiv4) {
+ theta -= PI;
+ switch_t = true;
+ }
+
+ // precalculate sin, cos, 1/cos
+ sin_theta = sin(theta);
+ cos_theta = cos(theta);
+ inv_cos_theta = 1.0f / cos_theta;
+ inv_sin_theta = 1.0f / sin_theta;
+
+ // precalculate kernel limits
+ lengthPerRow = m_pVolumeGeometry->getPixelLengthY() * inv_cos_theta;
+ updatePerRow = sin_theta * inv_cos_theta;
+ inv_pixelLengthX = 1.0f / m_pVolumeGeometry->getPixelLengthX();
+
+ // precalculate kernel limits
+ lengthPerCol = m_pVolumeGeometry->getPixelLengthX() * inv_sin_theta;
+ updatePerCol = cos_theta * inv_sin_theta;
+ inv_pixelLengthY = 1.0f / m_pVolumeGeometry->getPixelLengthY();
+
+ // loop detectors
+ for (iDetector = 0; iDetector < m_pProjectionGeometry->getDetectorCount(); ++iDetector) {
+
+ iRayIndex = _iProjection * m_pProjectionGeometry->getDetectorCount() + iDetector;
+
+ // POLICY: RAY PRIOR
+ if (!p.rayPrior(iRayIndex)) continue;
+
+ // get t
+ t = m_pProjectionGeometry->indexToDetectorOffset(iDetector);
+ if (switch_t) {
+ t = -t;
+ }
+
+ // vertically
+ if (theta <= PIdiv4) {
+
+ // calculate x for row 0
+ P = (t - sin_theta * m_pVolumeGeometry->pixelRowToCenterY(0)) * inv_cos_theta;
+ x = m_pVolumeGeometry->coordXToColF(P) - 0.5f;
+
+ // for each row
+ for (row = 0; row < m_pVolumeGeometry->getGridRowCount(); ++row) {
+
+ // get coords
+ x1 = (int)((x > 0.0f) ? x : x-1.0f);
+ x2 = x - x1;
+ x += updatePerRow;
+
+ // add weights
+ if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridColCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, (1.0f - x2) * lengthPerRow);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ if (x1+1 >= 0 && x1+1 < m_pVolumeGeometry->getGridColCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1+1);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, (x2) * lengthPerRow);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ }
+ }
+
+ // horizontally
+ else if (PIdiv4 <= theta && theta <= 3*PIdiv4) {
+
+ // calculate point P
+ P = (t - cos_theta * m_pVolumeGeometry->pixelColToCenterX(0)) * inv_sin_theta;
+ x = m_pVolumeGeometry->coordYToRowF(P) - 0.5f;
+
+ // for each row
+ for (col = 0; col < m_pVolumeGeometry->getGridColCount(); ++col) {
+
+ // get coords
+ x1 = (int)((x > 0.0f) ? x : x-1.0f);
+ x2 = x - x1;
+ x += updatePerCol;
+
+ // add weights
+ if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridRowCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1, col);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, (1.0f - x2) * lengthPerCol);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ if (x1+1 >= 0 && x1+1 < m_pVolumeGeometry->getGridRowCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1+1, col);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, x2 * lengthPerCol);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ }
+ }
+
+ // POLICY: RAY POSTERIOR
+ p.rayPosterior(iRayIndex);
+
+ } // end loop detector
+}
+
+//----------------------------------------------------------------------------------------
+// PROJECT SINGLE RAY
+template <typename Policy>
+void CParallelBeamLinearKernelProjector2D::projectSingleRay(int _iProjection, int _iDetector, Policy& p)
+{
+ int iVolumeIndex, iRayIndex;
+
+ iRayIndex = _iProjection * m_pProjectionGeometry->getDetectorCount() + _iDetector;
+
+ // POLICY: RAY PRIOR
+ if (!p.rayPrior(iRayIndex)) return;
+
+ // get theta
+ float32 theta = m_pProjectionGeometry->getProjectionAngle(_iProjection);
+ bool switch_t = false;
+ if (theta >= 7*PIdiv4) theta -= 2*PI;
+ if (theta >= 3*PIdiv4) {
+ theta -= PI;
+ switch_t = true;
+ }
+
+ // get t
+ float32 t = m_pProjectionGeometry->indexToDetectorOffset(_iDetector);
+ if (switch_t) {
+ t = -t;
+ }
+
+ // vertically
+ if (theta <= PIdiv4) {
+
+ // precalculate sin, 1/cos
+ float32 sin_theta = sin(theta);
+ float32 inv_cos_theta = 1.0f / cos(theta);
+
+ // precalculate kernel limits
+ float32 lengthPerRow = m_pVolumeGeometry->getPixelLengthY() * inv_cos_theta;
+ float32 updatePerRow = sin_theta * inv_cos_theta;
+
+ int row, x1;
+ float32 P,x,x2;
+
+ // calculate x for row 0
+ P = (t - sin_theta * m_pVolumeGeometry->pixelRowToCenterY(0)) * inv_cos_theta;
+ x = m_pVolumeGeometry->coordXToColF(P) - 0.5f;
+
+ // for each row
+ for (row = 0; row < m_pVolumeGeometry->getGridRowCount(); ++row) {
+
+ // get coords
+ x1 = (int)((x > 0.0f) ? x : x-1.0f);
+ x2 = x - x1;
+ x += updatePerRow;
+
+ // add weights
+ if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridColCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, (1.0f - x2) * lengthPerRow);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ if (x1+1 >= 0 && x1+1 < m_pVolumeGeometry->getGridColCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, x1+1);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, (x2) * lengthPerRow);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ }
+ }
+
+ // horizontally
+ else if (PIdiv4 <= theta && theta <= 3*PIdiv4) {
+
+ // precalculate cos 1/sin
+ float32 cos_theta = cos(theta);
+ float32 inv_sin_theta = 1.0f / sin(theta);
+
+ // precalculate kernel limits
+ float32 lengthPerCol = m_pVolumeGeometry->getPixelLengthX() * inv_sin_theta;
+ float32 updatePerCol = cos_theta * inv_sin_theta;
+
+ int col, x1;
+ float32 P,x,x2;
+
+ // calculate point P
+ P = (t - cos_theta * m_pVolumeGeometry->pixelColToCenterX(0)) * inv_sin_theta;
+ x = m_pVolumeGeometry->coordYToRowF(P) - 0.5f;
+
+ // for each row
+ for (col = 0; col < m_pVolumeGeometry->getGridColCount(); ++col) {
+
+ // get coords
+ x1 = (int)((x > 0.0f) ? x : x-1.0f);
+ x2 = x - x1;
+ x += updatePerCol;
+
+ // add weights
+ if (x1 >= 0 && x1 < m_pVolumeGeometry->getGridRowCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1, col);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, (1.0f - x2) * lengthPerCol);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ if (x1+1 >= 0 && x1+1 < m_pVolumeGeometry->getGridRowCount()) {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(x1+1, col);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, x2 * lengthPerCol);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+ }
+ }
+
+ // POLICY: RAY POSTERIOR
+ p.rayPosterior(iRayIndex);
+}
diff --git a/include/astra/ParallelBeamStripKernelProjector2D.h b/include/astra/ParallelBeamStripKernelProjector2D.h
new file mode 100644
index 0000000..de056de
--- /dev/null
+++ b/include/astra/ParallelBeamStripKernelProjector2D.h
@@ -0,0 +1,191 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_PARALLELBEAMSTROKEKERNELPROJECTOR
+#define _INC_ASTRA_PARALLELBEAMSTROKEKERNELPROJECTOR
+
+#include "ParallelProjectionGeometry2D.h"
+#include "Float32Data2D.h"
+#include "Projector2D.h"
+
+namespace astra
+{
+
+
+/** This class implements a two-dimensional projector based on a strip based kernel.
+ *
+ * \par XML Configuration
+ * \astra_xml_item{ProjectionGeometry, xml node, The geometry of the projection.}
+ * \astra_xml_item{VolumeGeometry, xml node, The geometry of the volume.}
+ *
+ * \par MATLAB example
+ * \astra_code{
+ * cfg = astra_struct('strip');\n
+ * cfg.ProjectionGeometry = proj_geom;\n
+ * cfg.VolumeGeometry = vol_geom;\n
+ * proj_id = astra_mex_projector('create'\, cfg);\n
+ * }
+ */
+class _AstraExport CParallelBeamStripKernelProjector2D : public CProjector2D {
+
+protected:
+
+ /** Initial clearing. Only to be used by constructors.
+ */
+ virtual void _clear();
+
+ /** Check the values of this object. If everything is ok, the object can be set to the initialized state.
+ * The following statements are then guaranteed to hold:
+ * - no NULL pointers
+ * - all sub-objects are initialized properly
+ * - blobvalues are ok
+ */
+ virtual bool _check();
+
+public:
+
+ // type of the projector, needed to register with CProjectorFactory
+ static std::string type;
+
+ /** Default constructor.
+ */
+ CParallelBeamStripKernelProjector2D();
+
+ /** Constructor.
+ *
+ * @param _pProjectionGeometry Information class about the geometry of the projection. Will be HARDCOPIED.
+ * @param _pReconstructionGeometry Information class about the geometry of the reconstruction volume. Will be HARDCOPIED.
+ */
+ CParallelBeamStripKernelProjector2D(CParallelProjectionGeometry2D* _pProjectionGeometry,
+ CVolumeGeometry2D* _pReconstructionGeometry);
+
+ /** Destructor, is virtual to show that we are aware subclass destructor are called.
+ */
+ ~CParallelBeamStripKernelProjector2D();
+
+ /** Initialize the projector with a config object.
+ *
+ * @param _cfg Configuration Object
+ * @return initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ /** Initialize the projector.
+ *
+ * @param _pProjectionGeometry Information class about the geometry of the projection. Will be HARDCOPIED.
+ * @param _pReconstructionGeometry Information class about the geometry of the reconstruction volume. Will be HARDCOPIED.
+ * @return initialization successful?
+ */
+ virtual bool initialize(CParallelProjectionGeometry2D* _pProjectionGeometry,
+ CVolumeGeometry2D* _pReconstructionGeometry);
+
+ /** Clear this class.
+ */
+ virtual void clear();
+
+ /** Returns the number of weights required for storage of all weights of one projection.
+ *
+ * @param _iProjectionIndex Index of the projection (zero-based).
+ * @return Size of buffer (given in SPixelWeight elements) needed to store weighted pixels.
+ */
+ virtual int getProjectionWeightsCount(int _iProjectionIndex);
+
+ /** Compute the pixel weights for a single ray, from the source to a detector pixel.
+ *
+ * @param _iProjectionIndex Index of the projection
+ * @param _iDetectorIndex Index of the detector pixel
+ * @param _pWeightedPixels Pointer to a pre-allocated array, consisting of _iMaxPixelCount elements
+ * of type SPixelWeight. On return, this array contains a list of the index
+ * and weight for all pixels on the ray.
+ * @param _iMaxPixelCount Maximum number of pixels (and corresponding weights) that can be stored in _pWeightedPixels.
+ * This number MUST be greater than the total number of pixels on the ray.
+ * @param _iStoredPixelCount On return, this variable contains the total number of pixels on the
+ * ray (that have been stored in the list _pWeightedPixels).
+ */
+ virtual void computeSingleRayWeights(int _iProjectionIndex,
+ int _iDetectorIndex,
+ SPixelWeight* _pWeightedPixels,
+ int _iMaxPixelCount,
+ int& _iStoredPixelCount);
+
+ /** Create a list of detectors that are influenced by point [_iRow, _iCol].
+ *
+ * @param _iRow row of the point
+ * @param _iCol column of the point
+ * @return list of SDetector2D structs
+ */
+ virtual std::vector<SDetector2D> projectPoint(int _iRow, int _iCol);
+
+ /** Policy-based projection of all rays. This function will calculate each non-zero projection
+ * weight and use this value for a task provided by the policy object.
+ *
+ * @param _policy Policy object. Should contain prior, addWeight and posterior function.
+ */
+ template <typename Policy>
+ void project(Policy& _policy);
+
+ /** Policy-based projection of all rays of a single projection. This function will calculate
+ * each non-zero projection weight and use this value for a task provided by the policy object.
+ *
+ * @param _iProjection Wwhich projection should be projected?
+ * @param _policy Policy object. Should contain prior, addWeight and posterior function.
+ */
+ template <typename Policy>
+ void projectSingleProjection(int _iProjection, Policy& _policy);
+
+ /** Policy-based projection of a single ray. This function will calculate each non-zero
+ * projection weight and use this value for a task provided by the policy object.
+ *
+ * @param _iProjection Which projection should be projected?
+ * @param _iDetector Which detector should be projected?
+ * @param _policy Policy object. Should contain prior, addWeight and posterior function.
+ */
+ template <typename Policy>
+ void projectSingleRay(int _iProjection, int _iDetector, Policy& _policy);
+
+protected:
+
+ /** Return the type of this projector.
+ *
+ * @return identification type of this projector
+ */
+ virtual std::string getType();
+
+};
+
+//----------------------------------------------------------------------------------------
+
+inline std::string CParallelBeamStripKernelProjector2D::getType()
+{
+ return type;
+}
+
+} // namespace astra
+
+#endif
+
diff --git a/include/astra/ParallelBeamStripKernelProjector2D.inl b/include/astra/ParallelBeamStripKernelProjector2D.inl
new file mode 100644
index 0000000..c55fa8e
--- /dev/null
+++ b/include/astra/ParallelBeamStripKernelProjector2D.inl
@@ -0,0 +1,739 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+
+//----------------------------------------------------------------------------------------
+// PROJECT ALL
+template <typename Policy>
+void CParallelBeamStripKernelProjector2D::project(Policy& p)
+{
+ ASTRA_ASSERT(m_bIsInitialized);
+
+ // Some variables
+ float32 theta, t;
+ int row, col;
+ int iAngle;
+ int iDetector;
+ float32 res;
+ float32 PL, PLimitL, PLimitR;
+ float32 xL, xR, XLimitL, XLimitR;
+ int x1L,x1R;
+ float32 x2L, x2R, updateX;
+ int iVolumeIndex, iRayIndex;
+
+ float32 sin_theta, cos_theta, inv_sin_theta, inv_cos_theta;
+ float32 fabs_sin_theta, fabs_cos_theta, fabs_inv_sin_theta, fabs_inv_cos_theta;
+ float32 PW, PH, DW, inv_PW, inv_PH;
+ float32 S, T, U, V, inv_4T;
+
+ // loop angles
+ for (iAngle = 0; iAngle < m_pProjectionGeometry->getProjectionAngleCount(); ++iAngle) {
+
+ // get values
+ theta = m_pProjectionGeometry->getProjectionAngle(iAngle);
+ bool switch_t = false;
+ if (theta >= 7*PIdiv4) theta -= 2*PI;
+ if (theta >= 3*PIdiv4) {
+ theta -= PI;
+ switch_t = true;
+ }
+
+ // Precalculate sin, cos, 1/cos
+ sin_theta = sin(theta);
+ cos_theta = cos(theta);
+ inv_cos_theta = 1.0f / cos_theta;
+ inv_sin_theta = 1.0f / sin_theta;
+
+ fabs_sin_theta = (sin_theta < 0.0f) ? -sin_theta : sin_theta;
+ fabs_cos_theta = (cos_theta < 0.0f) ? -cos_theta : cos_theta;
+ fabs_inv_cos_theta = (inv_cos_theta < 0.0f) ? -inv_cos_theta : inv_cos_theta;
+ fabs_inv_sin_theta = (inv_sin_theta < 0.0f) ? -inv_sin_theta : inv_sin_theta;
+
+ // Other precalculations
+ PW = m_pVolumeGeometry->getPixelLengthX();
+ PH = m_pVolumeGeometry->getPixelLengthY();
+ DW = m_pProjectionGeometry->getDetectorWidth();
+ inv_PW = 1.0f / PW;
+ inv_PH = 1.0f / PH;
+
+ // [-45?,45?] and [135?,225?]
+ if (theta < PIdiv4) {
+
+ // Precalculate kernel limits
+ S = -0.5f * fabs_sin_theta * fabs_inv_cos_theta;
+ T = -S;
+ U = 1.0f + S;
+ V = 1.0f - S;
+ inv_4T = 0.25f / T;
+
+ updateX = sin_theta * inv_cos_theta;
+
+ // loop detectors
+ for (iDetector = 0; iDetector < m_pProjectionGeometry->getDetectorCount(); ++iDetector) {
+
+ iRayIndex = iAngle * m_pProjectionGeometry->getDetectorCount() + iDetector;
+
+ // POLICY: RAY PRIOR
+ if (!p.rayPrior(iRayIndex)) continue;
+
+ // get t
+ t = m_pProjectionGeometry->indexToDetectorOffset(iDetector);
+ if (switch_t) t = -t;
+
+ // calculate left strip extremes (volume coordinates)
+ PL = (t - sin_theta * m_pVolumeGeometry->pixelRowToCenterY(0) - DW*0.5f) * inv_cos_theta;
+ PLimitL = PL - 0.5f * fabs_sin_theta * fabs_inv_cos_theta * PH;
+ PLimitR = PLimitL + DW * inv_cos_theta + PH * fabs_sin_theta * fabs_inv_cos_theta;
+
+ // calculate strip extremes (pixel coordinates)
+ XLimitL = (PLimitL - m_pVolumeGeometry->getWindowMinX()) * inv_PW;
+ XLimitR = (PLimitR - m_pVolumeGeometry->getWindowMinX()) * inv_PW;
+ xL = (PL - m_pVolumeGeometry->getWindowMinX()) * inv_PW;
+ xR = xL + (DW * inv_cos_theta) * inv_PW;
+
+ // for each row
+ for (row = 0; row < m_pVolumeGeometry->getGridRowCount(); ++row) {
+
+ // get strip extremes in column indices
+ x1L = int((XLimitL > 0.0f) ? XLimitL : XLimitL-1.0f);
+ x1R = int((XLimitR > 0.0f) ? XLimitR : XLimitR-1.0f);
+
+ // get coords w.r.t leftmost column hit by strip
+ x2L = xL - x1L;
+ x2R = xR - x1L;
+
+ // update strip extremes for the next row
+ XLimitL += updateX;
+ XLimitR += updateX;
+ xL += updateX;
+ xR += updateX;
+
+ // for each affected col
+ for (col = x1L; col <= x1R; ++col) {
+
+ if (col < 0 || col >= m_pVolumeGeometry->getGridColCount()) { x2L -= 1.0f; x2R -= 1.0f; continue; }
+
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, col);
+ // POLICY: PIXEL PRIOR
+ if (!p.pixelPrior(iVolumeIndex)) { x2L -= 1.0f; x2R -= 1.0f; continue; }
+
+ // right
+ if (x2R >= V) res = 1.0f;
+ else if (x2R > U) res = x2R - (x2R-U)*(x2R-U)*inv_4T;
+ else if (x2R >= T) res = x2R;
+ else if (x2R > S) res = (x2R-S)*(x2R-S) * inv_4T;
+ else { x2L -= 1.0f; x2R -= 1.0f; continue; }
+
+ // left
+ if (x2L <= S) {} // - 0.0f
+ else if (x2L < T) res -= (x2L-S)*(x2L-S) * inv_4T;
+ else if (x2L <= U) res -= x2L;
+ else if (x2L < V) res -= x2L - (x2L-U)*(x2L-U)*inv_4T;
+ else { x2L -= 1.0f; x2R -= 1.0f; continue; }
+
+ // POLICY: ADD
+ p.addWeight(iRayIndex, iVolumeIndex, PW*PH * res);
+
+ // POLICY: PIXEL POSTERIOR
+ p.pixelPosterior(iVolumeIndex);
+
+ x2L -= 1.0f;
+ x2R -= 1.0f;
+
+ } // end col loop
+
+ } // end row loop
+
+ // POLICY: RAY POSTERIOR
+ p.rayPosterior(iRayIndex);
+
+ } // end detector loop
+
+ // [45?,135?] and [225?,315?]
+ // horizontaly
+ } else {
+
+ // Precalculate kernel limits
+ S = -0.5f * fabs_cos_theta * fabs_inv_sin_theta;
+ T = -S;
+ U = 1.0f + S;
+ V = 1.0f - S;
+ inv_4T = 0.25f / T;
+
+ updateX = cos_theta * inv_sin_theta;
+
+ // loop detectors
+ for (iDetector = 0; iDetector < m_pProjectionGeometry->getDetectorCount(); ++iDetector) {
+
+ iRayIndex = iAngle * m_pProjectionGeometry->getDetectorCount() + iDetector;
+
+ // POLICY: RAY PRIOR
+ if (!p.rayPrior(iRayIndex)) continue;
+
+ // get t
+ t = m_pProjectionGeometry->indexToDetectorOffset(iDetector);
+ if (switch_t) t = -t;
+
+ // calculate left strip extremes (volume coordinates)
+ PL = (t - cos_theta * m_pVolumeGeometry->pixelColToCenterX(0) + DW*0.5f) * inv_sin_theta;
+ PLimitL = PL + 0.5f * fabs_cos_theta * fabs_inv_sin_theta * PW;
+ PLimitR = PLimitL - DW * inv_sin_theta - PH * fabs_cos_theta * fabs_inv_sin_theta;
+
+ // calculate strip extremes (pixel coordinates)
+ XLimitL = (m_pVolumeGeometry->getWindowMaxY() - PLimitL) * inv_PH;
+ XLimitR = (m_pVolumeGeometry->getWindowMaxY() - PLimitR) * inv_PH;
+ xL = (m_pVolumeGeometry->getWindowMaxY() - PL) * inv_PH;
+ xR = xL + (DW * fabs_inv_sin_theta) * inv_PH;
+
+ // for each col
+ for (col = 0; col < m_pVolumeGeometry->getGridColCount(); ++col) {
+
+ // get strip extremes in column indices
+ x1L = int((XLimitL > 0.0f) ? XLimitL : XLimitL-1.0f);
+ x1R = int((XLimitR > 0.0f) ? XLimitR : XLimitR-1.0f);
+
+ // get coords w.r.t leftmost column hit by strip
+ x2L = xL - x1L;
+ x2R = xR - x1L;
+
+ // update strip extremes for the next row
+ XLimitL += updateX;
+ XLimitR += updateX;
+ xL += updateX;
+ xR += updateX;
+
+ // for each affected col
+ for (row = x1L; row <= x1R; ++row) {
+
+ if (row < 0 || row >= m_pVolumeGeometry->getGridRowCount()) { x2L -= 1.0f; x2R -= 1.0f; continue; }
+
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, col);
+
+ // POLICY: PIXEL PRIOR
+ if (!p.pixelPrior(iVolumeIndex)) { x2L -= 1.0f; x2R -= 1.0f; continue; }
+
+ // right
+ if (x2R >= V) res = 1.0f;
+ else if (x2R > U) res = x2R - (x2R-U)*(x2R-U)*inv_4T;
+ else if (x2R >= T) res = x2R;
+ else if (x2R > S) res = (x2R-S)*(x2R-S) * inv_4T;
+ else { x2L -= 1.0f; x2R -= 1.0f; continue; }
+
+ // left
+ if (x2L <= S) {} // - 0.0f
+ else if (x2L < T) res -= (x2L-S)*(x2L-S) * inv_4T;
+ else if (x2L <= U) res -= x2L;
+ else if (x2L < V) res -= x2L - (x2L-U)*(x2L-U)*inv_4T;
+ else { x2L -= 1.0f; x2R -= 1.0f; continue; }
+
+ // POLICY: ADD
+ p.addWeight(iRayIndex, iVolumeIndex, PW*PH * res);
+
+ // POLICY: PIXEL POSTERIOR
+ p.pixelPosterior(iVolumeIndex);
+
+ x2L -= 1.0f;
+ x2R -= 1.0f;
+
+ } // end row loop
+
+ } // end col loop
+
+ // POLICY: RAY POSTERIOR
+ p.rayPosterior(iRayIndex);
+
+ } // end detector loop
+
+
+ } // end theta switch
+
+ } // end angle loop
+}
+
+
+//----------------------------------------------------------------------------------------
+// PROJECT SINGLE PROJECTION
+template <typename Policy>
+void CParallelBeamStripKernelProjector2D::projectSingleProjection(int _iProjection, Policy& p)
+{
+ // Some variables
+ float32 theta, t;
+ int row, col, iDetector;
+ float32 res;
+ float32 PL, PLimitL, PLimitR;
+ float32 xL, xR, XLimitL, XLimitR;
+ int x1L,x1R;
+ float32 x2L, x2R, updateX;
+ int iVolumeIndex, iRayIndex;
+
+ float32 sin_theta, cos_theta, inv_sin_theta, inv_cos_theta;
+ float32 fabs_sin_theta, fabs_cos_theta, fabs_inv_sin_theta, fabs_inv_cos_theta;
+ float32 PW, PH, DW, inv_PW, inv_PH;
+ float32 S, T, U, V, inv_4T;
+
+ // get values
+ theta = m_pProjectionGeometry->getProjectionAngle(_iProjection);
+ bool switch_t = false;
+ if (theta >= 7*PIdiv4) theta -= 2*PI;
+ if (theta >= 3*PIdiv4) {
+ theta -= PI;
+ switch_t = true;
+ }
+
+ // Precalculate sin, cos, 1/cos
+ sin_theta = sin(theta);
+ cos_theta = cos(theta);
+ inv_cos_theta = 1.0f / cos_theta;
+ inv_sin_theta = 1.0f / sin_theta;
+
+ fabs_sin_theta = (sin_theta < 0.0f) ? -sin_theta : sin_theta;
+ fabs_cos_theta = (cos_theta < 0.0f) ? -cos_theta : cos_theta;
+ fabs_inv_cos_theta = (inv_cos_theta < 0.0f) ? -inv_cos_theta : inv_cos_theta;
+ fabs_inv_sin_theta = (inv_sin_theta < 0.0f) ? -inv_sin_theta : inv_sin_theta;
+
+ // Other precalculations
+ PW = m_pVolumeGeometry->getPixelLengthX();
+ PH = m_pVolumeGeometry->getPixelLengthY();
+ DW = m_pProjectionGeometry->getDetectorWidth();
+ inv_PW = 1.0f / PW;
+ inv_PH = 1.0f / PH;
+
+ // [-45?,45?] and [135?,225?]
+ if (theta < PIdiv4) {
+
+ // Precalculate kernel limits
+ S = -0.5f * fabs_sin_theta * fabs_inv_cos_theta;
+ T = -S;
+ U = 1.0f + S;
+ V = 1.0f - S;
+ inv_4T = 0.25f / T;
+
+ updateX = sin_theta * inv_cos_theta;
+
+ // loop detectors
+ for (iDetector = 0; iDetector < m_pProjectionGeometry->getDetectorCount(); ++iDetector) {
+
+ iRayIndex = _iProjection * m_pProjectionGeometry->getDetectorCount() + iDetector;
+
+ // POLICY: RAY PRIOR
+ if (!p.rayPrior(iRayIndex)) continue;
+
+ // get t
+ t = m_pProjectionGeometry->indexToDetectorOffset(iDetector);
+ if (switch_t) t = -t;
+
+ // calculate left strip extremes (volume coordinates)
+ PL = (t - sin_theta * m_pVolumeGeometry->pixelRowToCenterY(0) - DW*0.5f) * inv_cos_theta;
+ PLimitL = PL - 0.5f * fabs_sin_theta * fabs_inv_cos_theta * PH;
+ PLimitR = PLimitL + DW * inv_cos_theta + PH * fabs_sin_theta * fabs_inv_cos_theta;
+
+ // calculate strip extremes (pixel coordinates)
+ XLimitL = (PLimitL - m_pVolumeGeometry->getWindowMinX()) * inv_PW;
+ XLimitR = (PLimitR - m_pVolumeGeometry->getWindowMinX()) * inv_PW;
+ xL = (PL - m_pVolumeGeometry->getWindowMinX()) * inv_PW;
+ xR = xL + (DW * inv_cos_theta) * inv_PW;
+
+ // for each row
+ for (row = 0; row < m_pVolumeGeometry->getGridRowCount(); ++row) {
+
+ // get strip extremes in column indices
+ x1L = int((XLimitL > 0.0f) ? XLimitL : XLimitL-1.0f);
+ x1R = int((XLimitR > 0.0f) ? XLimitR : XLimitR-1.0f);
+
+ // get coords w.r.t leftmost column hit by strip
+ x2L = xL - x1L;
+ x2R = xR - x1L;
+
+ // update strip extremes for the next row
+ XLimitL += updateX;
+ XLimitR += updateX;
+ xL += updateX;
+ xR += updateX;
+
+ // for each affected col
+ for (col = x1L; col <= x1R; ++col) {
+
+ if (col < 0 || col >= m_pVolumeGeometry->getGridColCount()) { x2L -= 1.0f; x2R -= 1.0f; continue; }
+
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, col);
+
+ // POLICY: PIXEL PRIOR
+ if (!p.pixelPrior(iVolumeIndex)) { x2L -= 1.0f; x2R -= 1.0f; continue; }
+
+ // right
+ if (x2R >= V) res = 1.0f;
+ else if (x2R > U) res = x2R - (x2R-U)*(x2R-U)*inv_4T;
+ else if (x2R >= T) res = x2R;
+ else if (x2R > S) res = (x2R-S)*(x2R-S) * inv_4T;
+ else { x2L -= 1.0f; x2R -= 1.0f; continue; }
+
+ // left
+ if (x2L <= S) {} // - 0.0f
+ else if (x2L < T) res -= (x2L-S)*(x2L-S) * inv_4T;
+ else if (x2L <= U) res -= x2L;
+ else if (x2L < V) res -= x2L - (x2L-U)*(x2L-U)*inv_4T;
+ else { x2L -= 1.0f; x2R -= 1.0f; continue; }
+
+ // POLICY: ADD
+ p.addWeight(iRayIndex, iVolumeIndex, PW*PH * res);
+
+ // POLICY: PIXEL POSTERIOR
+ p.pixelPosterior(iVolumeIndex);
+
+ x2L -= 1.0f;
+ x2R -= 1.0f;
+
+ } // end col loop
+
+ } // end row loop
+
+ // POLICY: RAY POSTERIOR
+ p.rayPosterior(iRayIndex);
+
+ } // end detector loop
+
+ // [45?,135?] and [225?,315?]
+ // horizontaly
+ } else {
+
+ // Precalculate kernel limits
+ S = -0.5f * fabs_cos_theta * fabs_inv_sin_theta;
+ T = -S;
+ U = 1.0f + S;
+ V = 1.0f - S;
+ inv_4T = 0.25f / T;
+
+ updateX = cos_theta * inv_sin_theta;
+
+ // loop detectors
+ for (iDetector = 0; iDetector < m_pProjectionGeometry->getDetectorCount(); ++iDetector) {
+
+ iRayIndex = _iProjection * m_pProjectionGeometry->getDetectorCount() + iDetector;
+
+ // POLICY: RAY PRIOR
+ if (!p.rayPrior(iRayIndex)) continue;
+
+ // get t
+ t = m_pProjectionGeometry->indexToDetectorOffset(iDetector);
+ if (switch_t) t = -t;
+
+ // calculate left strip extremes (volume coordinates)
+ PL = (t - cos_theta * m_pVolumeGeometry->pixelColToCenterX(0) + DW*0.5f) * inv_sin_theta;
+ PLimitL = PL + 0.5f * fabs_cos_theta * fabs_inv_sin_theta * PW;
+ PLimitR = PLimitL - DW * inv_sin_theta - PH * fabs_cos_theta * fabs_inv_sin_theta;
+
+ // calculate strip extremes (pixel coordinates)
+ XLimitL = (m_pVolumeGeometry->getWindowMaxY() - PLimitL) * inv_PH;
+ XLimitR = (m_pVolumeGeometry->getWindowMaxY() - PLimitR) * inv_PH;
+ xL = (m_pVolumeGeometry->getWindowMaxY() - PL) * inv_PH;
+ xR = xL + (DW * fabs_inv_sin_theta) * inv_PH;
+
+ // for each col
+ for (col = 0; col < m_pVolumeGeometry->getGridColCount(); ++col) {
+
+ // get strip extremes in column indices
+ x1L = int((XLimitL > 0.0f) ? XLimitL : XLimitL-1.0f);
+ x1R = int((XLimitR > 0.0f) ? XLimitR : XLimitR-1.0f);
+
+ // get coords w.r.t leftmost column hit by strip
+ x2L = xL - x1L;
+ x2R = xR - x1L;
+
+ // update strip extremes for the next row
+ XLimitL += updateX;
+ XLimitR += updateX;
+ xL += updateX;
+ xR += updateX;
+
+ // for each affected col
+ for (row = x1L; row <= x1R; ++row) {
+
+ if (row < 0 || row >= m_pVolumeGeometry->getGridRowCount()) { x2L -= 1.0f; x2R -= 1.0f; continue; }
+
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, col);
+
+ // POLICY: PIXEL PRIOR
+ if (!p.pixelPrior(iVolumeIndex)) { x2L -= 1.0f; x2R -= 1.0f; continue; }
+
+ // right
+ if (x2R >= V) res = 1.0f;
+ else if (x2R > U) res = x2R - (x2R-U)*(x2R-U)*inv_4T;
+ else if (x2R >= T) res = x2R;
+ else if (x2R > S) res = (x2R-S)*(x2R-S) * inv_4T;
+ else { x2L -= 1.0f; x2R -= 1.0f; continue; }
+
+ // left
+ if (x2L <= S) {} // - 0.0f
+ else if (x2L < T) res -= (x2L-S)*(x2L-S) * inv_4T;
+ else if (x2L <= U) res -= x2L;
+ else if (x2L < V) res -= x2L - (x2L-U)*(x2L-U)*inv_4T;
+ else { x2L -= 1.0f; x2R -= 1.0f; continue; }
+
+ // POLICY: ADD
+ p.addWeight(iRayIndex, iVolumeIndex, PW*PH * res);
+
+ // POLICY: PIXEL POSTERIOR
+ p.pixelPosterior(iVolumeIndex);
+
+ x2L -= 1.0f;
+ x2R -= 1.0f;
+
+ } // end row loop
+
+ } // end col loop
+
+ // POLICY: RAY POSTERIOR
+ p.rayPosterior(iRayIndex);
+
+ } // end detector loop
+
+ } // end theta switch
+}
+
+
+//----------------------------------------------------------------------------------------
+// PROJECT SINGLE RAY
+template <typename Policy>
+void CParallelBeamStripKernelProjector2D::projectSingleRay(int _iProjection, int _iDetector, Policy& p)
+{
+ int iRayIndex = _iProjection * m_pProjectionGeometry->getDetectorCount() + _iDetector;
+
+ // POLICY: RAY PRIOR
+ if (!p.rayPrior(iRayIndex)) return;
+
+ // Some variables
+ float32 theta, t;
+ int row, col;
+ float32 res;
+ float32 PL, PLimitL, PLimitR;
+ float32 xL, xR, XLimitL, XLimitR;
+ int x1L,x1R;
+ float32 x2L, x2R, updateX;
+ int iVolumeIndex;
+
+ float32 sin_theta, cos_theta, inv_sin_theta, inv_cos_theta;
+ float32 fabs_sin_theta, fabs_cos_theta, fabs_inv_sin_theta, fabs_inv_cos_theta;
+ float32 PW, PH, DW, inv_PW, inv_PH;
+ float32 S, T, U, V, inv_4T;
+
+ // get values
+ theta = m_pProjectionGeometry->getProjectionAngle(_iProjection);
+ bool switch_t = false;
+ if (theta >= 7*PIdiv4) theta -= 2*PI;
+ if (theta >= 3*PIdiv4) {
+ theta -= PI;
+ switch_t = true;
+ }
+
+ // Precalculate sin, cos, 1/cos
+ sin_theta = sin(theta);
+ cos_theta = cos(theta);
+ inv_cos_theta = 1.0f / cos_theta;
+ inv_sin_theta = 1.0f / sin_theta;
+
+ fabs_sin_theta = (sin_theta < 0.0f) ? -sin_theta : sin_theta;
+ fabs_cos_theta = (cos_theta < 0.0f) ? -cos_theta : cos_theta;
+ fabs_inv_cos_theta = (inv_cos_theta < 0.0f) ? -inv_cos_theta : inv_cos_theta;
+ fabs_inv_sin_theta = (inv_sin_theta < 0.0f) ? -inv_sin_theta : inv_sin_theta;
+
+ // Other precalculations
+ PW = m_pVolumeGeometry->getPixelLengthX();
+ PH = m_pVolumeGeometry->getPixelLengthY();
+ DW = m_pProjectionGeometry->getDetectorWidth();
+ inv_PW = 1.0f / PW;
+ inv_PH = 1.0f / PH;
+
+ // [-45?,45?] and [135?,225?]
+ if (theta < PIdiv4) {
+
+ // Precalculate kernel limits
+ S = -0.5f * fabs_sin_theta * fabs_inv_cos_theta;
+ T = -S;
+ U = 1.0f + S;
+ V = 1.0f - S;
+ inv_4T = 0.25f / T;
+
+ updateX = sin_theta * inv_cos_theta;
+
+ // get t
+ t = m_pProjectionGeometry->indexToDetectorOffset(_iDetector);
+ if (switch_t) t = -t;
+
+ // calculate left strip extremes (volume coordinates)
+ PL = (t - sin_theta * m_pVolumeGeometry->pixelRowToCenterY(0) - DW*0.5f) * inv_cos_theta;
+ PLimitL = PL - 0.5f * fabs_sin_theta * fabs_inv_cos_theta * PH;
+ PLimitR = PLimitL + DW * inv_cos_theta + PH * fabs_sin_theta * fabs_inv_cos_theta;
+
+ // calculate strip extremes (pixel coordinates)
+ XLimitL = (PLimitL - m_pVolumeGeometry->getWindowMinX()) * inv_PW;
+ XLimitR = (PLimitR - m_pVolumeGeometry->getWindowMinX()) * inv_PW;
+ xL = (PL - m_pVolumeGeometry->getWindowMinX()) * inv_PW;
+ xR = xL + (DW * inv_cos_theta) * inv_PW;
+
+ // for each row
+ for (row = 0; row < m_pVolumeGeometry->getGridRowCount(); ++row) {
+
+ // get strip extremes in column indices
+ x1L = int((XLimitL > 0.0f) ? XLimitL : XLimitL-1.0f);
+ x1R = int((XLimitR > 0.0f) ? XLimitR : XLimitR-1.0f);
+
+ // get coords w.r.t leftmost column hit by strip
+ x2L = xL - x1L;
+ x2R = xR - x1L;
+
+ // update strip extremes for the next row
+ XLimitL += updateX;
+ XLimitR += updateX;
+ xL += updateX;
+ xR += updateX;
+
+ // for each affected col
+ for (col = x1L; col <= x1R; ++col) {
+
+ if (col < 0 || col >= m_pVolumeGeometry->getGridColCount()) { x2L -= 1.0f; x2R -= 1.0f; continue; }
+
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, col);
+
+ // POLICY: PIXEL PRIOR
+ if (!p.pixelPrior(iVolumeIndex)) { x2L -= 1.0f; x2R -= 1.0f; continue; }
+
+ // right
+ if (x2R >= V) res = 1.0f;
+ else if (x2R > U) res = x2R - (x2R-U)*(x2R-U)*inv_4T;
+ else if (x2R >= T) res = x2R;
+ else if (x2R > S) res = (x2R-S)*(x2R-S) * inv_4T;
+ else { x2L -= 1.0f; x2R -= 1.0f; continue; }
+
+ // left
+ if (x2L <= S) {} // - 0.0f
+ else if (x2L < T) res -= (x2L-S)*(x2L-S) * inv_4T;
+ else if (x2L <= U) res -= x2L;
+ else if (x2L < V) res -= x2L - (x2L-U)*(x2L-U)*inv_4T;
+ else { x2L -= 1.0f; x2R -= 1.0f; continue; }
+
+ // POLICY: ADD
+ p.addWeight(iRayIndex, iVolumeIndex, PW*PH * res);
+
+ // POLICY: PIXEL POSTERIOR
+ p.pixelPosterior(iVolumeIndex);
+
+ x2L -= 1.0f;
+ x2R -= 1.0f;
+
+ } // end col loop
+
+ } // end row loop
+
+ // [45?,135?] and [225?,315?]
+ // horizontaly
+ } else {
+
+ // Precalculate kernel limits
+ S = -0.5f * fabs_cos_theta * fabs_inv_sin_theta;
+ T = -S;
+ U = 1.0f + S;
+ V = 1.0f - S;
+ inv_4T = 0.25f / T;
+
+ updateX = cos_theta * inv_sin_theta;
+
+ // get t
+ t = m_pProjectionGeometry->indexToDetectorOffset(_iDetector);
+ if (switch_t) t = -t;
+
+ // calculate left strip extremes (volume coordinates)
+ PL = (t - cos_theta * m_pVolumeGeometry->pixelColToCenterX(0) + DW*0.5f) * inv_sin_theta;
+ PLimitL = PL + 0.5f * fabs_cos_theta * fabs_inv_sin_theta * PW;
+ PLimitR = PLimitL - DW * inv_sin_theta - PH * fabs_cos_theta * fabs_inv_sin_theta;
+
+ // calculate strip extremes (pixel coordinates)
+ XLimitL = (m_pVolumeGeometry->getWindowMaxY() - PLimitL) * inv_PH;
+ XLimitR = (m_pVolumeGeometry->getWindowMaxY() - PLimitR) * inv_PH;
+ xL = (m_pVolumeGeometry->getWindowMaxY() - PL) * inv_PH;
+ xR = xL + (DW * fabs_inv_sin_theta) * inv_PH;
+
+ // for each col
+ for (col = 0; col < m_pVolumeGeometry->getGridColCount(); ++col) {
+
+ // get strip extremes in column indices
+ x1L = int((XLimitL > 0.0f) ? XLimitL : XLimitL-1.0f);
+ x1R = int((XLimitR > 0.0f) ? XLimitR : XLimitR-1.0f);
+
+ // get coords w.r.t leftmost column hit by strip
+ x2L = xL - x1L;
+ x2R = xR - x1L;
+
+ // update strip extremes for the next row
+ XLimitL += updateX;
+ XLimitR += updateX;
+ xL += updateX;
+ xR += updateX;
+
+ // for each affected col
+ for (row = x1L; row <= x1R; ++row) {
+
+ if (row < 0 || row >= m_pVolumeGeometry->getGridRowCount()) { x2L -= 1.0f; x2R -= 1.0f; continue; }
+
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, col);
+
+ // POLICY: PIXEL PRIOR
+ if (!p.pixelPrior(iVolumeIndex)) { x2L -= 1.0f; x2R -= 1.0f; continue; }
+
+ // right
+ if (x2R >= V) res = 1.0f;
+ else if (x2R > U) res = x2R - (x2R-U)*(x2R-U)*inv_4T;
+ else if (x2R >= T) res = x2R;
+ else if (x2R > S) res = (x2R-S)*(x2R-S) * inv_4T;
+ else { x2L -= 1.0f; x2R -= 1.0f; continue; }
+
+ // left
+ if (x2L <= S) {} // - 0.0f
+ else if (x2L < T) res -= (x2L-S)*(x2L-S) * inv_4T;
+ else if (x2L <= U) res -= x2L;
+ else if (x2L < V) res -= x2L - (x2L-U)*(x2L-U)*inv_4T;
+ else { x2L -= 1.0f; x2R -= 1.0f; continue; }
+
+ // POLICY: ADD
+ p.addWeight(iRayIndex, iVolumeIndex, PW*PH * res);
+
+ // POLICY: PIXEL POSTERIOR
+ p.pixelPosterior(iVolumeIndex);
+
+ x2L -= 1.0f;
+ x2R -= 1.0f;
+
+ } // end row loop
+
+ } // end col loop
+
+ } // end theta switch
+
+ // POLICY: RAY POSTERIOR
+ p.rayPosterior(iRayIndex);
+
+}
diff --git a/include/astra/ParallelProjectionGeometry2D.h b/include/astra/ParallelProjectionGeometry2D.h
new file mode 100644
index 0000000..c91fb4d
--- /dev/null
+++ b/include/astra/ParallelProjectionGeometry2D.h
@@ -0,0 +1,153 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_PARALLELPROJECTIONGEOMETRY2D
+#define _INC_ASTRA_PARALLELPROJECTIONGEOMETRY2D
+
+#include "ProjectionGeometry2D.h"
+
+namespace astra
+{
+
+/**
+ * This class defines a 2D parallel beam projection geometry.
+ *
+ * <img src="../images/par_proj_geom.svg" width="600"/>
+ * This geometry is defined by a number of parameters:
+ * - The number of detectors (DetCount).
+ * The distance between the first detector and the projection of the origin \f$O\f$ is equal to
+ * the distance between the last detector and the projection of \f$O\f$.
+ * - The width of each detector (detector width). All detectors are equidistant.
+ * - A list of projection angles (\f$\theta\f$), measured w.r.t. the y-axis of the volume. In Radians. Should lie in the interval \f$[-\frac{\pi}{4},\frac{7\pi}{4}]\f$.
+ *
+ * This class provides functionality to convert between detector index and detector offset \f$t\f$.
+ *
+ * \par XML Configuration
+ * \astra_xml_item{DetectorCount, int, Number of detectors for each projection.}
+ * \astra_xml_item{DetectorWidth, float, Width of each detector.}
+ * \astra_xml_item{ProjectionAngles, vector of float, projection angles w.r.t. the y-axis of the volume in radians.}
+ *
+ * \par MATLAB example
+ * \astra_code{
+ * proj_geom = astra_struct('parallel');\n
+ * proj_geom.DetectorCount = 512;\n
+ * proj_geom.DetectorWidth = 1.0;\n
+ * proj_geom.ProjectionAngles = linspace(0\,pi\,100);\n
+ * }
+ */
+class _AstraExport CParallelProjectionGeometry2D : public CProjectionGeometry2D
+{
+public:
+
+ /** Default constructor. Sets all numeric member variables to 0 and all pointer member variables to NULL.
+ *
+ * If an object is constructed using this default constructor, it must always be followed by a call
+ * to one of the init() methods before the object can be used. Any use before calling init() is not allowed,
+ * except calling the member function isInitialized().
+ *
+ */
+ CParallelProjectionGeometry2D();
+
+ /** Constructor. Create an instance of the CParallelProjectionGeometry2D class.
+ *
+ * @param _iProjectionAngleCount Number of projection angles.
+ * @param _iDetectorCount Number of detectors, i.e., the number of detector measurements for each projection angle.
+ * @param _fDetectorWidth Width of a detector cell, in unit lengths. All detector cells are assumed to have equal width.
+ * @param _pfProjectionAngles Pointer to an array of projection angles. The angles will be copied from this array.
+ */
+ CParallelProjectionGeometry2D(int _iProjectionAngleCount,
+ int _iDetectorCount,
+ float32 _fDetectorWidth,
+ const float32* _pfProjectionAngles,
+ const float32* _pfExtraDetectorOffsets = 0);
+
+ /** Copy constructor.
+ */
+ CParallelProjectionGeometry2D(const CParallelProjectionGeometry2D& _projGeom);
+
+ /** Destructor.
+ */
+ ~CParallelProjectionGeometry2D();
+
+ /** Assignment operator.
+ */
+ CParallelProjectionGeometry2D& operator=(const CParallelProjectionGeometry2D& _other);
+
+ /** Initialize the geometry with a config object.
+ *
+ * @param _cfg Configuration Object
+ * @return initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ /** Initialization. Initializes an instance of the CProjectionGeometry2D class. If the object has been
+ * initialized before, the object is reinitialized and memory is freed and reallocated if necessary.
+ *
+ * @param _iProjectionAngleCount Number of projection angles.
+ * @param _iDetectorCount Number of detectors, i.e., the number of detector measurements for each projection angle.
+ * @param _fDetectorWidth Width of a detector cell, in unit lengths. All detector cells are assumed to have equal width.
+ * @param _pfProjectionAngles Pointer to an array of projection angles. The angles will be copied from this array.
+ */
+ bool initialize(int _iProjectionAngleCount,
+ int _iDetectorCount,
+ float32 _fDetectorWidth,
+ const float32* _pfProjectionAngles,
+ const float32* _pfExtraDetectorOffsets = 0);
+
+ /** Create a hard copy.
+ */
+ virtual CProjectionGeometry2D* clone();
+
+ /** Return true if this geometry instance is the same as the one specified.
+ *
+ * @return true if this geometry instance is the same as the one specified.
+ */
+ virtual bool isEqual(CProjectionGeometry2D*) const;
+
+ /** Returns true if the type of geometry defined in this class is the one specified in _sType.
+ *
+ * @param _sType geometry type to compare to.
+ * @return true if _sType == "parallel".
+ */
+ virtual bool isOfType(const std::string& _sType);
+
+ /**
+ * Returns a vector describing the direction of a ray belonging to a certain detector,
+ * the direction is the same for all detectors in one projection
+ *
+ * @param _iProjectionIndex index of projection
+ * @param _iProjectionIndex index of detector
+ *
+ * @return a unit vector describing the direction
+ */
+ virtual CVector3D getProjectionDirection(int _iProjectionIndex, int _iDetectorIndex = 0);
+};
+
+} // namespace astra
+
+#endif /* _INC_ASTRA_PARALLELPROJECTIONGEOMETRY2D */
diff --git a/include/astra/ParallelProjectionGeometry3D.h b/include/astra/ParallelProjectionGeometry3D.h
new file mode 100644
index 0000000..85d0687
--- /dev/null
+++ b/include/astra/ParallelProjectionGeometry3D.h
@@ -0,0 +1,165 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_PARALLELPROJECTIONGEOMETRY3D
+#define _INC_ASTRA_PARALLELPROJECTIONGEOMETRY3D
+
+#include "ProjectionGeometry3D.h"
+#include "ParallelProjectionGeometry2D.h"
+
+namespace astra
+{
+
+/**
+ * This class defines a 3D parallel beam projection geometry.
+ *
+ * \par XML Configuration
+ * \astra_xml_item{DetectorRowCount, int, Number of detectors for each projection.}
+ * \astra_xml_item{DetectorColCount, int, Number of detectors for each projection.}
+ * \astra_xml_item{DetectorWidth, float, Width of each detector.}
+ * \astra_xml_item{DetectorHeight, float, Width of each detector.}
+ * \astra_xml_item{ProjectionAngles, vector of float, projection angles in radians.}
+ *
+ * \par MATLAB example
+ * \astra_code{
+ * proj_geom = astra_struct('parallel');\n
+ * proj_geom.DetectorRowCount = 512;\n
+ * proj_geom.DetectorColCount = 512;\n
+ * proj_geom.DetectorWidth = 1.0;\n
+ * proj_geom.DetectorHeight = 1.0;\n
+ * proj_geom.ProjectionAngles = linspace(0,pi,100);\n
+ * }
+ */
+class _AstraExport CParallelProjectionGeometry3D : public CProjectionGeometry3D
+{
+protected:
+
+public:
+
+ /** Default constructor. Sets all numeric member variables to 0 and all pointer member variables to NULL.
+ *
+ * If an object is constructed using this default constructor, it must always be followed by a call
+ * to one of the initialize() methods before the object can be used. Any use before calling initialize()
+ * is not allowed, except calling the member function isInitialized().
+ */
+ CParallelProjectionGeometry3D();
+
+ /** Constructor. Create an instance of the CParallelProjectionGeometry3D class.
+ *
+ * @param _iProjectionAngleCount Number of projection angles.
+ * @param _iDetectorRowCount Number of rows of detectors.
+ * @param _iDetectorColCount Number of columns detectors.
+ * @param _fDetectorWidth Width of a detector cell, in unit lengths. All detector cells are assumed to have equal width.
+ * @param _fDetectorHeight Height of a detector cell, in unit lengths. All detector cells are assumed to have equal width.
+ * @param _pfProjectionAngles Pointer to an array of projection angles. The angles will be copied from this array. All angles
+ * are represented in radians and lie in the [0,2pi[ interval.
+ */
+ CParallelProjectionGeometry3D(int _iProjectionAngleCount,
+ int _iDetectorRowCount,
+ int _iDetectorColCount,
+ float32 _fDetectorWidth,
+ float32 _fDetectorHeight,
+ const float32* _pfProjectionAngles,
+ const float32* _pfExtraDetectorOffsetsX = NULL,
+ const float32* _pfExtraDetectorOffsetsY = NULL);
+
+ /** Copy constructor.
+ */
+ CParallelProjectionGeometry3D(const CParallelProjectionGeometry3D& _projGeom);
+
+ /** Destructor.
+ */
+ ~CParallelProjectionGeometry3D();
+
+ /** Initialize the geometry with a config object.
+ *
+ * @param _cfg Configuration Object
+ * @return initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ /** Initialize the geometry. If the object has been initialized before, the object is reinitialized
+ * and memory is freed and reallocated if necessary.
+ *
+ * @param _iProjectionAngleCount Number of projection angles.
+ * @param _iDetectorRowCount Number of rows of detectors.
+ * @param _iDetectorColCount Number of columns detectors.
+ * @param _fDetectorWidth Width of a detector cell, in unit lengths. All detector cells are assumed to have equal width.
+ * @param _fDetectorHeight Height of a detector cell, in unit lengths. All detector cells are assumed to have equal height.
+ * @param _pfProjectionAngles Pointer to an array of projection angles. The angles will be copied from this array. All angles
+ * are represented in radians and lie in the [0,2pi[ interval.
+ */
+ bool initialize(int _iProjectionAngleCount,
+ int _iDetectorRowCount,
+ int _iDetectorColCount,
+ float32 _fDetectorWidth,
+ float32 _fDetectorHeight,
+ const float32* _pfProjectionAngles,
+ const float32* _pfExtraDetectorOffsetsX = NULL,
+ const float32* _pfExtraDetectorOffsetsY = NULL);
+
+ /** Create a hard copy.
+ */
+ virtual CProjectionGeometry3D* clone() const;
+
+ /** Return true if this geometry instance is the same as the one specified.
+ *
+ * @return true if this geometry instance is the same as the one specified.
+ */
+ virtual bool isEqual(const CProjectionGeometry3D*) const;
+
+ /** Returns true if the type of geometry defined in this class is the one specified in _sType.
+ *
+ * @param _sType geometry type to compare to.
+ * @return true if _sType == "parallel".
+ */
+ virtual bool isOfType(const std::string& _sType) const;
+
+ /** Turn this object into an XML object.
+ *
+ * @param _sNode The XML object to fill.
+ */
+ virtual void toXML(XMLNode* _sNode) const;
+
+ /**
+ * Returns a vector giving the projection direction for a projection and detector index
+ */
+ virtual CVector3D getProjectionDirection(int _iProjectionIndex, int _iDetectorIndex) const;
+
+ /**
+ * Creates (= allocates) a 2D projection geometry used when projecting one slice using a 2D projector
+ *
+ * @return the 2D geometry, this pointer needs to be delete-ed after use.
+ */
+ CParallelProjectionGeometry2D * createProjectionGeometry2D() const;
+
+};
+
+} // namespace astra
+
+#endif /* _INC_ASTRA_PARALLELPROJECTIONGEOMETRY3D */
diff --git a/include/astra/ParallelVecProjectionGeometry3D.h b/include/astra/ParallelVecProjectionGeometry3D.h
new file mode 100644
index 0000000..0b4a766
--- /dev/null
+++ b/include/astra/ParallelVecProjectionGeometry3D.h
@@ -0,0 +1,157 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_PARALLELVECPROJECTIONGEOMETRY3D
+#define _INC_ASTRA_PARALLELVECPROJECTIONGEOMETRY3D
+
+#include "ProjectionGeometry3D.h"
+#include "../cuda/3d/dims3d.h"
+
+namespace astra
+{
+
+/**
+ * This class defines a 3D parallel beam projection geometry.
+ *
+ * \par XML Configuration
+ * \astra_xml_item{DetectorRowCount, int, Number of detectors for each projection.}
+ * \astra_xml_item{DetectorColCount, int, Number of detectors for each projection.}
+ *
+ * \par MATLAB example
+ * \astra_code{
+ * proj_geom = astra_struct('parallel3d_vec');\n
+ * proj_geom.DetectorRowCount = 512;\n
+ * proj_geom.DetectorColCount = 512;\n
+ * proj_geom.Vectors = V;\n
+ * }
+ *
+ * \par Vectors
+ * Vectors is a matrix containing the actual geometry. Each row corresponds
+ * to a single projection, and consists of:
+ * ( rayX, rayY, rayZ, dX, dY, dZ, uX, uY, uZ, vX, vY, vZ )
+ * ray: the ray direction
+ * d : the corner of the detector
+ * u : the vector from detector pixel (0,0) to (0,1)
+ * v : the vector from detector pixel (0,0) to (1,0)
+ */
+class _AstraExport CParallelVecProjectionGeometry3D : public CProjectionGeometry3D
+{
+protected:
+
+ SPar3DProjection *m_pProjectionAngles;
+
+public:
+
+ /** Default constructor. Sets all numeric member variables to 0 and all pointer member variables to NULL.
+ *
+ * If an object is constructed using this default constructor, it must always be followed by a call
+ * to one of the initialize() methods before the object can be used. Any use before calling initialize()
+ * is not allowed, except calling the member function isInitialized().
+ */
+ CParallelVecProjectionGeometry3D();
+
+ /** Constructor. Create an instance of the CParallelProjectionGeometry3D class.
+ *
+ * @param _iProjectionAngleCount Number of projection angles.
+ * @param _iDetectorRowCount Number of rows of detectors.
+ * @param _iDetectorColCount Number of columns detectors.
+ * @param _pProjectionAngles Pointer to an array of projection angles. The angles will be copied from this array.
+ */
+ CParallelVecProjectionGeometry3D(int _iProjectionAngleCount,
+ int _iDetectorRowCount,
+ int _iDetectorColCount,
+ const SPar3DProjection* _pProjectionAngles);
+
+ /** Copy constructor.
+ */
+ CParallelVecProjectionGeometry3D(const CParallelVecProjectionGeometry3D& _projGeom);
+
+ /** Destructor.
+ */
+ ~CParallelVecProjectionGeometry3D();
+
+ /** Initialize the geometry with a config object.
+ *
+ * @param _cfg Configuration Object
+ * @return initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ /** Initialize the geometry. If the object has been initialized before, the object is reinitialized
+ * and memory is freed and reallocated if necessary.
+ *
+ * @param _iProjectionAngleCount Number of projection angles.
+ * @param _iDetectorRowCount Number of rows of detectors.
+ * @param _iDetectorColCount Number of columns detectors.
+ * @param _pProjectionAngles Pointer to an array of projection angles. The angles will be copied from this array.
+ */
+ bool initialize(int _iProjectionAngleCount,
+ int _iDetectorRowCount,
+ int _iDetectorColCount,
+ const SPar3DProjection* _pProjectionAngles);
+
+
+ virtual bool _check();
+
+ /** Create a hard copy.
+ */
+ virtual CProjectionGeometry3D* clone() const;
+
+ /** Return true if this geometry instance is the same as the one specified.
+ *
+ * @return true if this geometry instance is the same as the one specified.
+ */
+ virtual bool isEqual(const CProjectionGeometry3D*) const;
+
+ /** Returns true if the type of geometry defined in this class is the one specified in _sType.
+ *
+ * @param _sType geometry type to compare to.
+ * @return true if _sType == "parallel3d_vec".
+ */
+ virtual bool isOfType(const std::string& _sType) const;
+
+ /** Turn this object into an XML object.
+ *
+ * @param _sNode The XML object to fill.
+ */
+ virtual void toXML(XMLNode* _sNode) const;
+
+ /**
+ * Returns a vector giving the projection direction for a projection and detector index
+ */
+ virtual CVector3D getProjectionDirection(int _iProjectionIndex, int _iDetectorIndex) const;
+
+
+ const SPar3DProjection* getProjectionVectors() const { return m_pProjectionAngles; }
+
+
+};
+
+} // namespace astra
+
+#endif /* _INC_ASTRA_PARALLELVECPROJECTIONGEOMETRY3D */
diff --git a/include/astra/PlatformDepSystemCode.h b/include/astra/PlatformDepSystemCode.h
new file mode 100644
index 0000000..1e254b4
--- /dev/null
+++ b/include/astra/PlatformDepSystemCode.h
@@ -0,0 +1,83 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef PLATFORMDEPSYSTEMCODE_H
+#define PLATFORMDEPSYSTEMCODE_H
+
+#include <cstdio>
+
+#ifndef _WIN32
+#include <stdint.h>
+#endif
+
+namespace astra
+{
+
+#ifdef _WIN32
+ typedef __int64 int64;
+#else
+ typedef int64_t int64;
+#endif
+
+class CPlatformDepSystemCode
+{
+public:
+
+ /**
+ * Clock with resolution of 1 ms. Windows implementation will return number of ms since system start,
+ * but this is not a requirement for the implementation. Just as long as the subtraction of two acquired
+ * values will result in a time interval in ms.
+ *
+ * @return a value that increases with 1 every ms
+ */
+ static unsigned long getMSCount();
+
+ /**
+ * fseek variant that works with 64 bit ints.
+ *
+ * @param _pStream file handler of file in which needs to be seek-ed
+ * @param _iOffset 64 bit int telling the new offset in the file
+ * @param _iOrigin typical fseek directive telling how _iOffset needs to be interpreted (SEEK_SET, ...)
+ *
+ * @return 0 if successful
+ */
+ static int fseek64(FILE * _pStream, astra::int64 _iOffset, int _iOrigin);
+
+ /**
+ * 64-bit ftell variant
+ *
+ * @param _pStream file handle
+ *
+ * @return the position in the file
+ */
+ static astra::int64 ftell64(FILE * _pStream);
+};
+
+}
+
+#endif /* PLATFORMDEPSYSTEMCODE_H */
diff --git a/include/astra/ProjectionGeometry2D.h b/include/astra/ProjectionGeometry2D.h
new file mode 100644
index 0000000..bcaee7a
--- /dev/null
+++ b/include/astra/ProjectionGeometry2D.h
@@ -0,0 +1,373 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_PROJECTIONGEOMETRY2D
+#define _INC_ASTRA_PROJECTIONGEOMETRY2D
+
+#include "Globals.h"
+#include "Config.h"
+#include "Vector3D.h"
+
+#include <string>
+#include <cmath>
+#include <vector>
+
+namespace astra
+{
+
+/**
+ * This abstract base class defines the projection geometry.
+ * It has a number of data fields, such as width of detector
+ * pixels, projection angles, number of detector pixels and object offsets
+ * for every projection angle.
+ */
+class _AstraExport CProjectionGeometry2D
+{
+
+protected:
+
+ bool m_bInitialized; ///< Has the object been intialized?
+
+ /** Number of projection angles
+ */
+ int m_iProjectionAngleCount;
+
+ /** Number of detectors, i.e., the number of detector measurements for each projection angle.
+ */
+ int m_iDetectorCount;
+
+ /** Width of a detector pixel, i.e., the distance between projected rays (or width of projected strips).
+ */
+ float32 m_fDetectorWidth;
+
+ /** An array of m_iProjectionAngleCount elements containing an extra detector offset for each projection.
+ */
+ float32* m_pfExtraDetectorOffset;
+
+ /** Dynamically allocated array of projection angles. All angles are represented in radians and lie in
+ * the [0,2pi[ interval.
+ */
+ float32* m_pfProjectionAngles;
+
+ /** Default constructor. Sets all numeric member variables to 0 and all pointer member variables to NULL.
+ *
+ * If an object is constructed using this default constructor, it must always be followed by a call
+ * to one of the init() methods before the object can be used. Any use before calling init() is not
+ * allowed, except calling the member function isInitialized().
+ *
+ */
+ CProjectionGeometry2D();
+
+ /** Constructor. Create an instance of the CProjectionGeometry2D class.
+ *
+ * @param _iProjectionAngleCount Number of projection angles.
+ * @param _iDetectorCount Number of detectors, i.e., the number of detector measurements for each projection angle.
+ * @param _fDetectorWidth Width of a detector cell, in unit lengths. All detector cells are assumed to have equal width.
+ * @param _pfProjectionAngles Pointer to an array of projection angles. The angles will be copied from this array.
+ * All angles are represented in radians.
+ */
+ CProjectionGeometry2D(int _iProjectionAngleCount,
+ int _iDetectorCount,
+ float32 _fDetectorWidth,
+ const float32* _pfProjectionAngles,
+ const float32* _pfExtraDetectorOffsets = 0);
+
+ /** Copy constructor.
+ */
+ CProjectionGeometry2D(const CProjectionGeometry2D& _projGeom);
+
+ /** Check variable values.
+ */
+ bool _check();
+
+ /** 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 _clear();
+
+ /** Initialization. Initializes an instance of the CProjectionGeometry2D class. If the object has been
+ * initialized before, the object is reinitialized and memory is freed and reallocated if necessary.
+ *
+ * @param _iProjectionAngleCount Number of projection angles.
+ * @param _iDetectorCount Number of detectors, i.e., the number of detector measurements for each projection angle.
+ * @param _fDetectorWidth Width of a detector cell, in unit lengths. All detector cells are assumed to have equal width.
+ * @param _pfProjectionAngles Pointer to an array of projection angles. The angles will be copied from this array.
+ */
+ bool _initialize(int _iProjectionAngleCount,
+ int _iDetectorCount,
+ float32 _fDetectorWidth,
+ const float32* _pfProjectionAngles,
+ const float32* _pfExtraDetectorOffsets = 0);
+
+public:
+
+ /** Destructor
+ */
+ virtual ~CProjectionGeometry2D();
+
+ /** Clear all member variables, setting all numeric variables to 0 and all pointers to NULL.
+ */
+ virtual void clear();
+
+ /** Create a hard copy.
+ */
+ virtual CProjectionGeometry2D* clone() = 0;
+
+ /** Initialize the geometry with a config object.
+ *
+ * @param _cfg Configuration Object
+ * @return initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ /** Get the initialization state of the object.
+ *
+ * @return true iff the object has been initialized
+ */
+ bool isInitialized() const;
+
+ /** Return true if this geometry instance is the same as the one specified.
+ *
+ * @return true if this geometry instance is the same as the one specified.
+ */
+ virtual bool isEqual(CProjectionGeometry2D*) const = 0;
+
+ /** Get the number of projection angles.
+ *
+ * @return Number of projection angles
+ */
+ int getProjectionAngleCount() const;
+
+ /** Get the number of detectors.
+ *
+ * @return Number of detectors, i.e., the number of detector measurements for each projection angle.
+ */
+ int getDetectorCount() const;
+
+ /** Get the width of a detector.
+ *
+ * @return Width of a detector, in unit lengths
+ */
+ float32 getDetectorWidth() const;
+
+ /** Get a projection angle, given by its index. The angle is represented in Radians.
+ *
+ * @return Projection angle with index _iProjectionIndex
+ */
+ float32 getProjectionAngle(int _iProjectionIndex) const;
+
+ /** Returns a buffer containing all projection angles. The element count of the buffer is equal
+ * to the number given by getProjectionAngleCount.
+ *
+ * The angles are in radians.
+ *
+ * @return Pointer to buffer containing the angles.
+ */
+ const float32* getProjectionAngles() const;
+
+ /** Get a projection angle, given by its index. The angle is represented in degrees.
+ *
+ * @return Projection angle with index _iProjectionIndex
+ */
+ float32 getProjectionAngleDegrees(int _iProjectionIndex) const;
+
+ float32 getExtraDetectorOffset(int iAngle) const;
+ const float32* getExtraDetectorOffset() const { return m_pfExtraDetectorOffset; }
+
+ /** Get the index coordinate of a point on a detector array.
+ *
+ * @param _fOffset distance between the center of the detector array and a certain point
+ * @return the location of the point in index coordinates (still float, not rounded)
+ */
+ virtual float32 detectorOffsetToIndexFloat(float32 _fOffset) const;
+
+ /** Get the index coordinate of a point on a detector array.
+ *
+ * @param _fOffset distance between the center of the detector array and a certain point
+ * @return the index of the detector that is hit, -1 if detector array isn't hit.
+ */
+ virtual int detectorOffsetToIndex(float32 _fOffset) const;
+
+ /** Get the offset of a detector based on its index coordinate.
+ *
+ * @param _iIndex the index of the detector.
+ * @return the offset from the center of the detector array.
+ */
+ virtual float32 indexToDetectorOffset(int _iIndex) const;
+
+ /** Get the angle and detector index of a sinogram pixel
+ *
+ * @param _iIndex the index of the detector pixel in the sinogram.
+ * @param _iAngleIndex output: index of angle
+ * @param _iDetectorIndex output: index of detector
+ */
+ virtual void indexToAngleDetectorIndex(int _iIndex, int& _iAngleIndex, int& _iDetectorIndex) const;
+
+ /** Get the value for t and theta, based upon the row and column index.
+ *
+ * @param _iRow row index
+ * @param _iColumn column index
+ * @param _fT output: value of t
+ * @param _fTheta output: value of theta, always lies within the [0,pi[ interval.
+ */
+ virtual void getRayParams(int _iRow, int _iColumn, float32& _fT, float32& _fTheta) const;
+
+ /** Returns true if the type of geometry defined in this class is the one specified in _sType.
+ *
+ * @param _sType geometry type to compare to.
+ * @return true if the type of geometry defined in this class is the one specified in _sType.
+ */
+ virtual bool isOfType(const std::string& _sType) = 0;
+
+ /**
+ * Returns a vector describing the direction of a ray belonging to a certain detector
+ *
+ * @param _iProjectionIndex index of projection
+ * @param _iProjectionIndex index of detector
+ *
+ * @return a unit vector describing the direction
+ */
+ virtual CVector3D getProjectionDirection(int _iProjectionIndex, int _iDetectorIndex) = 0;
+
+
+ //< For Config unused argument checking
+ ConfigCheckData* configCheckData;
+ friend class ConfigStackCheck<CProjectionGeometry2D>;
+};
+
+
+
+//----------------------------------------------------------------------------------------
+// Inline member functions
+//----------------------------------------------------------------------------------------
+
+
+inline float32 CProjectionGeometry2D::getExtraDetectorOffset(int _iAngle) const
+{
+ return m_pfExtraDetectorOffset ? m_pfExtraDetectorOffset[_iAngle] : 0.0f;
+}
+
+
+// Get the initialization state.
+inline bool CProjectionGeometry2D::isInitialized() const
+{
+ return m_bInitialized;
+}
+
+
+// Get the number of detectors.
+inline int CProjectionGeometry2D::getDetectorCount() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_iDetectorCount;
+}
+
+// Get the width of a single detector (in unit lengths).
+inline float32 CProjectionGeometry2D::getDetectorWidth() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_fDetectorWidth;
+}
+
+// Get the number of projection angles.
+inline int CProjectionGeometry2D::getProjectionAngleCount() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_iProjectionAngleCount;
+}
+
+// Get pointer to buffer used to store projection angles.
+inline const float32* CProjectionGeometry2D::getProjectionAngles() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_pfProjectionAngles;
+}
+
+// Get a projection angle, represented in Radians.
+inline float32 CProjectionGeometry2D::getProjectionAngle(int _iProjectionIndex) const
+{
+ // basic checks
+ ASTRA_ASSERT(m_bInitialized);
+ ASTRA_ASSERT(_iProjectionIndex >= 0);
+ ASTRA_ASSERT(_iProjectionIndex < m_iProjectionAngleCount);
+
+ return m_pfProjectionAngles[_iProjectionIndex];
+}
+
+// Get a projection angle, represented in degrees.
+inline float32 CProjectionGeometry2D::getProjectionAngleDegrees(int _iProjectionIndex) const
+{
+ // basic checks
+ ASTRA_ASSERT(m_bInitialized);
+ ASTRA_ASSERT(_iProjectionIndex >= 0);
+ ASTRA_ASSERT(_iProjectionIndex < m_iProjectionAngleCount);
+
+ return (m_pfProjectionAngles[_iProjectionIndex] * 180.0f / PI32);
+}
+
+// Get T and Theta
+inline void CProjectionGeometry2D::getRayParams(int _iRow, int _iColumn, float32& _fT, float32& _fTheta) const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ _fT = indexToDetectorOffset(_iColumn);
+ _fTheta = getProjectionAngle(_iRow);
+ if (PI <= _fTheta) {
+ _fTheta -= PI;
+ _fT = -_fT;
+ }
+}
+
+// detector offset -> detector index
+inline int CProjectionGeometry2D::detectorOffsetToIndex(float32 _fOffset) const
+{
+ int res = (int)(detectorOffsetToIndexFloat(_fOffset) + 0.5f);
+ return (res > 0 && res <= m_iDetectorCount) ? res : -1;
+}
+
+// detector offset -> detector index (float)
+inline float32 CProjectionGeometry2D::detectorOffsetToIndexFloat(float32 _fOffset) const
+{
+ return (_fOffset / m_fDetectorWidth) + ((m_iDetectorCount-1.0f) * 0.5f);
+}
+
+// detector index -> detector offset
+inline float32 CProjectionGeometry2D::indexToDetectorOffset(int _iIndex) const
+{
+ return (_iIndex - (m_iDetectorCount-1.0f) * 0.5f) * m_fDetectorWidth;
+}
+
+// sinogram index -> angle and detecor index
+inline void CProjectionGeometry2D::indexToAngleDetectorIndex(int _iIndex, int& _iAngleIndex, int& _iDetectorIndex) const
+{
+ _iAngleIndex = _iIndex / m_iDetectorCount;
+ _iDetectorIndex = _iIndex % m_iDetectorCount;
+}
+
+} // end namespace astra
+
+#endif /* _INC_ASTRA_PROJECTIONGEOMETRY2D */
diff --git a/include/astra/ProjectionGeometry3D.h b/include/astra/ProjectionGeometry3D.h
new file mode 100644
index 0000000..0deffa6
--- /dev/null
+++ b/include/astra/ProjectionGeometry3D.h
@@ -0,0 +1,589 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_PROJECTIONGEOMETRY3D
+#define _INC_ASTRA_PROJECTIONGEOMETRY3D
+
+#include "Globals.h"
+#include "Config.h"
+#include "Vector3D.h"
+
+#include <string>
+#include <cmath>
+#include <vector>
+
+namespace astra
+{
+
+class XMLNode;
+
+/**
+ * This class defines the interface for each 3D projection geometry.
+ * It has a number of data fields, such as width and height of detector
+ * pixels, projection angles and number of rows and columns of detector pixels.
+ *
+ * \par XML Configuration
+ * \astra_xml_item{DetectorRowCount, int, Number of detectors for each projection.}
+ * \astra_xml_item{DetectorColCount, int, Number of detectors for each projection.}
+ * \astra_xml_item{DetectorWidth, float, Width of each detector.}
+ * \astra_xml_item{DetectorHeight, float, Width of each detector.}
+ * \astra_xml_item{ProjectionAngles, vector of float, projection angles in radians.}
+ */
+class _AstraExport CProjectionGeometry3D
+{
+
+protected:
+
+ /** Has the object been intialized with acceptable values?
+ */
+ bool m_bInitialized;
+
+ /** Number of projection angles.
+ */
+ int m_iProjectionAngleCount;
+
+ /** Number of rows of detectors.
+ */
+ int m_iDetectorRowCount;
+
+ /** Number of columns of detectors.
+ */
+ int m_iDetectorColCount;
+
+ /** Total number of detectors.
+ */
+ int m_iDetectorTotCount;
+
+ /** The x-distance between projected rays on the detector plate (or width of projected strips).
+ */
+ float32 m_fDetectorSpacingX;
+
+ /** The y-distance between projected rays on the detector plate (or height of projected strips).
+ */
+ float32 m_fDetectorSpacingY;
+
+ /** Dynamically allocated array of projection angles. All angles are represented in radians and lie in
+ * the [0,2pi[ interval.
+ */
+ float32* m_pfProjectionAngles;
+
+ /** Dynamically allocated array of vectors that represents the amount by which an image has been shifted after
+ * projection. Each projection image has a 2 shifts associated with it, one x-translation and y-translation
+ */
+ float32* m_pfExtraDetectorOffsetsX;
+ float32* m_pfExtraDetectorOffsetsY;
+
+ /** Default constructor. Sets all numeric member variables to 0 and all pointer member variables to NULL.
+ *
+ * If an object is constructed using this default constructor, it must always be followed by a call
+ * to one of the initialize() methods before the object can be used. Any use before calling initialize()
+ * is not allowed, except calling the member function isInitialized().
+ *
+ */
+ CProjectionGeometry3D();
+
+ /** Constructor. Create an instance of the CProjectionGeometry3D class.
+ *
+ * @param _iProjectionAngleCount Number of projection angles.
+ * @param _iDetectorRowCount Number of rows of detectors.
+ * @param _iDetectorColCount Number of columns detectors.
+ * @param _fDetectorSpacingX Spacing between the detector points on the X-axis, in unit lengths. Assumed to be constant throughout the entire detector plate.
+ * @param _fDetectorSpacingY Spacing between the detector points on the Y-axis, in unit lengths. Assumed to be constant throughout the entire detector plate.
+ * @param _pfProjectionAngles Pointer to an array of projection angles. The angles will be copied from this array. All angles
+ * are represented in radians and lie in the [0,2pi[ interval.
+ */
+ CProjectionGeometry3D(int _iProjectionAngleCount,
+ int _iDetectorRowCount,
+ int _iDetectorColCount,
+ float32 _fDetectorSpacingX,
+ float32 _fDetectorSpacingY,
+ const float32* _pfProjectionAngles,
+ const float32* _pfExtraDetectorOffsetsX = NULL,
+ const float32* _pfExtraDetectorOffsetsY = NULL);
+
+ /** Copy constructor.
+ */
+ CProjectionGeometry3D(const CProjectionGeometry3D& _projGeom);
+
+ /** Check the values of this object. If everything is ok, the object can be set to the initialized state.
+ * The following statements are then guaranteed to hold:
+ * - number of rows and columns is larger than zero
+ * - detector spacing is larger than zero
+ * - number of angles is larger than zero
+ * - (autofix) each angle lies in [0,2pi[
+ */
+ bool _check();
+
+ /** 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 _clear();
+
+ /** Initialize the geometry. If the object has been initialized before, the object is reinitialized
+ * and memory is freed and reallocated if necessary.
+ *
+ * @param _iProjectionAngleCount Number of projection angles.
+ * @param _iDetectorRowCount Number of rows of detectors.
+ * @param _iDetectorColCount Number of columns detectors.
+ * @param _fDetectorSpacingX Spacing between the detector points on the X-axis, in unit lengths. Assumed to be constant throughout the entire detector plate.
+ * @param _fDetectorSpacingY Spacing between the detector points on the Y-axis, in unit lengths. Assumed to be constant throughout the entire detector plate.
+ * @param _pfProjectionAngles Pointer to an array of projection angles. The angles will be copied from this array. All angles
+ * are represented in radians and lie in the [0,2pi[ interval.
+ */
+ bool _initialize(int _iProjectionAngleCount,
+ int _iDetectorRowCount,
+ int _iDetectorColCount,
+ float32 _fDetectorSpacingX,
+ float32 _fDetectorSpacingY,
+ const float32* _pfProjectionAngles,
+ const float32* _pfExtraDetectorOffsetsX = NULL,
+ const float32* _pfExtraDetectorOffsetsY = NULL);
+
+public:
+
+ /** Destructor
+ */
+ virtual ~CProjectionGeometry3D();
+
+ /** Clear all member variables, setting all numeric variables to 0 and all pointers to NULL.
+ */
+ virtual void clear();
+
+ /** Create a hard copy.
+ */
+ virtual CProjectionGeometry3D* clone() const = 0;
+
+ /** Initialize the geometry with a config object.
+ *
+ * @param _cfg Configuration Object
+ * @return initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ /** Get the initialization state of the object.
+ *
+ * @return true iff the object has been initialized
+ */
+ bool isInitialized() const;
+
+ /** Return true if this geometry instance is the same as the one specified.
+ *
+ * @return true if this geometry instance is the same as the one specified.
+ */
+ virtual bool isEqual(const CProjectionGeometry3D *) const = 0;
+
+ /** Get the number of projections.
+ *
+ * @return Number of projections
+ */
+ int getProjectionCount() const;
+
+ /** Get the number of rows of detectors.
+ *
+ * @return Number of rows of detectors.
+ */
+ int getDetectorRowCount() const;
+
+ /** Get the number of columns of detectors.
+ *
+ * @return Number of columns of detectors.
+ */
+ int getDetectorColCount() const;
+
+ /** Get the total number of detectors.
+ *
+ * @return Total number of detectors.
+ */
+ int getDetectorTotCount() const;
+
+ /** Get the width of a detector.
+ *
+ * @return Width of a detector, in unit lengths
+ */
+ float32 getDetectorSpacingX() const;
+
+ /** Get the height of a detector.
+ *
+ * @return Height of a detector, in unit lengths
+ */
+ float32 getDetectorSpacingY() const;
+
+ /** Get a projection angle, given by its index. The angle is represented in Radians.
+ *
+ * @return Projection angle with index _iProjectionIndex
+ */
+ float32 getProjectionAngle(int _iProjectionIndex) const;
+
+ /** Get a projection angle, given by its index. The angle is represented in degrees.
+ *
+ * @return Projection angle with index _iProjectionIndex
+ */
+// float32 getProjectionAngleDegrees(int _iProjectionIndex) const;
+
+ /** Returns a buffer containing all projection angles. The element count of the buffer is equal
+ * to the number given by getProjectionAngleCount.
+ *
+ * The angles are in radians.
+ *
+ * @return Pointer to buffer containing the angles.
+ */
+ const float32* getProjectionAngles() const;
+
+ const float32* getExtraDetectorOffsetsX() const;
+
+ const float32* getExtraDetectorOffsetsY() const;
+
+ float32 getExtraDetectorOffsetX(int _iProjectionIndex) const;
+
+ float32 getExtraDetectorOffsetY(int _iProjectionIndex) const;
+
+ AstraError setExtraDetectorOffsetsX(float32* _pfExtraDetectorOffsetsX);
+
+ AstraError setExtraDetectorOffsetsY(float32* _pfExtraDetectorOffsetsY);
+
+ /** Get the column index coordinate of a point on a detector array.
+ *
+ * @param _fOffsetX Distance between the center of the detector array and a certain point (both on the X-axis).
+ * @return The location of the point in index X-coordinates (still float, not rounded)
+ */
+ virtual float32 detectorOffsetXToColIndexFloat(float32 _fOffsetX) const;
+
+ /** Get the row index coordinate of a point on a detector array.
+ *
+ * @param _fOffsetY Distance between the center of the detector array and a certain point (both on the Y-axis).
+ * @return The location of the point in index Y-coordinates (still float, not rounded)
+ */
+ virtual float32 detectorOffsetYToRowIndexFloat(float32 _fOffsetY) const;
+
+ /** Get the offset of a detector on the X-axis based on its index coordinate.
+ *
+ * @param _iIndex the index of the detector.
+ * @return the offset from the center of the detector array on the X-axis.
+ */
+ virtual float32 indexToDetectorOffsetX(int _iIndex) const;
+
+ /** Get the offset of a detector on the Y-axis based on its index coordinate.
+ *
+ * @param _iIndex the index of the detector.
+ * @return the offset from the center of the detector array on the Y-axis.
+ */
+ virtual float32 indexToDetectorOffsetY(int _iIndex) const;
+
+ /** Get the offset of a detector on the X-axis based on its column index coordinate.
+ *
+ * @param _iIndex the index of the detector.
+ * @return the offset from the center of the detector array on the X-axis.
+ */
+ virtual float32 colIndexToDetectorOffsetX(int _iIndex) const;
+
+ /** Get the offset of a detector on the Y-axis based on its row index coordinate.
+ *
+ * @param _iIndex the index of the detector.
+ * @return the offset from the center of the detector array on the Y-axis.
+ */
+ virtual float32 rowIndexToDetectorOffsetY(int _iIndex) const;
+
+ /** Get the row and column index of a detector based on its index.
+ *
+ * @param _iDetectorIndex in: the index of the detector.
+ * @param _iDetectorRow out: the row index of the detector.
+ * @param _iDetectorCol out: the column index of the detector.
+ */
+ virtual void detectorIndexToRowCol(int _iDetectorIndex, int& _iDetectorRow, int& _iDetectorCol) const;
+
+ /** Get the angle and detector index of a detector
+ *
+ * @param _iIndex the index of the detector.
+ * @param _iAngleIndex output: index of angle
+ * @param _iDetectorIndex output: index of dectecor
+ */
+ virtual void indexToAngleDetectorIndex(int _iIndex, int& _iAngleIndex, int& _iDetectorIndex) const;
+
+ /** Returns true if the type of geometry defined in this class is the one specified in _sType.
+ *
+ * @param _sType geometry type to compare to.
+ * @return true if the type of geometry defined in this class is the one specified in _sType.
+ */
+ virtual bool isOfType(const std::string& _sType) const = 0;
+
+ /** Turn this object into an XML object.
+ *
+ * @param _sNode The XML object to fill.
+ */
+ virtual void toXML(XMLNode* _sNode) const = 0;
+
+ /**
+ * Returns a vector giving the projection direction for a projection and detector index
+ */
+ virtual CVector3D getProjectionDirection(int _iProjectionIndex, int _iDetectorIndex) const = 0;
+
+
+ //< For Config unused argument checking
+ ConfigCheckData* configCheckData;
+ friend class ConfigStackCheck<CProjectionGeometry3D>;
+};
+
+
+
+//----------------------------------------------------------------------------------------
+// Inline member functions
+//----------------------------------------------------------------------------------------
+// Get the initialization state.
+inline bool CProjectionGeometry3D::isInitialized() const
+{
+ return m_bInitialized;
+}
+
+//----------------------------------------------------------------------------------------
+// Get the number of detectors.
+inline int CProjectionGeometry3D::getDetectorRowCount() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_iDetectorRowCount;
+}
+
+//----------------------------------------------------------------------------------------
+// Get the number of detectors.
+inline int CProjectionGeometry3D::getDetectorColCount() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_iDetectorColCount;
+}
+
+//----------------------------------------------------------------------------------------
+// Get the number of detectors.
+inline int CProjectionGeometry3D::getDetectorTotCount() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_iDetectorTotCount;
+}
+
+//----------------------------------------------------------------------------------------
+// Get the width of a single detector (in unit lengths).
+inline float32 CProjectionGeometry3D::getDetectorSpacingX() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_fDetectorSpacingX;
+}
+//----------------------------------------------------------------------------------------
+// Get the width of a single detector (in unit lengths).
+inline float32 CProjectionGeometry3D::getDetectorSpacingY() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_fDetectorSpacingY;
+}
+
+//----------------------------------------------------------------------------------------
+// Get the number of projection angles.
+inline int CProjectionGeometry3D::getProjectionCount() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_iProjectionAngleCount;
+}
+
+//----------------------------------------------------------------------------------------
+// Get a projection angle, represented in Radians.
+inline float32 CProjectionGeometry3D::getProjectionAngle(int _iProjectionIndex) const
+{
+ // basic checks
+ ASTRA_ASSERT(m_bInitialized);
+ ASTRA_ASSERT(_iProjectionIndex >= 0);
+ ASTRA_ASSERT(_iProjectionIndex < m_iProjectionAngleCount);
+
+ return m_pfProjectionAngles[_iProjectionIndex];
+}
+
+/*
+//----------------------------------------------------------------------------------------
+// Get a projection angle, represented in degrees.
+inline float32 CProjectionGeometry3D::getProjectionAngleDegrees(int _iProjectionIndex) const
+{
+ // basic checks
+ ASTRA_ASSERT(m_bInitialized);
+ ASTRA_ASSERT(_iProjectionIndex >= 0);
+ ASTRA_ASSERT(_iProjectionIndex < m_iProjectionAngleCount);
+
+ return (m_pfProjectionAngles[_iProjectionIndex] * 180.0f / PI32);
+}
+*/
+
+
+//----------------------------------------------------------------------------------------
+// Get pointer to buffer used to store projection angles.
+inline const float32* CProjectionGeometry3D::getProjectionAngles() const
+{
+ // basic checks
+ ASTRA_ASSERT(m_bInitialized);
+
+ return m_pfProjectionAngles;
+}
+
+
+//----------------------------------------------------------------------------------------
+// Get pointer to buffer used to store x-translations of the projection images.
+inline const float32* CProjectionGeometry3D::getExtraDetectorOffsetsX() const
+{
+ // basic checks
+ ASTRA_ASSERT(m_bInitialized);
+
+ return m_pfExtraDetectorOffsetsX;
+}
+
+//----------------------------------------------------------------------------------------
+// Get pointer to buffer used to store y-translations of the projection images.
+inline const float32* CProjectionGeometry3D::getExtraDetectorOffsetsY() const
+{
+ // basic checks
+ ASTRA_ASSERT(m_bInitialized);
+
+ return m_pfExtraDetectorOffsetsY;
+}
+//----------------------------------------------------------------------------------------
+// Get the x-translation of a specific projection image.
+inline float32 CProjectionGeometry3D::getExtraDetectorOffsetX(int _iProjectionIndex) const
+{
+ // basic checks
+ ASTRA_ASSERT(m_bInitialized);
+
+ return m_pfExtraDetectorOffsetsX[_iProjectionIndex];
+}
+
+//----------------------------------------------------------------------------------------
+// Get the y-translation of a specific projection image.
+inline float32 CProjectionGeometry3D::getExtraDetectorOffsetY(int _iProjectionIndex) const
+{
+ // basic checks
+ ASTRA_ASSERT(m_bInitialized);
+
+ return m_pfExtraDetectorOffsetsX[_iProjectionIndex];
+}
+//----------------------------------------------------------------------------------------
+// detector offset X -> detector column index (float)
+inline float32 CProjectionGeometry3D::detectorOffsetXToColIndexFloat(float32 _fOffsetX) const
+{
+ // basic checks
+ ASTRA_ASSERT(m_bInitialized);
+
+ return (_fOffsetX / m_fDetectorSpacingX) + ((m_iDetectorColCount-1.0f) / 2.0f);
+}
+
+//----------------------------------------------------------------------------------------
+// detector offset Y -> detector row index (float)
+inline float32 CProjectionGeometry3D::detectorOffsetYToRowIndexFloat(float32 _fOffsetY) const
+{
+ // basic checks
+ ASTRA_ASSERT(m_bInitialized);
+
+ return (_fOffsetY / m_fDetectorSpacingY) + ((m_iDetectorRowCount-1.0f) / 2.0f);
+}
+
+//----------------------------------------------------------------------------------------
+// detector index -> detector offset X
+inline float32 CProjectionGeometry3D::indexToDetectorOffsetX(int _iIndex) const
+{
+ // basic checks
+ ASTRA_ASSERT(m_bInitialized);
+ ASTRA_ASSERT(_iIndex >= 0);
+ ASTRA_ASSERT(_iIndex < m_iDetectorTotCount);
+
+ _iIndex = _iIndex % m_iDetectorColCount;
+ return (_iIndex - (m_iDetectorColCount-1.0f) / 2.0f) * m_fDetectorSpacingX;
+}
+
+//----------------------------------------------------------------------------------------
+// detector index -> detector offset Y
+inline float32 CProjectionGeometry3D::indexToDetectorOffsetY(int _iIndex) const
+{
+ // basic checks
+ ASTRA_ASSERT(m_bInitialized);
+ ASTRA_ASSERT(_iIndex >= 0);
+ ASTRA_ASSERT(_iIndex < m_iDetectorTotCount);
+
+ _iIndex = _iIndex / m_iDetectorColCount;
+ return -(_iIndex - (m_iDetectorRowCount-1.0f) / 2.0f) * m_fDetectorSpacingY;
+}
+
+//----------------------------------------------------------------------------------------
+// detector index -> detector offset X
+inline float32 CProjectionGeometry3D::colIndexToDetectorOffsetX(int _iIndex) const
+{
+ // basic checks
+ ASTRA_ASSERT(m_bInitialized);
+ ASTRA_ASSERT(_iIndex >= 0);
+ ASTRA_ASSERT(_iIndex < m_iDetectorColCount);
+
+ return (_iIndex - (m_iDetectorColCount-1.0f) / 2.0f) * m_fDetectorSpacingX;
+}
+
+//----------------------------------------------------------------------------------------
+// detector index -> detector offset Y
+inline float32 CProjectionGeometry3D::rowIndexToDetectorOffsetY(int _iIndex) const
+{
+ // basic checks
+ ASTRA_ASSERT(m_bInitialized);
+ ASTRA_ASSERT(_iIndex >= 0);
+ ASTRA_ASSERT(_iIndex < m_iDetectorRowCount);
+
+ return (_iIndex - (m_iDetectorRowCount-1.0f) / 2.0f) * m_fDetectorSpacingY;
+}
+
+//----------------------------------------------------------------------------------------
+// detector index -> row index & column index
+inline void CProjectionGeometry3D::detectorIndexToRowCol(int _iDetectorIndex, int& _iDetectorRow, int& _iDetectorCol) const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ ASTRA_ASSERT(_iDetectorIndex >= 0);
+ ASTRA_ASSERT(_iDetectorIndex < m_iDetectorTotCount);
+
+ _iDetectorRow = _iDetectorIndex / m_iDetectorColCount;
+ _iDetectorCol = _iDetectorIndex % m_iDetectorColCount;
+}
+
+//----------------------------------------------------------------------------------------
+inline void CProjectionGeometry3D::indexToAngleDetectorIndex(int _iIndex, int& _iAngleIndex, int& _iDetectorIndex) const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ ASTRA_ASSERT(_iIndex >= 0);
+ ASTRA_ASSERT(_iIndex < m_iDetectorTotCount * m_iProjectionAngleCount);
+
+// int det_row = _iIndex / (m_iDetectorColCount*m_iProjectionAngleCount);
+// int det_col = _iIndex % m_iDetectorColCount;
+//
+// _iAngleIndex = _iIndex % (m_iDetectorColCount*m_iProjectionAngleCount) / m_iDetectorColCount;
+// _iDetectorIndex = det_row * m_iDetectorColCount + det_col;
+
+ _iAngleIndex = (_iIndex % (m_iDetectorColCount*m_iProjectionAngleCount)) / m_iDetectorColCount;
+ _iDetectorIndex = _iIndex / m_iProjectionAngleCount + (_iIndex % m_iDetectorColCount);
+
+}
+
+//----------------------------------------------------------------------------------------
+
+} // end namespace astra
+
+#endif /* _INC_ASTRA_PROJECTIONGEOMETRY2D */
diff --git a/include/astra/Projector2D.h b/include/astra/Projector2D.h
new file mode 100644
index 0000000..a359aba
--- /dev/null
+++ b/include/astra/Projector2D.h
@@ -0,0 +1,204 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef INC_ASTRA_PROJECTOR2D
+#define INC_ASTRA_PROJECTOR2D
+
+#include <cmath>
+#include <vector>
+
+#include "Globals.h"
+#include "Config.h"
+#include "Float32Data2D.h"
+#include "ParallelProjectionGeometry2D.h"
+#include "ProjectionGeometry2D.h"
+#include "VolumeGeometry2D.h"
+
+namespace astra
+{
+
+class CSparseMatrix;
+
+
+/** This is a base interface class for a two-dimensional projector. Each subclass should at least
+ * implement the core projection functions computeProjectionRayWeights and projectPoint. For
+ * extra efficiency one might also like to overwrite other functions such as computeProjectionRayWeights,
+ * computeRayForwardProj_ART, ...
+ *
+ * \par XML Configuration
+ * \astra_xml_item{ProjectionGeometry, xml node, The geometry of the projection.}
+ * \astra_xml_item{VolumeGeometry, xml node, The geometry of the volume.}
+ */
+class _AstraExport CProjector2D
+{
+
+protected:
+ CProjectionGeometry2D* m_pProjectionGeometry; ///< Used projection geometry
+ CVolumeGeometry2D* m_pVolumeGeometry; ///< Used volume geometry
+ bool m_bIsInitialized; ///< Has this class been initialized?
+
+ /** Default Constructor.
+ */
+ CProjector2D();
+
+ /** Constructor.
+ *
+ * @param _pProjectionGeometry Information class about the geometry of the projection. Will be HARDCOPIED.
+ * @param _pVolumeGeometry Information class about the geometry of the reconstruction volume. Will be HARDCOPIED.
+ */
+ CProjector2D(CProjectionGeometry2D* _pProjectionGeometry, CVolumeGeometry2D* _pVolumeGeometry);
+
+ /** Initial clearing. Only to be used by constructors.
+ */
+ virtual void _clear();
+
+ /** Check the values of this object. If everything is ok, the object can be set to the initialized state.
+ * The following statements are then guaranteed to hold:
+ * - no NULL pointers
+ * - all sub-objects are initialized properly
+ */
+ virtual bool _check();
+
+public:
+
+ /** Destructor.
+ */
+ virtual ~CProjector2D();
+
+ /** Clear this class.
+ */
+ virtual void clear();
+
+ /** Initialize the projector with a config object.
+ * This function does not set m_bInitialized to true.
+ *
+ * @param _cfg Configuration Object
+ * @return initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ /** Fetch the Projection Geometry of this projector.
+ *
+ * @return Projection Geometry class.
+ */
+ CProjectionGeometry2D* getProjectionGeometry();
+
+ /** Fetch the Volume Geometry of this projector.
+ *
+ * @return Volume Geometry class.
+ */
+ CVolumeGeometry2D* getVolumeGeometry();
+
+ /** Compute the pixel weights for a single ray, from the source to a detector pixel.
+ *
+ * @param _iProjectionIndex Index of the projection
+ * @param _iDetectorIndex Index of the detector pixel
+ * @param _pWeightedPixels Pointer to a pre-allocated array, consisting of _iMaxPixelCount elements
+ * of type SPixelWeight. On return, this array contains a list of the index
+ * and weight for all pixels on the ray.
+ * @param _iMaxPixelCount Maximum number of pixels (and corresponding weights) that can be stored in _pWeightedPixels.
+ * This number MUST be greater than the total number of pixels on the ray.
+ * @param _iStoredPixelCount On return, this variable contains the total number of pixels on the
+ * ray (that have been stored in the list _pWeightedPixels).
+ */
+ virtual void computeSingleRayWeights(int _iProjectionIndex,
+ int _iDetectorIndex,
+ SPixelWeight *_pWeightedPixels,
+ int _iMaxPixelCount,
+ int &_iStoredPixelCount) = 0;
+
+ /** Compute the pixel weights for all rays in a single projection, from the source to a each of the
+ * detector pixels. All pixels and their weights are stored consecutively in the array _pWeightedPixels.
+ * The array starts with all pixels on the first ray, followed by all pixels on the second ray, the third
+ * ray, etc. Note that a pixel may occur in the list more than once, as it can be on several rays.
+ *
+ * @param _iProjectionIndex Index of the projection (zero-based).
+ * @param _pfWeightedPixels Pointer to a pre-allocated array, consisting of getProjectionWeightsCount()
+ * elements of type SPixelWeight. On return, this array contains a list of
+ * the index and weight for all pixels on each of the rays. The elements for
+ * every ray start at equal offsets (ray_index * _pWeightedPixels / ray_count).
+ * @param _piRayStoredPixelCount Pointer to a pre-allocated array, containing a single integer for each
+ * ray in the projection. On return, this array contains the number of
+ * pixels on the ray, for each ray in the given projection.
+ */
+ virtual void computeProjectionRayWeights(int _iProjectionIndex,
+ SPixelWeight* _pfWeightedPixels,
+ int* _piRayStoredPixelCount);
+
+ /** Create a list of detectors that are influenced by point [_iRow, _iCol].
+ *
+ * @param _iRow row of the point
+ * @param _iCol column of the point
+ * @return list of SDetector2D structs
+ */
+ virtual std::vector<SDetector2D> projectPoint(int _iRow, int _iCol) = 0;
+
+ /** Returns the number of weights required for storage of all weights of one projection ray.
+ *
+ * @param _iProjectionIndex Index of the projection (zero-based).
+ * @return Size of buffer (given in SPixelWeight elements) needed to store weighted pixels.
+ */
+ virtual int getProjectionWeightsCount(int _iProjectionIndex) = 0;
+
+ /** Returns the projection as an explicit sparse matrix.
+ * @return a newly allocated CSparseMatrix. Delete afterwards.
+ */
+ CSparseMatrix* getMatrix();
+
+ /** Has the projector been initialized?
+ *
+ * @return initialized successfully
+ */
+ bool isInitialized();
+
+ /** get a description of the class
+ *
+ * @return description string
+ */
+ virtual std::string description() const {return " ";};
+
+ virtual std::string getType() { return " "; }
+
+private:
+ //< For Config unused argument checking
+ ConfigCheckData* configCheckData;
+ friend class ConfigStackCheck<CProjector2D>;
+};
+
+// inline functions
+inline bool CProjector2D::isInitialized() { return m_bIsInitialized; }
+inline CProjectionGeometry2D* CProjector2D::getProjectionGeometry() { return m_pProjectionGeometry; }
+inline CVolumeGeometry2D* CProjector2D::getVolumeGeometry() { return m_pVolumeGeometry; }
+
+
+
+
+
+} // namespace astra
+
+#endif /* INC_ASTRA_PROJECTOR2D */
diff --git a/include/astra/Projector2DImpl.inl b/include/astra/Projector2DImpl.inl
new file mode 100644
index 0000000..97341c8
--- /dev/null
+++ b/include/astra/Projector2DImpl.inl
@@ -0,0 +1,37 @@
+/*
+-----------------------------------------------------------------------
+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 "ParallelBeamLinearKernelProjector2D.inl"
+#include "ParallelBeamLineKernelProjector2D.inl"
+#include "ParallelBeamStripKernelProjector2D.inl"
+#include "ParallelBeamBlobKernelProjector2D.inl"
+#include "FanFlatBeamStripKernelProjector2D.inl"
+#include "FanFlatBeamLineKernelProjector2D.inl"
+#include "SparseMatrixProjector2D.inl"
+
diff --git a/include/astra/Projector3D.h b/include/astra/Projector3D.h
new file mode 100644
index 0000000..ec81bc8
--- /dev/null
+++ b/include/astra/Projector3D.h
@@ -0,0 +1,185 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef INC_ASTRA_PROJECTOR3D
+#define INC_ASTRA_PROJECTOR3D
+
+#include <cmath>
+#include <vector>
+
+#include "Globals.h"
+#include "Config.h"
+#include "ProjectionGeometry3D.h"
+#include "VolumeGeometry3D.h"
+
+namespace astra
+{
+
+class CSparseMatrix;
+
+
+/** This is a base interface class for a three-dimensional projector. Each subclass should at least
+ * implement the core projection functions computeProjectionRayWeights and projectPoint.
+ *
+ * \par XML Configuration
+ * \astra_xml_item{ProjectionGeometry, xml node, The geometry of the projection.}
+ * \astra_xml_item{VolumeGeometry, xml node, The geometry of the volume.}
+ */
+class _AstraExport CProjector3D
+{
+
+protected:
+
+ CProjectionGeometry3D* m_pProjectionGeometry; ///< Used projection geometry
+ CVolumeGeometry3D* m_pVolumeGeometry; ///< Used volume geometry
+ bool m_bIsInitialized; ///< Has this class been initialized?
+
+ /** Check variable values.
+ */
+ bool _check();
+
+ /** 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 _clear();
+
+public:
+
+ /**
+ * Default Constructor.
+ */
+ CProjector3D();
+
+ /** Destructor, is virtual to show that we are aware subclass destructor is called.
+ */
+ virtual ~CProjector3D();
+
+ /** Clear all member variables, setting all numeric variables to 0 and all pointers to NULL.
+ */
+ void clear();
+
+ /** Initialize the projector with a config object.
+ * This function does not set m_bInitialized to true.
+ *
+ * @param _cfg Configuration Object
+ * @return initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ /** Fetch the Projection Geometry of this projector.
+ *
+ * @return Projection Geometry class.
+ */
+ CProjectionGeometry3D* getProjectionGeometry();
+
+ /** Fetch the Volume Geometry of this projector.
+ *
+ * @return Volume Geometry class.
+ */
+ CVolumeGeometry3D* getVolumeGeometry();
+
+ /** Compute the pixel weights for a single ray, from the source to a detector pixel.
+ *
+ * @param _iProjectionIndex Index of the projection.
+ * @param _iSliceIndex Index of the detector pixel (1-d index).
+ * @param _iDetectorIndex Index of the detector pixel (1-d index).
+ * @param _pWeightedPixels Pointer to a pre-allocated array, consisting of _iMaxPixelCount elements
+ * of type SPixelWeight. On return, this array contains a list of the index
+ * and weight for all pixels on the ray.
+ * @param _iMaxPixelCount Maximum number of pixels (and corresponding weights) that can be stored in _pWeightedPixels.
+ * This number MUST be greater than the total number of pixels on the ray.
+ * @param _iStoredPixelCount On return, this variable contains the total number of pixels on the
+ * ray (that have been stored in the list _pWeightedPixels).
+ */
+ virtual void computeSingleRayWeights(int _iProjectionIndex, int _iSliceIndex, int _iDetectorIndex, SPixelWeight* _pWeightedPixels, int _iMaxPixelCount, int& _iStoredPixelCount) = 0;
+
+ /** Compute the pixel weights for all rays in a single projection, from the source to a each of the
+ * detector pixels. All pixels and their weights are stored consecutively in the array _pWeightedPixels.
+ * The array starts with all pixels on the first ray, followed by all pixels on the second ray, the third
+ * ray, etc. Note that a pixel may occur in the list more than once, as it can be on several rays.
+ *
+ * @param _iProjectionIndex Index of the projection (zero-based).
+ * @param _pfWeightedPixels Pointer to a pre-allocated array, consisting of getProjectionWeightsCount()
+ * elements of type SPixelWeight. On return, this array contains a list of
+ * the index and weight for all pixels on each of the rays. The elements for
+ * every ray start at equal offsets (ray_index * _pWeightedPixels / ray_count).
+ * @param _piRayStoredPixelCount Pointer to a pre-allocated array, containing a single integer for each
+ * ray in the projection. On return, this array contains the number of
+ * pixels on the ray, for each ray in the given projection.
+ */
+ virtual void computeProjectionRayWeights(int _iProjectionIndex, SPixelWeight* _pfWeightedPixels, int* _piRayStoredPixelCount);
+
+ /** Create a list of detectors that are influenced by point [_iRow, _iCol].
+ *
+ * @param _iRow row of the point
+ * @param _iCol column of the point
+ * @return list of SDetector2D structs
+ */
+ //virtual std::vector<SDetector2D> projectPoint(int _iRow, int _iCol) = 0;
+
+ /** Returns the number of weights required for storage of all weights of one projection.
+ *
+ * @param _iProjectionIndex Index of the projection (zero-based).
+ * @return Size of buffer (given in SWeightedPixel3D elements) needed to store weighted pixels.
+ */
+ virtual int getProjectionWeightsCount(int _iProjectionIndex) = 0;
+
+ /** Has the projector been initialized?
+ *
+ * @return initialized successfully
+ */
+ bool isInitialized();
+
+ /** get a description of the class
+ *
+ * @return description string
+ */
+ virtual std::string description() const = 0;
+
+ /**
+ * Returns a string describing the projector type
+ */
+ virtual std::string getType() = 0;
+
+private:
+ //< For Config unused argument checking
+ ConfigCheckData* configCheckData;
+ friend class ConfigStackCheck<CProjector3D>;
+
+};
+
+// inline functions
+inline bool CProjector3D::isInitialized() { return m_bIsInitialized; }
+inline CProjectionGeometry3D* CProjector3D::getProjectionGeometry() { return m_pProjectionGeometry; }
+inline CVolumeGeometry3D* CProjector3D::getVolumeGeometry() { return m_pVolumeGeometry; }
+
+
+
+} // namespace astra
+
+#endif /* INC_ASTRA_PROJECTOR3D */
diff --git a/include/astra/ProjectorTypelist.h b/include/astra/ProjectorTypelist.h
new file mode 100644
index 0000000..ddc345a
--- /dev/null
+++ b/include/astra/ProjectorTypelist.h
@@ -0,0 +1,104 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_PROJECTORTYPELIST
+#define _INC_ASTRA_PROJECTORTYPELIST
+
+#include "Projector2D.h"
+#include "TypeList.h"
+
+using namespace astra;
+using namespace astra::typelist;
+
+// Projector2D
+#include "Projector2D.h"
+#include "ParallelBeamLineKernelProjector2D.h"
+#include "ParallelBeamLinearKernelProjector2D.h"
+#include "ParallelBeamBlobKernelProjector2D.h"
+#include "ParallelBeamStripKernelProjector2D.h"
+#include "SparseMatrixProjector2D.h"
+#include "FanFlatBeamLineKernelProjector2D.h"
+#include "FanFlatBeamStripKernelProjector2D.h"
+
+#ifdef ASTRA_CUDA
+#include "CudaProjector2D.h"
+namespace astra{
+
+ typedef TYPELIST_8(
+ CFanFlatBeamLineKernelProjector2D,
+ CFanFlatBeamStripKernelProjector2D,
+ CParallelBeamLinearKernelProjector2D,
+ CParallelBeamLineKernelProjector2D,
+ CParallelBeamBlobKernelProjector2D,
+ CParallelBeamStripKernelProjector2D,
+ CSparseMatrixProjector2D,
+ CCudaProjector2D)
+ Projector2DTypeList;
+}
+
+
+
+#else
+
+namespace astra{
+ typedef TYPELIST_7(
+ CFanFlatBeamLineKernelProjector2D,
+ CFanFlatBeamStripKernelProjector2D,
+ CParallelBeamLinearKernelProjector2D,
+ CParallelBeamLineKernelProjector2D,
+ CParallelBeamBlobKernelProjector2D,
+ CParallelBeamStripKernelProjector2D,
+ CSparseMatrixProjector2D)
+ Projector2DTypeList;
+}
+
+#endif
+
+// Projector3D
+#include "Projector3D.h"
+
+#ifdef ASTRA_CUDA
+
+#include "CudaProjector3D.h"
+namespace astra {
+ typedef TYPELIST_1(
+ CCudaProjector3D
+ )
+ Projector3DTypeList;
+}
+
+#else
+
+namespace astra {
+ typedef TYPELIST_0 Projector3DTypeList;
+}
+
+#endif
+
+
+#endif
diff --git a/include/astra/ReconstructionAlgorithm2D.h b/include/astra/ReconstructionAlgorithm2D.h
new file mode 100644
index 0000000..25a6c0a
--- /dev/null
+++ b/include/astra/ReconstructionAlgorithm2D.h
@@ -0,0 +1,222 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_RECONSTRUCTIONALGORITHM2D
+#define _INC_ASTRA_RECONSTRUCTIONALGORITHM2D
+
+#include "Globals.h"
+#include "Config.h"
+
+#include "Algorithm.h"
+
+#include "Projector2D.h"
+#include "Float32ProjectionData2D.h"
+#include "Float32VolumeData2D.h"
+
+
+namespace astra {
+
+/**
+ * This is a base class for the different implementations of 2D reconstruction algorithms.
+ *
+ * \par XML Configuration
+ * \astra_xml_item{ProjectorId, integer, Identifier of a projector as it is stored in the ProjectorManager.}
+ * \astra_xml_item{ProjectionDataId, integer, Identifier of a projection data object as it is stored in the DataManager.}
+ * \astra_xml_item{ReconstructionDataId, integer, Identifier of a volume data object as it is stored in the DataManager.}
+ * \astra_xml_item_option{ReconstructionMaskId, integer, not used, Identifier of a volume data object that acts as a reconstruction mask. 1 = reconstruct on this pixel. 0 = don't reconstruct on this pixel.}
+ * \astra_xml_item_option{SinogramMaskId, integer, not used, Identifier of a projection data object that acts as a projection mask. 1 = reconstruct using this ray. 0 = don't use this ray while reconstructing.}
+ * \astra_xml_item_option{UseMinConstraint, bool, false, Use minimum value constraint.}
+ * \astra_xml_item_option{MinConstraintValue, float, 0, Minimum constraint value.}
+ * \astra_xml_item_option{UseMaxConstraint, bool, false, Use maximum value constraint.}
+ * \astra_xml_item_option{MaxConstraintValue, float, 255, Maximum constraint value.}
+ */
+class _AstraExport CReconstructionAlgorithm2D : public CAlgorithm {
+
+public:
+
+ /** Default constructor, containing no code.
+ */
+ CReconstructionAlgorithm2D();
+
+ /** Destructor.
+ */
+ virtual ~CReconstructionAlgorithm2D();
+
+ /** Initialize the algorithm with a config object.
+ *
+ * @param _cfg Configuration Object
+ * @return initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ /** Initialize class.
+ *
+ * @param _pProjector Projector Object.
+ * @param _pSinogram ProjectionData2D object containing the sinogram data.
+ * @param _pReconstruction VolumeData2D object for storing the reconstructed volume.
+ */
+ bool initialize(CProjector2D* _pProjector,
+ CFloat32ProjectionData2D* _pSinogram,
+ CFloat32VolumeData2D* _pReconstruction);
+
+ /** Clear this class.
+ */
+ virtual void clear();
+
+ /** Add a min/max constraint to the reconstruction process
+ *
+ * @param _bUseMin True if the algorithm should use a min constraint.
+ * @param _fMinValue Lower value to clip pixel values to.
+ * @param _bUseMax True if the algorithm should use a max constraint.
+ * @param _fMaxValue Upper value to clip pixel values to.
+ */
+ void setConstraints(bool _bUseMin, float32 _fMinValue, bool _bUseMax, float32 _fMaxValue);
+
+ /** Set a fixed reconstruction mask. A pixel will only be used in the reconstruction if the
+ * corresponding value in the mask is 1.
+ *
+ * @param _pMask Volume Data object containing fixed reconstruction mask
+ * @param _bEnable enable the use of this mask
+ */
+ void setReconstructionMask(CFloat32VolumeData2D* _pMask, bool _bEnable = true);
+
+ /** Set a fixed sinogram mask. A detector value will only be used in the reconstruction if the
+ * corresponding value in the mask is 1.
+ *
+ * @param _pMask Projection Data object containing fixed sinogram mask
+ * @param _bEnable enable the use of this mask
+ */
+ void setSinogramMask(CFloat32ProjectionData2D* _pMask, bool _bEnable = true);
+
+ /** Get all information parameters.
+ *
+ * @return map with all boost::any object
+ */
+ virtual map<string,boost::any> getInformation();
+
+ /** Get a single piece of information.
+ *
+ * @param _sIdentifier identifier string to specify which piece of information you want
+ * @return boost::any object
+ */
+ virtual boost::any getInformation(std::string _sIdentifier);
+
+ /** Get projector object
+ *
+ * @return projector
+ */
+ CProjector2D* getProjector() const;
+
+ /** Get sinogram data object
+ *
+ * @return sinogram data object
+ */
+ CFloat32ProjectionData2D* getSinogram() const;
+
+ /** Get Reconstructed Data
+ *
+ * @return reconstruction
+ */
+ CFloat32VolumeData2D* getReconstruction() const;
+
+ /** Get Fixed Reconstruction Mask
+ *
+ * @return fixed reconstruction mask
+ */
+ CFloat32VolumeData2D* getReconstructionMask() const;
+
+ /** Perform a number of iterations.
+ *
+ * @param _iNrIterations amount of iterations to perform.
+ */
+ virtual void run(int _iNrIterations = 0) = 0;
+
+ /** Get a description of the class.
+ *
+ * @return description string
+ */
+ virtual std::string description() const;
+
+ /** Get the norm of the residual image.
+ * Only a few algorithms support this method.
+ *
+ * @param _fNorm if supported, the norm is returned here
+ * @return true if this operation is supported
+ */
+ virtual bool getResidualNorm(float32& _fNorm) { return false; }
+
+protected:
+
+ /** Check this object.
+ *
+ * @return object initialized
+ */
+ bool _check();
+
+ /** Initial clearing. Only to be used by constructors.
+ */
+ void _clear();
+
+ //< Projector object.
+ CProjector2D* m_pProjector;
+ //< ProjectionData2D object containing the sinogram.
+ CFloat32ProjectionData2D* m_pSinogram;
+ //< VolumeData2D object for storing the reconstruction volume.
+ CFloat32VolumeData2D* m_pReconstruction;
+
+ //< Use minimum value constraint?
+ bool m_bUseMinConstraint;
+ //< Minimum value constraint.
+ float32 m_fMinValue;
+ //< Use maximum value constraint?
+ bool m_bUseMaxConstraint;
+ //< Maximum value constraint.
+ float32 m_fMaxValue;
+
+ //< Dataobject containing fixed reconstruction mask (0 = don't reconstruct)
+ CFloat32VolumeData2D* m_pReconstructionMask;
+ //< Use the fixed reconstruction mask?
+ bool m_bUseReconstructionMask;
+
+ //< Dataobject containing fixed reconstruction mask (0 = don't reconstruct)
+ CFloat32ProjectionData2D* m_pSinogramMask;
+ //< Use the fixed reconstruction mask?
+ bool m_bUseSinogramMask;
+
+};
+
+// inline functions
+inline std::string CReconstructionAlgorithm2D::description() const { return "3D Reconstruction Algorithm"; };
+inline CProjector2D* CReconstructionAlgorithm2D::getProjector() const { return m_pProjector; }
+inline CFloat32ProjectionData2D* CReconstructionAlgorithm2D::getSinogram() const { return m_pSinogram; }
+inline CFloat32VolumeData2D* CReconstructionAlgorithm2D::getReconstruction() const { return m_pReconstruction; }
+inline CFloat32VolumeData2D* CReconstructionAlgorithm2D::getReconstructionMask() const { return m_pReconstructionMask; }
+
+} // end namespace
+
+#endif
diff --git a/include/astra/ReconstructionAlgorithm3D.h b/include/astra/ReconstructionAlgorithm3D.h
new file mode 100644
index 0000000..063ff6e
--- /dev/null
+++ b/include/astra/ReconstructionAlgorithm3D.h
@@ -0,0 +1,223 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_RECONSTRUCTIONALGORITHM3D
+#define _INC_ASTRA_RECONSTRUCTIONALGORITHM3D
+
+#include "Globals.h"
+#include "Config.h"
+
+#include "Algorithm.h"
+
+#include "Float32ProjectionData3D.h"
+#include "Float32VolumeData3D.h"
+
+
+namespace astra {
+
+class CProjector3D;
+
+/**
+ * This is a base class for the different implementations of 3D reconstruction algorithms.
+ *
+ * \par XML Configuration
+ * \astra_xml_item{ProjectorId, integer, Identifier of a projector as it is stored in the ProjectorManager.}
+ * \astra_xml_item{ProjectionDataId, integer, Identifier of a projection data object as it is stored in the DataManager.}
+ * \astra_xml_item{ReconstructionDataId, integer, Identifier of a volume data object as it is stored in the DataManager.}
+ * \astra_xml_item_option{ReconstructionMaskId, integer, not used, Identifier of a volume data object that acts as a reconstruction mask. 1 = reconstruct on this pixel. 0 = don't reconstruct on this pixel.}
+ * \astra_xml_item_option{SinogramMaskId, integer, not used, Identifier of a projection data object that acts as a projection mask. 1 = reconstruct using this ray. 0 = don't use this ray while reconstructing.}
+ * \astra_xml_item_option{UseMinConstraint, bool, false, Use minimum value constraint.}
+ * \astra_xml_item_option{MinConstraintValue, float, 0, Minimum constraint value.}
+ * \astra_xml_item_option{UseMaxConstraint, bool, false, Use maximum value constraint.}
+ * \astra_xml_item_option{MaxConstraintValue, float, 255, Maximum constraint value.}
+ */
+class _AstraExport CReconstructionAlgorithm3D : public CAlgorithm {
+
+public:
+
+ /** Default constructor, containing no code.
+ */
+ CReconstructionAlgorithm3D();
+
+ /** Destructor.
+ */
+ virtual ~CReconstructionAlgorithm3D();
+
+ /** Initialize the algorithm with a config object.
+ *
+ * @param _cfg Configuration Object
+ * @return initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ /** Initialize class.
+ *
+ * @param _pProjector Projector Object.
+ * @param _pSinogram ProjectionData3D object containing the sinogram data.
+ * @param _pReconstruction VolumeData3D object for storing the reconstructed volume.
+ */
+ bool initialize(CProjector3D* _pProjector,
+ CFloat32ProjectionData3D* _pSinogram,
+ CFloat32VolumeData3D* _pReconstruction);
+
+ /** Clear this class.
+ */
+ virtual void clear();
+
+ /** Add a min/max constraint to the reconstruction process
+ *
+ * @param _bUseMin True if the algorithm should use a min constraint.
+ * @param _fMinValue Lower value to clip pixel values to.
+ * @param _bUseMax True if the algorithm should use a max constraint.
+ * @param _fMaxValue Upper value to clip pixel values to.
+ */
+ void setConstraints(bool _bUseMin, float32 _fMinValue, bool _bUseMax, float32 _fMaxValue);
+
+ /** Set a fixed reconstruction mask. A pixel will only be used in the reconstruction if the
+ * corresponding value in the mask is 1.
+ *
+ * @param _pMask Volume Data object containing fixed reconstruction mask
+ * @param _bEnable enable the use of this mask
+ */
+ void setReconstructionMask(CFloat32VolumeData3D* _pMask, bool _bEnable = true);
+
+ /** Set a fixed sinogram mask. A detector value will only be used in the reconstruction if the
+ * corresponding value in the mask is 1.
+ *
+ * @param _pMask Projection Data object containing fixed sinogram mask
+ * @param _bEnable enable the use of this mask
+ */
+ void setSinogramMask(CFloat32ProjectionData3D* _pMask, bool _bEnable = true);
+
+ /** Get all information parameters.
+ *
+ * @return map with all boost::any object
+ */
+ virtual map<string,boost::any> getInformation();
+
+ /** Get a single piece of information.
+ *
+ * @param _sIdentifier identifier string to specify which piece of information you want
+ * @return boost::any object
+ */
+ virtual boost::any getInformation(std::string _sIdentifier);
+
+ /** Get projector object
+ *
+ * @return projector
+ */
+ CProjector3D* getProjector() const;
+
+ /** Get sinogram data object
+ *
+ * @return sinogram data object
+ */
+ CFloat32ProjectionData3D* getSinogram() const;
+
+ /** Get Reconstructed Data
+ *
+ * @return reconstruction
+ */
+ CFloat32VolumeData3D* getReconstruction() const;
+
+ /** Get Fixed Reconstruction Mask
+ *
+ * @return fixed reconstruction mask
+ */
+ CFloat32VolumeData3D* getReconstructionMask() const;
+
+ /** Perform a number of iterations.
+ *
+ * @param _iNrIterations amount of iterations to perform.
+ */
+ virtual void run(int _iNrIterations = 0) = 0;
+
+ /** Get a description of the class.
+ *
+ * @return description string
+ */
+ virtual std::string description() const;
+
+ /** Get the norm of the residual image.
+ * Only a few algorithms support this method.
+ *
+ * @param _fNorm if supported, the norm is returned here
+ * @return true if this operation is supported
+ */
+ virtual bool getResidualNorm(float32& _fNorm) { return false; }
+
+protected:
+
+ /** Check this object.
+ *
+ * @return object initialized
+ */
+ bool _check();
+
+ /** Initial clearing. Only to be used by constructors.
+ */
+ virtual void _clear();
+
+ //< Projector object.
+ CProjector3D* m_pProjector;
+ //< ProjectionData3D object containing the sinogram.
+ CFloat32ProjectionData3D* m_pSinogram;
+ //< VolumeData3D object for storing the reconstruction volume.
+ CFloat32VolumeData3D* m_pReconstruction;
+
+ //< Use minimum value constraint?
+ bool m_bUseMinConstraint;
+ //< Minimum value constraint.
+ float32 m_fMinValue;
+ //< Use maximum value constraint?
+ bool m_bUseMaxConstraint;
+ //< Maximum value constraint.
+ float32 m_fMaxValue;
+
+ //< Dataobject containing fixed reconstruction mask (0 = don't reconstruct)
+ CFloat32VolumeData3D* m_pReconstructionMask;
+ //< Use the fixed reconstruction mask?
+ bool m_bUseReconstructionMask;
+
+ //< Dataobject containing fixed reconstruction mask (0 = don't reconstruct)
+ CFloat32ProjectionData3D* m_pSinogramMask;
+ //< Use the fixed reconstruction mask?
+ bool m_bUseSinogramMask;
+
+};
+
+// inline functions
+inline std::string CReconstructionAlgorithm3D::description() const { return "3D Reconstruction Algorithm"; };
+inline CProjector3D* CReconstructionAlgorithm3D::getProjector() const { return m_pProjector; }
+inline CFloat32ProjectionData3D* CReconstructionAlgorithm3D::getSinogram() const { return m_pSinogram; }
+inline CFloat32VolumeData3D* CReconstructionAlgorithm3D::getReconstruction() const { return m_pReconstruction; }
+inline CFloat32VolumeData3D* CReconstructionAlgorithm3D::getReconstructionMask() const { return m_pReconstructionMask; }
+
+} // end namespace
+
+#endif
diff --git a/include/astra/SartAlgorithm.h b/include/astra/SartAlgorithm.h
new file mode 100644
index 0000000..1a79a60
--- /dev/null
+++ b/include/astra/SartAlgorithm.h
@@ -0,0 +1,226 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_SARTALGORITHM
+#define _INC_ASTRA_SARTALGORITHM
+
+#include "Globals.h"
+#include "Config.h"
+
+#include "Algorithm.h"
+#include "ReconstructionAlgorithm2D.h"
+
+#include "Projector2D.h"
+#include "Float32ProjectionData2D.h"
+#include "Float32VolumeData2D.h"
+
+#include "DataProjector.h"
+
+namespace astra {
+
+/**
+ * \brief
+ * This class contains the implementation of the SART (Simultaneous Algebraic Reconstruction Technique) algorithm.
+ *
+ * The update step of pixel \f$v_j\f$ for projection \f$phi\f$ and iteration \f$k\f$ is given by:
+ * \f[
+ * v_j^{(k+1)} = v_j^{(k)} + \frac{\sum_{p_i \in P_\phi} \left( \lambda \frac{p_i - \sum_{r=1}^{N} w_{ir}v_r^{(k)}} {\sum_{r=1}^{N}w_{ir} } \right)} {\sum_{p_i \in P_\phi}w_{ij}}
+ * \f]
+ *
+ * \par XML Configuration
+ * \astra_xml_item{ProjectorId, integer, Identifier of a projector as it is stored in the ProjectorManager.}
+ * \astra_xml_item{ProjectionDataId, integer, Identifier of a projection data object as it is stored in the DataManager.}
+ * \astra_xml_item{ReconstructionDataId, integer, Identifier of a volume data object as it is stored in the DataManager.}
+ * \astra_xml_item_option{ReconstructionMaskId, integer, not used, Identifier of a volume data object that acts as a reconstruction mask. 1 = reconstruct on this pixel. 0 = don't reconstruct on this pixel.}
+ * \astra_xml_item_option{SinogramMaskId, integer, not used, Identifier of a projection data object that acts as a projection mask. 1 = reconstruct using this ray. 0 = don't use this ray while reconstructing.}
+ * \astra_xml_item_option{UseMinConstraint, bool, false, Use minimum value constraint.}
+ * \astra_xml_item_option{MinConstraintValue, float, 0, Minimum constraint value.}
+ * \astra_xml_item_option{UseMaxConstraint, bool, false, Use maximum value constraint.}
+ * \astra_xml_item_option{MaxConstraintValue, float, 255, Maximum constraint value.}
+ * \astra_xml_item_option{ProjectionOrder, string, "sequential", the order in which the projections are updated. 'sequential', 'random' or 'custom'}
+ * \astra_xml_item_option{ProjectionOrderList, vector of float, not used, if ProjectionOrder='custom': use this order.}
+ *
+ * \par MATLAB example
+ * \astra_code{
+ * cfg = astra_struct('SART');\n
+ * cfg.ProjectorId = proj_id;\n
+ * cfg.ProjectionDataId = sino_id;\n
+ * cfg.ReconstructionDataId = recon_id;\n
+ * cfg.option.MaskId = mask_id;\n
+ * cfg.option.UseMinConstraint = 'yes';\n
+ * cfg.option.UseMaxConstraint = 'yes';\n
+ * cfg.option.MaxConstraintValue = 1024;\n
+ * cfg.option.ProjectionOrder = 'custom';\n
+* cfg.option.ProjectionOrderList = randperm(100);\n
+ * alg_id = astra_mex_algorithm('create'\, cfg);\n
+ * astra_mex_algorithm('iterate'\, alg_id\, 10);\n
+ * astra_mex_algorithm('delete'\, alg_id);\n
+ * }
+ */
+class _AstraExport CSartAlgorithm : public CReconstructionAlgorithm2D {
+
+protected:
+
+ /** Initial clearing. Only to be used by constructors.
+ */
+ virtual void _clear();
+
+ /** Check the values of this object. If everything is ok, the object can be set to the initialized state.
+ * The following statements are then guaranteed to hold:
+ * - valid projector
+ * - valid data objects
+ * - projection order all within range
+ */
+ virtual bool _check();
+
+ // temporary data objects
+ CFloat32ProjectionData2D* m_pTotalRayLength;
+ CFloat32VolumeData2D* m_pTotalPixelWeight;
+ CFloat32ProjectionData2D* m_pDiffSinogram;
+
+ int m_iIterationCount;
+
+public:
+
+ // type of the algorithm, needed to register with CAlgorithmFactory
+ static std::string type;
+
+ /** Default constructor, containing no code.
+ */
+ CSartAlgorithm();
+
+ /** Constructor.
+ *
+ * @param _pProjector Projector Object.
+ * @param _pSinogram ProjectionData2D object containing the sinogram data.
+ * @param _pReconstruction VolumeData2D object for storing the reconstructed volume.
+ */
+ CSartAlgorithm(CProjector2D* _pProjector,
+ CFloat32ProjectionData2D* _pSinogram,
+ CFloat32VolumeData2D* _pReconstruction);
+
+ /** Constructor.
+ *
+ * @param _pProjector Projector Object.
+ * @param _pSinogram ProjectionData2D object containing the sinogram data.
+ * @param _pReconstruction VolumeData2D object for storing the reconstructed volume.
+ * @param _piProjectionOrder array containing a projection order.
+ * @param _iProjectionCount number of elements in _piProjectionOrder.
+ */
+ CSartAlgorithm(CProjector2D* _pProjector,
+ CFloat32ProjectionData2D* _pSinogram,
+ CFloat32VolumeData2D* _pReconstruction,
+ int* _piProjectionOrder,
+ int _iProjectionCount);
+
+ /** Destructor.
+ */
+ virtual ~CSartAlgorithm();
+
+ /** Clear this class.
+ */
+ virtual void clear();
+
+ /** Initialize the algorithm with a config object.
+ *
+ * @param _cfg Configuration Object
+ * @return initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ /** Initialize class, no optionals, use sequential order.
+ *
+ * @param _pProjector Projector Object.
+ * @param _pSinogram ProjectionData2D object containing the sinogram data.
+ * @param _pReconstruction VolumeData2D object for storing the reconstructed volume.
+ * @return initialization successful?
+ */
+ virtual bool initialize(CProjector2D* _pProjector,
+ CFloat32ProjectionData2D* _pSinogram,
+ CFloat32VolumeData2D* _pReconstruction);
+
+ /** Initialize class, use custom order.
+ *
+ * @param _pProjector Projector Object.
+ * @param _pSinogram ProjectionData2D object containing the sinogram data.
+ * @param _pReconstruction VolumeData2D object for storing the reconstructed volume.
+ * @param _piProjectionOrder array containing a projection order.
+ * @param _iProjectionCount number of elements in _piProjectionOrder.
+ * @return initialization successful?
+ */
+ virtual bool initialize(CProjector2D* _pProjector,
+ CFloat32ProjectionData2D* _pSinogram,
+ CFloat32VolumeData2D* _pReconstruction,
+ int* _piProjectionOrder,
+ int _iProjectionCount);
+
+ /** Get all information parameters
+ *
+ * @return map with all boost::any object
+ */
+ virtual map<string,boost::any> getInformation();
+
+ /** Get a single piece of information represented as a boost::any
+ *
+ * @param _sIdentifier identifier string to specify which piece of information you want
+ * @return boost::any object
+ */
+ virtual boost::any getInformation(std::string _sIdentifier);
+
+ /** Perform a number of iterations. Each iteration is a forward and backprojection of
+ * a single projection index.
+ *
+ * @param _iNrIterations amount of iterations to perform.
+ */
+ virtual void run(int _iNrIterations = 1);
+
+ /** Get a description of the class.
+ *
+ * @return description string
+ */
+ virtual std::string description() const;
+
+protected:
+
+
+ //< Order of the projections.
+ int* m_piProjectionOrder;
+ //< Number of projections specified in m_piProjectionOrder.
+ int m_iProjectionCount;
+ //< Current index in the projection order array.
+ int m_iCurrentProjection;
+
+};
+
+// inline functions
+inline std::string CSartAlgorithm::description() const { return CSartAlgorithm::type; };
+
+
+} // end namespace
+
+#endif
diff --git a/include/astra/Singleton.h b/include/astra/Singleton.h
new file mode 100644
index 0000000..5a494e4
--- /dev/null
+++ b/include/astra/Singleton.h
@@ -0,0 +1,87 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_SINGLETON
+#define _INC_ASTRA_SINGLETON
+
+#include <cassert>
+
+#ifndef _MSC_VER
+#include <stdint.h>
+#endif
+
+namespace astra {
+ /**
+ * This singleton interface class ensures that any of its children can be instatiated only once. This is used by the ObjectFactories.
+ **/
+template<typename T>
+class Singleton {
+
+ public:
+
+ // constructor
+ Singleton() {
+ assert(!m_singleton);
+ int offset = (uintptr_t)(T*)1 - (uintptr_t)(Singleton<T>*)(T*)1;
+ m_singleton = (T*)((uintptr_t)this + offset);
+ };
+
+ // destructor
+ virtual ~Singleton() {
+ assert(m_singleton);
+ m_singleton = 0;
+ }
+
+ // get singleton
+ static T& getSingleton() {
+ if (!m_singleton)
+ m_singleton = new T();
+ return *m_singleton;
+ }
+ static T* getSingletonPtr() {
+ if (!m_singleton)
+ m_singleton = new T();
+ return m_singleton;
+ }
+
+ private:
+
+ // the singleton
+ static T* m_singleton;
+
+};
+
+#define DEFINE_SINGLETON(T) template<> T* Singleton<T >::m_singleton = 0
+
+// This is a hack to support statements like
+// DEFINE_SINGLETON2(CTemplatedClass<C1, C2>);
+#define DEFINE_SINGLETON2(A,B) template<> A,B* Singleton<A,B >::m_singleton = 0
+
+} // end namespace
+
+#endif
diff --git a/include/astra/SirtAlgorithm.h b/include/astra/SirtAlgorithm.h
new file mode 100644
index 0000000..5cbc4d4
--- /dev/null
+++ b/include/astra/SirtAlgorithm.h
@@ -0,0 +1,217 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_SIRTALGORITHM
+#define _INC_ASTRA_SIRTALGORITHM
+
+#include "Globals.h"
+#include "Config.h"
+
+#include "Algorithm.h"
+#include "ReconstructionAlgorithm2D.h"
+
+#include "Projector2D.h"
+#include "Float32ProjectionData2D.h"
+#include "Float32VolumeData2D.h"
+
+#include "DataProjector.h"
+
+namespace astra {
+
+/**
+ * \brief
+ * This class contains the implementation of the SIRT (Simultaneous Iterative Reconstruction Technique) algorithm.
+ *
+ * The update step of pixel \f$v_j\f$ for iteration \f$k\f$ is given by:
+ * \f[
+ * v_j^{(k+1)} = v_j^{(k)} + \alpha \sum_{i=1}^{M} \left( \frac{w_{ij}\left( p_i - \sum_{r=1}^{N} w_{ir}v_r^{(k)}\right)}{\sum_{k=1}^{N} w_{ik}} \right) \frac{1}{\sum_{l=1}^{M}w_{lj}}
+ * \f]
+ *
+ * \par XML Configuration
+ * \astra_xml_item{ProjectorId, integer, Identifier of a projector as it is stored in the ProjectorManager.}
+ * \astra_xml_item{ProjectionDataId, integer, Identifier of a projection data object as it is stored in the DataManager.}
+ * \astra_xml_item{ReconstructionDataId, integer, Identifier of a volume data object as it is stored in the DataManager.}
+ * \astra_xml_item_option{ReconstructionMaskId, integer, not used, Identifier of a volume data object that acts as a reconstruction mask. 1 = reconstruct on this pixel. 0 = don't reconstruct on this pixel.}
+ * \astra_xml_item_option{SinogramMaskId, integer, not used, Identifier of a projection data object that acts as a projection mask. 1 = reconstruct using this ray. 0 = don't use this ray while reconstructing.}
+ * \astra_xml_item_option{UseMinConstraint, bool, false, Use minimum value constraint.}
+ * \astra_xml_item_option{MinConstraintValue, float, 0, Minimum constraint value.}
+ * \astra_xml_item_option{UseMaxConstraint, bool, false, Use maximum value constraint.}
+ * \astra_xml_item_option{MaxConstraintValue, float, 255, Maximum constraint value.}
+ *
+ * \par XML Example
+ * \astra_code{
+ * &lt;Algorithm type="SIRT"&gt;\n
+ * &lt;ProjectorID&gt;proj_id&lt;/ProjectorID&gt;\n
+ * &lt;ProjectionDataId&gt;sino_id&lt;/ProjectionDataId&gt;\n
+ * &lt;ReconstructionDataId&gt;recon_id&lt;/ReconstructionDataId&gt;\n
+ * &lt;Option key="ReconstructionMaskId" value="3"/&gt;\n
+ * &lt;Option key="SinogramMaskId" value="4"/&gt;\n
+ * &lt;Option key="UseMinConstraint" value="yes"/&gt;\n
+ * &lt;Option key="UseMaxConstraint" value="yes"/&gt;\n
+ * &lt;Option key="MaxConstraintValue" value="1024"/&gt;\n
+ * &lt;/Algorithm&gt;
+ * }
+ *
+ * \par MATLAB example
+ * \astra_code{
+ * cfg = astra_struct('SIRT');\n
+ * cfg.ProjectorId = proj_id;\n
+ * cfg.ProjectionDataId = sino_id;\n
+ * cfg.ReconstructionDataId = recon_id;\n
+ * cfg.option.SinogramMaskId = smask_id;\n
+ * cfg.option.ReconstructionMaskId = mask_id;\n
+ * cfg.option.UseMinConstraint = 'yes';\n
+ * cfg.option.UseMaxConstraint = 'yes';\n
+ * cfg.option.MaxConstraintValue = 1024;\n
+ * alg_id = astra_mex_algorithm('create'\, cfg);\n
+ * astra_mex_algorithm('iterate'\, alg_id\, 10);\n
+ * astra_mex_algorithm('delete'\, alg_id);\n
+ * }
+ *
+ * \par References
+ * [1] "Computational Analysis and Improvement of SIRT", J. Gregor, T. Benson, IEEE Transactions on Medical Imaging, Vol. 22, No. 7, July 2008.
+ */
+class _AstraExport CSirtAlgorithm : public CReconstructionAlgorithm2D {
+
+protected:
+
+ /** Init stuff
+ */
+ virtual void _init();
+
+ /** Initial clearing. Only to be used by constructors.
+ */
+ virtual void _clear();
+
+ /** Check the values of this object. If everything is ok, the object can be set to the initialized state.
+ * The following statements are then guaranteed to hold:
+ * - valid projector
+ * - valid data objects
+ */
+ virtual bool _check();
+
+ /** Temporary data object for storing the total ray lengths
+ */
+ CFloat32ProjectionData2D* m_pTotalRayLength;
+
+ /** Temporary data object for storing the total pixel weigths
+ */
+ CFloat32VolumeData2D* m_pTotalPixelWeight;
+
+ /** Temporary data object for storing the difference between the forward projected
+ * reconstruction, and the measured projection data
+ */
+ CFloat32ProjectionData2D* m_pDiffSinogram;
+
+ /** Temporary data object for storing volume data
+ */
+ CFloat32VolumeData2D* m_pTmpVolume;
+
+ /** The number of performed iterations
+ */
+ int m_iIterationCount;
+
+public:
+
+ // type of the algorithm, needed to register with CAlgorithmFactory
+ static std::string type;
+
+ /** Default constructor, containing no code.
+ */
+ CSirtAlgorithm();
+
+ /** Default constructor
+ *
+ * @param _pProjector Projector Object.
+ * @param _pSinogram ProjectionData2D object containing the sinogram data.
+ * @param _pReconstruction VolumeData2D object for storing the reconstructed volume.
+ */
+ CSirtAlgorithm(CProjector2D* _pProjector,
+ CFloat32ProjectionData2D* _pSinogram,
+ CFloat32VolumeData2D* _pReconstruction);
+
+ /** Destructor.
+ */
+ virtual ~CSirtAlgorithm();
+
+ /** Clear this class.
+ */
+ virtual void clear();
+
+ /** Initialize the algorithm with a config object.
+ *
+ * @param _cfg Configuration Object
+ * @return Initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ /** Initialize class.
+ *
+ * @param _pProjector Projector Object.
+ * @param _pSinogram ProjectionData2D object containing the sinogram data.
+ * @param _pReconstruction VolumeData2D object for storing the reconstructed volume.
+ * @return Initialization successful?
+ */
+ bool initialize(CProjector2D* _pProjector,
+ CFloat32ProjectionData2D* _pSinogram,
+ CFloat32VolumeData2D* _pReconstruction);
+
+ /** Get all information parameters.
+ *
+ * @return Map with all available identifier strings and their values.
+ */
+ virtual map<string,boost::any> getInformation();
+
+ /** Get a single piece of information represented as a boost::any
+ *
+ * @param _sIdentifier Identifier string to specify which piece of information you want.
+ * @return One piece of information.
+ */
+ virtual boost::any getInformation(std::string _sIdentifier);
+
+ /** Perform a number of iterations.
+ *
+ * @param _iNrIterations amount of iterations to perform.
+ */
+ virtual void run(int _iNrIterations = 0);
+
+ /** Get a description of the class.
+ *
+ * @return description string
+ */
+ virtual std::string description() const;
+
+};
+
+// inline functions
+inline std::string CSirtAlgorithm::description() const { return CSirtAlgorithm::type; };
+
+
+} // end namespace
+
+#endif
diff --git a/include/astra/SparseMatrix.h b/include/astra/SparseMatrix.h
new file mode 100644
index 0000000..e07be87
--- /dev/null
+++ b/include/astra/SparseMatrix.h
@@ -0,0 +1,144 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_SPARSEMATRIX
+#define _INC_ASTRA_SPARSEMATRIX
+
+namespace astra
+{
+
+
+/** This class implements a sparse matrix. It is stored as three arrays.
+ * The values are stored row-by-row.
+ * m_pfValues contains the values
+ * m_piColIndices contains the col indices of the values
+ * m_plRowStarts contains the start offsets of the rows
+ */
+
+
+class _AstraExport CSparseMatrix {
+public:
+ CSparseMatrix();
+
+ // TODO: are ints large enough for width/height?
+ CSparseMatrix(unsigned int _iHeight, unsigned int _iWidth,
+ unsigned long _lSize);
+
+ /** Initialize the matrix structure.
+ * It does not initialize any values.
+ *
+ * @param _iHeight number of rows
+ * @param _iWidth number of columns
+ * @param _lSize maximum number of non-zero entries
+ * @return initialization successful?
+ */
+
+ bool initialize(unsigned int _iHeight, unsigned int _iWidth,
+ unsigned long _lSize);
+
+ /** Destructor.
+ */
+ ~CSparseMatrix();
+
+ /** Has the matrix structure been initialized?
+ *
+ * @return initialized successfully
+ */
+ bool isInitialized() const { return m_bInitialized; }
+
+ /** get a description of the class
+ *
+ * @return description string
+ */
+ std::string description() const;
+
+ /** get the data for a single row. Entries are stored from left to right.
+ *
+ * @param _iRow the row
+ * @param _iSize the returned number of elements in the row
+ * @param _pfValues the values of the non-zero entries in the row
+ * @param _piColIndices the column indices of the non-zero entries
+ */
+ void getRowData(unsigned int _iRow, unsigned int& _iSize,
+ const float32*& _pfValues, const unsigned int*& _piColIndices) const
+ {
+ assert(_iRow < m_iHeight);
+ unsigned long lStart = m_plRowStarts[_iRow];
+ _iSize = m_plRowStarts[_iRow+1] - lStart;
+ _pfValues = &m_pfValues[lStart];
+ _piColIndices = &m_piColIndices[lStart];
+ }
+
+ /** get the number of elements in a row
+ *
+ * @param _iRow the row
+ * @return number of stored entries in the row
+ */
+ unsigned int getRowSize(unsigned int _iRow) const
+ {
+ assert(_iRow < m_iHeight);
+ return m_plRowStarts[_iRow+1] - m_plRowStarts[_iRow];
+ }
+
+
+ /** Matrix width
+ */
+ unsigned int m_iHeight;
+
+ /** Matrix height
+ */
+ unsigned int m_iWidth;
+
+ /** Maximum number of non-zero entries
+ */
+ unsigned long m_lSize;
+
+ /** Contains the numeric values of all non-zero elements
+ */
+ float32* m_pfValues;
+
+ /** Contains the colon index of all non-zero elements
+ */
+ unsigned int* m_piColIndices;
+
+ /** The indices in this array point to the first element of each row in the m_pfValues array
+ */
+ unsigned long* m_plRowStarts;
+
+protected:
+
+ /** Is the class initialized?
+ */
+ bool m_bInitialized;
+};
+
+
+}
+
+
+#endif
diff --git a/include/astra/SparseMatrixProjectionGeometry2D.h b/include/astra/SparseMatrixProjectionGeometry2D.h
new file mode 100644
index 0000000..e334dd1
--- /dev/null
+++ b/include/astra/SparseMatrixProjectionGeometry2D.h
@@ -0,0 +1,154 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_SPARSEMATRIXPROJECTIONGEOMETRY2D
+#define _INC_ASTRA_SPARSEMATRIXPROJECTIONGEOMETRY2D
+
+#include "ProjectionGeometry2D.h"
+
+namespace astra
+{
+
+class CSparseMatrix;
+
+/**
+ * This class defines a projection geometry determined by an arbitrary
+ * sparse matrix.
+ *
+ * The projection data is assumed to be grouped by 'angle' and 'detector pixel'.
+ * This does not have any effect on the algorithms, but only on the
+ * way the projection data is stored and accessed.
+ */
+class _AstraExport CSparseMatrixProjectionGeometry2D : public CProjectionGeometry2D
+{
+public:
+
+ /** Default constructor. Sets all numeric member variables to 0 and all pointer member variables to NULL.
+ *
+ * If an object is constructed using this default constructor, it must always be followed by a call
+ * to one of the init() methods before the object can be used. Any use before calling init() is not allowed,
+ * except calling the member function isInitialized().
+ *
+ */
+ CSparseMatrixProjectionGeometry2D();
+
+ /** Constructor. Create an instance of the CSparseMatrixProjectionGeometry2D class.
+ *
+ * @param _iProjectionAngleCount Number of projection angles.
+ * @param _iDetectorCount Number of detectors, i.e., the number of detector measurements for each projection angle.
+ * @param _pMatrix Pointer to a CSparseMatrix. The caller is responsible for keeping this matrix valid until it is no longer required.
+ */
+ CSparseMatrixProjectionGeometry2D(int _iProjectionAngleCount,
+ int _iDetectorCount,
+ const CSparseMatrix* _pMatrix);
+
+ /** Copy constructor.
+ */
+ CSparseMatrixProjectionGeometry2D(const CSparseMatrixProjectionGeometry2D& _projGeom);
+
+ /** Destructor.
+ */
+ ~CSparseMatrixProjectionGeometry2D();
+
+ /** Assignment operator.
+ */
+ CSparseMatrixProjectionGeometry2D& operator=(const CSparseMatrixProjectionGeometry2D& _other);
+
+ /** Initialize the geometry with a config object. This does not allow
+ * setting a matrix. Use the setMatrix() method for that afterwards.
+ *
+ * @param _cfg Configuration Object
+ * @return initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ /** Initialization. Initializes an instance of the CProjectionGeometry2D class. If the object has been
+ * initialized before, the object is reinitialized and memory is freed and reallocated if necessary.
+ *
+ * @param _iProjectionAngleCount Number of projection angles.
+ * @param _iDetectorCount Number of detectors, i.e., the number of detector measurements for each projection angle.
+ * @param _pMatrix Pointer to a CSparseMatrix. The caller is responsible for keeping this matrix valid until it is no longer required.
+ */
+ bool initialize(int _iProjectionAngleCount,
+ int _iDetectorCount,
+ const CSparseMatrix* _pMatrix);
+
+ /** Set the associated sparse matrix. The previous one is deleted.
+ *
+ * @param _pMatrix Pointer to a CSparseMatrix. The caller is responsible for keeping this matrix valid until it is no longer required.
+ * @return initialization successful?
+ */
+
+ bool setMatrix(CSparseMatrix* _pMatrix);
+
+ /** Get a pointer to the associated sparse matrix.
+ * @return the associated sparse matrix
+ */
+ const CSparseMatrix* getMatrix() const { return m_pMatrix; }
+
+ /** Create a hard copy.
+ */
+ virtual CProjectionGeometry2D* clone();
+
+ /** Return true if this geometry instance is the same as the one specified.
+ *
+ * @return true if this geometry instance is the same as the one specified.
+ */
+ virtual bool isEqual(CProjectionGeometry2D*) const;
+
+ /** Returns true if the type of geometry defined in this class is the one specified in _sType.
+ *
+ * @param _sType geometry type to compare to.
+ * @return true if _sType == "parallel".
+ */
+ virtual bool isOfType(const std::string& _sType);
+
+ /**
+ * Returns a vector describing the direction of a ray belonging to a certain detector
+ *
+ * @param _iProjectionIndex index of projection
+ * @param _iProjectionIndex index of detector
+ *
+ * @return a unit vector describing the direction
+ */
+ virtual CVector3D getProjectionDirection(int _iProjectionIndex, int _iDetectorIndex);
+
+protected:
+
+ /** Check this object.
+ *
+ * @return object initialized
+ */
+ bool _check();
+
+ const CSparseMatrix* m_pMatrix;
+};
+
+} // namespace astra
+
+#endif /* _INC_ASTRA_SPARSEMATRIXPROJECTIONGEOMETRY2D */
diff --git a/include/astra/SparseMatrixProjector2D.h b/include/astra/SparseMatrixProjector2D.h
new file mode 100644
index 0000000..f2554bf
--- /dev/null
+++ b/include/astra/SparseMatrixProjector2D.h
@@ -0,0 +1,210 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_SPARSEMATRIXPROJECTOR2D
+#define _INC_ASTRA_SPARSEMATRIXPROJECTOR2D
+
+#include "SparseMatrixProjectionGeometry2D.h"
+#include "SparseMatrix.h"
+#include "Float32Data2D.h"
+#include "Projector2D.h"
+
+namespace astra
+{
+
+
+/** This class implements a two-dimensional projector using a projection geometry defined by an arbitrary sparse matrix.
+ *
+ * \par XML Configuration
+ * \astra_xml_item{ProjectionGeometry, xml node, The geometry of the projection.}
+ * \astra_xml_item{VolumeGeometry, xml node, The geometry of the volume.}
+ *
+ * \par MATLAB example
+ * \astra_code{
+ * cfg = astra_struct('sparse_matrix');\n
+ * cfg.ProjectionGeometry = proj_geom;\n
+ * cfg.VolumeGeometry = vol_geom;\n
+ * proj_id = astra_mex_projector('create'\, cfg);\n
+ * }
+ */
+class _AstraExport CSparseMatrixProjector2D : public CProjector2D {
+
+protected:
+
+ /** Initial clearing. Only to be used by constructors.
+ */
+ virtual void _clear();
+
+ /** Check the values of this object. If everything is ok, the object can be set to the initialized state.
+ * The following statements are then guaranteed to hold:
+ * - no NULL pointers
+ * - all sub-objects are initialized properly
+ * - matrix dimensions match volume geometry
+ */
+ virtual bool _check();
+
+public:
+
+ // type of the projector, needed to register with CProjectorFactory
+ static std::string type;
+
+ /** Default constructor.
+ */
+ CSparseMatrixProjector2D();
+
+ /** Constructor.
+ *
+ * @param _pProjectionGeometry Information class about the geometry of the projection. Will be HARDCOPIED.
+ * @param _pReconstructionGeometry Information class about the geometry of the reconstruction volume. Will be HARDCOPIED.
+ */
+ CSparseMatrixProjector2D(CSparseMatrixProjectionGeometry2D* _pProjectionGeometry,
+ CVolumeGeometry2D* _pReconstructionGeometry);
+
+ /** Destructor, is virtual to show that we are aware subclass destructor are called.
+ */
+ ~CSparseMatrixProjector2D();
+
+ /** Initialize the projector with a config object.
+ *
+ * @param _cfg Configuration Object
+ * @return initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ /** Initialize the projector.
+ *
+ * @param _pProjectionGeometry Information class about the geometry of the projection. Will be HARDCOPIED.
+ * @param _pReconstructionGeometry Information class about the geometry of the reconstruction volume. Will be HARDCOPIED.
+ * @return initialization successful?
+ */
+ virtual bool initialize(CSparseMatrixProjectionGeometry2D* _pProjectionGeometry,
+ CVolumeGeometry2D* _pReconstructionGeometry);
+
+ /** Clear this class.
+ */
+ virtual void clear();
+
+ /** Returns the number of weights required for storage of all weights of one projection.
+ *
+ * @param _iProjectionIndex Index of the projection (zero-based).
+ * @return Size of buffer (given in SPixelWeight elements) needed to store weighted pixels.
+ */
+ virtual int getProjectionWeightsCount(int _iProjectionIndex);
+
+ /** Compute the pixel weights for a single ray, from the source to a detector pixel.
+ *
+ * @param _iProjectionIndex Index of the projection
+ * @param _iDetectorIndex Index of the detector pixel
+ * @param _pWeightedPixels Pointer to a pre-allocated array, consisting of _iMaxPixelCount elements
+ * of type SPixelWeight. On return, this array contains a list of the index
+ * and weight for all pixels on the ray.
+ * @param _iMaxPixelCount Maximum number of pixels (and corresponding weights) that can be stored in _pWeightedPixels.
+ * This number MUST be greater than the total number of pixels on the ray.
+ * @param _iStoredPixelCount On return, this variable contains the total number of pixels on the
+ * ray (that have been stored in the list _pWeightedPixels).
+ */
+ virtual void computeSingleRayWeights(int _iProjectionIndex,
+ int _iDetectorIndex,
+ SPixelWeight* _pWeightedPixels,
+ int _iMaxPixelCount,
+ int& _iStoredPixelCount);
+
+ /** Create a list of detectors that are influenced by point [_iRow, _iCol].
+ *
+ * @param _iRow row of the point
+ * @param _iCol column of the point
+ * @return list of SDetector2D structs
+ */
+ virtual std::vector<SDetector2D> projectPoint(int _iRow, int _iCol);
+
+ /** Policy-based projection of all rays. This function will calculate each non-zero projection
+ * weight and use this value for a task provided by the policy object.
+ *
+ * @param _policy Policy object. Should contain prior, addWeight and posterior function.
+ */
+ template <typename Policy>
+ void project(Policy& _policy);
+
+ /** Policy-based projection of all rays of a single projection. This function will calculate
+ * each non-zero projection weight and use this value for a task provided by the policy object.
+ *
+ * @param _iProjection Wwhich projection should be projected?
+ * @param _policy Policy object. Should contain prior, addWeight and posterior function.
+ */
+ template <typename Policy>
+ void projectSingleProjection(int _iProjection, Policy& _policy);
+
+ /** Policy-based projection of a single ray. This function will calculate each non-zero
+ * projection weight and use this value for a task provided by the policy object.
+ *
+ * @param _iProjection Which projection should be projected?
+ * @param _iDetector Which detector should be projected?
+ * @param _policy Policy object. Should contain prior, addWeight and posterior function.
+ */
+ template <typename Policy>
+ void projectSingleRay(int _iProjection, int _iDetector, Policy& _policy);
+
+ /** Policy-based voxel-projection of a single pixel. This function will calculate
+ * each non-zero projection weight and use this value for a task provided by the policy object.
+ *
+ * @param _iRow
+ * @param _iCol
+ * @param _policy Policy object. Should contain prior, addWeight and posterior function.
+ */
+ template <typename Policy>
+ void projectSingleVoxel(int _iRow, int _iCol, Policy& _policy) {}
+
+ /** Policy-based voxel-projection of all voxels. This function will calculate
+ * each non-zero projection weight and use this value for a task provided by the policy object.
+ *
+ * @param _policy Policy object. Should contain prior, addWeight and posterior function.
+ */
+ template <typename Policy>
+ void projectAllVoxels(Policy& _policy) {}
+
+protected:
+
+ /** Return the type of this projector.
+ *
+ * @return identification type of this projector
+ */
+ virtual std::string getType();
+
+};
+
+//----------------------------------------------------------------------------------------
+
+inline std::string CSparseMatrixProjector2D::getType()
+{
+ return type;
+}
+
+} // namespace astra
+
+#endif
+
diff --git a/include/astra/SparseMatrixProjector2D.inl b/include/astra/SparseMatrixProjector2D.inl
new file mode 100644
index 0000000..8256232
--- /dev/null
+++ b/include/astra/SparseMatrixProjector2D.inl
@@ -0,0 +1,90 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+
+//----------------------------------------------------------------------------------------
+// PROJECT ALL
+template <typename Policy>
+void CSparseMatrixProjector2D::project(Policy& p)
+{
+ ASTRA_ASSERT(m_bIsInitialized);
+
+ for (int i = 0; i < m_pProjectionGeometry->getProjectionAngleCount(); ++i)
+ for (int j = 0; j < m_pProjectionGeometry->getDetectorCount(); ++j)
+ projectSingleRay(i, j, p);
+}
+
+
+//----------------------------------------------------------------------------------------
+// PROJECT SINGLE PROJECTION
+template <typename Policy>
+void CSparseMatrixProjector2D::projectSingleProjection(int _iProjection, Policy& p)
+{
+ ASTRA_ASSERT(m_bIsInitialized);
+
+ for (int j = 0; j < m_pProjectionGeometry->getDetectorCount(); ++j)
+ projectSingleRay(_iProjection, j, p);
+}
+
+
+//----------------------------------------------------------------------------------------
+// PROJECT SINGLE RAY
+template <typename Policy>
+void CSparseMatrixProjector2D::projectSingleRay(int _iProjection, int _iDetector, Policy& p)
+{
+ ASTRA_ASSERT(m_bIsInitialized);
+
+ int iRayIndex = _iProjection * m_pProjectionGeometry->getDetectorCount() + _iDetector;
+ const CSparseMatrix* pMatrix = dynamic_cast<CSparseMatrixProjectionGeometry2D*>(m_pProjectionGeometry)->getMatrix();
+
+ // POLICY: RAY PRIOR
+ if (!p.rayPrior(iRayIndex)) return;
+
+ const unsigned int* piColIndices;
+ const float32* pfValues;
+ unsigned int iSize;
+
+ pMatrix->getRowData(iRayIndex, iSize, pfValues, piColIndices);
+
+ for (unsigned int i = 0; i < iSize; ++i) {
+ unsigned int iVolumeIndex = piColIndices[i];
+
+ // POLICY: PIXEL PRIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+
+ // POLICY: ADD
+ p.addWeight(iRayIndex, iVolumeIndex, pfValues[i]);
+
+ // POLICY: PIXEL POSTERIOR
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+
+ // POLICY: RAY POSTERIOR
+ p.rayPosterior(iRayIndex);
+}
diff --git a/include/astra/TypeList.h b/include/astra/TypeList.h
new file mode 100644
index 0000000..fcf985d
--- /dev/null
+++ b/include/astra/TypeList.h
@@ -0,0 +1,236 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_TYPELIST
+#define _INC_ASTRA_TYPELIST
+
+#include "Globals.h"
+#include <cstring>
+
+namespace astra {
+namespace typelist {
+
+ //-----------------------------------------------------------------------------------------
+ // basic types
+ /**
+ * Type to serve as tail of typelist
+ **/
+ class NullType { };
+ struct FalseType { enum { value = false }; };
+ struct TrueType { enum { value = true }; };
+
+ //-----------------------------------------------------------------------------------------
+ // define typelist
+ /**
+ * Typelist definition
+ * \par References
+ * [1] Modern C++ design: generic programming and design patterns applied, Andrei Alexandrescu
+ **/
+ template <class T, class U>
+ struct TypeList
+ {
+ typedef T Head;
+ typedef U Tail;
+ };
+
+ //-----------------------------------------------------------------------------------------
+ // linearize typelist
+ #define TYPELIST_0 NullType
+ #define TYPELIST_1(T1) TypeList<T1, NullType>
+ #define TYPELIST_2(T1,T2) TypeList<T1, TYPELIST_1(T2) >
+ #define TYPELIST_3(T1,T2,T3) TypeList<T1, TYPELIST_2(T2,T3) >
+ #define TYPELIST_4(T1,T2,T3,T4) TypeList<T1, TYPELIST_3(T2,T3,T4) >
+ #define TYPELIST_5(T1,T2,T3,T4,T5) TypeList<T1, TYPELIST_4(T2,T3,T4,T5) >
+ #define TYPELIST_6(T1,T2,T3,T4,T5,T6) TypeList<T1, TYPELIST_5(T2,T3,T4,T5,T6) >
+ #define TYPELIST_7(T1,T2,T3,T4,T5,T6,T7) TypeList<T1, TYPELIST_6(T2,T3,T4,T5,T6,T7) >
+ #define TYPELIST_8(T1,T2,T3,T4,T5,T6,T7,T8) TypeList<T1, TYPELIST_7(T2,T3,T4,T5,T6,T7,T8) >
+ #define TYPELIST_9(T1,T2,T3,T4,T5,T6,T7,T8,T9) TypeList<T1, TYPELIST_8(T2,T3,T4,T5,T6,T7,T8,T9)>
+ #define TYPELIST_10(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10) \
+ TypeList<T1, TYPELIST_9(T2,T3,T4,T5,T6,T7,T8,T9,T10) >
+ #define TYPELIST_11(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11) \
+ TypeList<T1, TYPELIST_10(T2,T3,T4,T5,T6,T7,T8,T9,T10,T11) >
+ #define TYPELIST_12(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12) \
+ TypeList<T1, TYPELIST_11(T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12) >
+ #define TYPELIST_13(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13) \
+ TypeList<T1, TYPELIST_12(T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13) >
+ #define TYPELIST_14(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14) \
+ TypeList<T1, TYPELIST_13(T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14) >
+ #define TYPELIST_15(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15) \
+ TypeList<T1, TYPELIST_14(T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15) >
+ #define TYPELIST_16(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16) \
+ TypeList<T1, TYPELIST_15(T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16) >
+ #define TYPELIST_17(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17) \
+ TypeList<T1, TYPELIST_16(T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17) >
+ #define TYPELIST_18(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18) \
+ TypeList<T1, TYPELIST_17(T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18) >
+ #define TYPELIST_19(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19) \
+ TypeList<T1, TYPELIST_18(T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19) >
+ #define TYPELIST_20(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20) \
+ TypeList<T1, TYPELIST_19(T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20) >
+ #define TYPELIST_21(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21) \
+ TypeList<T1, TYPELIST_20(T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21) >
+ #define TYPELIST_22(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22) \
+ TypeList<T1, TYPELIST_21(T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22) >
+ #define TYPELIST_23(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23) \
+ TypeList<T1, TYPELIST_22(T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23) >
+
+ #define TYPELIST_24(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24) \
+ TypeList<T1, TYPELIST_23(T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24) >
+
+ #define TYPELIST_25(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25) \
+ TypeList<T1, TYPELIST_24(T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25) >
+
+ #define TYPELIST_26(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26) \
+ TypeList<T1, TYPELIST_25(T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26) >
+
+ #define TYPELIST_27(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27) \
+ TypeList<T1, TYPELIST_26(T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27) >
+
+ #define TYPELIST_28(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28) \
+ TypeList<T1, TYPELIST_27(T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28) >
+
+ #define TYPELIST_29(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29) \
+ TypeList<T1, TYPELIST_28(T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29) >
+
+ #define TYPELIST_30(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30) \
+ TypeList<T1, TYPELIST_29(T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30) >
+
+ #define TYPELIST_31(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31) \
+ TypeList<T1, TYPELIST_30(T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31) >
+
+ #define TYPELIST_32(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32) \
+ TypeList<T1, TYPELIST_31(T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32) >
+
+ #define TYPELIST_33(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33) \
+ TypeList<T1, TYPELIST_32(T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33) >
+
+ #define TYPELIST_34(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34) \
+ TypeList<T1, TYPELIST_33(T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34) >
+
+ #define TYPELIST_35(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35) \
+ TypeList<T1, TYPELIST_34(T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35) >
+
+ #define TYPELIST_36(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36) \
+ TypeList<T1, TYPELIST_35(T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36) >
+
+ #define TYPELIST_37(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36,T37) \
+ TypeList<T1, TYPELIST_36(T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36,T37) >
+
+ #define TYPELIST_38(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36,T37,T38) \
+ TypeList<T1, TYPELIST_37(T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36,T37,T38) >
+
+ #define TYPELIST_39(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36,T37,T38,T39) \
+ TypeList<T1, TYPELIST_38(T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36,T37,T38,T39) >
+
+ #define TYPELIST_40(T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36,T37,T38,T39,T40) \
+ TypeList<T1, TYPELIST_39(T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36,T37,T38,T39,T40) >
+
+
+ //-----------------------------------------------------------------------------------------
+ // calculate length of a typelist
+ template <class TList> struct Length;
+ template <> struct Length<NullType>
+ {
+ enum { value = 0 };
+ };
+ template <class T, class U>
+ struct Length< TypeList<T,U> >
+ {
+ enum { value = 1 + Length<U>::value };
+ };
+
+ //-----------------------------------------------------------------------------------------
+ // indexed access
+ template <class TList, unsigned int i> struct TypeAt;
+ template <class Head, class Tail>
+ struct TypeAt<TypeList<Head,Tail> , 0>
+ {
+ typedef Head Result;
+ };
+ template <class Head, class Tail, unsigned int i>
+ struct TypeAt<TypeList<Head,Tail>, i>
+ {
+ typedef typename TypeAt<Tail, i-1>::Result Result;
+ };
+
+
+ //-----------------------------------------------------------------------------------------
+ // append to typelist
+ template <class TList, class T> struct Append;
+ template <>
+ struct Append<NullType, NullType> {
+ typedef NullType Result;
+ };
+ template <class T>
+ struct Append<NullType, T> {
+ typedef TYPELIST_1(T) Result;
+ };
+ template <class Head, class Tail>
+ struct Append<NullType, TypeList<Head,Tail> > {
+ typedef TypeList<Head,Tail> Result;
+ };
+ template <class Head, class Tail, class T>
+ struct Append<TypeList<Head,Tail>, T> {
+ typedef TypeList<Head, typename Append<Tail, T>::Result> Result;
+ };
+
+ //-----------------------------------------------------------------------------------------
+ // create a new object
+ template <class TList>
+ struct CreateObject {
+ template <class U>
+ static void find (U& functor) {
+ if (functor(TList::Head::type)) {
+ functor.res = new typename TList::Head();
+ }
+ CreateObject<typename TList::Tail>::find(functor);
+ }
+ };
+ template <>
+ struct CreateObject<NullType> {
+ template <class U>
+ static void find(U& functor) {}
+ };
+
+ template <typename Base>
+ struct functor_find {
+ functor_find() { res = NULL; }
+ bool operator() (string name) {
+ return strcmp(tofind.c_str(), name.c_str()) == 0;
+ }
+ string tofind;
+ Base* res;
+ };
+
+
+
+
+} // end namespace typelist
+} // end namespace astra
+
+#endif
diff --git a/include/astra/Utilities.h b/include/astra/Utilities.h
new file mode 100644
index 0000000..7bf0cae
--- /dev/null
+++ b/include/astra/Utilities.h
@@ -0,0 +1,131 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_UTILIES
+#define _INC_ASTRA_UTILIES
+
+#include <string>
+#include <vector>
+#include <algorithm>
+#include <sstream>
+#include <map>
+
+#include "Globals.h"
+
+namespace astra {
+
+/**
+ * This class contains some usefull static utility functions for std strings.
+ */
+class StringUtil {
+
+public:
+ /**
+ * Removes whitespace characters such as spaces and tabs at the extremas.
+ * Optionally you can specify which extrema to trim (default=both)
+ *
+ * @param _sString The string to trim.
+ * @param _bLeft Trim the left extrema? Default = true.
+ * @param _bRight Trim the right extrema? Default = true.
+ */
+ static void trim(std::string& _sString, bool _bLeft = true, bool _bRight = true);
+
+ /**
+ * Returns a vector of strings that contains all the substrings delimited by
+ * the characters in _sDelims.
+ *
+ * @param _sString The string to split.
+ * @param _sDelims The delimiter string.
+ * @return Vector of strings.
+ */
+ static std::vector<std::string> split(const std::string& _sString, const std::string& _sDelims);
+
+ /**
+ * Cast a string to an integer.
+ *
+ * @param _sString The string to cast.
+ * @param _iValue Output integer parameter.
+ * @return success?
+ */
+ static bool toInt(const std::string& _sString, int& _iValue);
+
+ /**
+ * Cast a string to a float32.
+ *
+ * @param _sString The string to cast.
+ * @param _fValue Output float32 parameter.
+ * @return success?
+ */
+ static bool toFloat32(const std::string& _sString, float32& _fValue);
+
+ /**
+ * Convert a string to lower case.
+ *
+ * @param _sString The string to convert.
+ */
+ static void toLowerCase(std::string& _sString);
+
+ /**
+ * Convert a string to upper case.
+ *
+ * @param _sString The string to convert.
+ */
+ static void toUpperCase(std::string& _sString);
+};
+
+/**
+ * This class contains some usefull static utility functions for std strings.
+ */
+class FileSystemUtil {
+
+public:
+ /**
+ * Get the extensions of a filename. Always in lower case.
+ *
+ * @param _sFilename file to get extensions from.
+ * @return Extension (lower case). Empty string if filename is a directory or not a valid file format.
+ */
+ static std::string getExtension(std::string& _sFilename);
+
+
+};
+
+
+template<typename T, typename S>
+std::map<T,S> mergeMap(std::map<T,S> _mMap1, std::map<T,S> _mMap2)
+{
+ std::map<T,S> result = _mMap1;
+ for (typename std::map<T,S>::iterator it = _mMap2.begin(); it != _mMap2.end(); it++) {
+ result[(*it).first] = (*it).second;
+ }
+ return result;
+}
+
+} // end namespace
+
+#endif
diff --git a/include/astra/Vector3D.h b/include/astra/Vector3D.h
new file mode 100644
index 0000000..ee923c9
--- /dev/null
+++ b/include/astra/Vector3D.h
@@ -0,0 +1,131 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_VECTOR3D
+#define _INC_ASTRA_VECTOR3D
+
+#include "Globals.h"
+
+namespace astra {
+
+/**
+ * This class defines a three-dimensional vector type.
+ */
+class CVector3D
+{
+ float32 m_fX; ///< X Coordinate
+ float32 m_fY; ///< Y Coordinate
+ float32 m_fZ; ///< Z Coordinate
+
+public:
+ /**
+ * Default constructor
+ */
+ CVector3D();
+
+ /**
+ * Constructor initializing member variables
+ */
+ CVector3D(float32 _fX, float32 _fY, float32 _fZ);
+
+ /**
+ * Returns the X-coordinate stored in this vector
+ */
+ float32 getX() const;
+
+ /**
+ * Returns the Y-coordinate stored in this vector
+ */
+ float32 getY() const;
+
+ /**
+ * Returns the Z-coordinate stored in this vector
+ */
+ float32 getZ() const;
+
+ /**
+ * Sets the X-coordinate stored in this vector
+ */
+ void setX(float32 _fX);
+
+ /**
+ * Sets the X-coordinate stored in this vector
+ */
+ void setY(float32 _fY);
+
+ /**
+ * Sets the X-coordinate stored in this vector
+ */
+ void setZ(float32 _fZ);
+};
+
+inline CVector3D::CVector3D()
+{
+ m_fX = m_fY = m_fZ = 0.0f;
+}
+
+inline CVector3D::CVector3D(float32 _fX, float32 _fY, float32 _fZ)
+{
+ m_fX = _fX;
+ m_fY = _fY;
+ m_fZ = _fZ;
+}
+
+inline float32 CVector3D::getX() const
+{
+ return m_fX;
+}
+
+inline float32 CVector3D::getY() const
+{
+ return m_fY;
+}
+
+inline float32 CVector3D::getZ() const
+{
+ return m_fZ;
+}
+
+inline void CVector3D::setX(float32 _fX)
+{
+ m_fX = _fX;
+}
+
+inline void CVector3D::setY(float32 _fY)
+{
+ m_fY = _fY;
+}
+
+inline void CVector3D::setZ(float32 _fZ)
+{
+ m_fZ = _fZ;
+}
+
+}
+
+#endif /* _INC_ASTRA_VECTOR3D */
diff --git a/include/astra/VolumeGeometry2D.h b/include/astra/VolumeGeometry2D.h
new file mode 100644
index 0000000..99d480d
--- /dev/null
+++ b/include/astra/VolumeGeometry2D.h
@@ -0,0 +1,608 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_VOLUMEGEOMETRY2D
+#define _INC_ASTRA_VOLUMEGEOMETRY2D
+
+#include "Globals.h"
+#include "Config.h"
+
+namespace astra
+{
+
+/**
+ * This class represents a pixel grid that is placed in the geometry. It defines a rectangular volume window.
+ *
+ * \par XML Configuration
+ * \astra_xml_item{GridColCount, integer, Number of columns in this geometry.}
+ * \astra_xml_item{GridRowCount, integer, Number of rows in this geometry.}
+ * \astra_xml_item_option{WindowMinX, float, Minimal X-coordinate in the volume window.}
+ * \astra_xml_item_option{WindowMaxX, float, Maximal X-coordinate in the volume window.}
+ * \astra_xml_item_option{WindowMinY, float, Minimal Y-coordinate in the volume window.}
+ * \astra_xml_item_option{WindowMaxY, float, Maximal Y-coordinate in the volume window.}
+ *
+ * \par MATLAB example
+ * \astra_code{
+ * vol_geom = struct();\n
+ * vol_geom.GridColCount = 1024;\n
+ * vol_geom.GridRowCount = 768;\n
+ * vol_geom.option.WindowMinX = -512;\n
+ * vol_geom.option.WindowMaxX = -384;\n
+ * vol_geom.option.WindowMinY = 512;\n
+ * vol_geom.option.WindowMaxY = 384;\n
+ * }
+ */
+class _AstraExport CVolumeGeometry2D {
+
+protected:
+ bool m_bInitialized; ///< Has this object been initialized?
+
+ int m_iGridColCount; ///< number of columns in the volume grid.
+ int m_iGridRowCount; ///< number of rows in the volume grid.
+ int m_iGridTotCount; ///< total number of pixels in the volume grid (= m_iGridColCount * m_iGridRowCount).
+
+ /** Width of the volume window, in unit lengths.
+ *
+ * Note that this width is independent of the number of pixels in the X-direction, as the width of a pixel can
+ * be different from 1.
+ */
+ float32 m_fWindowLengthX;
+
+ /** Height of the volume window, in unit lengths.
+ *
+ * Note that this height is independent of the number of pixels in the Y-direction, as the height of a pixel can
+ * be different from 1.
+ */
+ float32 m_fWindowLengthY;
+
+ float32 m_fWindowArea; ///< Total area of the volume window, in unit lengths squared.
+
+ float32 m_fPixelLengthX; ///< Width of a single pixel, in unit lengths.
+ float32 m_fPixelLengthY; ///< Height of a single pixel, in unit lengths.
+ float32 m_fPixelArea; ///< Area of a single pixel, in unit lengths squared.
+
+ float32 m_fDivPixelLengthX; ///< 1/m_fPixelLengthX, used for fast division.
+ float32 m_fDivPixelLengthY; ///< 1/m_fPixelLengthY, used for fast division.
+
+ float32 m_fWindowMinX; ///< Minimal X-coordinate in the volume window.
+ float32 m_fWindowMinY; ///< Maximal X-coordinate in the volume window.
+ float32 m_fWindowMaxX; ///< Minimal Y-coordinate in the volume window.
+ float32 m_fWindowMaxY; ///< Maximal Y-coordinate in the volume window.
+
+ /** Check the values of this object. If everything is ok, the object can be set to the initialized state.
+ * The following statements are then guaranteed to hold:
+ * - number of rows and columns is larger than zero
+ * - window minima is smaller than window maxima
+ * - m_iGridTotCount, m_fWindowLengthX, m_fWindowLengthY, m_fWindowArea, m_fPixelLengthX,
+ * m_fPixelLengthY, m_fPixelArea, m_fDivPixelLengthX and m_fDivPixelLengthY are initialized ok
+ */
+ bool _check();
+
+
+ /** Calculate values of all member variables from m_iGridRow/ColCount, m_fWindow*
+ */
+ void _calculateDependents();
+public:
+
+ /** Default constructor. Sets all numeric member variables to 0 and all pointer member variables to NULL.
+ *
+ * If an object is constructed using this default constructor, it must always be followed by a call
+ * to one of the init() methods before the object can be used. Any use before calling init() is not allowed,
+ * except calling the member function isInitialized().
+ */
+ CVolumeGeometry2D();
+
+ /** Constructor. Create an instance of the CVolumeGeometry2D class.
+ * The minimal and coordinates values of the geometry will be set to -/+ the number of rows/columns.
+ *
+ * @param _iGridCountX Number of columns in the volume grid.
+ * @param _iGridCountY Number of rows in the volume grid.
+ */
+ CVolumeGeometry2D(int _iGridCountX,
+ int _iGridCountY);
+
+ /** Constructor. Create an instance of the CVolumeGeometry2D class.
+ *
+ * @param _iGridCountX Number of columns in the volume grid.
+ * @param _iGridCountY Number of rows in the volume grid.
+ * @param _fWindowMinX Minimal X-coordinate in the volume window.
+ * @param _fWindowMinY Minimal Y-coordinate in the volume window.
+ * @param _fWindowMaxX Maximal X-coordinate in the volume window.
+ * @param _fWindowMaxY Maximal Y-coordinate in the volume window.
+ */
+ CVolumeGeometry2D(int _iGridCountX,
+ int _iGridCountY,
+ float32 _fWindowMinX,
+ float32 _fWindowMinY,
+ float32 _fWindowMaxX,
+ float32 _fWindowMaxY);
+
+ /** Destructor.
+ */
+ virtual ~CVolumeGeometry2D();
+
+ /** Clear all member variables, setting all numeric variables to 0 and all pointers to NULL.
+ */
+ void clear();
+
+ /** Create a hard copy.
+ */
+ CVolumeGeometry2D* clone();
+
+ /** Initialize the volume geometry with a config object.
+ *
+ * @param _cfg Configuration Object.
+ * @return initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ /** Initialization. Initializes an instance of the CVolumeGeometry2D class.
+ * The minimal and maximal coordinates of the geometry will be set to -/+ half the number of rows/columns.
+ *
+ * If the object has been initialized before, the object is reinitialized and
+ * memory is freed and reallocated if necessary.
+ *
+ * @param _iGridColCount Number of columns in the volume grid.
+ * @param _iGridRowCount Number of rows in the volume grid.
+ * @return initialization successful
+ */
+ bool initialize(int _iGridColCount, int _iGridRowCount);
+
+ /** Initialization. Initializes an instance of the CVolumeGeometry2D class.
+ *
+ * If the object has been initialized before, the object is reinitialized and
+ * memory is freed and reallocated if necessary.
+ *
+ * @param _iGridColCount Number of columns in the volume grid.
+ * @param _iGridRowCount Number of rows in the volume grid.
+ * @param _fWindowMinX Minimal X-coordinate in the volume window.
+ * @param _fWindowMinY Minimal Y-coordinate in the volume window.
+ * @param _fWindowMaxX Maximal X-coordinate in the volume window.
+ * @param _fWindowMaxY Maximal Y-coordinate in the volume window.
+ * @return initialization successful
+ */
+ bool initialize(int _iGridColCount,
+ int _iGridRowCount,
+ float32 _fWindowMinX,
+ float32 _fWindowMinY,
+ float32 _fWindowMaxX,
+ float32 _fWindowMaxY);
+
+ /** Get the initialization state of the object.
+ *
+ * @return true iff the object has been initialized.
+ */
+ bool isInitialized() const;
+
+ /** Return true if this geometry instance is the same as the one specified.
+ *
+ * @return true if this geometry instance is the same as the one specified.
+ */
+ virtual bool isEqual(CVolumeGeometry2D*) const;
+
+ /** Get the number of columns in the volume grid.
+ *
+ * @return Number of columns in the volume grid.
+ */
+ int getGridColCount() const;
+
+ /** Get the number of rows in the volume grid.
+ *
+ * @return Number of rows in the volume grid.
+ */
+ int getGridRowCount() const;
+
+ /** Get the total number of pixels in the volume grid.
+ *
+ * @return Total number of pixels.
+ */
+ int getGridTotCount() const;
+
+ /** Get the horizontal length of the volume window, in unit lengths.
+ *
+ * @return Horizontal length of the volume window.
+ */
+ float32 getWindowLengthX() const;
+
+ /** Get the vertical length of the volume window, in unit lengths.
+ *
+ * @return Vertical length of the volume window.
+ */
+ float32 getWindowLengthY() const;
+
+ /** Get the total area of the volume window, in unit lengths squared.
+ *
+ * @return Total area of the volume window.
+ */
+ float32 getWindowArea() const;
+
+ /** Get the horizontal length of a single pixel (i.e., width), in unit lengths.
+ *
+ * @return Horizontal length of a single pixel.
+ */
+ float32 getPixelLengthX() const;
+
+ /** Get the vertical length of a single pixel (i.e., height), in unit lengths.
+ *
+ * @return Vertical length of a single pixel.
+ */
+ float32 getPixelLengthY() const;
+
+ /** Get the area of a single pixel (width*height), in unit lengths squared.
+ *
+ * @return Area of a single pixel.
+ */
+ float32 getPixelArea() const;
+
+ /** Get the minimal X-coordinate in the volume window.
+ *
+ * @return Minimal X-coordinate in the volume window.
+ */
+ float32 getWindowMinX() const;
+
+ /** Get the minimal Y-coordinate in the volume window.
+ *
+ * @return Minimal Y-coordinate in the volume window.
+ */
+ float32 getWindowMinY() const;
+
+ /** Get the maximal X-coordinate in the volume window.
+ *
+ * @return Maximal X-coordinate in the volume window.
+ */
+ float32 getWindowMaxX() const;
+
+ /** Get the maximal Y-coordinate in the volume window.
+ *
+ * @return Maximal Y-coordinate in the volume window.
+ */
+ float32 getWindowMaxY() const;
+
+ /** Convert column and row index of a pixel to a single index in the interval [0..getGridTotCount()-1].
+ *
+ * @param _iPixelCol Column index of the pixel, in the interval [0..getGridColCount()-1].
+ * @param _iPixelRow Row index of the pixel, in the interval [0..getGridRowCount()-1].
+ * @return Computed index of the pixel, in the interval [0..getGridTotCount()-1].
+ */
+ int pixelRowColToIndex(int _iPixelRow, int _iPixelCol) const;
+
+ /** Convert a pixel index (from the interval [0..getGridTotCount()-1] to a column and row index.
+ *
+ * @param _iPixelIndex Index of the pixel, in the interval [0..getGridTotCount()-1].
+ * @param _iPixelRow Computed row index of the pixel, in the interval [0..getGridRowCount()-1].
+ * @param _iPixelCol Computed column index of the pixel, in the interval [0..getGridColCount()-1].
+ */
+ void pixelIndexToRowCol(int _iPixelIndex, int &_iPixelRow, int &_iPixelCol) const;
+
+ /** Convert a pixel column index to the X-coordinate of its center.
+ *
+ * @param _iPixelCol Column index of the pixel.
+ * @return X-coordinate of the pixel center.
+ */
+ float32 pixelColToCenterX(int _iPixelCol) const;
+
+ /** Convert a pixel column index to the minimum X-coordinate of points in that column.
+ *
+ * @param _iPixelCol Column index of the pixel.
+ * @return Minimum X-coordinate.
+ */
+ float32 pixelColToMinX(int _iPixelCol) const;
+
+ /** Convert a pixel column index to the maximum X-coordinate of points in that column.
+ *
+ * @param _iPixelCol Column index of the pixel.
+ * @return Maximum X-coordinate.
+ */
+ float32 pixelColToMaxX(int _iPixelCol) const;
+
+ /** Convert a pixel row index to the Y-coordinate of its center.
+ *
+ * @param _iPixelRow Row index of the pixel.
+ * @return Y-coordinate of the pixel center.
+ */
+ float32 pixelRowToCenterY(int _iPixelRow) const;
+
+ /** Convert a pixel row index to the minimum Y-coordinate of points in that row.
+ *
+ * @param _iPixelRow Row index of the pixel.
+ * @return Minimum Y-coordinate.
+ */
+ float32 pixelRowToMinY(int _iPixelRow) const;
+
+ /** Convert a pixel row index to the maximum Y-coordinate of points in that row.
+ *
+ * @param _iPixelRow Row index of the pixel.
+ * @return Maximum Y-coordinate.
+ */
+ float32 pixelRowToMaxY(int _iPixelRow) const;
+
+ /** Convert an X-coordinate to a column index in the volume grid.
+ *
+ * @param _fCoordX X-coordinate.
+ * @return If the X-coordinate falls within a column of the volume grid, the column index is returned.
+ * Otherwise, a value of -1 is returned.
+ */
+ int coordXToCol(float32 _fCoordX) const;
+
+ /** Convert a Y-coordinate to a row index in the volume grid.
+ *
+ * @param _fCoordY Y-coordinate
+ * @return If the Y-coordinate falls within a row of the volume grid, the row index is returned.
+ * Otherwise, a value of -1 is returned.
+ */
+ int coordYToRow(float32 _fCoordY) const;
+
+ /** Convert an X-coordinate to an offset in the volume grid.
+ * WindowMinX is converted to 0.
+ *
+ * @param _fCoordX X-coordinate.
+ * @return The corresponding offset in the volume grid
+ */
+ float coordXToColF(float32 _fCoordX) const;
+
+ /** Convert a Y-coordinate to an offset in the volume grid.
+ * WindowMaxY is converted to 0.
+ *
+ * @param _fCoordY Y-coordinate
+ * @return The corresponding offset in the volume grid
+ */
+ float coordYToRowF(float32 _fCoordY) const;
+
+
+ //< For Config unused argument checking
+ ConfigCheckData* configCheckData;
+ friend class ConfigStackCheck<CVolumeGeometry2D>;
+};
+
+
+
+// Get the initialization state of the object.
+inline bool CVolumeGeometry2D::isInitialized() const
+{
+ return m_bInitialized;
+}
+
+// Get the number of columns in the volume grid.
+inline int CVolumeGeometry2D::getGridColCount() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_iGridColCount;
+}
+
+// Get the number of rows in the volume grid.
+inline int CVolumeGeometry2D::getGridRowCount() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_iGridRowCount;
+}
+
+// Get the total number of pixels in the volume window.
+inline int CVolumeGeometry2D::getGridTotCount() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_iGridTotCount;
+}
+
+// Get the horizontal length of the volume window, in unit lengths.
+inline float32 CVolumeGeometry2D::getWindowLengthX() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_fWindowLengthX;
+}
+
+// Get the vertical length of the volume window, in unit lengths.
+inline float32 CVolumeGeometry2D::getWindowLengthY() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_fWindowLengthY;
+}
+
+// Get the total area of the volume window, in unit lengths squared.
+inline float32 CVolumeGeometry2D::getWindowArea() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_fWindowArea;
+}
+
+// Get the horizontal length of a single pixel (i.e., width), in unit lengths.
+inline float32 CVolumeGeometry2D::getPixelLengthX() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_fPixelLengthX;
+}
+
+// Get the vertical length of a single pixel (i.e., height), in unit lengths.
+inline float32 CVolumeGeometry2D::getPixelLengthY() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_fPixelLengthY;
+}
+
+// Get the area of a single pixel (width*height), in unit lengths squared.
+inline float32 CVolumeGeometry2D::getPixelArea() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_fPixelArea;
+}
+
+ // Get the minimal X-coordinate in the volume window.
+inline float32 CVolumeGeometry2D::getWindowMinX() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_fWindowMinX;
+}
+
+ // Get the minimal Y-coordinate in the volume window.
+inline float32 CVolumeGeometry2D::getWindowMinY() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_fWindowMinY;
+}
+
+ // Get the maximal X-coordinate in the volume window.
+inline float32 CVolumeGeometry2D::getWindowMaxX() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_fWindowMaxX;
+}
+
+ // Get the maximal Y-coordinate in the volume window.
+inline float32 CVolumeGeometry2D::getWindowMaxY() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_fWindowMaxY;
+}
+
+// Convert column and row index of a pixel to a single index in the interval [0..getGridCountTot()-1].
+inline int CVolumeGeometry2D::pixelRowColToIndex(int _iPixelRow, int _iPixelCol) const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ ASTRA_ASSERT(_iPixelCol >= 0);
+ ASTRA_ASSERT(_iPixelCol < m_iGridColCount);
+ ASTRA_ASSERT(_iPixelRow >= 0);
+ ASTRA_ASSERT(_iPixelRow < m_iGridRowCount);
+ return (_iPixelRow * m_iGridColCount + _iPixelCol);
+}
+
+
+// Convert a pixel index (from the interval [0..getGridCountTot()-1] to a column and row index.
+inline void CVolumeGeometry2D::pixelIndexToRowCol(int _iPixelIndex, int &_iPixelRow, int &_iPixelCol) const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ ASTRA_ASSERT(_iPixelIndex >= 0);
+ ASTRA_ASSERT(_iPixelIndex < m_iGridTotCount);
+
+ _iPixelCol = (_iPixelIndex % m_iGridColCount);
+ _iPixelRow = (_iPixelIndex / m_iGridColCount);
+}
+
+// Convert a pixel column index to the X-coordinate of its center
+inline float32 CVolumeGeometry2D::pixelColToCenterX(int _iPixelCol) const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ ASTRA_ASSERT(_iPixelCol >= 0);
+ ASTRA_ASSERT(_iPixelCol < m_iGridColCount);
+
+ return (m_fWindowMinX + (float32(_iPixelCol) + 0.5f) * m_fPixelLengthX);
+}
+
+// Convert a pixel column index to the minimum X-coordinate of points in that column
+inline float32 CVolumeGeometry2D::pixelColToMinX(int _iPixelCol) const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ ASTRA_ASSERT(_iPixelCol >= 0);
+ ASTRA_ASSERT(_iPixelCol < m_iGridColCount);
+
+ return (m_fWindowMinX + float32(_iPixelCol) * m_fPixelLengthX);
+}
+
+// Convert a pixel column index to the maximum X-coordinate of points in that column
+inline float32 CVolumeGeometry2D::pixelColToMaxX(int _iPixelCol) const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ ASTRA_ASSERT(_iPixelCol >= 0);
+ ASTRA_ASSERT(_iPixelCol < m_iGridColCount);
+
+ return (m_fWindowMinX + (float32(_iPixelCol) + 1.0f) * m_fPixelLengthX);
+}
+
+// Convert a pixel row index to the Y-coordinate of its center
+inline float32 CVolumeGeometry2D::pixelRowToCenterY(int _iPixelRow) const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ ASTRA_ASSERT(_iPixelRow >= 0);
+ ASTRA_ASSERT(_iPixelRow < m_iGridRowCount);
+
+ return (m_fWindowMaxY - (float32(_iPixelRow) + 0.5f) * m_fPixelLengthY);
+}
+
+// Convert a pixel row index to the minimum Y-coordinate of points in that row
+inline float32 CVolumeGeometry2D::pixelRowToMinY(int _iPixelRow) const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ ASTRA_ASSERT(_iPixelRow >= 0);
+ ASTRA_ASSERT(_iPixelRow < m_iGridRowCount);
+
+ return (m_fWindowMaxY - (float32(_iPixelRow) + 1.0f) * m_fPixelLengthY);
+}
+
+// Convert a pixel row index to the maximum Y-coordinate of points in that row
+inline float32 CVolumeGeometry2D::pixelRowToMaxY(int _iPixelRow) const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ ASTRA_ASSERT(_iPixelRow >= 0);
+ ASTRA_ASSERT(_iPixelRow < m_iGridRowCount);
+
+ return (m_fWindowMaxY - (float32(_iPixelRow) * m_fPixelLengthY));
+}
+
+// Convert an X-coordinate to a column index in the volume grid
+inline int CVolumeGeometry2D::coordXToCol(float32 _fCoordX) const
+{
+ if (_fCoordX < m_fWindowMinX) return -1;
+ if (_fCoordX > m_fWindowMaxX) return -1;
+
+ int iCol = int((_fCoordX - m_fWindowMinX) * m_fDivPixelLengthX);
+ ASTRA_ASSERT(iCol >= 0);
+ ASTRA_ASSERT(iCol < m_iGridColCount);
+
+ return iCol;
+}
+
+// Convert a Y-coordinate to a row index in the volume grid
+inline int CVolumeGeometry2D::coordYToRow(float32 _fCoordY) const
+{
+ if (_fCoordY < m_fWindowMinY) return -1;
+ if (_fCoordY > m_fWindowMaxY) return -1;
+
+ int iRow = int((m_fWindowMaxY - _fCoordY) * m_fDivPixelLengthY);
+ ASTRA_ASSERT(iRow >= 0);
+ ASTRA_ASSERT(iRow < m_iGridRowCount);
+
+ return iRow;
+}
+
+// Convert an X-coordinate to an offset in the volume grid
+// (WindowMinX is converted to 0)
+inline float CVolumeGeometry2D::coordXToColF(float32 _fCoordX) const
+{
+ return (_fCoordX - m_fWindowMinX) * m_fDivPixelLengthX;
+}
+
+// Convert a Y-coordinate to an offset in the volume grid
+// (WindowMaxY is converted to 0)
+inline float CVolumeGeometry2D::coordYToRowF(float32 _fCoordY) const
+{
+ return (m_fWindowMaxY - _fCoordY) * m_fDivPixelLengthY;
+}
+
+
+
+} // end namespace astra
+
+#endif /* _INC_ASTRA_VOLUMEGEOMETRY2D */
diff --git a/include/astra/VolumeGeometry3D.h b/include/astra/VolumeGeometry3D.h
new file mode 100644
index 0000000..4ca8042
--- /dev/null
+++ b/include/astra/VolumeGeometry3D.h
@@ -0,0 +1,842 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_VOLUMEGEOMETRY3D
+#define _INC_ASTRA_VOLUMEGEOMETRY3D
+
+#include "Globals.h"
+#include "Config.h"
+#include "VolumeGeometry2D.h"
+
+namespace astra
+{
+
+/**
+ * This class represents a 3D pixel grid that is placed in the geometry. It defines a rectangular volume window.
+ *
+ * \par XML Configuration
+ * \astra_xml_item{GridColCount, integer, Number of columns in this geometry.}
+ * \astra_xml_item{GridRowCount, integer, Number of rows in this geometry.}
+ * \astra_xml_item{GridSliceCount, integer, Number of slices in this geometry.}
+ * \astra_xml_item_option{WindowMinX, float, -GridColCount/2, Minimal X-coordinate in the volume window.}
+ * \astra_xml_item_option{WindowMaxX, float, GridColCount/2, Maximal X-coordinate in the volume window.}
+ * \astra_xml_item_option{WindowMinY, float, -GridRowCount/2, Minimal Y-coordinate in the volume window.}
+ * \astra_xml_item_option{WindowMaxY, float, GridRowCount/2, Maximal Y-coordinate in the volume window.}
+ * \astra_xml_item_option{WindowMinZ, float, -GridSliceCount/2, Minimal Z-coordinate in the volume window.}
+ * \astra_xml_item_option{WindowMaxZ, float, GridSliceCount/2, Maximal Z-coordinate in the volume window.}
+ *
+ * \par MATLAB example
+ * \astra_code{
+ * vol_geom = struct();\n
+ * vol_geom.GridColCount = 1024;\n
+ * vol_geom.GridRowCount = 768;\n
+ * vol_geom.GridSliceCount = 300;\n
+ * vol_geom.option.WindowMinX = -512;\n
+ * vol_geom.option.WindowMaxX = -384;\n
+ * vol_geom.option.WindowMinY = 512;\n
+ * vol_geom.option.WindowMaxY = 384;\n
+ * vol_geom.option.WindowMinZ = -150;\n
+ * vol_geom.option.WindowMaxZ = 150;\n
+ * }
+ */
+class _AstraExport CVolumeGeometry3D {
+
+protected:
+ bool m_bInitialized; ///< Has this object been initialized?
+
+ int m_iGridColCount; ///< number of columns in the volume grid.
+ int m_iGridRowCount; ///< number of rows in the volume grid.
+ int m_iGridSliceCount; ///< number of slices in the volume grid.
+ int m_iGridTotCount; ///< total number of pixels in the volume grid (= m_iGridColCount * m_iGridRowCount * m_iGridSliceCount).
+
+ /** Width of the volume window, in unit lengths.
+ *
+ * Note that this width is independent of the number of pixels in the X-direction, as the width of a pixel can
+ * be different from 1.
+ */
+ float32 m_fWindowLengthX;
+
+ /** Height of the volume window, in unit lengths.
+ *
+ * Note that this height is independent of the number of pixels in the Y-direction, as the height of a pixel can
+ * be different from 1.
+ */
+ float32 m_fWindowLengthY;
+
+ /** Depth of the volume window, in unit lengths.
+ *
+ * Note that this depth is independent of the number of pixels in the Z-direction, as the depth of a pixel can
+ * be different from 1.
+ */
+ float32 m_fWindowLengthZ;
+
+ /** Total area of the volume window, in unit lengths squared.
+ */
+ float32 m_fWindowArea;
+
+ float32 m_fPixelLengthX; ///< Width of a single pixel, in unit lengths.
+ float32 m_fPixelLengthY; ///< Height of a single pixel, in unit lengths.
+ float32 m_fPixelLengthZ; ///< Depth of a single pixel, in unit lengths.
+ float32 m_fPixelArea; ///< Area of a single pixel, in unit lengths squared.
+
+ float32 m_fDivPixelLengthX; ///< 1/m_fPixelLengthX, used for fast division.
+ float32 m_fDivPixelLengthY; ///< 1/m_fPixelLengthY, used for fast division.
+ float32 m_fDivPixelLengthZ; ///< 1/m_fPixelLengthZ, used for fast division.
+
+ float32 m_fWindowMinX; ///< Minimal X-coordinate in the volume window.
+ float32 m_fWindowMinY; ///< Minimal Y-coordinate in the volume window.
+ float32 m_fWindowMinZ; ///< Minimal Z-coordinate in the volume window.
+ float32 m_fWindowMaxX; ///< Maximal X-coordinate in the volume window.
+ float32 m_fWindowMaxY; ///< Maximal Y-coordinate in the volume window.
+ float32 m_fWindowMaxZ; ///< Maximal Z-coordinate in the volume window.
+
+ /** Check the values of this object. If everything is ok, the object can be set to the initialized state.
+ * The following statements are then guaranteed to hold:
+ * - number of rows, columns and slices is larger than zero
+ * - window minima is smaller than window maxima
+ * - m_iGridTotCount, m_fWindowLengthX, m_fWindowLengthY, m_fWindowLengthZ, m_fWindowArea, m_fPixelLengthX,
+ * m_fPixelLengthY, m_fPixelLengthZ, m_fPixelArea, m_fDivPixelLengthX, m_fDivPixelLengthY
+ * and m_fDivPixelLengthZ are initialized ok
+ */
+ bool _check();
+
+public:
+
+ /** Default constructor. Sets all numeric member variables to 0 and all pointer member variables to NULL.
+ *
+ * If an object is constructed using this default constructor, it must always be followed by a call
+ * to one of the init() methods before the object can be used. Any use before calling init() is not allowed,
+ * except calling the member function isInitialized().
+ */
+ CVolumeGeometry3D();
+
+ /** Constructor. Create an instance of the CVolumeGeometry2D class.
+ * The minimal and coordinates values of the geometry will be set to -/+ the number of rows/columns.
+ *
+ * @param _iGridCountX Number of columns in the volume grid.
+ * @param _iGridCountY Number of rows in the volume grid.
+ * @param _iGridCountZ Number of slices in the volume grid.
+ */
+ CVolumeGeometry3D(int _iGridCountX, int _iGridCountY, int _iGridCountZ);
+
+ /** Constructor. Create an instance of the CVolumeGeometry2D class.
+ *
+ * @param _iGridCountX Number of columns in the volume grid.
+ * @param _iGridCountY Number of rows in the volume grid.
+ * @param _iGridCountZ Number of slices in the volume grid.
+ * @param _fWindowMinX Minimal X-coordinate in the volume window.
+ * @param _fWindowMinY Minimal Y-coordinate in the volume window.
+ * @param _fWindowMinZ Minimal Z-coordinate in the volume window.
+ * @param _fWindowMaxX Maximal X-coordinate in the volume window.
+ * @param _fWindowMaxY Maximal Y-coordinate in the volume window.
+ * @param _fWindowMaxZ Maximal Z-coordinate in the volume window.
+ */
+ CVolumeGeometry3D(int _iGridCountX,
+ int _iGridCountY,
+ int _iGridCountZ,
+ float32 _fWindowMinX,
+ float32 _fWindowMinY,
+ float32 _fWindowMinZ,
+ float32 _fWindowMaxX,
+ float32 _fWindowMaxY,
+ float32 _fWindowMaxZ);
+
+ /**
+ * Copy constructor
+ */
+ CVolumeGeometry3D(const CVolumeGeometry3D& _other);
+
+ /**
+ * Assignment operator
+ */
+ CVolumeGeometry3D& operator=(const CVolumeGeometry3D& _other);
+
+ /** Destructor.
+ */
+ virtual ~CVolumeGeometry3D();
+
+ /** Clear all member variables, setting all numeric variables to 0 and all pointers to NULL.
+ */
+ void clear();
+
+ /** Create a hard copy.
+ */
+ CVolumeGeometry3D* clone() const;
+
+ /** Initialize the volume geometry with a config object.
+ *
+ * @param _cfg Configuration Object.
+ * @return initialization successful?
+ */
+ virtual bool initialize(const Config& _cfg);
+
+ /** Initialization. Initializes an instance of the CVolumeGeometry3D class.
+ * The minimal and maximal coordinates of the geometry will be set to -/+ half the number of rows/columns/slices.
+ *
+ * If the object has been initialized before, the object is reinitialized and
+ * memory is freed and reallocated if necessary.
+ *
+ * @param _iGridColCount Number of columns in the volume grid.
+ * @param _iGridRowCount Number of rows in the volume grid.
+ * @param _iGridSliceCount Number of slices in the volume grid.
+ * @return initialization successful
+ */
+ bool initialize(int _iGridColCount, int _iGridRowCount, int _iGridSliceCount);
+
+ /** Initialization. Initializes an instance of the CVolumeGeometry3D class.
+ *
+ * If the object has been initialized before, the object is reinitialized and
+ * memory is freed and reallocated if necessary.
+ *
+ * @param _iGridColCount Number of columns in the volume grid.
+ * @param _iGridRowCount Number of rows in the volume grid.
+ * @param _iGridSliceCount Number of slices in the volume grid.
+ * @param _fWindowMinX Minimal X-coordinate in the volume window.
+ * @param _fWindowMinY Minimal Y-coordinate in the volume window.
+ * @param _fWindowMinZ Minimal Z-coordinate in the volume window.
+ * @param _fWindowMaxX Maximal X-coordinate in the volume window.
+ * @param _fWindowMaxY Maximal Y-coordinate in the volume window.
+ * @param _fWindowMaxZ Maximal Z-coordinate in the volume window.
+ * @return initialization successful
+ */
+ bool initialize(int _iGridColCount,
+ int _iGridRowCount,
+ int _iGridSliceCount,
+ float32 _fWindowMinX,
+ float32 _fWindowMinY,
+ float32 _fWindowMinZ,
+ float32 _fWindowMaxX,
+ float32 _fWindowMaxY,
+ float32 _fWindowMaxZ);
+
+ /** Get the initialization state of the object.
+ *
+ * @return true iff the object has been initialized.
+ */
+ bool isInitialized() const;
+
+ /** Return true if this geometry instance is the same as the one specified.
+ *
+ * @return true if this geometry instance is the same as the one specified.
+ */
+ virtual bool isEqual(const CVolumeGeometry3D*) const;
+
+ /** Get the number of columns in the volume grid.
+ *
+ * @return Number of columns in the volume grid.
+ */
+ int getGridColCount() const;
+
+ /** Get the number of rows in the volume grid.
+ *
+ * @return Number of rows in the volume grid.
+ */
+ int getGridRowCount() const;
+
+ /** Get the number of slices in the volume grid.
+ *
+ * @return Number of slices in the volume grid.
+ */
+ int getGridSliceCount() const;
+
+ /** Get the total number of pixels in the volume grid.
+ *
+ * @return Total number of pixels.
+ */
+ int getGridTotCount() const;
+
+ /** Get the horizontal length of the volume window, in unit lengths.
+ *
+ * @return Horizontal length of the volume window.
+ */
+ float32 getWindowLengthX() const;
+
+ /** Get the vertical length of the volume window, in unit lengths.
+ *
+ * @return Vertical length of the volume window.
+ */
+ float32 getWindowLengthY() const;
+
+ /** Get the depth of the volume window, in unit lengths.
+ *
+ * @return Depth of the volume window.
+ */
+ float32 getWindowLengthZ() const;
+
+ /** Get the total area of the volume window, in unit lengths squared.
+ *
+ * @return Total area of the volume window.
+ */
+ float32 getWindowArea() const;
+
+ /** Get the horizontal length of a single pixel (i.e., width), in unit lengths.
+ *
+ * @return Horizontal length of a single pixel.
+ */
+ float32 getPixelLengthX() const;
+
+ /** Get the vertical length of a single pixel (i.e., height), in unit lengths.
+ *
+ * @return Vertical length of a single pixel.
+ */
+ float32 getPixelLengthY() const;
+
+ /** Get the depth of a single pixel in unit lengths.
+ *
+ * @return Depth of a single pixel.
+ */
+ float32 getPixelLengthZ() const;
+
+ /** Get the area of a single pixel (width*height*depth), in unit lengths squared.
+ *
+ * @return Area of a single pixel.
+ */
+ float32 getPixelArea() const;
+
+ /** Get the minimal X-coordinate in the volume window.
+ *
+ * @return Minimal X-coordinate in the volume window.
+ */
+ float32 getWindowMinX() const;
+
+ /** Get the minimal Y-coordinate in the volume window.
+ *
+ * @return Minimal Y-coordinate in the volume window.
+ */
+ float32 getWindowMinY() const;
+
+ /** Get the minimal Z-coordinate in the volume window.
+ *
+ * @return Minimal Z-coordinate in the volume window.
+ */
+ float32 getWindowMinZ() const;
+
+ /** Get the maximal X-coordinate in the volume window.
+ *
+ * @return Maximal X-coordinate in the volume window.
+ */
+ float32 getWindowMaxX() const;
+
+ /** Get the maximal Y-coordinate in the volume window.
+ *
+ * @return Maximal Y-coordinate in the volume window.
+ */
+ float32 getWindowMaxY() const;
+
+ /** Get the maximal Z-coordinate in the volume window.
+ *
+ * @return Maximal Z-coordinate in the volume window.
+ */
+ float32 getWindowMaxZ() const;
+
+ /** Convert row, column and slice index of a pixel to a single index in the interval [0..getGridTotCount()-1].
+ *
+ * @param _iPixelRow Row index of the pixel, in the interval [0..getGridRowCount()-1].
+ * @param _iPixelCol Column index of the pixel, in the interval [0..getGridColCount()-1].
+ * @param _iPixelSlice Slice index of the pixel, in the interval [0..getGridSliceCount()-1].
+ * @return Computed index of the pixel, in the interval [0..getGridTotCount()-1].
+ */
+ int pixelRowColSliceToIndex(int _iPixelRow, int _iPixelCol, int _iPixelSlice) const;
+
+ /** Convert a pixel index (from the interval [0..getGridTotCount()-1] to row, column and slice index.
+ *
+ * @param _iPixelIndex Index of the pixel, in the interval [0..getGridTotCount()-1].
+ * @param _iPixelRow Computed row index of the pixel, in the interval [0..getGridRowCount()-1].
+ * @param _iPixelCol Computed column index of the pixel, in the interval [0..getGridColCount()-1].
+ * @param _iPixelSlice Computed slice index of the pixel, in the interval [0..getGridSliceCount()-1].
+ */
+ void pixelIndexToRowColSlice(int _iPixelIndex, int &_iPixelRow, int &_iPixelCol, int &_iPixelSlice) const;
+
+ /** Convert a pixel column index to the X-coordinate of its center.
+ *
+ * @param _iPixelCol Column index of the pixel.
+ * @return X-coordinate of the pixel center.
+ */
+ float32 pixelColToCenterX(int _iPixelCol) const;
+
+ /** Convert a pixel column index to the minimum X-coordinate of points in that column.
+ *
+ * @param _iPixelCol Column index of the pixel.
+ * @return Minimum X-coordinate.
+ */
+ float32 pixelColToMinX(int _iPixelCol) const;
+
+ /** Convert a pixel column index to the maximum X-coordinate of points in that column.
+ *
+ * @param _iPixelCol Column index of the pixel.
+ * @return Maximum X-coordinate.
+ */
+ float32 pixelColToMaxX(int _iPixelCol) const;
+
+ /** Convert a pixel row index to the Y-coordinate of its center.
+ *
+ * @param _iPixelRow Row index of the pixel.
+ * @return Y-coordinate of the pixel center.
+ */
+ float32 pixelRowToCenterY(int _iPixelRow) const;
+
+ /** Convert a pixel row index to the minimum Y-coordinate of points in that row.
+ *
+ * @param _iPixelRow Row index of the pixel.
+ * @return Minimum Y-coordinate.
+ */
+ float32 pixelRowToMinY(int _iPixelRow) const;
+
+ /** Convert a pixel row index to the maximum Y-coordinate of points in that row.
+ *
+ * @param _iPixelRow Row index of the pixel.
+ * @return Maximum Y-coordinate.
+ */
+ float32 pixelRowToMaxY(int _iPixelRow) const;
+
+ /** Convert a pixel slice index to the Z-coordinate of its center.
+ *
+ * @param _iPixelSlice Slice index of the pixel.
+ * @return Z-coordinate of the pixel center.
+ */
+ float32 pixelSliceToCenterZ(int _iPixelSlice) const;
+
+ /** Convert a pixel slice index to the minimum Z-coordinate of points in that slice.
+ *
+ * @param _iPixelSlice Slice index of the pixel.
+ * @return Minimum Z-coordinate.
+ */
+ float32 pixelSliceToMinZ(int _iPixelSlice) const;
+
+ /** Convert a pixel slice index to the maximum Z-coordinate of points in that slice.
+ *
+ * @param _iPixelSlice Slice index of the pixel.
+ * @return Maximum Z-coordinate.
+ */
+ float32 pixelSliceToMaxZ(int _iPixelSlice) const;
+
+ /** Convert an X-coordinate to a column index in the volume grid.
+ *
+ * @param _fCoordX X-coordinate.
+ * @return If the X-coordinate falls within a column of the volume grid, the column index is returned.
+ * Otherwise, a value of -1 is returned.
+ */
+ int coordXToCol(float32 _fCoordX) const;
+
+ /** Convert a Y-coordinate to a row index in the volume grid.
+ *
+ * @param _fCoordY Y-coordinate
+ * @return If the Y-coordinate falls within a row of the volume grid, the row index is returned.
+ * Otherwise, a value of -1 is returned.
+ */
+ int coordYToRow(float32 _fCoordY) const;
+
+ /** Convert a Z-coordinate to a slice index in the volume grid.
+ *
+ * @param _fCoordZ Z-coordinate
+ * @return If the Z-coordinate falls within a slice of the volume grid, the slice index is returned.
+ * Otherwise, a value of -1 is returned.
+ */
+ int coordZToSlice(float32 _fCoordZ) const;
+
+ /** Convert an X-coordinate to a column index in the volume grid.
+ *
+ * @param _fCoordX X-coordinate.
+ * @return If the X-coordinate falls within a column of the volume grid, the column index is returned.
+ * Otherwise, a value of -1 is returned.
+ */
+ float32 coordXToColFloat(float32 _fCoordX) const;
+
+ /** Convert a Y-coordinate to a row index in the volume grid.
+ *
+ * @param _fCoordY Y-coordinate
+ * @return If the Y-coordinate falls within a row of the volume grid, the row index is returned.
+ * Otherwise, a value of -1 is returned.
+ */
+ float32 coordYToRowFloat(float32 _fCoordY) const;
+
+ /** Convert a Z-coordinate to a slice index in the volume grid.
+ *
+ * @param _fCoordZ Z-coordinate
+ * @return If the Z-coordinate falls within a slice of the volume grid, the slice index is returned.
+ * Otherwise, a value of -1 is returned.
+ */
+ float32 coordZToSliceFloat(float32 _fCoordZ) const;
+
+ CVolumeGeometry2D * createVolumeGeometry2D() const;
+
+
+ //< For Config unused argument checking
+ ConfigCheckData* configCheckData;
+ friend class ConfigStackCheck<CVolumeGeometry3D>;
+};
+
+
+//----------------------------------------------------------------------------------------
+// Get the initialization state of the object.
+inline bool CVolumeGeometry3D::isInitialized() const
+{
+ return m_bInitialized;
+}
+
+//----------------------------------------------------------------------------------------
+// Get the number of columns in the volume grid.
+inline int CVolumeGeometry3D::getGridColCount() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_iGridColCount;
+}
+
+//----------------------------------------------------------------------------------------
+// Get the number of rows in the volume grid.
+inline int CVolumeGeometry3D::getGridRowCount() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_iGridRowCount;
+}
+
+//----------------------------------------------------------------------------------------
+// Get the number of rows in the volume grid.
+inline int CVolumeGeometry3D::getGridSliceCount() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_iGridSliceCount;
+}
+
+//----------------------------------------------------------------------------------------
+// Get the total number of pixels in the volume window.
+inline int CVolumeGeometry3D::getGridTotCount() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_iGridTotCount;
+}
+
+//----------------------------------------------------------------------------------------
+// Get the horizontal length of the volume window, in unit lengths.
+inline float32 CVolumeGeometry3D::getWindowLengthX() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_fWindowLengthX;
+}
+
+//----------------------------------------------------------------------------------------
+// Get the vertical length of the volume window, in unit lengths.
+inline float32 CVolumeGeometry3D::getWindowLengthY() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_fWindowLengthY;
+}
+
+//----------------------------------------------------------------------------------------
+// Get the vertical length of the volume window, in unit lengths.
+inline float32 CVolumeGeometry3D::getWindowLengthZ() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_fWindowLengthZ;
+}
+
+//----------------------------------------------------------------------------------------
+// Get the total area of the volume window, in unit lengths squared.
+inline float32 CVolumeGeometry3D::getWindowArea() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_fWindowArea;
+}
+
+//----------------------------------------------------------------------------------------
+// Get the horizontal length of a single pixel (i.e., width), in unit lengths.
+inline float32 CVolumeGeometry3D::getPixelLengthX() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_fPixelLengthX;
+}
+
+//----------------------------------------------------------------------------------------
+// Get the vertical length of a single pixel (i.e., height), in unit lengths.
+inline float32 CVolumeGeometry3D::getPixelLengthY() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_fPixelLengthY;
+}
+
+//----------------------------------------------------------------------------------------
+// Get the depth of a single pixel in unit lengths.
+inline float32 CVolumeGeometry3D::getPixelLengthZ() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_fPixelLengthZ;
+}
+
+//----------------------------------------------------------------------------------------
+// Get the area of a single pixel (width*height), in unit lengths squared.
+inline float32 CVolumeGeometry3D::getPixelArea() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_fPixelArea;
+}
+
+//----------------------------------------------------------------------------------------
+// Get the minimal X-coordinate in the volume window.
+inline float32 CVolumeGeometry3D::getWindowMinX() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_fWindowMinX;
+}
+
+//----------------------------------------------------------------------------------------
+// Get the minimal Y-coordinate in the volume window.
+inline float32 CVolumeGeometry3D::getWindowMinY() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_fWindowMinY;
+}
+
+//----------------------------------------------------------------------------------------
+// Get the minimal Y-coordinate in the volume window.
+inline float32 CVolumeGeometry3D::getWindowMinZ() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_fWindowMinZ;
+}
+
+//----------------------------------------------------------------------------------------
+// Get the maximal X-coordinate in the volume window.
+inline float32 CVolumeGeometry3D::getWindowMaxX() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_fWindowMaxX;
+}
+
+//----------------------------------------------------------------------------------------
+// Get the maximal Y-coordinate in the volume window.
+inline float32 CVolumeGeometry3D::getWindowMaxY() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_fWindowMaxY;
+}
+
+//----------------------------------------------------------------------------------------
+// Get the maximal Z-coordinate in the volume window.
+inline float32 CVolumeGeometry3D::getWindowMaxZ() const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return m_fWindowMaxZ;
+}
+
+//----------------------------------------------------------------------------------------
+// Convert row, column and slice index of a pixel to a single index in the interval [0..getGridCountTot()-1].
+inline int CVolumeGeometry3D::pixelRowColSliceToIndex(int _iPixelRow, int _iPixelCol, int _iPixelSlice) const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ ASTRA_ASSERT(_iPixelCol >= 0);
+ ASTRA_ASSERT(_iPixelCol < m_iGridColCount);
+ ASTRA_ASSERT(_iPixelRow >= 0);
+ ASTRA_ASSERT(_iPixelRow < m_iGridRowCount);
+ ASTRA_ASSERT(_iPixelSlice >= 0);
+ ASTRA_ASSERT(_iPixelSlice < m_iGridSliceCount);
+
+ return (m_iGridColCount*m_iGridRowCount*_iPixelSlice + _iPixelRow * m_iGridColCount + _iPixelCol);
+}
+
+//----------------------------------------------------------------------------------------
+// Convert a pixel index (from the interval [0..getGridCountTot()-1] to a row, column and slice index.
+inline void CVolumeGeometry3D::pixelIndexToRowColSlice(int _iPixelIndex, int &_iPixelRow, int &_iPixelCol, int &_iPixelSlice) const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ ASTRA_ASSERT(_iPixelIndex >= 0);
+ ASTRA_ASSERT(_iPixelIndex < m_iGridTotCount);
+
+ _iPixelSlice = _iPixelIndex / (m_iGridRowCount*m_iGridColCount);
+ _iPixelRow = (_iPixelIndex-_iPixelSlice*m_iGridRowCount*m_iGridColCount) / m_iGridColCount;
+ _iPixelCol = (_iPixelIndex-_iPixelSlice*m_iGridRowCount*m_iGridColCount) % m_iGridColCount;
+}
+
+//----------------------------------------------------------------------------------------
+// Convert a pixel column index to the X-coordinate of its center
+inline float32 CVolumeGeometry3D::pixelColToCenterX(int _iPixelCol) const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ ASTRA_ASSERT(_iPixelCol >= 0);
+ ASTRA_ASSERT(_iPixelCol < m_iGridColCount);
+
+ return (m_fWindowMinX + (float32(_iPixelCol) + 0.5f) * m_fPixelLengthX);
+}
+
+//----------------------------------------------------------------------------------------
+// Convert a pixel column index to the minimum X-coordinate of points in that column
+inline float32 CVolumeGeometry3D::pixelColToMinX(int _iPixelCol) const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ ASTRA_ASSERT(_iPixelCol >= 0);
+ ASTRA_ASSERT(_iPixelCol < m_iGridColCount);
+
+ return (m_fWindowMinX + float32(_iPixelCol) * m_fPixelLengthX);
+}
+
+//----------------------------------------------------------------------------------------
+// Convert a pixel column index to the maximum X-coordinate of points in that column
+inline float32 CVolumeGeometry3D::pixelColToMaxX(int _iPixelCol) const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ ASTRA_ASSERT(_iPixelCol >= 0);
+ ASTRA_ASSERT(_iPixelCol < m_iGridColCount);
+
+ return (m_fWindowMaxX + (float32(_iPixelCol) + 1.0f) * m_fPixelLengthX);
+}
+
+//----------------------------------------------------------------------------------------
+// Convert a pixel row index to the Y-coordinate of its center
+inline float32 CVolumeGeometry3D::pixelRowToCenterY(int _iPixelRow) const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ ASTRA_ASSERT(_iPixelRow >= 0);
+ ASTRA_ASSERT(_iPixelRow < m_iGridRowCount);
+
+ return (m_fWindowMaxY - (float32(_iPixelRow) + 0.5f) * m_fPixelLengthY);
+}
+
+//----------------------------------------------------------------------------------------
+// Convert a pixel row index to the minimum Y-coordinate of points in that row
+inline float32 CVolumeGeometry3D::pixelRowToMinY(int _iPixelRow) const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ ASTRA_ASSERT(_iPixelRow >= 0);
+ ASTRA_ASSERT(_iPixelRow < m_iGridRowCount);
+
+ return (m_fWindowMaxY - (float32(_iPixelRow) + 1.0f) * m_fPixelLengthY);
+}
+
+//----------------------------------------------------------------------------------------
+// Convert a pixel row index to the maximum Y-coordinate of points in that row
+inline float32 CVolumeGeometry3D::pixelRowToMaxY(int _iPixelRow) const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ ASTRA_ASSERT(_iPixelRow >= 0);
+ ASTRA_ASSERT(_iPixelRow < m_iGridRowCount);
+
+ return (m_fWindowMaxY - (float32(_iPixelRow) * m_fPixelLengthY));
+}
+
+//----------------------------------------------------------------------------------------
+// Convert a pixel slice index to the Z-coordinate of its center
+inline float32 CVolumeGeometry3D::pixelSliceToCenterZ(int _iPixelSlice) const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ ASTRA_ASSERT(_iPixelSlice >= 0);
+ ASTRA_ASSERT(_iPixelSlice < m_iGridSliceCount);
+
+ return (m_fWindowMaxZ - (float32(_iPixelSlice) + 0.5f) * m_fPixelLengthZ);
+}
+
+//----------------------------------------------------------------------------------------
+// Convert a pixel row index to the minimum Y-coordinate of points in that row
+inline float32 CVolumeGeometry3D::pixelSliceToMinZ(int _iPixelSlice) const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ ASTRA_ASSERT(_iPixelSlice >= 0);
+ ASTRA_ASSERT(_iPixelSlice < m_iGridSliceCount);
+
+ return (m_fWindowMaxZ - (float32(_iPixelSlice) + 1.0f) * m_fPixelLengthZ);
+}
+
+//----------------------------------------------------------------------------------------
+// Convert a pixel row index to the maximum Y-coordinate of points in that row
+inline float32 CVolumeGeometry3D::pixelSliceToMaxZ(int _iPixelSlice) const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ ASTRA_ASSERT(_iPixelSlice >= 0);
+ ASTRA_ASSERT(_iPixelSlice < m_iGridSliceCount);
+
+ return (m_fWindowMaxZ - (float32(_iPixelSlice) * m_fPixelLengthZ));
+}
+
+//----------------------------------------------------------------------------------------
+// Convert an X-coordinate to a column index in the volume grid
+inline int CVolumeGeometry3D::coordXToCol(float32 _fCoordX) const
+{
+ if (_fCoordX < m_fWindowMinX) return -1;
+ if (_fCoordX > m_fWindowMaxX) return -1;
+
+ int iCol = int((_fCoordX - m_fWindowMinX) * m_fDivPixelLengthX);
+ ASTRA_ASSERT(iCol >= 0);
+ ASTRA_ASSERT(iCol < m_iGridColCount);
+
+ return iCol;
+}
+
+//----------------------------------------------------------------------------------------
+// Convert a Y-coordinate to a row index in the volume grid
+inline int CVolumeGeometry3D::coordYToRow(float32 _fCoordY) const
+{
+ if (_fCoordY < m_fWindowMinY) return -1;
+ if (_fCoordY > m_fWindowMaxY) return -1;
+
+ int iRow = int((m_fWindowMaxY - _fCoordY) * m_fDivPixelLengthY);
+ ASTRA_ASSERT(iRow >= 0);
+ ASTRA_ASSERT(iRow < m_iGridRowCount);
+
+ return iRow;
+}
+
+//----------------------------------------------------------------------------------------
+// Convert a Z-coordinate to a slice index in the volume grid
+inline int CVolumeGeometry3D::coordZToSlice(float32 _fCoordZ) const
+{
+ if (_fCoordZ < m_fWindowMinZ) return -1;
+ if (_fCoordZ > m_fWindowMaxZ) return -1;
+
+ int iSlice = int((m_fWindowMaxZ - _fCoordZ) * m_fDivPixelLengthZ);
+ ASTRA_ASSERT(iSlice >= 0);
+ ASTRA_ASSERT(iSlice < m_iGridSliceCount);
+
+ return iSlice;
+}
+
+//----------------------------------------------------------------------------------------
+// Convert an X-coordinate to a column index in the volume grid
+inline float32 CVolumeGeometry3D::coordXToColFloat(float32 _fCoordX) const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return (_fCoordX - m_fWindowMinX) * m_fDivPixelLengthX;
+}
+
+//----------------------------------------------------------------------------------------
+// Convert a Y-coordinate to a row index in the volume grid
+inline float32 CVolumeGeometry3D::coordYToRowFloat(float32 _fCoordY) const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return (m_fWindowMaxY - _fCoordY) * m_fDivPixelLengthY;
+}
+
+//----------------------------------------------------------------------------------------
+// Convert a Z-coordinate to a slice index in the volume grid
+inline float32 CVolumeGeometry3D::coordZToSliceFloat(float32 _fCoordZ) const
+{
+ ASTRA_ASSERT(m_bInitialized);
+ return (m_fWindowMaxZ - _fCoordZ) * m_fDivPixelLengthZ;
+}
+//----------------------------------------------------------------------------------------
+
+} // end namespace astra
+
+#endif /* _INC_ASTRA_VOLUMEGEOMETRY2D */
diff --git a/include/astra/XMLDocument.h b/include/astra/XMLDocument.h
new file mode 100644
index 0000000..dbcc679
--- /dev/null
+++ b/include/astra/XMLDocument.h
@@ -0,0 +1,101 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_XMLDOCUMENT
+#define _INC_ASTRA_XMLDOCUMENT
+
+#include <string>
+
+#if 1
+namespace rapidxml {
+ template<class Ch> class xml_document;
+}
+#else
+#include "rapidxml.hpp"
+#endif
+
+#include "Globals.h"
+#include "XMLNode.h"
+
+using namespace std;
+
+namespace astra {
+
+/** This class encapsulates an XML Document of the Xerces DOM Parser.
+ */
+class _AstraExport XMLDocument {
+
+public:
+
+ /** Default Constructor
+ */
+ XMLDocument();
+
+ /** Destructor
+ */
+ ~XMLDocument();
+
+ /** Construct an XML DOM tree and Document from an XML file
+ *
+ * @param sFilename Location of the XML file.
+ * @return XML Document containing the DOM tree
+ */
+ static XMLDocument* readFromFile(string sFilename);
+
+ /** Construct an empty XML DOM tree with a specific root tag.
+ *
+ * @param sRootName Element name of the root tag.
+ * @return XML Document with an empty root node
+ */
+ static XMLDocument* createDocument(string sRootName);
+
+ /** Get the rootnode of the XML document
+ *
+ * @return first XML node of the document
+ */
+ XMLNode* getRootNode();
+
+ /** Save an XML DOM tree to an XML file
+ *
+ * @param sFilename Location of the XML file.
+ */
+ void saveToFile(string sFilename);
+
+
+private:
+
+ //!< Document of rapidxml
+ rapidxml::xml_document<char>* fDOMDocument;
+
+ std::string fBuf;
+
+};
+
+} // end namespace
+
+#endif
diff --git a/include/astra/XMLNode.h b/include/astra/XMLNode.h
new file mode 100644
index 0000000..3ed6417
--- /dev/null
+++ b/include/astra/XMLNode.h
@@ -0,0 +1,325 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_XMLNODE
+#define _INC_ASTRA_XMLNODE
+
+#include <list>
+#include <string>
+#include <vector>
+
+#if 1
+namespace rapidxml {
+ template<class Ch> class xml_node;
+}
+#else
+#include "rapidxml.hpp"
+#endif
+
+#include "Globals.h"
+#include "Utilities.h"
+
+using namespace std;
+
+namespace astra {
+
+/**
+ * This class encapsulates an XML Node of the Xerces DOM Parser.
+ */
+class _AstraExport XMLNode {
+
+friend class XMLDocument;
+
+public:
+
+ /** Default Constructor
+ */
+ XMLNode();
+
+ /** Deconstructor
+ */
+ ~XMLNode();
+
+
+ /** Get a single child XML node. If there are more, the first one is returned
+ *
+ * @param _sName tagname of the requested child node
+ * @return first child node with the correct tagname, null pointer if it doesn't exist
+ */
+ XMLNode* getSingleNode(string _sName);
+
+ /** Get all child XML nodes that have the tagname name
+ *
+ * @param _sName tagname of the requested child nodes
+ * @return list with all child nodes with the correct tagname
+ */
+ std::list<XMLNode*> getNodes(string _sName);
+
+ /** Get all child XML nodes
+ *
+ * @return list with all child nodes
+ */
+ std::list<XMLNode*> getNodes();
+
+ /** Get the name of this node
+ *
+ * @return name of node
+ */
+ std::string getName();
+
+ /** Get the content of the XML node as a single string.
+ *
+ * @return node content
+ */
+ string getContent();
+
+ /** Get the content of the XML node as a numerical.
+ *
+ * @return node content
+ */
+ float32 getContentNumerical();
+
+ /** Get the content of the XML node as a boolean.
+ *
+ * @return node content
+ */
+ bool getContentBool();
+
+ /** Get the content of the XML node as a vector of strings.
+ *
+ * @return node content
+ */
+ vector<string> getContentArray();
+
+ /** Get the content of the XML node as a c-array of float32 data.
+ *
+ * @param _pfData data array, shouldn't be initialized already.
+ * @param _iSize number of elements stored in _pfData
+ */
+ void getContentNumericalArray(float32*& _pfData, int& _iSize);
+
+ /** Get the content of the XML node as a stl container of float32 data.
+ *
+ * @return node content
+ */
+ vector<float32> getContentNumericalArray();
+ vector<double> getContentNumericalArrayDouble();
+
+
+
+ /** Does this node contain an attribute with a certain name?
+ *
+ * @param _sName of the attribute.
+ * @return attribute value, empty string if it doesn't exist.
+ */
+ bool hasAttribute(string _sName);
+
+ /** Get the value of an attribute.
+ *
+ * @param _sName of the attribute.
+ * @param _sDefaultValue value to return if the attribute isn't found
+ * @return attribute value, _sDefaultValue if it doesn't exist.
+ */
+ string getAttribute(string _sName, string _sDefaultValue = "");
+
+ /** Get the value of a numerical attribute.
+ *
+ * @param _sName of the attribute.
+ * @param _fDefaultValue value to return if the attribute isn't found
+ * @return attribute value, _fDefaultValue if it doesn't exist.
+ */
+ float32 getAttributeNumerical(string _sName, float32 _fDefaultValue = 0);
+ double getAttributeNumericalDouble(string _sName, double _fDefaultValue = 0);
+
+ /** Get the value of a boolean attribute.
+ *
+ * @param _sName of the attribute.
+ * @param _bDefaultValue value to return if the attribute isn't found
+ * @return attribute value, _bDefaultValue if it doesn't exist.
+ */
+ bool getAttributeBool(string _sName, bool _bDefaultValue = false);
+
+
+
+
+ /** Does this node contain an option with a certain key?
+ *
+ * @param _sKey option key
+ * @return true if option does exist
+ */
+ bool hasOption(string _sKey);
+
+ /** Get the value of an option within this XML Node
+ *
+ * @param _sKey option key
+ * @param _sDefaultValue value to return if key isn't found
+ * @return option value, _sDefaultValue if the option doesn't exist
+ */
+ string getOption(string _sKey, string _sDefaultValue = "");
+
+ /** Get the value of an option within this XML Node
+ *
+ * @param _sKey option key
+ * @param _fDefaultValue value to return if key isn't found
+ * @return option value, _fDefaultValue if the option doesn't exist
+ */
+ float32 getOptionNumerical(string _sKey, float32 _fDefaultValue = 0);
+
+ /** Get the value of an option within this XML Node
+ *
+ * @param _sKey option key
+ * @param _bDefaultValue value to return if key isn't found
+ * @return option value, _bDefaultValue if the option doesn't exist
+ */
+ bool getOptionBool(string _sKey, bool _bDefaultValue = false);
+
+ /** Get the value of an option within this XML Node
+ *
+ * @param _sKey option key
+ * @return numerical array
+ */
+ vector<float32> getOptionNumericalArray(string _sKey);
+
+
+
+
+
+ /** Create a new XML node as a child to this one: &lt;...&gt;&lt;_sNodeName/&gt;</...&gt;
+ *
+ * @param _sNodeName the name of the new childnode
+ * @return new child node
+ */
+ XMLNode* addChildNode(string _sNodeName);
+
+ /** Create a new XML node as a child to this one, also add some content:
+ * &lt;...&gt;&lt;_sNodeName&gt;_sValue&lt;/_sNodeName>&lt;/...&gt;
+ *
+ * @param _sNodeName the name of the new childnode
+ * @param _sValue some node content
+ * @return new child node
+ */
+ XMLNode* addChildNode(string _sNodeName, string _sValue);
+
+ /** Create a new XML node as a child to this one, also add some numerical content:
+ * &lt;...&gt;&lt;_sNodeName&gt;_sValue&lt;/_sNodeName>&lt;/...&gt;
+ *
+ * @param _sNodeName the name of the new childnode
+ * @param _fValue some node content
+ * @return new child node
+ */
+ XMLNode* addChildNode(string _sNodeName, float32 _fValue);
+
+ /** Create a new XML node as a child to this one, also add a list of numerical content:
+ * &lt;...&gt;&lt;_sNodeName&gt;_sValue&lt;/_sNodeName>&lt;/...&gt;
+ *
+ * @param _sNodeName the name of the new childnode
+ * @param _pfList list data
+ * @param _iSize number of elements in _pfList
+ * @return new child node
+ */
+ XMLNode* addChildNode(string _sNodeName, float32* _pfList, int _iSize);
+
+ /** Add some text to the node: &lt;...&gt;_sText&lt;/...&gt;
+ *
+ * @param _sText text to insert
+ */
+ void setContent(string _sText);
+
+ /** Add a number to the node: &lt;...&gt;_sText&lt;/...&gt;
+ *
+ * @param _fValue number to insert
+ */
+ void setContent(float32 _fValue);
+
+ /** Add a list of numerical data to the node: &lt;...&gt;_sText&lt;/...&gt;
+ *
+ * @param _pfList data
+ * @param _iSize number of elements in the list
+ */
+ void setContent(float32* _pfList, int _iSize);
+
+ /** Add an attribute to this node: &lt;... _sName="_sValue"&gt;
+ *
+ * @param _sName name of the attribute
+ * @param _sValue value of the attribute
+ */
+ void addAttribute(string _sName, string _sValue);
+
+ /** Add an attribute with numerical data to this node: &lt;... _sName="_fValue"&gt;
+ *
+ * @param _sName name of the attribute
+ * @param _sValue value of the attribute
+ */
+ void addAttribute(string _sName, float32 _fValue);
+
+ /** Add an option node as a child: &lt;Option key="&lt;_sKey&gt;" value="&lt;_sValue&gt;"/>
+ *
+ * @param _sKey option key
+ * @param _sValue option value
+ */
+ void addOption(string _sKey, string _sValue);
+
+ /** Add an option node as a child: &lt;Option key="&lt;_sKey&gt;" value="&lt;_sValue&gt;"/>
+ *
+ * @param _sKey option key
+ * @param _sValue option value
+ */
+ void addOption(string _sKey, float32 _fValue);
+
+
+ /** Print to String
+ */
+ std::string toString();
+
+ /** Print the node
+ */
+ void print();
+
+protected:
+
+ /** Private Constructor.
+ *
+ * @param n rapidxml node
+ */
+ XMLNode(rapidxml::xml_node<char>* n);
+
+ /** Link this object to a rapidxml node
+ * @param n object of the Xerces C++ library
+ */
+ void setDOMNode(rapidxml::xml_node<char>* n);
+
+ // todo: rename "fDOMElement" to "m_fDOMElement"?
+
+ //!< Node of rapidxml
+ rapidxml::xml_node<char>* fDOMElement;
+
+};
+
+} // end namespace
+
+#endif
diff --git a/include/astra/jama_wrapper.h b/include/astra/jama_wrapper.h
new file mode 100644
index 0000000..2fbdef8
--- /dev/null
+++ b/include/astra/jama_wrapper.h
@@ -0,0 +1,35 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+// Wrapper include for jama header files
+
+#ifdef JAMA_NO_SUBDIR
+#include "jama_lu.h"
+#else
+#include <tnt/jama_lu.h>
+#endif
diff --git a/include/astra/swrap.h b/include/astra/swrap.h
new file mode 100644
index 0000000..af45838
--- /dev/null
+++ b/include/astra/swrap.h
@@ -0,0 +1,41 @@
+/*
+-----------------------------------------------------------------------
+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$
+*/
+
+#ifndef _INC_ASTRA_SWRAP_H
+#define _INC_ASTRA_SWRAP_H
+
+#ifndef _MSC_VER
+
+#include <cstdio>
+
+typedef int errno_t;
+errno_t fopen_s(FILE** pFile, const char *filename, const char *mode);
+
+#endif
+
+#endif