diff options
| -rw-r--r-- | include/astra/ParallelBeamLinearKernelProjector2D.h | 4 | ||||
| -rw-r--r-- | include/astra/ParallelBeamLinearKernelProjector2D.inl | 139 | ||||
| -rw-r--r-- | src/ParallelBeamLinearKernelProjector2D.cpp | 2 | 
3 files changed, 139 insertions, 6 deletions
| diff --git a/include/astra/ParallelBeamLinearKernelProjector2D.h b/include/astra/ParallelBeamLinearKernelProjector2D.h index 855093a..3b84380 100644 --- a/include/astra/ParallelBeamLinearKernelProjector2D.h +++ b/include/astra/ParallelBeamLinearKernelProjector2D.h @@ -30,6 +30,7 @@ $Id$  #define _INC_ASTRA_PARALLELLINEARKERNELPROJECTOR  #include "ParallelProjectionGeometry2D.h" +#include "ParallelVecProjectionGeometry2D.h"  #include "Float32Data2D.h"  #include "Projector2D.h" @@ -185,6 +186,9 @@ protected:  	void projectBlock_internal(int _iProjFrom, int _iProjTo,  	                           int _iDetFrom, int _iDetTo, Policy& _policy); +	template <typename Policy> +	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 67e0d58..04577de 100644 --- a/include/astra/ParallelBeamLinearKernelProjector2D.inl +++ b/include/astra/ParallelBeamLinearKernelProjector2D.inl @@ -30,22 +30,37 @@ $Id$  template <typename Policy>  void CParallelBeamLinearKernelProjector2D::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>  void CParallelBeamLinearKernelProjector2D::projectSingleProjection(int _iProjection, Policy& p)  { -	projectBlock_internal(_iProjection, _iProjection + 1, -	                      0, m_pProjectionGeometry->getDetectorCount(), p); +	if (dynamic_cast<CParallelProjectionGeometry2D*>(m_pProjectionGeometry)) { +		projectBlock_internal(_iProjection, _iProjection + 1, +	                          0, m_pProjectionGeometry->getDetectorCount(), p); +	} else if (dynamic_cast<CParallelVecProjectionGeometry2D*>(m_pProjectionGeometry)) { +		projectBlock_internal_vector(_iProjection, _iProjection + 1, +	                                 0, m_pProjectionGeometry->getDetectorCount(), p); +	}  }  template <typename Policy>  void CParallelBeamLinearKernelProjector2D::projectSingleRay(int _iProjection, int _iDetector, Policy& p)  { -	projectBlock_internal(_iProjection, _iProjection + 1, +	if (dynamic_cast<CParallelProjectionGeometry2D*>(m_pProjectionGeometry)) { +		projectBlock_internal(_iProjection, _iProjection + 1,  	                      _iDetector, _iDetector + 1, p); +	} else if (dynamic_cast<CParallelVecProjectionGeometry2D*>(m_pProjectionGeometry)) { +		projectBlock_internal_vector(_iProjection, _iProjection + 1, +	                      _iDetector, _iDetector + 1, p); +	}  }  //---------------------------------------------------------------------------------------- @@ -182,3 +197,117 @@ void CParallelBeamLinearKernelProjector2D::projectBlock_internal(int _iProjFrom,  } +//---------------------------------------------------------------------------------------- +// PROJECT BLOCK - vector projection geometry +template <typename Policy> +void CParallelBeamLinearKernelProjector2D::projectBlock_internal_vector(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; + +	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(); + +	int colCount = m_pVolumeGeometry->getGridColCount(); +	int rowCount = m_pVolumeGeometry->getGridRowCount(); + +	// loop angles +	for (iAngle = _iProjFrom; iAngle < _iProjTo; ++iAngle) { + +		proj = &pVecProjectionGeometry->getProjectionVectors()[iAngle]; + +		bool vertical = fabs(proj->fRayX) < fabs(proj->fRayY); +		if (vertical) { +			lengthPerRow = m_pVolumeGeometry->getPixelLengthX() * sqrt(proj->fRayY*proj->fRayY + proj->fRayX*proj->fRayX) / abs(proj->fRayY); +			update_c = -m_pVolumeGeometry->getPixelLengthY() * (proj->fRayX/proj->fRayY) * inv_pixelLengthX; +		} else { +			lengthPerCol = m_pVolumeGeometry->getPixelLengthY() * sqrt(proj->fRayY*proj->fRayY + proj->fRayX*proj->fRayX) / abs(proj->fRayX); +			update_r = -m_pVolumeGeometry->getPixelLengthX() * (proj->fRayY/proj->fRayX) * inv_pixelLengthY; +		} + +		// 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 +				x = detX + (proj->fRayX/proj->fRayY)*(m_pVolumeGeometry->pixelRowToCenterY(0)-detY); +				c = (x - m_pVolumeGeometry->getWindowMinX()) * inv_pixelLengthX - 0.5f; + +				// for each row +				for (row = 0; row < rowCount; ++row, c += update_c) { + +					col = int(c); +					offset = c - float32(col); + +					if (col <= 0 || col >= colCount-1) continue; + +					iVolumeIndex = row * colCount + col; +					// POLICY: PIXEL PRIOR + ADD + POSTERIOR +					if (p.pixelPrior(iVolumeIndex)) { +						p.addWeight(iRayIndex, iVolumeIndex, (1.0f - offset) * lengthPerRow); +						p.pixelPosterior(iVolumeIndex); +					} +					 +					iVolumeIndex++; +					// POLICY: PIXEL PRIOR + ADD + POSTERIOR +					if (p.pixelPrior(iVolumeIndex)) { +						p.addWeight(iRayIndex, iVolumeIndex, offset * lengthPerRow); +						p.pixelPosterior(iVolumeIndex); +					} + +				} +			} + +			// horizontally +			else { + +				// calculate y for col 0 +				y = detY + (proj->fRayY/proj->fRayX)*(m_pVolumeGeometry->pixelColToCenterX(0)-detX); +				r = (m_pVolumeGeometry->getWindowMaxY() - y) * inv_pixelLengthY - 0.5f; + +				// for each col +				for (col = 0; col < colCount; ++col, r += update_r) { + +					int row = int(r); +					offset = r - float32(row); + +					if (row <= 0 || row >= rowCount-1) continue; + +					iVolumeIndex = row * colCount + col; +					// POLICY: PIXEL PRIOR + ADD + POSTERIOR +					if (p.pixelPrior(iVolumeIndex)) { +						p.addWeight(iRayIndex, iVolumeIndex, (1.0f - offset) * lengthPerCol); +						p.pixelPosterior(iVolumeIndex); +					} + +					iVolumeIndex += colCount; +					// POLICY: PIXEL PRIOR + ADD + POSTERIOR +					if (p.pixelPrior(iVolumeIndex)) { +						p.addWeight(iRayIndex, iVolumeIndex, offset * lengthPerCol); +						p.pixelPosterior(iVolumeIndex); +					} + +				} +			} +	 +			// POLICY: RAY POSTERIOR +			p.rayPosterior(iRayIndex); +	 +		} // end loop detector +	} // end loop angles +}
\ No newline at end of file diff --git a/src/ParallelBeamLinearKernelProjector2D.cpp b/src/ParallelBeamLinearKernelProjector2D.cpp index a710664..043db71 100644 --- a/src/ParallelBeamLinearKernelProjector2D.cpp +++ b/src/ParallelBeamLinearKernelProjector2D.cpp @@ -89,7 +89,7 @@ bool CParallelBeamLinearKernelProjector2D::_check()  	// check base class  	ASTRA_CONFIG_CHECK(CProjector2D::_check(), "ParallelBeamLinearKernelProjector2D", "Error in Projector2D initialization"); -	ASTRA_CONFIG_CHECK(dynamic_cast<CParallelProjectionGeometry2D*>(m_pProjectionGeometry), "ParallelBeamLinearKernelProjector2D", "Unsupported projection geometry"); +	ASTRA_CONFIG_CHECK(dynamic_cast<CParallelProjectionGeometry2D*>(m_pProjectionGeometry) || dynamic_cast<CParallelVecProjectionGeometry2D*>(m_pProjectionGeometry), "ParallelBeamLinearKernelProjector2D", "Unsupported projection geometry");  	/// TODO: ADD PIXEL H/W LIMITATIONS  	ASTRA_CONFIG_CHECK(m_pVolumeGeometry->getPixelLengthX() == m_pVolumeGeometry->getPixelLengthY(), "ParallelBeamLinearKernelProjector2D", "Pixel height must equal pixel width."); | 
