summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/astra/ParallelBeamLineKernelProjector2D.h7
-rw-r--r--include/astra/ParallelBeamLineKernelProjector2D.inl202
-rw-r--r--src/ParallelBeamLineKernelProjector2D.cpp108
3 files changed, 261 insertions, 56 deletions
diff --git a/include/astra/ParallelBeamLineKernelProjector2D.h b/include/astra/ParallelBeamLineKernelProjector2D.h
index 24f43d5..dd5eab2 100644
--- a/include/astra/ParallelBeamLineKernelProjector2D.h
+++ b/include/astra/ParallelBeamLineKernelProjector2D.h
@@ -30,6 +30,7 @@ $Id$
#define _INC_ASTRA_PARALLELBEAMLINEKERNELPROJECTOR
#include "ParallelProjectionGeometry2D.h"
+#include "ParallelVecProjectionGeometry2D.h"
#include "Float32Data2D.h"
#include "Projector2D.h"
@@ -180,6 +181,12 @@ protected:
template <typename Policy>
void projectBlock_internal(int _iProjFrom, int _iProjTo,
int _iDetFrom, int _iDetTo, Policy& _policy);
+
+ /** Internal policy-based projection of a range of angles and range.
+ * (_i*From is inclusive, _i*To exclusive) */
+ template <typename Policy>
+ void projectBlock_internal_vector(int _iProjFrom, int _iProjTo,
+ int _iDetFrom, int _iDetTo, Policy& _policy);
};
inline std::string CParallelBeamLineKernelProjector2D::getType()
diff --git a/include/astra/ParallelBeamLineKernelProjector2D.inl b/include/astra/ParallelBeamLineKernelProjector2D.inl
index 199d69e..31aa138 100644
--- a/include/astra/ParallelBeamLineKernelProjector2D.inl
+++ b/include/astra/ParallelBeamLineKernelProjector2D.inl
@@ -29,8 +29,13 @@ $Id$
template <typename Policy>
void CParallelBeamLineKernelProjector2D::project(Policy& p)
{
- projectBlock_internal(0, m_pProjectionGeometry->getProjectionAngleCount(),
- 0, m_pProjectionGeometry->getDetectorCount(), p);
+ if (dynamic_cast<CParallelProjectionGeometry2D*>(m_pProjectionGeometry)) {
+ projectBlock_internal(0, m_pProjectionGeometry->getProjectionAngleCount(),
+ 0, m_pProjectionGeometry->getDetectorCount(), p);
+ } else if (dynamic_cast<CParallelVecProjectionGeometry2D*>(m_pProjectionGeometry)) {
+ projectBlock_internal_vector(0, m_pProjectionGeometry->getProjectionAngleCount(),
+ 0, m_pProjectionGeometry->getDetectorCount(), p);
+ }
}
template <typename Policy>
@@ -49,7 +54,7 @@ void CParallelBeamLineKernelProjector2D::projectSingleRay(int _iProjection, int
//----------------------------------------------------------------------------------------
-// PROJECT BLOCK
+// PROJECT BLOCK - default projection geometry
template <typename Policy>
void CParallelBeamLineKernelProjector2D::projectBlock_internal(int _iProjFrom, int _iProjTo, int _iDetFrom, int _iDetTo, Policy& p)
{
@@ -59,6 +64,11 @@ void CParallelBeamLineKernelProjector2D::projectBlock_internal(int _iProjFrom, i
int iVolumeIndex, iRayIndex, row, col, iAngle, iDetector, x1;
bool switch_t;
+ float32 old_theta;
+ const SParProjection * proj = 0;
+
+ const CParallelProjectionGeometry2D* pProjectionGeometry = dynamic_cast<CParallelProjectionGeometry2D*>(m_pProjectionGeometry);
+
// loop angles
for (iAngle = _iProjFrom; iAngle < _iProjTo; ++iAngle) {
@@ -287,3 +297,189 @@ void CParallelBeamLineKernelProjector2D::projectBlock_internal(int _iProjFrom, i
}
+//----------------------------------------------------------------------------------------
+// PROJECT BLOCK - vector projection geometry
+template <typename Policy>
+void CParallelBeamLineKernelProjector2D::projectBlock_internal_vector(int _iProjFrom, int _iProjTo, int _iDetFrom, int _iDetTo, Policy& p)
+{
+ // variables
+ float32 detX, detY, S, T, I, x, y, c, r, update_c, update_r, offset;
+ float32 lengthPerRow, lengthPerCol, inv_pixelLengthX, inv_pixelLengthY, invTminSTimesLengthPerRow, invTminSTimesLengthPerCol;
+ int iVolumeIndex, iRayIndex, row, col, iAngle, iDetector;
+
+ const SParProjection * proj = 0;
+ const CParallelVecProjectionGeometry2D* pVecProjectionGeometry = dynamic_cast<CParallelVecProjectionGeometry2D*>(m_pProjectionGeometry);
+
+ inv_pixelLengthX = 1.0f / m_pVolumeGeometry->getPixelLengthX();
+ inv_pixelLengthY = 1.0f / m_pVolumeGeometry->getPixelLengthY();
+
+ // loop angles
+ for (iAngle = _iProjFrom; iAngle < _iProjTo; ++iAngle) {
+
+ proj = &pVecProjectionGeometry->getProjectionVectors()[iAngle];
+
+ bool vertical = fabs(proj->fRayX) < fabs(proj->fRayY);
+ if (vertical) {
+ S = abs(0.5f * (1.0f - proj->fRayY/proj->fRayX));
+ T = abs(0.5f * (1.0f + proj->fRayY/proj->fRayX));
+ lengthPerRow = m_pVolumeGeometry->getPixelLengthX() * sqrt(proj->fRayY*proj->fRayY + proj->fRayX*proj->fRayX) / abs(proj->fRayY);
+ invTminSTimesLengthPerRow = lengthPerRow / (T - S);
+ } else {
+ S = abs(0.5f * (1.0f - proj->fRayX/proj->fRayY));
+ T = abs(0.5f * (1.0f + proj->fRayX/proj->fRayY));
+ lengthPerCol = m_pVolumeGeometry->getPixelLengthY() * sqrt(proj->fRayY*proj->fRayY + proj->fRayX*proj->fRayX) / abs(proj->fRayX);
+ invTminSTimesLengthPerCol = lengthPerCol / (T - S);
+ }
+
+ // loop detectors
+ for (iDetector = _iDetFrom; iDetector < _iDetTo; ++iDetector) {
+
+ iRayIndex = iAngle * m_pProjectionGeometry->getDetectorCount() + iDetector;
+
+ // POLICY: RAY PRIOR
+ if (!p.rayPrior(iRayIndex)) continue;
+
+ detX = proj->fDetSX + (iDetector+0.5f) * proj->fDetUX;
+ detY = proj->fDetSY + (iDetector+0.5f) * proj->fDetUY;
+
+ // vertically
+ if (vertical) {
+
+ // calculate x for row 0
+ float32 x = detX + (proj->fRayX/proj->fRayY)*(m_pVolumeGeometry->pixelRowToCenterY(0)-detY);
+ float32 c = (x - m_pVolumeGeometry->getWindowMinX()) * inv_pixelLengthX - 0.5f;
+ float32 update_c = -m_pVolumeGeometry->getPixelLengthY() * (proj->fRayX/proj->fRayY) * inv_pixelLengthX;
+
+ // for each row
+ for (row = 0; row < m_pVolumeGeometry->getGridRowCount(); ++row, c += update_c) {
+
+ col = int(c+0.5f);
+ offset = c - float32(col);
+
+ if (col <= 0 || col >= m_pVolumeGeometry->getGridColCount()-1) continue;
+
+ // left
+ if (offset < -S) {
+ I = (offset + T) * invTminSTimesLengthPerRow;
+
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, col-1);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, lengthPerRow-I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, col);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+
+ // right
+ else if (S < offset) {
+ I = (offset - S) * invTminSTimesLengthPerRow;
+
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, col);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, lengthPerRow-I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, col+1);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+
+ // centre
+ else {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, col);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, lengthPerRow);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+
+ }
+ }
+
+ // horizontally
+ else {
+
+ // calculate y for col 0
+ float32 y = detY + (proj->fRayY/proj->fRayX)*(m_pVolumeGeometry->pixelColToCenterX(0)-detX);
+ float32 r = (m_pVolumeGeometry->getWindowMaxY() - y) * inv_pixelLengthY - 0.5f;
+ float32 update_r = -m_pVolumeGeometry->getPixelLengthX() * (proj->fRayY/proj->fRayX) * inv_pixelLengthY;
+
+ // for each col
+ for (col = 0; col < m_pVolumeGeometry->getGridColCount(); ++col, r += update_r) {
+
+ int row = int(r+0.5f);
+ float32 offset = r - float32(row);
+
+ if (row <= 0 || row >= m_pVolumeGeometry->getGridRowCount()-1) continue;
+
+ // up
+ if (offset < -S) {
+ I = (offset + T) * invTminSTimesLengthPerCol;
+
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row-1, col);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, lengthPerCol-I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, col);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+
+ // down
+ else if (S < offset) {
+ I = (offset - S) * invTminSTimesLengthPerCol;
+
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, col);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, lengthPerCol-I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row+1, col);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, I);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+
+ // centre
+ else {
+ iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, col);
+ // POLICY: PIXEL PRIOR + ADD + POSTERIOR
+ if (p.pixelPrior(iVolumeIndex)) {
+ p.addWeight(iRayIndex, iVolumeIndex, lengthPerCol);
+ p.pixelPosterior(iVolumeIndex);
+ }
+ }
+
+ }
+ } // end loop col
+
+ // POLICY: RAY POSTERIOR
+ p.rayPosterior(iRayIndex);
+
+ } // end loop detector
+ } // end loop angles
+
+} \ No newline at end of file
diff --git a/src/ParallelBeamLineKernelProjector2D.cpp b/src/ParallelBeamLineKernelProjector2D.cpp
index 5a23413..c94c024 100644
--- a/src/ParallelBeamLineKernelProjector2D.cpp
+++ b/src/ParallelBeamLineKernelProjector2D.cpp
@@ -88,7 +88,7 @@ bool CParallelBeamLineKernelProjector2D::_check()
// check base class
ASTRA_CONFIG_CHECK(CProjector2D::_check(), "ParallelBeamLineKernelProjector2D", "Error in Projector2D initialization");
- ASTRA_CONFIG_CHECK(dynamic_cast<CParallelProjectionGeometry2D*>(m_pProjectionGeometry), "ParallelBeamLineKernelProjector2D", "Unsupported projection geometry");
+ ASTRA_CONFIG_CHECK(dynamic_cast<CParallelProjectionGeometry2D*>(m_pProjectionGeometry) || dynamic_cast<CParallelVecProjectionGeometry2D*>(m_pProjectionGeometry), "ParallelBeamLineKernelProjector2D", "Unsupported projection geometry");
ASTRA_CONFIG_CHECK(m_pVolumeGeometry->getPixelLengthX() == m_pVolumeGeometry->getPixelLengthY(), "ParallelBeamLineKernelProjector2D", "Pixel height must equal pixel width.");
@@ -162,61 +162,63 @@ void CParallelBeamLineKernelProjector2D::computeSingleRayWeights(int _iProjectio
// Project Point
std::vector<SDetector2D> CParallelBeamLineKernelProjector2D::projectPoint(int _iRow, int _iCol)
{
- float32 xUL = m_pVolumeGeometry->pixelColToCenterX(_iCol) - m_pVolumeGeometry->getPixelLengthX() * 0.5f;
- float32 yUL = m_pVolumeGeometry->pixelRowToCenterY(_iRow) - m_pVolumeGeometry->getPixelLengthY() * 0.5f;
- float32 xUR = m_pVolumeGeometry->pixelColToCenterX(_iCol) + m_pVolumeGeometry->getPixelLengthX() * 0.5f;
- float32 yUR = m_pVolumeGeometry->pixelRowToCenterY(_iRow) - m_pVolumeGeometry->getPixelLengthY() * 0.5f;
- float32 xLL = m_pVolumeGeometry->pixelColToCenterX(_iCol) - m_pVolumeGeometry->getPixelLengthX() * 0.5f;
- float32 yLL = m_pVolumeGeometry->pixelRowToCenterY(_iRow) + m_pVolumeGeometry->getPixelLengthY() * 0.5f;
- float32 xLR = m_pVolumeGeometry->pixelColToCenterX(_iCol) + m_pVolumeGeometry->getPixelLengthX() * 0.5f;
- float32 yLR = m_pVolumeGeometry->pixelRowToCenterY(_iRow) + m_pVolumeGeometry->getPixelLengthY() * 0.5f;
-
std::vector<SDetector2D> res;
- // loop projectors and detectors
- for (int iProjection = 0; iProjection < m_pProjectionGeometry->getProjectionAngleCount(); ++iProjection) {
-
- // get projection angle
- float32 theta = m_pProjectionGeometry->getProjectionAngle(iProjection);
- if (theta >= 7*PIdiv4) theta -= 2*PI;
- bool inverse = false;
- if (theta >= 3*PIdiv4) {
- theta -= PI;
- inverse = true;
- }
-
- // calculate distance from the center of the voxel to the ray though the origin
- float32 tUL = xUL * cos(theta) + yUL * sin(theta);
- float32 tUR = xUR * cos(theta) + yUR * sin(theta);
- float32 tLL = xLL * cos(theta) + yLL * sin(theta);
- float32 tLR = xLR * cos(theta) + yLR * sin(theta);
- if (inverse) {
- tUL *= -1.0f;
- tUR *= -1.0f;
- tLL *= -1.0f;
- tLR *= -1.0f;
- }
- float32 tMin = min(tUL, min(tUR, min(tLL,tLR)));
- float32 tMax = max(tUL, max(tUR, max(tLL,tLR)));
-
- // calculate the offset on the detectorarray (in indices)
- int dmin = (int)floor(m_pProjectionGeometry->detectorOffsetToIndexFloat(tMin));
- int dmax = (int)ceil(m_pProjectionGeometry->detectorOffsetToIndexFloat(tMax));
-
- // add affected detectors to the list
- for (int i = dmin; i <= dmax; ++i) {
- if (i >= 0 && i < m_pProjectionGeometry->getDetectorCount()) {
- SDetector2D det;
- det.m_iAngleIndex = iProjection;
- det.m_iDetectorIndex = i;
- det.m_iIndex = iProjection * getProjectionGeometry()->getDetectorCount() + i;
- res.push_back(det);
- }
- }
- }
-
- // return result vector
return res;
+ // float32 xUL = m_pVolumeGeometry->pixelColToCenterX(_iCol) - m_pVolumeGeometry->getPixelLengthX() * 0.5f;
+ // float32 yUL = m_pVolumeGeometry->pixelRowToCenterY(_iRow) - m_pVolumeGeometry->getPixelLengthY() * 0.5f;
+ // float32 xUR = m_pVolumeGeometry->pixelColToCenterX(_iCol) + m_pVolumeGeometry->getPixelLengthX() * 0.5f;
+ // float32 yUR = m_pVolumeGeometry->pixelRowToCenterY(_iRow) - m_pVolumeGeometry->getPixelLengthY() * 0.5f;
+ // float32 xLL = m_pVolumeGeometry->pixelColToCenterX(_iCol) - m_pVolumeGeometry->getPixelLengthX() * 0.5f;
+ // float32 yLL = m_pVolumeGeometry->pixelRowToCenterY(_iRow) + m_pVolumeGeometry->getPixelLengthY() * 0.5f;
+ // float32 xLR = m_pVolumeGeometry->pixelColToCenterX(_iCol) + m_pVolumeGeometry->getPixelLengthX() * 0.5f;
+ // float32 yLR = m_pVolumeGeometry->pixelRowToCenterY(_iRow) + m_pVolumeGeometry->getPixelLengthY() * 0.5f;
+
+ // std::vector<SDetector2D> res;
+ // // loop projectors and detectors
+ // for (int iProjection = 0; iProjection < m_pProjectionGeometry->getProjectionAngleCount(); ++iProjection) {
+
+ // // get projection angle
+ // float32 theta = m_pProjectionGeometry->getProjectionAngle(iProjection);
+ // if (theta >= 7*PIdiv4) theta -= 2*PI;
+ // bool inverse = false;
+ // if (theta >= 3*PIdiv4) {
+ // theta -= PI;
+ // inverse = true;
+ // }
+
+ // // calculate distance from the center of the voxel to the ray though the origin
+ // float32 tUL = xUL * cos(theta) + yUL * sin(theta);
+ // float32 tUR = xUR * cos(theta) + yUR * sin(theta);
+ // float32 tLL = xLL * cos(theta) + yLL * sin(theta);
+ // float32 tLR = xLR * cos(theta) + yLR * sin(theta);
+ // if (inverse) {
+ // tUL *= -1.0f;
+ // tUR *= -1.0f;
+ // tLL *= -1.0f;
+ // tLR *= -1.0f;
+ // }
+ // float32 tMin = min(tUL, min(tUR, min(tLL,tLR)));
+ // float32 tMax = max(tUL, max(tUR, max(tLL,tLR)));
+
+ // // calculate the offset on the detectorarray (in indices)
+ // int dmin = (int)floor(m_pProjectionGeometry->detectorOffsetToIndexFloat(tMin));
+ // int dmax = (int)ceil(m_pProjectionGeometry->detectorOffsetToIndexFloat(tMax));
+
+ // // add affected detectors to the list
+ // for (int i = dmin; i <= dmax; ++i) {
+ // if (i >= 0 && i < m_pProjectionGeometry->getDetectorCount()) {
+ // SDetector2D det;
+ // det.m_iAngleIndex = iProjection;
+ // det.m_iDetectorIndex = i;
+ // det.m_iIndex = iProjection * getProjectionGeometry()->getDetectorCount() + i;
+ // res.push_back(det);
+ // }
+ // }
+ // }
+
+ // // return result vector
+ // return res;
}
//----------------------------------------------------------------------------------------