From a215ef4fb4ce341885aa74db65a5873c16637e69 Mon Sep 17 00:00:00 2001
From: Wim van Aarle <wimvanaarle@gmail.com>
Date: Thu, 5 Mar 2015 16:29:07 +0100
Subject: updated 'line' kernel projector

---
 .../astra/ParallelBeamLineKernelProjector2D.inl    | 202 ++++++++++++++++++++-
 1 file changed, 199 insertions(+), 3 deletions(-)

(limited to 'include/astra/ParallelBeamLineKernelProjector2D.inl')

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
-- 
cgit v1.2.3


From 1af118ebea7bffe4eba070dca35127234d39b426 Mon Sep 17 00:00:00 2001
From: Wim van Aarle <wimvanaarle@gmail.com>
Date: Fri, 6 Mar 2015 17:19:44 +0100
Subject: 'line' kernel optimizations

---
 .../astra/ParallelBeamLineKernelProjector2D.inl    | 73 +++++++++++++---------
 1 file changed, 43 insertions(+), 30 deletions(-)

(limited to 'include/astra/ParallelBeamLineKernelProjector2D.inl')

diff --git a/include/astra/ParallelBeamLineKernelProjector2D.inl b/include/astra/ParallelBeamLineKernelProjector2D.inl
index 31aa138..69978b0 100644
--- a/include/astra/ParallelBeamLineKernelProjector2D.inl
+++ b/include/astra/ParallelBeamLineKernelProjector2D.inl
@@ -34,22 +34,32 @@ void CParallelBeamLineKernelProjector2D::project(Policy& p)
 		                      0, m_pProjectionGeometry->getDetectorCount(), p);
 	} else if (dynamic_cast<CParallelVecProjectionGeometry2D*>(m_pProjectionGeometry)) {
 		projectBlock_internal_vector(0, m_pProjectionGeometry->getProjectionAngleCount(),
-		                             0, m_pProjectionGeometry->getDetectorCount(), p);		
+		                             0, m_pProjectionGeometry->getDetectorCount(), p);
 	}
 }
 
 template <typename Policy>
 void CParallelBeamLineKernelProjector2D::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 CParallelBeamLineKernelProjector2D::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);
+	}
 }
 
 
@@ -313,6 +323,9 @@ void CParallelBeamLineKernelProjector2D::projectBlock_internal_vector(int _iProj
 	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) {
 
@@ -320,15 +333,17 @@ void CParallelBeamLineKernelProjector2D::projectBlock_internal_vector(int _iProj
 
 		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));
+			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;
 		} else {
-			S = abs(0.5f * (1.0f - proj->fRayX/proj->fRayY));
-			T = abs(0.5f * (1.0f + proj->fRayX/proj->fRayY));
+			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;
 		}
 
 		// loop detectors
