From 2c1999b1bbfb7ef2ca1ae22b43e2a0ab8108073f Mon Sep 17 00:00:00 2001 From: Wim van Aarle Date: Thu, 12 Mar 2015 11:40:56 +0100 Subject: parallel projectors now always use vector geometries internally --- include/astra/ParallelBeamLineKernelProjector2D.h | 5 - .../astra/ParallelBeamLineKernelProjector2D.inl | 302 ++---------------- .../astra/ParallelBeamLinearKernelProjector2D.h | 4 - .../astra/ParallelBeamLinearKernelProjector2D.inl | 181 ++--------- include/astra/ParallelBeamStripKernelProjector2D.h | 6 - .../astra/ParallelBeamStripKernelProjector2D.inl | 343 +++------------------ include/astra/ParallelProjectionGeometry2D.h | 10 +- src/ParallelProjectionGeometry2D.cpp | 22 +- 8 files changed, 120 insertions(+), 753 deletions(-) diff --git a/include/astra/ParallelBeamLineKernelProjector2D.h b/include/astra/ParallelBeamLineKernelProjector2D.h index dd5eab2..5a10021 100644 --- a/include/astra/ParallelBeamLineKernelProjector2D.h +++ b/include/astra/ParallelBeamLineKernelProjector2D.h @@ -182,11 +182,6 @@ protected: 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 - 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 69978b0..dc3153d 100644 --- a/include/astra/ParallelBeamLineKernelProjector2D.inl +++ b/include/astra/ParallelBeamLineKernelProjector2D.inl @@ -29,302 +29,52 @@ $Id$ template void CParallelBeamLineKernelProjector2D::project(Policy& p) { - if (dynamic_cast(m_pProjectionGeometry)) { - projectBlock_internal(0, m_pProjectionGeometry->getProjectionAngleCount(), - 0, m_pProjectionGeometry->getDetectorCount(), p); - } else if (dynamic_cast(m_pProjectionGeometry)) { - projectBlock_internal_vector(0, m_pProjectionGeometry->getProjectionAngleCount(), - 0, m_pProjectionGeometry->getDetectorCount(), p); - } + projectBlock_internal(0, m_pProjectionGeometry->getProjectionAngleCount(), + 0, m_pProjectionGeometry->getDetectorCount(), p); } template void CParallelBeamLineKernelProjector2D::projectSingleProjection(int _iProjection, Policy& p) { - if (dynamic_cast(m_pProjectionGeometry)) { - projectBlock_internal(_iProjection, _iProjection + 1, - 0, m_pProjectionGeometry->getDetectorCount(), p); - } else if (dynamic_cast(m_pProjectionGeometry)) { - projectBlock_internal_vector(_iProjection, _iProjection + 1, - 0, m_pProjectionGeometry->getDetectorCount(), p); - } + projectBlock_internal(_iProjection, _iProjection + 1, + 0, m_pProjectionGeometry->getDetectorCount(), p); } template void CParallelBeamLineKernelProjector2D::projectSingleRay(int _iProjection, int _iDetector, Policy& p) { - if (dynamic_cast(m_pProjectionGeometry)) { - projectBlock_internal(_iProjection, _iProjection + 1, - _iDetector, _iDetector + 1, p); - } else if (dynamic_cast(m_pProjectionGeometry)) { - projectBlock_internal_vector(_iProjection, _iProjection + 1, + projectBlock_internal(_iProjection, _iProjection + 1, _iDetector, _iDetector + 1, p); - } } -//---------------------------------------------------------------------------------------- -// PROJECT BLOCK - default projection geometry -template -void CParallelBeamLineKernelProjector2D::projectBlock_internal(int _iProjFrom, int _iProjTo, int _iDetFrom, int _iDetTo, 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; - - float32 old_theta; - const SParProjection * proj = 0; - - const CParallelProjectionGeometry2D* pProjectionGeometry = dynamic_cast(m_pProjectionGeometry); - - // loop angles - for (iAngle = _iProjFrom; iAngle < _iProjTo; ++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 = _iDetFrom; iDetector < _iDetTo; ++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 BLOCK - vector projection geometry template -void CParallelBeamLineKernelProjector2D::projectBlock_internal_vector(int _iProjFrom, int _iProjTo, int _iDetFrom, int _iDetTo, Policy& p) +void CParallelBeamLineKernelProjector2D::projectBlock_internal(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; - + int iVolumeIndex, iRayIndex, row, col, iAngle, iDetector, colCount, rowCount, detCount; const SParProjection * proj = 0; - const CParallelVecProjectionGeometry2D* pVecProjectionGeometry = dynamic_cast(m_pProjectionGeometry); + // get vector geometry + const CParallelVecProjectionGeometry2D* pVecProjectionGeometry; + if (dynamic_cast(m_pProjectionGeometry)) { + pVecProjectionGeometry = dynamic_cast(m_pProjectionGeometry)->toVectorGeometry(); + } else { + pVecProjectionGeometry = dynamic_cast(m_pProjectionGeometry); + } + + // precomputations inv_pixelLengthX = 1.0f / m_pVolumeGeometry->getPixelLengthX(); inv_pixelLengthY = 1.0f / m_pVolumeGeometry->getPixelLengthY(); - - int colCount = m_pVolumeGeometry->getGridColCount(); - int rowCount = m_pVolumeGeometry->getGridRowCount(); + colCount = m_pVolumeGeometry->getGridColCount(); + rowCount = m_pVolumeGeometry->getGridRowCount(); + detCount = pVecProjectionGeometry->getDetectorCount(); // loop angles for (iAngle = _iProjFrom; iAngle < _iProjTo; ++iAngle) { @@ -333,17 +83,17 @@ void CParallelBeamLineKernelProjector2D::projectBlock_internal_vector(int _iProj bool vertical = fabs(proj->fRayX) < fabs(proj->fRayY); if (vertical) { - S = fabs(0.5f * (1.0f - proj->fRayY/proj->fRayX)); - T = fabs(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); update_c = -m_pVolumeGeometry->getPixelLengthY() * (proj->fRayX/proj->fRayY) * inv_pixelLengthX; + S = 0.5f - 0.5f*fabs(proj->fRayX/proj->fRayY); + T = 0.5f + 0.5f*fabs(proj->fRayX/proj->fRayY); + invTminSTimesLengthPerRow = lengthPerRow / (T - S); } else { - S = fabs(0.5f * (1.0f - proj->fRayX/proj->fRayY)); - T = fabs(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); update_r = -m_pVolumeGeometry->getPixelLengthX() * (proj->fRayY/proj->fRayX) * inv_pixelLengthY; + S = 0.5f - 0.5f*fabs(proj->fRayY/proj->fRayX); + T = 0.5f + 0.5f*fabs(proj->fRayY/proj->fRayX); + invTminSTimesLengthPerCol = lengthPerCol / (T - S); } // loop detectors @@ -495,4 +245,4 @@ void CParallelBeamLineKernelProjector2D::projectBlock_internal_vector(int _iProj } // end loop detector } // end loop angles -} \ No newline at end of file +} diff --git a/include/astra/ParallelBeamLinearKernelProjector2D.h b/include/astra/ParallelBeamLinearKernelProjector2D.h index 3b84380..8e25c38 100644 --- a/include/astra/ParallelBeamLinearKernelProjector2D.h +++ b/include/astra/ParallelBeamLinearKernelProjector2D.h @@ -186,10 +186,6 @@ protected: void projectBlock_internal(int _iProjFrom, int _iProjTo, int _iDetFrom, int _iDetTo, Policy& _policy); - template - void projectBlock_internal_vector(int _iProjFrom, int _iProjTo, - int _iDetFrom, int _iDetTo, Policy& _policy); - }; //---------------------------------------------------------------------------------------- diff --git a/include/astra/ParallelBeamLinearKernelProjector2D.inl b/include/astra/ParallelBeamLinearKernelProjector2D.inl index 04577de..9f898ce 100644 --- a/include/astra/ParallelBeamLinearKernelProjector2D.inl +++ b/include/astra/ParallelBeamLinearKernelProjector2D.inl @@ -26,195 +26,54 @@ along with the ASTRA Toolbox. If not, see . $Id$ */ - template void CParallelBeamLinearKernelProjector2D::project(Policy& p) { - if (dynamic_cast(m_pProjectionGeometry)) { - projectBlock_internal(0, m_pProjectionGeometry->getProjectionAngleCount(), - 0, m_pProjectionGeometry->getDetectorCount(), p); - } else if (dynamic_cast(m_pProjectionGeometry)) { - projectBlock_internal_vector(0, m_pProjectionGeometry->getProjectionAngleCount(), - 0, m_pProjectionGeometry->getDetectorCount(), p); - } + projectBlock_internal(0, m_pProjectionGeometry->getProjectionAngleCount(), + 0, m_pProjectionGeometry->getDetectorCount(), p); } template void CParallelBeamLinearKernelProjector2D::projectSingleProjection(int _iProjection, Policy& p) { - if (dynamic_cast(m_pProjectionGeometry)) { - projectBlock_internal(_iProjection, _iProjection + 1, - 0, m_pProjectionGeometry->getDetectorCount(), p); - } else if (dynamic_cast(m_pProjectionGeometry)) { - projectBlock_internal_vector(_iProjection, _iProjection + 1, - 0, m_pProjectionGeometry->getDetectorCount(), p); - } + projectBlock_internal(_iProjection, _iProjection + 1, + 0, m_pProjectionGeometry->getDetectorCount(), p); } template void CParallelBeamLinearKernelProjector2D::projectSingleRay(int _iProjection, int _iDetector, Policy& p) { - if (dynamic_cast(m_pProjectionGeometry)) { - projectBlock_internal(_iProjection, _iProjection + 1, - _iDetector, _iDetector + 1, p); - } else if (dynamic_cast(m_pProjectionGeometry)) { - projectBlock_internal_vector(_iProjection, _iProjection + 1, + projectBlock_internal(_iProjection, _iProjection + 1, _iDetector, _iDetector + 1, p); - } } -//---------------------------------------------------------------------------------------- -// PROJECT BLOCK -template -void CParallelBeamLinearKernelProjector2D::projectBlock_internal(int _iProjFrom, int _iProjTo, int _iDetFrom, int _iDetTo, 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 = _iProjFrom; iAngle < _iProjTo; ++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 = _iDetFrom; iDetector < _iDetTo; ++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 BLOCK - vector projection geometry template -void CParallelBeamLinearKernelProjector2D::projectBlock_internal_vector(int _iProjFrom, int _iProjTo, int _iDetFrom, int _iDetTo, Policy& p) +void CParallelBeamLinearKernelProjector2D::projectBlock_internal(int _iProjFrom, int _iProjTo, int _iDetFrom, int _iDetTo, Policy& p) { // variables float32 detX, detY, x, y, c, r, update_c, update_r, offset; float32 lengthPerRow, lengthPerCol, inv_pixelLengthX, inv_pixelLengthY; - int iVolumeIndex, iRayIndex, row, col, iAngle, iDetector; - + int iVolumeIndex, iRayIndex, row, col, iAngle, iDetector, colCount, rowCount, detCount; const SParProjection * proj = 0; - const CParallelVecProjectionGeometry2D* pVecProjectionGeometry = dynamic_cast(m_pProjectionGeometry); + // get vector geometry + const CParallelVecProjectionGeometry2D* pVecProjectionGeometry; + if (dynamic_cast(m_pProjectionGeometry)) { + pVecProjectionGeometry = dynamic_cast(m_pProjectionGeometry)->toVectorGeometry(); + } else { + pVecProjectionGeometry = dynamic_cast(m_pProjectionGeometry); + } + + // precomputations inv_pixelLengthX = 1.0f / m_pVolumeGeometry->getPixelLengthX(); inv_pixelLengthY = 1.0f / m_pVolumeGeometry->getPixelLengthY(); - - int colCount = m_pVolumeGeometry->getGridColCount(); - int rowCount = m_pVolumeGeometry->getGridRowCount(); + colCount = m_pVolumeGeometry->getGridColCount(); + rowCount = m_pVolumeGeometry->getGridRowCount(); + detCount = pVecProjectionGeometry->getDetectorCount(); // loop angles for (iAngle = _iProjFrom; iAngle < _iProjTo; ++iAngle) { @@ -310,4 +169,4 @@ void CParallelBeamLinearKernelProjector2D::projectBlock_internal_vector(int _iPr } // end loop detector } // end loop angles -} \ No newline at end of file +} diff --git a/include/astra/ParallelBeamStripKernelProjector2D.h b/include/astra/ParallelBeamStripKernelProjector2D.h index c2bb0ed..8fb665f 100644 --- a/include/astra/ParallelBeamStripKernelProjector2D.h +++ b/include/astra/ParallelBeamStripKernelProjector2D.h @@ -184,12 +184,6 @@ protected: 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 - void projectBlock_internal_vector(int _iProjFrom, int _iProjTo, - int _iDetFrom, int _iDetTo, Policy& _policy); - }; //---------------------------------------------------------------------------------------- diff --git a/include/astra/ParallelBeamStripKernelProjector2D.inl b/include/astra/ParallelBeamStripKernelProjector2D.inl index 684408b..31d222a 100644 --- a/include/astra/ParallelBeamStripKernelProjector2D.inl +++ b/include/astra/ParallelBeamStripKernelProjector2D.inl @@ -29,305 +29,51 @@ $Id$ template void CParallelBeamStripKernelProjector2D::project(Policy& p) { - if (dynamic_cast(m_pProjectionGeometry)) { - projectBlock_internal(0, m_pProjectionGeometry->getProjectionAngleCount(), - 0, m_pProjectionGeometry->getDetectorCount(), p); - } else if (dynamic_cast(m_pProjectionGeometry)) { - projectBlock_internal_vector(0, m_pProjectionGeometry->getProjectionAngleCount(), - 0, m_pProjectionGeometry->getDetectorCount(), p); - } + projectBlock_internal(0, m_pProjectionGeometry->getProjectionAngleCount(), + 0, m_pProjectionGeometry->getDetectorCount(), p); } template void CParallelBeamStripKernelProjector2D::projectSingleProjection(int _iProjection, Policy& p) { - if (dynamic_cast(m_pProjectionGeometry)) { - projectBlock_internal(_iProjection, _iProjection + 1, - 0, m_pProjectionGeometry->getDetectorCount(), p); - } else if (dynamic_cast(m_pProjectionGeometry)) { - projectBlock_internal_vector(_iProjection, _iProjection + 1, - 0, m_pProjectionGeometry->getDetectorCount(), p); - } + projectBlock_internal(_iProjection, _iProjection + 1, + 0, m_pProjectionGeometry->getDetectorCount(), p); } template void CParallelBeamStripKernelProjector2D::projectSingleRay(int _iProjection, int _iDetector, Policy& p) { - if (dynamic_cast(m_pProjectionGeometry)) { - projectBlock_internal(_iProjection, _iProjection + 1, - _iDetector, _iDetector + 1, p); - } else if (dynamic_cast(m_pProjectionGeometry)) { - projectBlock_internal_vector(_iProjection, _iProjection + 1, + projectBlock_internal(_iProjection, _iProjection + 1, _iDetector, _iDetector + 1, p); - } } + //---------------------------------------------------------------------------------------- // PROJECT BLOCK template void CParallelBeamStripKernelProjector2D::projectBlock_internal(int _iProjFrom, int _iProjTo, int _iDetFrom, int _iDetTo, 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 = _iProjFrom; iAngle < _iProjTo; ++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 = _iDetFrom; iDetector < _iDetTo; ++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 = _iDetFrom; iDetector < _iDetTo; ++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 BLOCK - vector projection geometry -template -void CParallelBeamStripKernelProjector2D::projectBlock_internal_vector(int _iProjFrom, int _iProjTo, int _iDetFrom, int _iDetTo, Policy& p) { // variables - float32 detX, detY, detLX, detLY, detRX, detRY, S, T, update_c, update_r, offsetL, offsetR, invTminS; - float32 lengthPerRow, lengthPerCol, inv_pixelLengthX, inv_pixelLengthY, pixelArea; - int iVolumeIndex, iRayIndex, iRayIndexL, iRayIndexR, row, row_top, row_bottom, col, col_left, col_right, iAngle, iDetector, colCount, rowCount; - + float32 detLX, detLY, detRX, detRY, S, T, update_c, update_r, offsetL, offsetR, invTminS; + float32 inv_pixelLengthX, inv_pixelLengthY, pixelArea, res, fRxOverRy, fRyOverRx; + int iVolumeIndex, iRayIndex, iAngle, iDetector; + int row, row_top, row_bottom, col, col_left, col_right, colCount, rowCount, detCount; const SParProjection * proj = 0; - const CParallelVecProjectionGeometry2D* pVecProjectionGeometry = dynamic_cast(m_pProjectionGeometry); + + // get vector geometry + const CParallelVecProjectionGeometry2D* pVecProjectionGeometry; + if (dynamic_cast(m_pProjectionGeometry)) { + pVecProjectionGeometry = dynamic_cast(m_pProjectionGeometry)->toVectorGeometry(); + } else { + pVecProjectionGeometry = dynamic_cast(m_pProjectionGeometry); + } + // precomputations inv_pixelLengthX = 1.0f / m_pVolumeGeometry->getPixelLengthX(); inv_pixelLengthY = 1.0f / m_pVolumeGeometry->getPixelLengthY(); pixelArea = m_pVolumeGeometry->getPixelLengthX() * m_pVolumeGeometry->getPixelLengthY(); - colCount = m_pVolumeGeometry->getGridColCount(); rowCount = m_pVolumeGeometry->getGridRowCount(); + detCount = pVecProjectionGeometry->getDetectorCount(); // loop angles for (iAngle = _iProjFrom; iAngle < _iProjTo; ++iAngle) { @@ -336,27 +82,29 @@ void CParallelBeamStripKernelProjector2D::projectBlock_internal_vector(int _iPro bool vertical = fabs(proj->fRayX) < fabs(proj->fRayY); if (vertical) { - S = 0.5f - 0.5f*fabs(proj->fRayX/proj->fRayY); - T = 0.5f + 0.5f*fabs(proj->fRayX/proj->fRayY); - update_c = -m_pVolumeGeometry->getPixelLengthY() * (proj->fRayX/proj->fRayY) * inv_pixelLengthX; + fRxOverRy = proj->fRayX/proj->fRayY; + update_c = -m_pVolumeGeometry->getPixelLengthY() * fRxOverRy * inv_pixelLengthX; + S = 0.5f - 0.5f*fabs(fRxOverRy); + T = 0.5f + 0.5f*fabs(fRxOverRy); invTminS = 1.0f / (T-S); } else { - S = 0.5f - 0.5f*fabs(proj->fRayY/proj->fRayX); - T = 0.5f + 0.5f*fabs(proj->fRayY/proj->fRayX); - update_r = -m_pVolumeGeometry->getPixelLengthX() * (proj->fRayY/proj->fRayX) * inv_pixelLengthY; + fRyOverRx = proj->fRayY/proj->fRayX; + update_r = -m_pVolumeGeometry->getPixelLengthX() * fRyOverRx * inv_pixelLengthY; + S = 0.5f - 0.5f*fabs(fRyOverRx); + T = 0.5f + 0.5f*fabs(fRyOverRx); invTminS = 1.0f / (T-S); } // loop detectors for (iDetector = _iDetFrom; iDetector < _iDetTo; ++iDetector) { - iRayIndex = iAngle * m_pProjectionGeometry->getDetectorCount() + iDetector; + iRayIndex = iAngle * detCount + iDetector; // POLICY: RAY PRIOR if (!p.rayPrior(iRayIndex)) continue; - detLX = proj->fDetSX + (iDetector+0.0f) * proj->fDetUX; - detLY = proj->fDetSY + (iDetector+0.0f) * proj->fDetUY; + detLX = proj->fDetSX + iDetector * proj->fDetUX; + detLY = proj->fDetSY + iDetector * proj->fDetUY; detRX = detLX + proj->fDetUX; detRY = detLY + proj->fDetUY; @@ -364,9 +112,9 @@ void CParallelBeamStripKernelProjector2D::projectBlock_internal_vector(int _iPro if (vertical) { // calculate cL and cR for row 0 - float32 xL = detLX + (proj->fRayX/proj->fRayY)*(m_pVolumeGeometry->pixelRowToCenterY(0)-detLY); + float32 xL = detLX + fRxOverRy*(m_pVolumeGeometry->pixelRowToCenterY(0)-detLY); float32 cL = (xL - m_pVolumeGeometry->getWindowMinX()) * inv_pixelLengthX - 0.5f; - float32 xR = detRX + (proj->fRayX/proj->fRayY)*(m_pVolumeGeometry->pixelRowToCenterY(0)-detRY); + float32 xR = detRX + fRxOverRy*(m_pVolumeGeometry->pixelRowToCenterY(0)-detRY); float32 cR = (xR - m_pVolumeGeometry->getWindowMinX()) * inv_pixelLengthX - 0.5f; if (cR < cL) { @@ -384,23 +132,23 @@ void CParallelBeamStripKernelProjector2D::projectBlock_internal_vector(int _iPro if (col_left < 0) col_left = 0; if (col_right > colCount-1) col_right = colCount-1; + offsetL = cL - float32(col_left); + offsetR = cR - float32(col_left); + // for each column - for (col = col_left; col <= col_right; ++col) { + for (col = col_left; col <= col_right; ++col, offsetL -= 1.0f, offsetR -= 1.0f) { iVolumeIndex = row * colCount + col; // POLICY: PIXEL PRIOR + ADD + POSTERIOR if (p.pixelPrior(iVolumeIndex)) { - offsetL = cL - float32(col); - offsetR = cR - float32(col); - // right ray edge - float32 res = 0.0f; if (T <= offsetR) res = 1.0f; else if (S < offsetR) res = 1.0f - 0.5f*(T-offsetR)*(T-offsetR)*invTminS; else if (-S < offsetR) res = 0.5f + offsetR; else if (-T < offsetR) res = 0.5f*(offsetR+T)*(offsetR+T)*invTminS; + else res = 0.0f; // left ray edge if (T <= offsetL) res -= 1.0f; @@ -408,7 +156,6 @@ void CParallelBeamStripKernelProjector2D::projectBlock_internal_vector(int _iPro else if (-S < offsetL) res -= 0.5f + offsetL; else if (-T < offsetL) res -= 0.5f*(offsetL+T)*(offsetL+T)*invTminS; - p.addWeight(iRayIndex, iVolumeIndex, pixelArea*res); p.pixelPosterior(iVolumeIndex); } @@ -420,9 +167,9 @@ void CParallelBeamStripKernelProjector2D::projectBlock_internal_vector(int _iPro else { // calculate rL and rR for row 0 - float32 yL = detLY + (proj->fRayY/proj->fRayX)*(m_pVolumeGeometry->pixelColToCenterX(0)-detLX); + float32 yL = detLY + fRyOverRx*(m_pVolumeGeometry->pixelColToCenterX(0)-detLX); float32 rL = (m_pVolumeGeometry->getWindowMaxY() - yL) * inv_pixelLengthY - 0.5f; - float32 yR = detRY + (proj->fRayY/proj->fRayX)*(m_pVolumeGeometry->pixelColToCenterX(0)-detRX); + float32 yR = detRY + fRyOverRx*(m_pVolumeGeometry->pixelColToCenterX(0)-detRX); float32 rR = (m_pVolumeGeometry->getWindowMaxY() - yR) * inv_pixelLengthY - 0.5f; if (rR < rL) { @@ -440,23 +187,23 @@ void CParallelBeamStripKernelProjector2D::projectBlock_internal_vector(int _iPro if (row_top < 0) row_top = 0; if (row_bottom > rowCount-1) row_bottom = rowCount-1; + offsetL = rL - float32(row_top); + offsetR = rR - float32(row_top); + // for each row - for (row = row_top; row <= row_bottom; ++row) { + for (row = row_top; row <= row_bottom; ++row, offsetL -= 1.0f, offsetR -= 1.0f) { iVolumeIndex = row * colCount + col; // POLICY: PIXEL PRIOR + ADD + POSTERIOR if (p.pixelPrior(iVolumeIndex)) { - offsetL = rL - float32(row); - offsetR = rR - float32(row); - // right ray edge - float32 res = 0.0f; if (T <= offsetR) res = 1.0f; else if (S < offsetR) res = 1.0f - 0.5f*(T-offsetR)*(T-offsetR)*invTminS; else if (-S < offsetR) res = 0.5f + offsetR; else if (-T < offsetR) res = 0.5f*(offsetR+T)*(offsetR+T)*invTminS; + else res = 0.0f; // left ray edge if (T <= offsetL) res -= 1.0f; diff --git a/include/astra/ParallelProjectionGeometry2D.h b/include/astra/ParallelProjectionGeometry2D.h index 2f7d36f..36b4b6f 100644 --- a/include/astra/ParallelProjectionGeometry2D.h +++ b/include/astra/ParallelProjectionGeometry2D.h @@ -30,6 +30,7 @@ $Id$ #define _INC_ASTRA_PARALLELPROJECTIONGEOMETRY2D #include "ProjectionGeometry2D.h" +#include "ParallelVecProjectionGeometry2D.h" namespace astra { @@ -134,7 +135,7 @@ public: * @param _sType geometry type to compare to. * @return true if _sType == "parallel". */ - virtual bool isOfType(const std::string& _sType); + virtual bool isOfType(const std::string& _sType); /** Get all settings in a Config object. * @@ -151,7 +152,12 @@ public: * * @return a unit vector describing the direction */ - virtual CVector3D getProjectionDirection(int _iProjectionIndex, int _iDetectorIndex = 0); + virtual CVector3D getProjectionDirection(int _iProjectionIndex, int _iDetectorIndex = 0); + + /** Create a vector geom + */ + CParallelVecProjectionGeometry2D* toVectorGeometry(); + }; } // namespace astra diff --git a/src/ParallelProjectionGeometry2D.cpp b/src/ParallelProjectionGeometry2D.cpp index cac8f30..64fc0b9 100644 --- a/src/ParallelProjectionGeometry2D.cpp +++ b/src/ParallelProjectionGeometry2D.cpp @@ -182,8 +182,8 @@ Config* CParallelProjectionGeometry2D::getConfiguration() const cfg->self->addChildNode("ProjectionAngles", m_pfProjectionAngles, m_iProjectionAngleCount); return cfg; } -//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- CVector3D CParallelProjectionGeometry2D::getProjectionDirection(int _iProjectionIndex, int _iDetectorIndex /* = 0 */) { CVector3D vOutput; @@ -197,4 +197,24 @@ CVector3D CParallelProjectionGeometry2D::getProjectionDirection(int _iProjection return vOutput; } +//---------------------------------------------------------------------------------------- +CParallelVecProjectionGeometry2D* CParallelProjectionGeometry2D::toVectorGeometry() +{ + SParProjection* vectors = new SParProjection[m_iProjectionAngleCount]; + for (int i = 0; i < m_iProjectionAngleCount; ++i) + { + vectors[i].fRayX = sinf(m_pfProjectionAngles[i]); + vectors[i].fRayY = -cosf(m_pfProjectionAngles[i]); + vectors[i].fDetUX = cosf(m_pfProjectionAngles[i]) * m_fDetectorWidth; + vectors[i].fDetUY = sinf(m_pfProjectionAngles[i]) * m_fDetectorWidth; + vectors[i].fDetSX = -0.5f * m_iDetectorCount * vectors[i].fDetUX; + vectors[i].fDetSY = -0.5f * m_iDetectorCount * vectors[i].fDetUY; + } + + CParallelVecProjectionGeometry2D* vecGeom = new CParallelVecProjectionGeometry2D(); + vecGeom->initialize(m_iProjectionAngleCount, m_iDetectorCount, vectors); + delete[] vectors; + return vecGeom; +} + } // end namespace astra -- cgit v1.2.3