@@ -346,30 +361,29 @@ void CParallelBeamLineKernelProjector2D::projectBlock_internal_vector(int _iProj
 			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;
+				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 < m_pVolumeGeometry->getGridRowCount(); ++row, c += update_c) {
+				for (row = 0; row < rowCount; ++row, c += update_c) {
 
 					col = int(c+0.5f);
 					offset = c - float32(col);
 
-					if (col <= 0 || col >= m_pVolumeGeometry->getGridColCount()-1) continue;
+					if (col <= 0 || col >= colCount-1) continue;
 
 					// left
 					if (offset < -S) {
 						I = (offset + T) * invTminSTimesLengthPerRow;
 
-						iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, col-1);
+						iVolumeIndex = row * colCount + 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);
+						iVolumeIndex++;
 						// POLICY: PIXEL PRIOR + ADD + POSTERIOR
 						if (p.pixelPrior(iVolumeIndex)) {
 							p.addWeight(iRayIndex, iVolumeIndex, I);
@@ -381,14 +395,14 @@ void CParallelBeamLineKernelProjector2D::projectBlock_internal_vector(int _iProj
 					else if (S < offset) {
 						I = (offset - S) * invTminSTimesLengthPerRow;
 
-						iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, col);
+						iVolumeIndex = row * colCount + 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);
+						iVolumeIndex++;
 						// POLICY: PIXEL PRIOR + ADD + POSTERIOR
 						if (p.pixelPrior(iVolumeIndex)) {
 							p.addWeight(iRayIndex, iVolumeIndex, I);
@@ -398,7 +412,7 @@ void CParallelBeamLineKernelProjector2D::projectBlock_internal_vector(int _iProj
 
 					// centre
 					else {
-						iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, col);
+						iVolumeIndex = row * colCount + col;
 						// POLICY: PIXEL PRIOR + ADD + POSTERIOR
 						if (p.pixelPrior(iVolumeIndex)) {
 							p.addWeight(iRayIndex, iVolumeIndex, lengthPerRow);
@@ -413,30 +427,29 @@ void CParallelBeamLineKernelProjector2D::projectBlock_internal_vector(int _iProj
 			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;
+				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 < m_pVolumeGeometry->getGridColCount(); ++col, r += update_r) {
+				for (col = 0; col < colCount; ++col, r += update_r) {
 
 					int row = int(r+0.5f);
-					float32 offset = r - float32(row);
+					offset = r - float32(row);
 
-					if (row <= 0 || row >= m_pVolumeGeometry->getGridRowCount()-1) continue;
+					if (row <= 0 || row >= rowCount-1) continue;
 
 					// up
 					if (offset < -S) {
 						I = (offset + T) * invTminSTimesLengthPerCol;
 
-						iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row-1, col);
+						iVolumeIndex = (row-1) * colCount + 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);
+						iVolumeIndex += colCount;
 						// POLICY: PIXEL PRIOR + ADD + POSTERIOR
 						if (p.pixelPrior(iVolumeIndex)) {
 							p.addWeight(iRayIndex, iVolumeIndex, I);
@@ -448,14 +461,14 @@ void CParallelBeamLineKernelProjector2D::projectBlock_internal_vector(int _iProj
 					else if (S < offset) {
 						I = (offset - S) * invTminSTimesLengthPerCol;
 
-						iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, col);
+						iVolumeIndex = row * colCount + 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);
+						iVolumeIndex += colCount;
 						// POLICY: PIXEL PRIOR + ADD + POSTERIOR
 						if (p.pixelPrior(iVolumeIndex)) {
 							p.addWeight(iRayIndex, iVolumeIndex, I);
@@ -465,7 +478,7 @@ void CParallelBeamLineKernelProjector2D::projectBlock_internal_vector(int _iProj
 
 					// centre
 					else {
-						iVolumeIndex = m_pVolumeGeometry->pixelRowColToIndex(row, col);
+						iVolumeIndex = row * colCount + col;
 						// POLICY: PIXEL PRIOR + ADD + POSTERIOR
 						if (p.pixelPrior(iVolumeIndex)) {
 							p.addWeight(iRayIndex, iVolumeIndex, lengthPerCol);
@@ -474,7 +487,7 @@ void CParallelBeamLineKernelProjector2D::projectBlock_internal_vector(int _iProj
 					}
 
 				}
-			} // end loop col
+			}
 	
 			// POLICY: RAY POSTERIOR
 			p.rayPosterior(iRayIndex);
-- 
cgit v1.2.3


From 2c1999b1bbfb7ef2ca1ae22b43e2a0ab8108073f Mon Sep 17 00:00:00 2001
From: Wim van Aarle <wimvanaarle@gmail.com>
Date: Thu, 12 Mar 2015 11:40:56 +0100
Subject: parallel projectors now always use vector geometries internally

---
 .../astra/ParallelBeamLineKernelProjector2D.inl    | 302 ++-------------------
 1 file changed, 26 insertions(+), 276 deletions(-)

(limited to 'include/astra/ParallelBeamLineKernelProjector2D.inl')

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 <typename Policy>
 void CParallelBeamLineKernelProjector2D::project(Policy& 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);
-	}
+	projectBlock_internal(0, m_pProjectionGeometry->getProjectionAngleCount(),
+		                  0, m_pProjectionGeometry->getDetectorCount(), p);
 }
 
 template <typename Policy>
 void CParallelBeamLineKernelProjector2D::projectSingleProjection(int _iProjection, Policy& 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);
-	}
+	projectBlock_internal(_iProjection, _iProjection + 1,
+	                      0, m_pProjectionGeometry->getDetectorCount(), p);
 }
 
 template <typename Policy>
 void CParallelBeamLineKernelProjector2D::projectSingleRay(int _iProjection, int _iDetector, Policy& p)
 {
-	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,
+	projectBlock_internal(_iProjection, _iProjection + 1,
 	                      _iDetector, _iDetector + 1, p);
-	}
 }
 
 
-//----------------------------------------------------------------------------------------
-// PROJECT BLOCK - default projection geometry
-template <typename Policy>
-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<CParallelProjectionGeometry2D*>(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 <typename Policy>
-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<CParallelVecProjectionGeometry2D*>(m_pProjectionGeometry);
 
+	// get vector geometry
+	const CParallelVecProjectionGeometry2D* pVecProjectionGeometry;
+	if (dynamic_cast<CParallelProjectionGeometry2D*>(m_pProjectionGeometry)) {
+		pVecProjectionGeometry = dynamic_cast<CParallelProjectionGeometry2D*>(m_pProjectionGeometry)->toVectorGeometry();
+	} else {
+		pVecProjectionGeometry = dynamic_cast<CParallelVecProjectionGeometry2D*>(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
+}
-- 
cgit v1.2.3


From 1ff4a270a7df1edb54dd91fe653d6a936b959b3a Mon Sep 17 00:00:00 2001
From: Wim van Aarle <wimvanaarle@gmail.com>
Date: Wed, 27 May 2015 15:48:48 +0200
Subject: some marginal gains + added documentation

---
 .../astra/ParallelBeamLineKernelProjector2D.inl    | 209 ++++++++++++++-------
 1 file changed, 140 insertions(+), 69 deletions(-)

(limited to 'include/astra/ParallelBeamLineKernelProjector2D.inl')

diff --git a/include/astra/ParallelBeamLineKernelProjector2D.inl b/include/astra/ParallelBeamLineKernelProjector2D.inl
index 9c58d60..199cfd7 100644
--- a/include/astra/ParallelBeamLineKernelProjector2D.inl
+++ b/include/astra/ParallelBeamLineKernelProjector2D.inl
@@ -25,6 +25,7 @@ along with the ASTRA Toolbox. If not, see <http://www.gnu.org/licenses/>.
 -----------------------------------------------------------------------
 $Id$
 */
+#define policy_weight(p,rayindex,volindex,weight) if (p.pixelPrior(volindex)) { p.addWeight(rayindex, volindex, weight); p.pixelPosterior(volindex); }
 
 template <typename Policy>
 void CParallelBeamLineKernelProjector2D::project(Policy& p)
@@ -48,10 +49,95 @@ void CParallelBeamLineKernelProjector2D::projectSingleRay(int _iProjection, int
 }
 
 
-
-
 //----------------------------------------------------------------------------------------
 // PROJECT BLOCK - vector projection geometry
+// 
+// Kernel limitations: isotropic pixels (PixelLengthX == PixelLengthY)
+//
+// For each angle/detector pair:
+// 
+// Let D=(Dx,Dy) denote the centre of the detector (point) in volume coordinates, and
+// let R=(Rx,Ry) denote the direction of the ray (vector).
+// 
+// For mainly vertical rays (|Rx|<=|Ry|), 
+// let E=(Ex,Ey) denote the centre of the most upper left pixel:
+//    E = (WindowMinX +  PixelLengthX/2, WindowMaxY - PixelLengthY/2),
+// and let F=(Fx,Fy) denote a vector to the next pixel 
+//    F = (PixelLengthX, 0)
+// 
+// The intersection of the ray (D+aR) with the centre line of the upper row of pixels (E+bF) is
+//    { Dx + a*Rx = Ex + b*Fx
+//    { Dy + a*Ry = Ey + b*Fy
+// Solving for (a,b) results in:
+//    a = (Ey + b*Fy - Dy)/Ry
+//      = (Ey - Dy)/Ry
+//    b = (Dx + a*Rx - Ex)/Fx
+//      = (Dx + (Ey - Dy)*Rx/Ry - Ex)/Fx
+//
+// Define c as the x-value of the intersection of the ray with the upper row in pixel coordinates. 
+//    c = b 
+//
+// The intersection of the ray (D+aR) with the centre line of the second row of pixels (E'+bF) with
+//    E'=(WindowMinX + PixelLengthX/2, WindowMaxY - 3*PixelLengthY/2)
+// expressed in x-value pixel coordinates is
+//    c' = (Dx + (Ey' - Dy)*Rx/Ry - Ex)/Fx.
+// And thus:
+//    deltac = c' - c = (Dx + (Ey' - Dy)*Rx/Ry - Ex)/Fx - (Dx + (Ey - Dy)*Rx/Ry - Ex)/Fx
+//                    = [(Ey' - Dy)*Rx/Ry - (Ey - Dy)*Rx/Ry]/Fx
+//                    = [Ey' - Ey]*(Rx/Ry)/Fx
+//                    = [Ey' - Ey]*(Rx/Ry)/Fx
+//                    = -PixelLengthY*(Rx/Ry)/Fx.
+// 
+// Given c on a certain row, its closest pixel (col), and the distance (offset) to it, can be found: 
+//    col = floor(c+1/2)
+//    offset = c - col
+//
+// The index of this pixel is
+//    volumeIndex = row * colCount + col
+//
+// The projection kernel is defined by
+//
+//         _____       LengthPerRow
+//       /|  |  |\
+//      / |  |  | \
+//   __/  |  |  |  \__ 0
+//    -T -S  0  S  T
+//
+// with S = 1/2 - 1/2*|Rx/Ry|, T = 1/2 + 1/2*|Rx/Ry|, and LengthPerRow = pixelLengthX * sqrt(Rx^2+Ry^2) / |Ry|
+//
+// And thus
+//                            { (offset+T)/(T-S) * LengthPerRow    if  -T <= offset < S
+//    W_(rayIndex,volIndex) = { LengthPerRow                       if  -S <= offset <= S
+//                            { (offset-S)/(T-S) * LengthPerRow    if   S < offset <= T
+//
+// If -T <= offset < S, the weight for the pixel directly to the left is
+//    W_(rayIndex,volIndex-1) = LengthPerRow - (offset+T)/(T-S) * LengthPerRow,
+// and if S < offset <= T, the weight for the pixel directly to the right is
+//    W_(rayIndex,volIndex+1) = LengthPerRow - (offset-S)/(T-S) * LengthPerRow.
+//
+//
+// Mainly horizontal rays (|Rx|<=|Ry|) are handled in a similar fashion:
+//
+//    E = (WindowMinX +  PixelLengthX/2, WindowMaxY - PixelLengthY/2),
+//    F = (0, -PixelLengthX)
+//
+//    a = (Ex + b*Fx - Dx)/Rx = (Ex - Dx)/Rx
+//    b = (Dy + a*Ry - Ey)/Fy = (Dy + (Ex - Dx)*Ry/Rx - Ey)/Fy
+//    r = b
+//    deltar = PixelLengthX*(Ry/Rx)/Fy.
+//    row = floor(r+1/2)
+//    offset = r - row
+//    S = 1/2 - 1/2*|Ry/Rx|
+//    T = 1/2 + 1/2*|Ry/Rx|
+//    LengthPerCol = pixelLengthY * sqrt(Rx^2+Ry^2) / |Rx|
+//
+//                            { (offset+T)/(T-S) * LengthPerCol    if  -T <= offset < S
+//    W_(rayIndex,volIndex) = { LengthPerCol                       if  -S <= offset <= S
+//                            { (offset-S)/(T-S) * LengthPerCol    if   S < offset <= T
+//
+//    W_(rayIndex,volIndex-colcount) = LengthPerCol - (offset+T)/(T-S) * LengthPerCol
+//    W_(rayIndex,volIndex+colcount) = LengthPerCol - (offset-S)/(T-S) * LengthPerCol
+//
 template <typename Policy>
 void CParallelBeamLineKernelProjector2D::projectBlock_internal(int _iProjFrom, int _iProjTo, int _iDetFrom, int _iDetTo, Policy& p)
 {
@@ -64,8 +150,10 @@ void CParallelBeamLineKernelProjector2D::projectBlock_internal(int _iProjFrom, i
 	}
 
 	// precomputations
-	const float32 inv_pixelLengthX = 1.0f / m_pVolumeGeometry->getPixelLengthX();
-	const float32 inv_pixelLengthY = 1.0f / m_pVolumeGeometry->getPixelLengthY();
+	const float32 pixelLengthX = m_pVolumeGeometry->getPixelLengthX();
+	const float32 pixelLengthY = m_pVolumeGeometry->getPixelLengthY();
+	const float32 inv_pixelLengthX = 1.0f / pixelLengthX;
+	const float32 inv_pixelLengthY = 1.0f / pixelLengthY;
 	const int colCount = m_pVolumeGeometry->getGridColCount();
 	const int rowCount = m_pVolumeGeometry->getGridRowCount();
 	const int detCount = pVecProjectionGeometry->getDetectorCount();
@@ -75,87 +163,92 @@ void CParallelBeamLineKernelProjector2D::projectBlock_internal(int _iProjFrom, i
 	for (int iAngle = _iProjFrom; iAngle < _iProjTo; ++iAngle) {
 
 		// variables
-		float32 detX, detY, S, T, I, x, y, c, r, update_c, update_r, offset;
-		float32 lengthPerRow, lengthPerCol, invTminSTimesLengthPerRow, invTminSTimesLengthPerCol;
+		float32 Dx, Dy, Ex, Ey, S, T, weight, c, r, deltac, deltar, offset;
+		float32 RxOverRy, RyOverRx, lengthPerRow, lengthPerCol, invTminSTimesLengthPerRow, invTminSTimesLengthPerCol;
 		int iVolumeIndex, iRayIndex, row, col, iDetector;
 
 		const SParProjection * 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;
-			S = 0.5f - 0.5f*fabs(proj->fRayX/proj->fRayY);
-			T = 0.5f + 0.5f*fabs(proj->fRayX/proj->fRayY);
+			RxOverRy = proj->fRayX/proj->fRayY;
+			lengthPerRow = pixelLengthX * sqrt(proj->fRayY*proj->fRayY + proj->fRayX*proj->fRayX) / abs(proj->fRayY);
+			deltac = -pixelLengthY * RxOverRy * inv_pixelLengthX;
+			S = 0.5f - 0.5f*fabs(RxOverRy);
+			T = 0.5f + 0.5f*fabs(RxOverRy);
 			invTminSTimesLengthPerRow = lengthPerRow / (T - S);
 		} 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;
-			S = 0.5f - 0.5f*fabs(proj->fRayY/proj->fRayX);
-			T = 0.5f + 0.5f*fabs(proj->fRayY/proj->fRayX);
+			RyOverRx = proj->fRayY/proj->fRayX;
+			lengthPerCol = pixelLengthY * sqrt(proj->fRayY*proj->fRayY + proj->fRayX*proj->fRayX) / abs(proj->fRayX);
+			deltar = -pixelLengthX * RyOverRx * inv_pixelLengthY;
+			S = 0.5f - 0.5f*fabs(RyOverRx);
+			T = 0.5f + 0.5f*fabs(RyOverRx);
 			invTminSTimesLengthPerCol = lengthPerCol / (T - S);
 		}
 
+		Ex = m_pVolumeGeometry->getWindowMinY() + pixelLengthX*0.5f;
+		Ey = m_pVolumeGeometry->getWindowMaxY() - pixelLengthY*0.5f;
+
 		// loop detectors
-		for (iDetector = _iDetFrom; iDetector < _iDetTo; ++iDetector) {
-			
+		for (int 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;
 
+			Dx = proj->fDetSX + (iDetector+0.5f) * proj->fDetUX;
+			Dy = proj->fDetSY + (iDetector+0.5f) * proj->fDetUY;
+
+			bool isin = false;
+			
 			// 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;
+				// calculate c for row 0
+				c = (Dx + (Ey - Dy)*RxOverRy - Ex) * inv_pixelLengthX;
 
-				// for each row
-				for (row = 0; row < rowCount; ++row, c += update_c) {
+				// loop rows
+				for (row = 0; row < rowCount; ++row, c += deltac) {
 
 					col = int(c+0.5f);
+					if (col <= 0 || col >= colCount-1) { if (!isin) continue; else break; }
 					offset = c - float32(col);
 
-					if (col <= 0 || col >= colCount-1) continue;
-
 					// left
 					if (offset < -S) {
-						I = (offset + T) * invTminSTimesLengthPerRow;
+						weight = (offset + T) * invTminSTimesLengthPerRow;
 
 						iVolumeIndex = row * colCount + col - 1;
 						// POLICY: PIXEL PRIOR + ADD + POSTERIOR
 						if (p.pixelPrior(iVolumeIndex)) {
-							p.addWeight(iRayIndex, iVolumeIndex, lengthPerRow-I);
+							p.addWeight(iRayIndex, iVolumeIndex, lengthPerRow-weight);
 							p.pixelPosterior(iVolumeIndex);
 						}
 
 						iVolumeIndex++;
 						// POLICY: PIXEL PRIOR + ADD + POSTERIOR
 						if (p.pixelPrior(iVolumeIndex)) {
-							p.addWeight(iRayIndex, iVolumeIndex, I);
+							p.addWeight(iRayIndex, iVolumeIndex, weight);
 							p.pixelPosterior(iVolumeIndex);
 						}
 					}
 
 					// right
 					else if (S < offset) {
-						I = (offset - S) * invTminSTimesLengthPerRow;
+						weight = (offset - S) * invTminSTimesLengthPerRow;
 
 						iVolumeIndex = row * colCount + col;
 						// POLICY: PIXEL PRIOR + ADD + POSTERIOR
 						if (p.pixelPrior(iVolumeIndex)) {
-							p.addWeight(iRayIndex, iVolumeIndex, lengthPerRow-I);
+							p.addWeight(iRayIndex, iVolumeIndex, lengthPerRow-weight);
 							p.pixelPosterior(iVolumeIndex);
 						}
 
 						iVolumeIndex++;
 						// POLICY: PIXEL PRIOR + ADD + POSTERIOR
 						if (p.pixelPrior(iVolumeIndex)) {
-							p.addWeight(iRayIndex, iVolumeIndex, I);
+							p.addWeight(iRayIndex, iVolumeIndex, weight);
 							p.pixelPosterior(iVolumeIndex);
 						}
 					}
@@ -169,73 +262,51 @@ void CParallelBeamLineKernelProjector2D::projectBlock_internal(int _iProjFrom, i
 							p.pixelPosterior(iVolumeIndex);
 						}
 					}
-		
+					isin = true;
 				}
 			}
 
 			// 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;
+				// calculate r for col 0
+				r = -(Dy + (Ex - Dx)*RyOverRx - Ey) * inv_pixelLengthY;
 
-				// for each col
-				for (col = 0; col < colCount; ++col, r += update_r) {
+				// loop columns
+				for (col = 0; col < colCount; ++col, r += deltar) {
 
-					int row = int(r+0.5f);
+					row = int(r+0.5f);
+					if (row <= 0 || row >= rowCount-1) { if (!isin) continue; else break; }
 					offset = r - float32(row);
 
-					if (row <= 0 || row >= rowCount-1) continue;
-
 					// up
 					if (offset < -S) {
-						I = (offset + T) * invTminSTimesLengthPerCol;
+						weight = (offset + T) * invTminSTimesLengthPerCol;
 
 						iVolumeIndex = (row-1) * colCount + col;
-						// POLICY: PIXEL PRIOR + ADD + POSTERIOR
-						if (p.pixelPrior(iVolumeIndex)) {
-							p.addWeight(iRayIndex, iVolumeIndex, lengthPerCol-I);
-							p.pixelPosterior(iVolumeIndex);
-						}
+						policy_weight(p, iRayIndex, iVolumeIndex, lengthPerCol-weight)
 
 						iVolumeIndex += colCount;
-						// POLICY: PIXEL PRIOR + ADD + POSTERIOR
-						if (p.pixelPrior(iVolumeIndex)) {
-							p.addWeight(iRayIndex, iVolumeIndex, I);
-							p.pixelPosterior(iVolumeIndex);
-						}
+						policy_weight(p, iRayIndex, iVolumeIndex, weight)
 					}
 
 					// down
 					else if (S < offset) {
-						I = (offset - S) * invTminSTimesLengthPerCol;
+						weight = (offset - S) * invTminSTimesLengthPerCol;
 
 						iVolumeIndex = row * colCount + col;
-						// POLICY: PIXEL PRIOR + ADD + POSTERIOR
-						if (p.pixelPrior(iVolumeIndex)) {
-							p.addWeight(iRayIndex, iVolumeIndex, lengthPerCol-I);
-							p.pixelPosterior(iVolumeIndex);
-						}
+						policy_weight(p, iRayIndex, iVolumeIndex, lengthPerCol-weight)
 
 						iVolumeIndex += colCount;
-						// POLICY: PIXEL PRIOR + ADD + POSTERIOR
-						if (p.pixelPrior(iVolumeIndex)) {
-							p.addWeight(iRayIndex, iVolumeIndex, I);
-							p.pixelPosterior(iVolumeIndex);
-						}
+						policy_weight(p, iRayIndex, iVolumeIndex, weight)
 					}
 
 					// centre
 					else {
 						iVolumeIndex = row * colCount + col;
-						// POLICY: PIXEL PRIOR + ADD + POSTERIOR
-						if (p.pixelPrior(iVolumeIndex)) {
-							p.addWeight(iRayIndex, iVolumeIndex, lengthPerCol);
-							p.pixelPosterior(iVolumeIndex);
-						}
+						policy_weight(p, iRayIndex, iVolumeIndex, lengthPerCol)
 					}
-
+					isin = true;
 				}
 			}
 	
-- 
cgit v1.2.3


From 741675b458bf23cf437a6c56f95483c5c66af774 Mon Sep 17 00:00:00 2001
From: Willem Jan Palenstijn <Willem.Jan.Palenstijn@cwi.nl>
Date: Fri, 29 Jul 2016 14:08:51 +0200
Subject: Fix memory leak in CPU projectors

---
 include/astra/ParallelBeamLineKernelProjector2D.inl | 3 +++
 1 file changed, 3 insertions(+)

(limited to 'include/astra/ParallelBeamLineKernelProjector2D.inl')

diff --git a/include/astra/ParallelBeamLineKernelProjector2D.inl b/include/astra/ParallelBeamLineKernelProjector2D.inl
index 199cfd7..b3e54f9 100644
--- a/include/astra/ParallelBeamLineKernelProjector2D.inl
+++ b/include/astra/ParallelBeamLineKernelProjector2D.inl
@@ -316,4 +316,7 @@ void CParallelBeamLineKernelProjector2D::projectBlock_internal(int _iProjFrom, i
 		} // end loop detector
 	} // end loop angles
 
+	if (dynamic_cast<CParallelProjectionGeometry2D*>(m_pProjectionGeometry))
+		delete pVecProjectionGeometry;
+
 }
-- 
cgit v1.2.3


From 514f3610e61fd14f237fdd1981b45c6cf3037b21 Mon Sep 17 00:00:00 2001
From: Willem Jan Palenstijn <Willem.Jan.Palenstijn@cwi.nl>
Date: Fri, 15 Sep 2017 17:37:37 +0200
Subject: Fix boundary issues in par_line

---
 .../astra/ParallelBeamLineKernelProjector2D.inl    | 28 +++++++++++-----------
 1 file changed, 14 insertions(+), 14 deletions(-)

(limited to 'include/astra/ParallelBeamLineKernelProjector2D.inl')

diff --git a/include/astra/ParallelBeamLineKernelProjector2D.inl b/include/astra/ParallelBeamLineKernelProjector2D.inl
index 83c16d7..6976cfd 100644
--- a/include/astra/ParallelBeamLineKernelProjector2D.inl
+++ b/include/astra/ParallelBeamLineKernelProjector2D.inl
@@ -210,8 +210,8 @@ void CParallelBeamLineKernelProjector2D::projectBlock_internal(int _iProjFrom, i
 				// loop rows
 				for (row = 0; row < rowCount; ++row, c += deltac) {
 
-					col = int(c+0.5f);
-					if (col <= 0 || col >= colCount-1) { if (!isin) continue; else break; }
+					col = int(floor(c+0.5f));
+					if (col < -1 || col > colCount) { if (!isin) continue; else break; }
 					offset = c - float32(col);
 
 					// left
@@ -220,14 +220,14 @@ void CParallelBeamLineKernelProjector2D::projectBlock_internal(int _iProjFrom, i
 
 						iVolumeIndex = row * colCount + col - 1;
 						// POLICY: PIXEL PRIOR + ADD + POSTERIOR
-						if (p.pixelPrior(iVolumeIndex)) {
+						if (col > 0 && p.pixelPrior(iVolumeIndex)) {
 							p.addWeight(iRayIndex, iVolumeIndex, lengthPerRow-weight);
 							p.pixelPosterior(iVolumeIndex);
 						}
 
 						iVolumeIndex++;
 						// POLICY: PIXEL PRIOR + ADD + POSTERIOR
-						if (p.pixelPrior(iVolumeIndex)) {
+						if (col >= 0 && col < colCount && p.pixelPrior(iVolumeIndex)) {
 							p.addWeight(iRayIndex, iVolumeIndex, weight);
 							p.pixelPosterior(iVolumeIndex);
 						}
@@ -239,21 +239,21 @@ void CParallelBeamLineKernelProjector2D::projectBlock_internal(int _iProjFrom, i
 
 						iVolumeIndex = row * colCount + col;
 						// POLICY: PIXEL PRIOR + ADD + POSTERIOR
-						if (p.pixelPrior(iVolumeIndex)) {
+						if (col >= 0 && col < colCount && p.pixelPrior(iVolumeIndex)) {
 							p.addWeight(iRayIndex, iVolumeIndex, lengthPerRow-weight);
 							p.pixelPosterior(iVolumeIndex);
 						}
 
 						iVolumeIndex++;
 						// POLICY: PIXEL PRIOR + ADD + POSTERIOR
-						if (p.pixelPrior(iVolumeIndex)) {
+						if (col + 1 < colCount && p.pixelPrior(iVolumeIndex)) {
 							p.addWeight(iRayIndex, iVolumeIndex, weight);
 							p.pixelPosterior(iVolumeIndex);
 						}
 					}
 
 					// centre
-					else {
+					else if (col >= 0 && col < colCount) {
 						iVolumeIndex = row * colCount + col;
 						// POLICY: PIXEL PRIOR + ADD + POSTERIOR
 						if (p.pixelPrior(iVolumeIndex)) {
@@ -274,8 +274,8 @@ void CParallelBeamLineKernelProjector2D::projectBlock_internal(int _iProjFrom, i
 				// loop columns
 				for (col = 0; col < colCount; ++col, r += deltar) {
 
-					row = int(r+0.5f);
-					if (row <= 0 || row >= rowCount-1) { if (!isin) continue; else break; }
+					row = int(floor(r+0.5f));
+					if (row < -1 || row > rowCount) { if (!isin) continue; else break; }
 					offset = r - float32(row);
 
 					// up
@@ -283,10 +283,10 @@ void CParallelBeamLineKernelProjector2D::projectBlock_internal(int _iProjFrom, i
 						weight = (offset + T) * invTminSTimesLengthPerCol;
 
 						iVolumeIndex = (row-1) * colCount + col;
-						policy_weight(p, iRayIndex, iVolumeIndex, lengthPerCol-weight)
+						if (row > 0) { policy_weight(p, iRayIndex, iVolumeIndex, lengthPerCol-weight) }
 
 						iVolumeIndex += colCount;
-						policy_weight(p, iRayIndex, iVolumeIndex, weight)
+						if (row >= 0 && row < rowCount) { policy_weight(p, iRayIndex, iVolumeIndex, weight) }
 					}
 
 					// down
@@ -294,14 +294,14 @@ void CParallelBeamLineKernelProjector2D::projectBlock_internal(int _iProjFrom, i
 						weight = (offset - S) * invTminSTimesLengthPerCol;
 
 						iVolumeIndex = row * colCount + col;
-						policy_weight(p, iRayIndex, iVolumeIndex, lengthPerCol-weight)
+						if (row >= 0 && row < rowCount) { policy_weight(p, iRayIndex, iVolumeIndex, lengthPerCol-weight) }
 
 						iVolumeIndex += colCount;
-						policy_weight(p, iRayIndex, iVolumeIndex, weight)
+						if (row + 1 < rowCount) { policy_weight(p, iRayIndex, iVolumeIndex, weight) }
 					}
 
 					// centre
-					else {
+					else if (row >= 0 && row < rowCount) {
 						iVolumeIndex = row * colCount + col;
 						policy_weight(p, iRayIndex, iVolumeIndex, lengthPerCol)
 					}
-- 
cgit v1.2.3


From 55b2cd9192ecd36d33155161023c6d55b8811408 Mon Sep 17 00:00:00 2001
From: Willem Jan Palenstijn <Willem.Jan.Palenstijn@cwi.nl>
Date: Fri, 15 Sep 2017 18:33:22 +0200
Subject: Homogenize style

---
 .../astra/ParallelBeamLineKernelProjector2D.inl    | 42 ++++++----------------
 1 file changed, 11 insertions(+), 31 deletions(-)

(limited to 'include/astra/ParallelBeamLineKernelProjector2D.inl')

diff --git a/include/astra/ParallelBeamLineKernelProjector2D.inl b/include/astra/ParallelBeamLineKernelProjector2D.inl
index 6976cfd..3236469 100644
--- a/include/astra/ParallelBeamLineKernelProjector2D.inl
+++ b/include/astra/ParallelBeamLineKernelProjector2D.inl
@@ -24,7 +24,7 @@ along with the ASTRA Toolbox. If not, see <http://www.gnu.org/licenses/>.
 
 -----------------------------------------------------------------------
 */
-#define policy_weight(p,rayindex,volindex,weight) if (p.pixelPrior(volindex)) { p.addWeight(rayindex, volindex, weight); p.pixelPosterior(volindex); }
+#define policy_weight(p,rayindex,volindex,weight) do { if (p.pixelPrior(volindex)) { p.addWeight(rayindex, volindex, weight); p.pixelPosterior(volindex); } } while (false)
 
 template <typename Policy>
 void CParallelBeamLineKernelProjector2D::project(Policy& p)
@@ -219,18 +219,10 @@ void CParallelBeamLineKernelProjector2D::projectBlock_internal(int _iProjFrom, i
 						weight = (offset + T) * invTminSTimesLengthPerRow;
 
 						iVolumeIndex = row * colCount + col - 1;
-						// POLICY: PIXEL PRIOR + ADD + POSTERIOR
-						if (col > 0 && p.pixelPrior(iVolumeIndex)) {
-							p.addWeight(iRayIndex, iVolumeIndex, lengthPerRow-weight);
-							p.pixelPosterior(iVolumeIndex);
-						}
+						if (col > 0) { policy_weight(p, iRayIndex, iVolumeIndex, lengthPerRow-weight); }
 
 						iVolumeIndex++;
-						// POLICY: PIXEL PRIOR + ADD + POSTERIOR
-						if (col >= 0 && col < colCount && p.pixelPrior(iVolumeIndex)) {
-							p.addWeight(iRayIndex, iVolumeIndex, weight);
-							p.pixelPosterior(iVolumeIndex);
-						}
+						if (col >= 0 && col < colCount) { policy_weight(p, iRayIndex, iVolumeIndex, weight); }
 					}
 
 					// right
@@ -238,28 +230,16 @@ void CParallelBeamLineKernelProjector2D::projectBlock_internal(int _iProjFrom, i
 						weight = (offset - S) * invTminSTimesLengthPerRow;
 
 						iVolumeIndex = row * colCount + col;
-						// POLICY: PIXEL PRIOR + ADD + POSTERIOR
-						if (col >= 0 && col < colCount && p.pixelPrior(iVolumeIndex)) {
-							p.addWeight(iRayIndex, iVolumeIndex, lengthPerRow-weight);
-							p.pixelPosterior(iVolumeIndex);
-						}
+						if (col >= 0 && col < colCount) { policy_weight(p, iRayIndex, iVolumeIndex, lengthPerRow-weight); }
 
 						iVolumeIndex++;
-						// POLICY: PIXEL PRIOR + ADD + POSTERIOR
-						if (col + 1 < colCount && p.pixelPrior(iVolumeIndex)) {
-							p.addWeight(iRayIndex, iVolumeIndex, weight);
-							p.pixelPosterior(iVolumeIndex);
-						}
+						if (col + 1 < colCount) { policy_weight(p, iRayIndex, iVolumeIndex, weight); }
 					}
 
 					// centre
 					else if (col >= 0 && col < colCount) {
 						iVolumeIndex = row * colCount + col;
-						// POLICY: PIXEL PRIOR + ADD + POSTERIOR
-						if (p.pixelPrior(iVolumeIndex)) {
-							p.addWeight(iRayIndex, iVolumeIndex, lengthPerRow);
-							p.pixelPosterior(iVolumeIndex);
-						}
+						policy_weight(p, iRayIndex, iVolumeIndex, lengthPerRow);
 					}
 					isin = true;
 				}
@@ -283,10 +263,10 @@ void CParallelBeamLineKernelProjector2D::projectBlock_internal(int _iProjFrom, i
 						weight = (offset + T) * invTminSTimesLengthPerCol;
 
 						iVolumeIndex = (row-1) * colCount + col;
-						if (row > 0) { policy_weight(p, iRayIndex, iVolumeIndex, lengthPerCol-weight) }
+						if (row > 0) { policy_weight(p, iRayIndex, iVolumeIndex, lengthPerCol-weight); }
 
 						iVolumeIndex += colCount;
-						if (row >= 0 && row < rowCount) { policy_weight(p, iRayIndex, iVolumeIndex, weight) }
+						if (row >= 0 && row < rowCount) { policy_weight(p, iRayIndex, iVolumeIndex, weight); }
 					}
 
 					// down
@@ -294,16 +274,16 @@ void CParallelBeamLineKernelProjector2D::projectBlock_internal(int _iProjFrom, i
 						weight = (offset - S) * invTminSTimesLengthPerCol;
 
 						iVolumeIndex = row * colCount + col;
-						if (row >= 0 && row < rowCount) { policy_weight(p, iRayIndex, iVolumeIndex, lengthPerCol-weight) }
+						if (row >= 0 && row < rowCount) { policy_weight(p, iRayIndex, iVolumeIndex, lengthPerCol-weight); }
 
 						iVolumeIndex += colCount;
-						if (row + 1 < rowCount) { policy_weight(p, iRayIndex, iVolumeIndex, weight) }
+						if (row + 1 < rowCount) { policy_weight(p, iRayIndex, iVolumeIndex, weight); }
 					}
 
 					// centre
 					else if (row >= 0 && row < rowCount) {
 						iVolumeIndex = row * colCount + col;
-						policy_weight(p, iRayIndex, iVolumeIndex, lengthPerCol)
+						policy_weight(p, iRayIndex, iVolumeIndex, lengthPerCol);
 					}
 					isin = true;
 				}
-- 
cgit v1.2.3


From 5fba1c8c07a8dc99351edc7c3d3784e01ddf583f Mon Sep 17 00:00:00 2001
From: Willem Jan Palenstijn <Willem.Jan.Palenstijn@cwi.nl>
Date: Wed, 20 Sep 2017 14:43:21 +0200
Subject: Remove broken openmp support from CPU kernels

The writes to the volume in the (ray-driven) backprojection are not done in a thread-safe way.
---
 include/astra/ParallelBeamLineKernelProjector2D.inl | 1 -
 1 file changed, 1 deletion(-)

(limited to 'include/astra/ParallelBeamLineKernelProjector2D.inl')

diff --git a/include/astra/ParallelBeamLineKernelProjector2D.inl b/include/astra/ParallelBeamLineKernelProjector2D.inl
index 3236469..773077d 100644
--- a/include/astra/ParallelBeamLineKernelProjector2D.inl
+++ b/include/astra/ParallelBeamLineKernelProjector2D.inl
@@ -158,7 +158,6 @@ void CParallelBeamLineKernelProjector2D::projectBlock_internal(int _iProjFrom, i
 	const int detCount = pVecProjectionGeometry->getDetectorCount();
 
 	// loop angles
-	#pragma omp parallel for
 	for (int iAngle = _iProjFrom; iAngle < _iProjTo; ++iAngle) {
 
 		// variables
-- 
cgit v1.2.3


From e1a3f0ba1fe7455d0c9183ad07f106aebc1c821f Mon Sep 17 00:00:00 2001
From: Willem Jan Palenstijn <Willem.Jan.Palenstijn@cwi.nl>
Date: Wed, 20 Sep 2017 16:45:41 +0200
Subject: Fix non-square window for CPU projectors

---
 include/astra/ParallelBeamLineKernelProjector2D.inl | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'include/astra/ParallelBeamLineKernelProjector2D.inl')

diff --git a/include/astra/ParallelBeamLineKernelProjector2D.inl b/include/astra/ParallelBeamLineKernelProjector2D.inl
index 773077d..d88d1cb 100644
--- a/include/astra/ParallelBeamLineKernelProjector2D.inl
+++ b/include/astra/ParallelBeamLineKernelProjector2D.inl
@@ -184,7 +184,7 @@ void CParallelBeamLineKernelProjector2D::projectBlock_internal(int _iProjFrom, i
 			invTminSTimesLengthPerCol = lengthPerCol / (T - S);
 		}
 
-		Ex = m_pVolumeGeometry->getWindowMinY() + pixelLengthX*0.5f;
+		Ex = m_pVolumeGeometry->getWindowMinX() + pixelLengthX*0.5f;
 		Ey = m_pVolumeGeometry->getWindowMaxY() - pixelLengthY*0.5f;
 
 		// loop detectors
-- 
cgit v1.2.3


From 90ef1f69d79a0c40414c5932dfa9bd69f363ae80 Mon Sep 17 00:00:00 2001
From: Willem Jan Palenstijn <Willem.Jan.Palenstijn@cwi.nl>
Date: Tue, 10 Oct 2017 13:15:53 +0200
Subject: Scale 2D projection results by detector pixel width

The strip and cuda projectors already did this scaling, so this
makes the other behave consistently.
---
 include/astra/ParallelBeamLineKernelProjector2D.inl | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

(limited to 'include/astra/ParallelBeamLineKernelProjector2D.inl')

diff --git a/include/astra/ParallelBeamLineKernelProjector2D.inl b/include/astra/ParallelBeamLineKernelProjector2D.inl
index d88d1cb..e516fe1 100644
--- a/include/astra/ParallelBeamLineKernelProjector2D.inl
+++ b/include/astra/ParallelBeamLineKernelProjector2D.inl
@@ -167,17 +167,19 @@ void CParallelBeamLineKernelProjector2D::projectBlock_internal(int _iProjFrom, i
 
 		const SParProjection * proj = &pVecProjectionGeometry->getProjectionVectors()[iAngle];
 
+		float32 detSize = sqrt(proj->fDetUX * proj->fDetUX + proj->fDetUY * proj->fDetUY);
+
 		bool vertical = fabs(proj->fRayX) < fabs(proj->fRayY);
 		if (vertical) {
 			RxOverRy = proj->fRayX/proj->fRayY;
-			lengthPerRow = pixelLengthX * sqrt(proj->fRayY*proj->fRayY + proj->fRayX*proj->fRayX) / abs(proj->fRayY);
+			lengthPerRow = detSize * pixelLengthX * sqrt(proj->fRayY*proj->fRayY + proj->fRayX*proj->fRayX) / abs(proj->fRayY);
 			deltac = -pixelLengthY * RxOverRy * inv_pixelLengthX;
 			S = 0.5f - 0.5f*fabs(RxOverRy);
 			T = 0.5f + 0.5f*fabs(RxOverRy);
 			invTminSTimesLengthPerRow = lengthPerRow / (T - S);
 		} else {
 			RyOverRx = proj->fRayY/proj->fRayX;
-			lengthPerCol = pixelLengthY * sqrt(proj->fRayY*proj->fRayY + proj->fRayX*proj->fRayX) / abs(proj->fRayX);
+			lengthPerCol = detSize * pixelLengthY * sqrt(proj->fRayY*proj->fRayY + proj->fRayX*proj->fRayX) / abs(proj->fRayX);
 			deltar = -pixelLengthX * RyOverRx * inv_pixelLengthY;
 			S = 0.5f - 0.5f*fabs(RyOverRx);
 			T = 0.5f + 0.5f*fabs(RyOverRx);
-- 
cgit v1.2.3


From 08df6c4167118e0a3b5f128078f9c13f206a171a Mon Sep 17 00:00:00 2001
From: Willem Jan Palenstijn <Willem.Jan.Palenstijn@cwi.nl>
Date: Thu, 12 Oct 2017 15:17:10 +0200
Subject: Fix some warnings

---
 .../astra/ParallelBeamLineKernelProjector2D.inl    | 179 ++++++++++-----------
 1 file changed, 89 insertions(+), 90 deletions(-)

(limited to 'include/astra/ParallelBeamLineKernelProjector2D.inl')

diff --git a/include/astra/ParallelBeamLineKernelProjector2D.inl b/include/astra/ParallelBeamLineKernelProjector2D.inl
index e516fe1..7db0a34 100644
--- a/include/astra/ParallelBeamLineKernelProjector2D.inl
+++ b/include/astra/ParallelBeamLineKernelProjector2D.inl
@@ -49,94 +49,94 @@ void CParallelBeamLineKernelProjector2D::projectSingleRay(int _iProjection, int
 
 
 //----------------------------------------------------------------------------------------
-// PROJECT BLOCK - vector projection geometry
-// 
-// Kernel limitations: isotropic pixels (PixelLengthX == PixelLengthY)
-//
-// For each angle/detector pair:
-// 
-// Let D=(Dx,Dy) denote the centre of the detector (point) in volume coordinates, and
-// let R=(Rx,Ry) denote the direction of the ray (vector).
-// 
-// For mainly vertical rays (|Rx|<=|Ry|), 
-// let E=(Ex,Ey) denote the centre of the most upper left pixel:
-//    E = (WindowMinX +  PixelLengthX/2, WindowMaxY - PixelLengthY/2),
-// and let F=(Fx,Fy) denote a vector to the next pixel 
-//    F = (PixelLengthX, 0)
-// 
-// The intersection of the ray (D+aR) with the centre line of the upper row of pixels (E+bF) is
-//    { Dx + a*Rx = Ex + b*Fx
-//    { Dy + a*Ry = Ey + b*Fy
-// Solving for (a,b) results in:
-//    a = (Ey + b*Fy - Dy)/Ry
-//      = (Ey - Dy)/Ry
-//    b = (Dx + a*Rx - Ex)/Fx
-//      = (Dx + (Ey - Dy)*Rx/Ry - Ex)/Fx
-//
-// Define c as the x-value of the intersection of the ray with the upper row in pixel coordinates. 
-//    c = b 
-//
-// The intersection of the ray (D+aR) with the centre line of the second row of pixels (E'+bF) with
-//    E'=(WindowMinX + PixelLengthX/2, WindowMaxY - 3*PixelLengthY/2)
-// expressed in x-value pixel coordinates is
-//    c' = (Dx + (Ey' - Dy)*Rx/Ry - Ex)/Fx.
-// And thus:
-//    deltac = c' - c = (Dx + (Ey' - Dy)*Rx/Ry - Ex)/Fx - (Dx + (Ey - Dy)*Rx/Ry - Ex)/Fx
-//                    = [(Ey' - Dy)*Rx/Ry - (Ey - Dy)*Rx/Ry]/Fx
-//                    = [Ey' - Ey]*(Rx/Ry)/Fx
-//                    = [Ey' - Ey]*(Rx/Ry)/Fx
-//                    = -PixelLengthY*(Rx/Ry)/Fx.
-// 
-// Given c on a certain row, its closest pixel (col), and the distance (offset) to it, can be found: 
-//    col = floor(c+1/2)
-//    offset = c - col
-//
-// The index of this pixel is
-//    volumeIndex = row * colCount + col
-//
-// The projection kernel is defined by
-//
-//         _____       LengthPerRow
-//       /|  |  |\
-//      / |  |  | \
-//   __/  |  |  |  \__ 0
-//    -T -S  0  S  T
-//
-// with S = 1/2 - 1/2*|Rx/Ry|, T = 1/2 + 1/2*|Rx/Ry|, and LengthPerRow = pixelLengthX * sqrt(Rx^2+Ry^2) / |Ry|
-//
-// And thus
-//                            { (offset+T)/(T-S) * LengthPerRow    if  -T <= offset < S
-//    W_(rayIndex,volIndex) = { LengthPerRow                       if  -S <= offset <= S
-//                            { (offset-S)/(T-S) * LengthPerRow    if   S < offset <= T
-//
-// If -T <= offset < S, the weight for the pixel directly to the left is
-//    W_(rayIndex,volIndex-1) = LengthPerRow - (offset+T)/(T-S) * LengthPerRow,
-// and if S < offset <= T, the weight for the pixel directly to the right is
-//    W_(rayIndex,volIndex+1) = LengthPerRow - (offset-S)/(T-S) * LengthPerRow.
-//
-//
-// Mainly horizontal rays (|Rx|<=|Ry|) are handled in a similar fashion:
-//
-//    E = (WindowMinX +  PixelLengthX/2, WindowMaxY - PixelLengthY/2),
-//    F = (0, -PixelLengthX)
-//
-//    a = (Ex + b*Fx - Dx)/Rx = (Ex - Dx)/Rx
-//    b = (Dy + a*Ry - Ey)/Fy = (Dy + (Ex - Dx)*Ry/Rx - Ey)/Fy
-//    r = b
-//    deltar = PixelLengthX*(Ry/Rx)/Fy.
-//    row = floor(r+1/2)
-//    offset = r - row
-//    S = 1/2 - 1/2*|Ry/Rx|
-//    T = 1/2 + 1/2*|Ry/Rx|
-//    LengthPerCol = pixelLengthY * sqrt(Rx^2+Ry^2) / |Rx|
-//
-//                            { (offset+T)/(T-S) * LengthPerCol    if  -T <= offset < S
-//    W_(rayIndex,volIndex) = { LengthPerCol                       if  -S <= offset <= S
-//                            { (offset-S)/(T-S) * LengthPerCol    if   S < offset <= T
-//
-//    W_(rayIndex,volIndex-colcount) = LengthPerCol - (offset+T)/(T-S) * LengthPerCol
-//    W_(rayIndex,volIndex+colcount) = LengthPerCol - (offset-S)/(T-S) * LengthPerCol
-//
+/* PROJECT BLOCK - vector projection geometry
+   
+   Kernel limitations: isotropic pixels (PixelLengthX == PixelLengthY)
+  
+   For each angle/detector pair:
+   
+   Let D=(Dx,Dy) denote the centre of the detector (point) in volume coordinates, and
+   let R=(Rx,Ry) denote the direction of the ray (vector).
+   
+   For mainly vertical rays (|Rx|<=|Ry|), 
+   let E=(Ex,Ey) denote the centre of the most upper left pixel:
+      E = (WindowMinX +  PixelLengthX/2, WindowMaxY - PixelLengthY/2),
+   and let F=(Fx,Fy) denote a vector to the next pixel 
+      F = (PixelLengthX, 0)
+   
+   The intersection of the ray (D+aR) with the centre line of the upper row of pixels (E+bF) is
+      { Dx + a*Rx = Ex + b*Fx
+      { Dy + a*Ry = Ey + b*Fy
+   Solving for (a,b) results in:
+      a = (Ey + b*Fy - Dy)/Ry
+        = (Ey - Dy)/Ry
+      b = (Dx + a*Rx - Ex)/Fx
+        = (Dx + (Ey - Dy)*Rx/Ry - Ex)/Fx
+  
+   Define c as the x-value of the intersection of the ray with the upper row in pixel coordinates. 
+      c = b 
+  
+   The intersection of the ray (D+aR) with the centre line of the second row of pixels (E'+bF) with
+      E'=(WindowMinX + PixelLengthX/2, WindowMaxY - 3*PixelLengthY/2)
+   expressed in x-value pixel coordinates is
+      c' = (Dx + (Ey' - Dy)*Rx/Ry - Ex)/Fx.
+   And thus:
+      deltac = c' - c = (Dx + (Ey' - Dy)*Rx/Ry - Ex)/Fx - (Dx + (Ey - Dy)*Rx/Ry - Ex)/Fx
+                      = [(Ey' - Dy)*Rx/Ry - (Ey - Dy)*Rx/Ry]/Fx
+                      = [Ey' - Ey]*(Rx/Ry)/Fx
+                      = [Ey' - Ey]*(Rx/Ry)/Fx
+                      = -PixelLengthY*(Rx/Ry)/Fx.
+   
+   Given c on a certain row, its closest pixel (col), and the distance (offset) to it, can be found: 
+      col = floor(c+1/2)
+      offset = c - col
+  
+   The index of this pixel is
+      volumeIndex = row * colCount + col
+  
+   The projection kernel is defined by
+  
+           _____       LengthPerRow
+         /|  |  |\
+        / |  |  | \
+     __/  |  |  |  \__ 0
+      -T -S  0  S  T
+  
+   with S = 1/2 - 1/2*|Rx/Ry|, T = 1/2 + 1/2*|Rx/Ry|, and LengthPerRow = pixelLengthX * sqrt(Rx^2+Ry^2) / |Ry|
+  
+   And thus
+                              { (offset+T)/(T-S) * LengthPerRow    if  -T <= offset < S
+      W_(rayIndex,volIndex) = { LengthPerRow                       if  -S <= offset <= S
+                              { (offset-S)/(T-S) * LengthPerRow    if   S < offset <= T
+  
+   If -T <= offset < S, the weight for the pixel directly to the left is
+      W_(rayIndex,volIndex-1) = LengthPerRow - (offset+T)/(T-S) * LengthPerRow,
+   and if S < offset <= T, the weight for the pixel directly to the right is
+      W_(rayIndex,volIndex+1) = LengthPerRow - (offset-S)/(T-S) * LengthPerRow.
+  
+  
+   Mainly horizontal rays (|Rx|<=|Ry|) are handled in a similar fashion:
+  
+      E = (WindowMinX +  PixelLengthX/2, WindowMaxY - PixelLengthY/2),
+      F = (0, -PixelLengthX)
+  
+      a = (Ex + b*Fx - Dx)/Rx = (Ex - Dx)/Rx
+      b = (Dy + a*Ry - Ey)/Fy = (Dy + (Ex - Dx)*Ry/Rx - Ey)/Fy
+      r = b
+      deltar = PixelLengthX*(Ry/Rx)/Fy.
+      row = floor(r+1/2)
+      offset = r - row
+      S = 1/2 - 1/2*|Ry/Rx|
+      T = 1/2 + 1/2*|Ry/Rx|
+      LengthPerCol = pixelLengthY * sqrt(Rx^2+Ry^2) / |Rx|
+  
+                              { (offset+T)/(T-S) * LengthPerCol    if  -T <= offset < S
+      W_(rayIndex,volIndex) = { LengthPerCol                       if  -S <= offset <= S
+                              { (offset-S)/(T-S) * LengthPerCol    if   S < offset <= T
+  
+      W_(rayIndex,volIndex-colcount) = LengthPerCol - (offset+T)/(T-S) * LengthPerCol
+      W_(rayIndex,volIndex+colcount) = LengthPerCol - (offset-S)/(T-S) * LengthPerCol
+*/
 template <typename Policy>
 void CParallelBeamLineKernelProjector2D::projectBlock_internal(int _iProjFrom, int _iProjTo, int _iDetFrom, int _iDetTo, Policy& p)
 {
@@ -155,7 +155,6 @@ void CParallelBeamLineKernelProjector2D::projectBlock_internal(int _iProjFrom, i
 	const float32 inv_pixelLengthY = 1.0f / pixelLengthY;
 	const int colCount = m_pVolumeGeometry->getGridColCount();
 	const int rowCount = m_pVolumeGeometry->getGridRowCount();
-	const int detCount = pVecProjectionGeometry->getDetectorCount();
 
 	// loop angles
 	for (int iAngle = _iProjFrom; iAngle < _iProjTo; ++iAngle) {
@@ -163,7 +162,7 @@ void CParallelBeamLineKernelProjector2D::projectBlock_internal(int _iProjFrom, i
 		// variables
 		float32 Dx, Dy, Ex, Ey, S, T, weight, c, r, deltac, deltar, offset;
 		float32 RxOverRy, RyOverRx, lengthPerRow, lengthPerCol, invTminSTimesLengthPerRow, invTminSTimesLengthPerCol;
-		int iVolumeIndex, iRayIndex, row, col, iDetector;
+		int iVolumeIndex, iRayIndex, row, col;
 
 		const SParProjection * proj = &pVecProjectionGeometry->getProjectionVectors()[iAngle];
 
-- 
cgit v1.2.3


From 6ccba6087654fbbd16644e7f0fd93daed479f9d3 Mon Sep 17 00:00:00 2001
From: Willem Jan Palenstijn <Willem.Jan.Palenstijn@cwi.nl>
Date: Tue, 28 Nov 2017 14:01:16 +0100
Subject: Fix FanFlatBeamLineKernelProjector memleak

---
 include/astra/ParallelBeamLineKernelProjector2D.inl | 1 +
 1 file changed, 1 insertion(+)

(limited to 'include/astra/ParallelBeamLineKernelProjector2D.inl')

diff --git a/include/astra/ParallelBeamLineKernelProjector2D.inl b/include/astra/ParallelBeamLineKernelProjector2D.inl
index 7db0a34..d07f989 100644
--- a/include/astra/ParallelBeamLineKernelProjector2D.inl
+++ b/include/astra/ParallelBeamLineKernelProjector2D.inl
@@ -295,6 +295,7 @@ void CParallelBeamLineKernelProjector2D::projectBlock_internal(int _iProjFrom, i
 		} // end loop detector
 	} // end loop angles
 
+	// Delete created vec geometry if required
 	if (dynamic_cast<CParallelProjectionGeometry2D*>(m_pProjectionGeometry))
 		delete pVecProjectionGeometry;
 
-- 
cgit v1.2.3