diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/ConeProjectionGeometry3D.cpp | 2 | ||||
| -rw-r--r-- | src/CudaFDKAlgorithm3D.cpp | 2 | ||||
| -rw-r--r-- | src/CudaFilteredBackProjectionAlgorithm.cpp | 219 | ||||
| -rw-r--r-- | src/CudaForwardProjectionAlgorithm.cpp | 66 | ||||
| -rw-r--r-- | src/CudaReconstructionAlgorithm2D.cpp | 63 | ||||
| -rw-r--r-- | src/FanFlatBeamLineKernelProjector2D.cpp | 2 | ||||
| -rw-r--r-- | src/FanFlatBeamStripKernelProjector2D.cpp | 2 | ||||
| -rw-r--r-- | src/FanFlatProjectionGeometry2D.cpp | 18 | ||||
| -rw-r--r-- | src/Float32Data2D.cpp | 2 | ||||
| -rw-r--r-- | src/GeometryUtil2D.cpp | 175 | ||||
| -rw-r--r-- | src/ParallelBeamBlobKernelProjector2D.cpp | 93 | ||||
| -rw-r--r-- | src/ParallelBeamLineKernelProjector2D.cpp | 110 | ||||
| -rw-r--r-- | src/ParallelBeamLinearKernelProjector2D.cpp | 4 | ||||
| -rw-r--r-- | src/ParallelBeamStripKernelProjector2D.cpp | 102 | ||||
| -rw-r--r-- | src/ParallelProjectionGeometry2D.cpp | 38 | ||||
| -rw-r--r-- | src/ParallelVecProjectionGeometry2D.cpp | 233 | ||||
| -rw-r--r-- | src/ProjectionGeometry2D.cpp | 26 | ||||
| -rw-r--r-- | src/Projector2D.cpp | 5 | ||||
| -rw-r--r-- | src/VolumeGeometry2D.cpp | 20 | 
19 files changed, 678 insertions, 504 deletions
diff --git a/src/ConeProjectionGeometry3D.cpp b/src/ConeProjectionGeometry3D.cpp index 217a916..e8b95f1 100644 --- a/src/ConeProjectionGeometry3D.cpp +++ b/src/ConeProjectionGeometry3D.cpp @@ -225,7 +225,7 @@ CVector3D CConeProjectionGeometry3D::getProjectionDirection(int _iProjectionInde  	#undef ROTATE -	CVector3D ret(fDetX - fSrcX, fDetY - fSrcY, fDetZ - fDetZ); +	CVector3D ret(fDetX - fSrcX, fDetY - fSrcY, fDetZ - fSrcZ);  	return ret;  } diff --git a/src/CudaFDKAlgorithm3D.cpp b/src/CudaFDKAlgorithm3D.cpp index e7c65be..f94a24f 100644 --- a/src/CudaFDKAlgorithm3D.cpp +++ b/src/CudaFDKAlgorithm3D.cpp @@ -156,7 +156,7 @@ bool CCudaFDKAlgorithm3D::initialize(const Config& _cfg)  		const CProjectionGeometry3D* projgeom = m_pSinogram->getGeometry();  		const CProjectionGeometry2D* filtgeom = pFilterData->getGeometry();  		int iPaddedDetCount = calcNextPowerOfTwo(2 * projgeom->getDetectorColCount()); -		int iHalfFFTSize = calcFFTFourSize(iPaddedDetCount); +		int iHalfFFTSize = astraCUDA::calcFFTFourierSize(iPaddedDetCount);  		if(filtgeom->getDetectorCount()!=iHalfFFTSize || filtgeom->getProjectionAngleCount()!=projgeom->getProjectionCount()){  			ASTRA_ERROR("Filter size does not match required size (%i angles, %i detectors)",projgeom->getProjectionCount(),iHalfFFTSize);  			return false; diff --git a/src/CudaFilteredBackProjectionAlgorithm.cpp b/src/CudaFilteredBackProjectionAlgorithm.cpp index a5d7b93..f3cca12 100644 --- a/src/CudaFilteredBackProjectionAlgorithm.cpp +++ b/src/CudaFilteredBackProjectionAlgorithm.cpp @@ -32,6 +32,7 @@ along with the ASTRA Toolbox. If not, see <http://www.gnu.org/licenses/>.  #include "astra/AstraObjectManager.h"  #include "astra/CudaProjector2D.h"  #include "../cuda/2d/astra.h" +#include "../cuda/2d/fbp.h"  #include "astra/Logging.h" @@ -43,8 +44,7 @@ string CCudaFilteredBackProjectionAlgorithm::type = "FBP_CUDA";  CCudaFilteredBackProjectionAlgorithm::CCudaFilteredBackProjectionAlgorithm()  {  	m_bIsInitialized = false; -	CReconstructionAlgorithm2D::_clear(); -	m_pFBP = 0; +	CCudaReconstructionAlgorithm2D::_clear();  	m_pfFilter = NULL;  	m_fFilterParameter = -1.0f;  	m_fFilterD = 1.0f; @@ -52,35 +52,8 @@ CCudaFilteredBackProjectionAlgorithm::CCudaFilteredBackProjectionAlgorithm()  CCudaFilteredBackProjectionAlgorithm::~CCudaFilteredBackProjectionAlgorithm()  { -	if(m_pfFilter != NULL) -	{ -		delete [] m_pfFilter; -		m_pfFilter = NULL; -	} - -	if(m_pFBP != NULL) -	{ -		delete m_pFBP; -		m_pFBP = NULL; -	} -} - -void CCudaFilteredBackProjectionAlgorithm::initializeFromProjector() -{ -	m_iPixelSuperSampling = 1; -	m_iGPUIndex = -1; - -	// Projector -	CCudaProjector2D* pCudaProjector = dynamic_cast<CCudaProjector2D*>(m_pProjector); -	if (!pCudaProjector) { -		if (m_pProjector) { -			ASTRA_WARN("non-CUDA Projector2D passed to FBP_CUDA"); -		} -	} else { -		m_iPixelSuperSampling = pCudaProjector->getVoxelSuperSampling(); -		m_iGPUIndex = pCudaProjector->getGPUIndex(); -	} - +	delete[] m_pfFilter; +	m_pfFilter = NULL;  }  bool CCudaFilteredBackProjectionAlgorithm::initialize(const Config& _cfg) @@ -94,51 +67,24 @@ bool CCudaFilteredBackProjectionAlgorithm::initialize(const Config& _cfg)  		clear();  	} -	// Projector -	XMLNode node = _cfg.self.getSingleNode("ProjectorId"); -	CCudaProjector2D* pCudaProjector = 0; -	if (node) { -		int id = node.getContentInt(); -		CProjector2D *projector = CProjector2DManager::getSingleton().get(id); -		pCudaProjector = dynamic_cast<CCudaProjector2D*>(projector); -		if (!pCudaProjector) { -			ASTRA_WARN("non-CUDA Projector2D passed"); -		} -	} -	CC.markNodeParsed("ProjectorId"); - - -	// sinogram data -	node = _cfg.self.getSingleNode("ProjectionDataId"); -	ASTRA_CONFIG_CHECK(node, "CudaFBP", "No ProjectionDataId tag specified."); -	int id = node.getContentInt(); -	m_pSinogram = dynamic_cast<CFloat32ProjectionData2D*>(CData2DManager::getSingleton().get(id)); -	CC.markNodeParsed("ProjectionDataId"); +	m_bIsInitialized = CCudaReconstructionAlgorithm2D::initialize(_cfg); +	if (!m_bIsInitialized) +		return false; -	// reconstruction data -	node = _cfg.self.getSingleNode("ReconstructionDataId"); -	ASTRA_CONFIG_CHECK(node, "CudaFBP", "No ReconstructionDataId tag specified."); -	id = node.getContentInt(); -	m_pReconstruction = dynamic_cast<CFloat32VolumeData2D*>(CData2DManager::getSingleton().get(id)); -	CC.markNodeParsed("ReconstructionDataId");  	// filter type -	node = _cfg.self.getSingleNode("FilterType"); +	XMLNode node = _cfg.self.getSingleNode("FilterType");  	if (node) -	{  		m_eFilter = _convertStringToFilter(node.getContent().c_str()); -	}  	else -	{  		m_eFilter = FILTER_RAMLAK; -	}  	CC.markNodeParsed("FilterType");  	// filter  	node = _cfg.self.getSingleNode("FilterSinogramId");  	if (node)  	{ -		id = node.getContentInt(); +		int id = node.getContentInt();  		const CFloat32ProjectionData2D * pFilterData = dynamic_cast<CFloat32ProjectionData2D*>(CData2DManager::getSingleton().get(id));  		m_iFilterWidth = pFilterData->getGeometry()->getDetectorCount();  		int iFilterProjectionCount = pFilterData->getGeometry()->getProjectionAngleCount(); @@ -187,20 +133,9 @@ bool CCudaFilteredBackProjectionAlgorithm::initialize(const Config& _cfg)  	initializeFromProjector(); -	// Deprecated options -	m_iPixelSuperSampling = (int)_cfg.self.getOptionNumerical("PixelSuperSampling", m_iPixelSuperSampling); -	CC.markOptionParsed("PixelSuperSampling"); -	// GPU number -	m_iGPUIndex = (int)_cfg.self.getOptionNumerical("GPUindex", -1); -	m_iGPUIndex = (int)_cfg.self.getOptionNumerical("GPUIndex", m_iGPUIndex); -	CC.markOptionParsed("GPUIndex"); -	if (!_cfg.self.hasOption("GPUIndex")) -		CC.markOptionParsed("GPUindex"); - - -	m_pFBP = new AstraFBP; -	m_bAstraFBPInit = false; +	m_pAlgo = new astraCUDA::FBP(); +	m_bAlgoInit = false;  	return check();  } @@ -225,9 +160,8 @@ bool CCudaFilteredBackProjectionAlgorithm::initialize(CFloat32ProjectionData2D *  	// success  	m_bIsInitialized = true; -	m_pFBP = new AstraFBP; - -	m_bAstraFBPInit = false; +	m_pAlgo = new astraCUDA::FBP(); +	m_bAlgoInit = false;  	if(_pfFilter != NULL)  	{ @@ -255,107 +189,26 @@ bool CCudaFilteredBackProjectionAlgorithm::initialize(CFloat32ProjectionData2D *  	return check();  } -void CCudaFilteredBackProjectionAlgorithm::run(int _iNrIterations /* = 0 */) -{ -	// check initialized -	ASTRA_ASSERT(m_bIsInitialized); - -	if (!m_bAstraFBPInit) { - -		const CVolumeGeometry2D& volgeom = *m_pReconstruction->getGeometry(); -		const CParallelProjectionGeometry2D* parprojgeom = dynamic_cast<CParallelProjectionGeometry2D*>(m_pSinogram->getGeometry()); -		const CFanFlatProjectionGeometry2D* fanprojgeom = dynamic_cast<CFanFlatProjectionGeometry2D*>(m_pSinogram->getGeometry()); - -		bool ok = true; - -		// TODO: non-square pixels? -		ok &= m_pFBP->setReconstructionGeometry(volgeom.getGridColCount(), -		                                         volgeom.getGridRowCount(), -		                                         volgeom.getPixelLengthX()); -		int iDetectorCount; -		if (parprojgeom) { - -			float *offsets, *angles, detSize, outputScale; - -			ok = convertAstraGeometry(&volgeom, parprojgeom, offsets, angles, detSize, outputScale); - - -			ok &= m_pFBP->setProjectionGeometry(parprojgeom->getProjectionAngleCount(), -			                                     parprojgeom->getDetectorCount(), -			                                     angles, -			                                     parprojgeom->getDetectorWidth()); -			iDetectorCount = parprojgeom->getDetectorCount(); - -			// TODO: Are detSize and outputScale handled correctly? -			if (offsets) -				ok &= m_pFBP->setTOffsets(offsets); -			ASTRA_ASSERT(ok); - -			delete[] offsets; -			delete[] angles; - -		} else if (fanprojgeom) { - -			astraCUDA::SFanProjection* projs; -			float outputScale; - -			// FIXME: Implement this, and clean up the interface to AstraFBP. -			if (abs(volgeom.getWindowMinX() + volgeom.getWindowMaxX()) > 0.00001 * volgeom.getPixelLengthX()) { -				// Off-center volume geometry isn't supported yet -				ASTRA_ASSERT(false); -			} -			if (abs(volgeom.getWindowMinY() + volgeom.getWindowMaxY()) > 0.00001 * volgeom.getPixelLengthY()) { -				// Off-center volume geometry isn't supported yet -				ASTRA_ASSERT(false); -			} - -			ok = convertAstraGeometry(&volgeom, fanprojgeom, projs, outputScale); - -			// CHECKME: outputScale? - -			ok &= m_pFBP->setFanGeometry(fanprojgeom->getProjectionAngleCount(), -			                             fanprojgeom->getDetectorCount(), -			                             projs, -			                             fanprojgeom->getProjectionAngles(), -			                             fanprojgeom->getOriginSourceDistance(), -			                             fanprojgeom->getOriginDetectorDistance(), - -		                                     fanprojgeom->getDetectorWidth(), -			                             m_bShortScan); - -			iDetectorCount = fanprojgeom->getDetectorCount(); - -			delete[] projs; -		} else { -			assert(false); -		} - -		ok &= m_pFBP->setPixelSuperSampling(m_iPixelSuperSampling); - -		ASTRA_ASSERT(ok); - -		ok &= m_pFBP->init(m_iGPUIndex); -		ASTRA_ASSERT(ok); +void CCudaFilteredBackProjectionAlgorithm::initCUDAAlgorithm() +{ +	CCudaReconstructionAlgorithm2D::initCUDAAlgorithm(); -		ok &= m_pFBP->setSinogram(m_pSinogram->getDataConst(), iDetectorCount); -		ASTRA_ASSERT(ok); +	astraCUDA::FBP* pFBP = dynamic_cast<astraCUDA::FBP*>(m_pAlgo); -		ok &= m_pFBP->setFilter(m_eFilter, m_pfFilter, m_iFilterWidth, m_fFilterD, m_fFilterParameter); +	bool ok = pFBP->setFilter(m_eFilter, m_pfFilter, m_iFilterWidth, m_fFilterD, m_fFilterParameter); +	if (!ok) { +		ASTRA_ERROR("CCudaFilteredBackProjectionAlgorithm: Failed to set filter");  		ASTRA_ASSERT(ok); - -		m_bAstraFBPInit = true;  	} -	bool ok = m_pFBP->run(); -	ASTRA_ASSERT(ok); - -	const CVolumeGeometry2D& volgeom = *m_pReconstruction->getGeometry(); -	ok &= m_pFBP->getReconstruction(m_pReconstruction->getData(), volgeom.getGridColCount()); - -	ASTRA_ASSERT(ok); +	ok &= pFBP->setShortScan(m_bShortScan); +	if (!ok) { +		ASTRA_ERROR("CCudaFilteredBackProjectionAlgorithm: Failed to set short-scan mode"); +	}  } +  bool CCudaFilteredBackProjectionAlgorithm::check()  {  	// check pointers @@ -382,28 +235,6 @@ bool CCudaFilteredBackProjectionAlgorithm::check()  	return true;  } -static int calcNextPowerOfTwo(int _iValue) -{ -	int iOutput = 1; - -	while(iOutput < _iValue) -	{ -		iOutput *= 2; -	} - -	return iOutput; -} - -int CCudaFilteredBackProjectionAlgorithm::calcIdealRealFilterWidth(int _iDetectorCount) -{ -	return calcNextPowerOfTwo(_iDetectorCount); -} - -int CCudaFilteredBackProjectionAlgorithm::calcIdealFourierFilterWidth(int _iDetectorCount) -{ -	return (calcNextPowerOfTwo(_iDetectorCount) / 2 + 1); -} -  static bool stringCompareLowerCase(const char * _stringA, const char * _stringB)  {  	int iCmpReturn = 0; diff --git a/src/CudaForwardProjectionAlgorithm.cpp b/src/CudaForwardProjectionAlgorithm.cpp index bac1251..f4cafe6 100644 --- a/src/CudaForwardProjectionAlgorithm.cpp +++ b/src/CudaForwardProjectionAlgorithm.cpp @@ -220,56 +220,48 @@ void CCudaForwardProjectionAlgorithm::run(int)  	// check initialized  	assert(m_bIsInitialized); -	CVolumeGeometry2D* pVolGeom = m_pVolume->getGeometry(); -	const CParallelProjectionGeometry2D* parProjGeom = dynamic_cast<CParallelProjectionGeometry2D*>(m_pSinogram->getGeometry()); -	const CFanFlatProjectionGeometry2D* fanProjGeom = dynamic_cast<CFanFlatProjectionGeometry2D*>(m_pSinogram->getGeometry()); -	const CFanFlatVecProjectionGeometry2D* fanVecProjGeom = dynamic_cast<CFanFlatVecProjectionGeometry2D*>(m_pSinogram->getGeometry()); +	bool ok; -	bool ok = false; -	if (parProjGeom) { +	const CVolumeGeometry2D* pVolGeom = m_pVolume->getGeometry(); +	const CProjectionGeometry2D* pProjGeom = m_pSinogram->getGeometry(); +	astraCUDA::SDimensions dims; -		float *offsets, *angles, detSize, outputScale; -		ok = convertAstraGeometry(pVolGeom, parProjGeom, offsets, angles, detSize, outputScale); +	ok = convertAstraGeometry_dims(pVolGeom, pProjGeom, dims); -		ASTRA_ASSERT(ok); // FIXME +	if (!ok) +		return; -		// FIXME: Output scaling +	astraCUDA::SParProjection* pParProjs = 0; +	astraCUDA::SFanProjection* pFanProjs = 0; +	float fOutputScale = 1.0f; -		ok = astraCudaFP(m_pVolume->getDataConst(), m_pSinogram->getData(), -		                 pVolGeom->getGridColCount(), pVolGeom->getGridRowCount(), -		                 parProjGeom->getProjectionAngleCount(), -		                 parProjGeom->getDetectorCount(), -		                 angles, offsets, detSize, -		                 m_iDetectorSuperSampling, 1.0f * outputScale, m_iGPUIndex); - -		delete[] offsets; -		delete[] angles; +	ok = convertAstraGeometry(pVolGeom, pProjGeom, pParProjs, pFanProjs, fOutputScale); +	if (!ok) +		return; -	} else if (fanProjGeom || fanVecProjGeom) { +	if (pParProjs) { +		assert(!pFanProjs); -		astraCUDA::SFanProjection* projs; -		float outputScale; +		ok = astraCudaFP(m_pVolume->getDataConst(), m_pSinogram->getData(), +		                 pVolGeom->getGridColCount(), pVolGeom->getGridRowCount(), +		                 pProjGeom->getProjectionAngleCount(), +		                 pProjGeom->getDetectorCount(), +		                 pParProjs, +		                 m_iDetectorSuperSampling, 1.0f * fOutputScale, m_iGPUIndex); -		if (fanProjGeom) { -			ok = convertAstraGeometry(pVolGeom, fanProjGeom, projs, outputScale); -		} else { -			ok = convertAstraGeometry(pVolGeom, fanVecProjGeom, projs, outputScale); -		} +		delete[] pParProjs; -		ASTRA_ASSERT(ok); +	} else { +		assert(pFanProjs);  		ok = astraCudaFanFP(m_pVolume->getDataConst(), m_pSinogram->getData(),  		                    pVolGeom->getGridColCount(), pVolGeom->getGridRowCount(), -		                    m_pSinogram->getGeometry()->getProjectionAngleCount(), -		                    m_pSinogram->getGeometry()->getDetectorCount(), -		                    projs, -		                    m_iDetectorSuperSampling, outputScale, m_iGPUIndex); - -		delete[] projs; - -	} else { +		                    pProjGeom->getProjectionAngleCount(), +		                    pProjGeom->getDetectorCount(), +		                    pFanProjs, +		                    m_iDetectorSuperSampling, fOutputScale, m_iGPUIndex); -		ASTRA_ASSERT(false); +		delete[] pFanProjs;  	} diff --git a/src/CudaReconstructionAlgorithm2D.cpp b/src/CudaReconstructionAlgorithm2D.cpp index 96f52f0..f37647c 100644 --- a/src/CudaReconstructionAlgorithm2D.cpp +++ b/src/CudaReconstructionAlgorithm2D.cpp @@ -249,69 +249,14 @@ bool CCudaReconstructionAlgorithm2D::setupGeometry()  	ok = m_pAlgo->setGPUIndex(m_iGPUIndex);  	if (!ok) return false; -	astraCUDA::SDimensions dims; -  	const CVolumeGeometry2D& volgeom = *m_pReconstruction->getGeometry(); +	const CProjectionGeometry2D& projgeom = *m_pSinogram->getGeometry(); -	// TODO: non-square pixels? -	dims.iVolWidth = volgeom.getGridColCount(); -	dims.iVolHeight = volgeom.getGridRowCount(); -	float fPixelSize = volgeom.getPixelLengthX(); - -	dims.iRaysPerDet = m_iDetectorSuperSampling; -	dims.iRaysPerPixelDim = m_iPixelSuperSampling; - - -	const CParallelProjectionGeometry2D* parProjGeom = dynamic_cast<CParallelProjectionGeometry2D*>(m_pSinogram->getGeometry()); -	const CFanFlatProjectionGeometry2D* fanProjGeom = dynamic_cast<CFanFlatProjectionGeometry2D*>(m_pSinogram->getGeometry()); -	const CFanFlatVecProjectionGeometry2D* fanVecProjGeom = dynamic_cast<CFanFlatVecProjectionGeometry2D*>(m_pSinogram->getGeometry()); - -	if (parProjGeom) { - -		float *offsets, *angles, detSize, outputScale; - -		ok = convertAstraGeometry(&volgeom, parProjGeom, offsets, angles, detSize, outputScale); - -		dims.iProjAngles = parProjGeom->getProjectionAngleCount(); -		dims.iProjDets = parProjGeom->getDetectorCount(); -		dims.fDetScale = parProjGeom->getDetectorWidth() / fPixelSize; - -		ok = m_pAlgo->setGeometry(dims, parProjGeom->getProjectionAngles()); -		ok &= m_pAlgo->setTOffsets(offsets); - -		// CHECKME: outputScale? detSize? - -		delete[] offsets; -		delete[] angles; - -	} else if (fanProjGeom || fanVecProjGeom) { - -		astraCUDA::SFanProjection* projs; -		float outputScale; - -		if (fanProjGeom) { -			ok = convertAstraGeometry(&volgeom, fanProjGeom, projs, outputScale); -		} else { -			ok = convertAstraGeometry(&volgeom, fanVecProjGeom, projs, outputScale); -		} - -		dims.iProjAngles = m_pSinogram->getGeometry()->getProjectionAngleCount(); -		dims.iProjDets = m_pSinogram->getGeometry()->getDetectorCount(); -		dims.fDetScale = m_pSinogram->getGeometry()->getDetectorWidth() / fPixelSize; - -		ok = m_pAlgo->setFanGeometry(dims, projs); - -		// CHECKME: outputScale? - -		delete[] projs; - -	} else { - -		ASTRA_ASSERT(false); - -	} +	ok = m_pAlgo->setGeometry(&volgeom, &projgeom);  	if (!ok) return false; +	ok = m_pAlgo->setSuperSampling(m_iDetectorSuperSampling, m_iPixelSuperSampling); +	if (!ok) return false;  	if (m_bUseReconstructionMask)  		ok &= m_pAlgo->enableVolumeMask(); diff --git a/src/FanFlatBeamLineKernelProjector2D.cpp b/src/FanFlatBeamLineKernelProjector2D.cpp index 4bfff58..7bec351 100644 --- a/src/FanFlatBeamLineKernelProjector2D.cpp +++ b/src/FanFlatBeamLineKernelProjector2D.cpp @@ -91,7 +91,7 @@ bool CFanFlatBeamLineKernelProjector2D::_check()  	ASTRA_CONFIG_CHECK(dynamic_cast<CFanFlatProjectionGeometry2D*>(m_pProjectionGeometry) || dynamic_cast<CFanFlatVecProjectionGeometry2D*>(m_pProjectionGeometry), "FanFlatBeamLineKernelProjector2D", "Unsupported projection geometry"); -	ASTRA_CONFIG_CHECK(m_pVolumeGeometry->getPixelLengthX() == m_pVolumeGeometry->getPixelLengthY(), "FanFlatBeamLineKernelProjector2D", "Pixel height must equal pixel width."); +	ASTRA_CONFIG_CHECK(abs(m_pVolumeGeometry->getPixelLengthX() / m_pVolumeGeometry->getPixelLengthY()) - 1 < eps, "FanFlatBeamLineKernelProjector2D", "Pixel height must equal pixel width.");  	// success  	return true; diff --git a/src/FanFlatBeamStripKernelProjector2D.cpp b/src/FanFlatBeamStripKernelProjector2D.cpp index 198c0ea..de12d49 100644 --- a/src/FanFlatBeamStripKernelProjector2D.cpp +++ b/src/FanFlatBeamStripKernelProjector2D.cpp @@ -89,7 +89,7 @@ bool CFanFlatBeamStripKernelProjector2D::_check()  	ASTRA_CONFIG_CHECK(dynamic_cast<CFanFlatProjectionGeometry2D*>(m_pProjectionGeometry), "FanFlatBeamLineKernelProjector2D", "Unsupported projection geometry"); -	ASTRA_CONFIG_CHECK(m_pVolumeGeometry->getPixelLengthX() == m_pVolumeGeometry->getPixelLengthY(), "FanFlatBeamStripKernelProjector2D", "Pixel height must equal pixel width."); +	ASTRA_CONFIG_CHECK(abs(m_pVolumeGeometry->getPixelLengthX() / m_pVolumeGeometry->getPixelLengthY()) - 1 < eps, "FanFlatBeamStripKernelProjector2D", "Pixel height must equal pixel width.");  	// success  	return true; diff --git a/src/FanFlatProjectionGeometry2D.cpp b/src/FanFlatProjectionGeometry2D.cpp index 28bc75e..697550c 100644 --- a/src/FanFlatProjectionGeometry2D.cpp +++ b/src/FanFlatProjectionGeometry2D.cpp @@ -27,6 +27,8 @@ along with the ASTRA Toolbox. If not, see <http://www.gnu.org/licenses/>.  #include "astra/FanFlatProjectionGeometry2D.h" +#include "astra/GeometryUtil2D.h" +  #include <cstring>  #include <sstream> @@ -213,7 +215,21 @@ Config* CFanFlatProjectionGeometry2D::getConfiguration() const  	cfg->self.addChildNode("ProjectionAngles", m_pfProjectionAngles, m_iProjectionAngleCount);  	return cfg;  } -//---------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------- +CFanFlatVecProjectionGeometry2D* CFanFlatProjectionGeometry2D::toVectorGeometry() +{ +	SFanProjection* vectors = genFanProjections(m_iProjectionAngleCount, +	                                            m_iDetectorCount, +	                                            m_fOriginSourceDistance, +	                                            m_fOriginDetectorDistance, +	                                            m_fDetectorWidth, +	                                            m_pfProjectionAngles); + +	CFanFlatVecProjectionGeometry2D* vecGeom = new CFanFlatVecProjectionGeometry2D(); +	vecGeom->initialize(m_iProjectionAngleCount, m_iDetectorCount, vectors); +	delete[] vectors; +	return vecGeom; +}  } // namespace astra diff --git a/src/Float32Data2D.cpp b/src/Float32Data2D.cpp index 56ea7cc..c5d2cc8 100644 --- a/src/Float32Data2D.cpp +++ b/src/Float32Data2D.cpp @@ -286,7 +286,7 @@ void CFloat32Data2D::_allocateData()  	ASTRA_ASSERT(!m_bInitialized);  	ASTRA_ASSERT(m_iSize > 0); -	ASTRA_ASSERT(m_iSize == (size_t)m_iWidth * m_iHeight); +	ASTRA_ASSERT((size_t)m_iSize == (size_t)m_iWidth * m_iHeight);  	ASTRA_ASSERT(m_pfData == NULL);  	ASTRA_ASSERT(m_ppfData2D == NULL); diff --git a/src/GeometryUtil2D.cpp b/src/GeometryUtil2D.cpp new file mode 100644 index 0000000..2ee6185 --- /dev/null +++ b/src/GeometryUtil2D.cpp @@ -0,0 +1,175 @@ +/* +----------------------------------------------------------------------- +Copyright: 2010-2015, iMinds-Vision Lab, University of Antwerp +           2014-2015, CWI, Amsterdam + +Contact: astra@uantwerpen.be +Website: http://sf.net/projects/astra-toolbox + +This file is part of the ASTRA Toolbox. + + +The ASTRA Toolbox is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +The ASTRA Toolbox is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with the ASTRA Toolbox. If not, see <http://www.gnu.org/licenses/>. + +----------------------------------------------------------------------- +$Id$ +*/ + +#include "astra/GeometryUtil2D.h" + +#include <cmath> + +namespace astra { + +SParProjection* genParProjections(unsigned int iProjAngles, +                                  unsigned int iProjDets, +                                  double fDetSize, +                                  const float *pfAngles, +                                  const float *pfExtraOffsets) +{ +	SParProjection base; +	base.fRayX = 0.0f; +	base.fRayY = 1.0f; + +	base.fDetSX = iProjDets * fDetSize * -0.5f; +	base.fDetSY = 0.0f; + +	base.fDetUX = fDetSize; +	base.fDetUY = 0.0f; + +	SParProjection* p = new SParProjection[iProjAngles]; + +#define ROTATE0(name,i,alpha) do { p[i].f##name##X = base.f##name##X * cos(alpha) - base.f##name##Y * sin(alpha); p[i].f##name##Y = base.f##name##X * sin(alpha) + base.f##name##Y * cos(alpha); } while(0) + +	for (unsigned int i = 0; i < iProjAngles; ++i) { +		if (pfExtraOffsets) { +			// TODO +		} + +		ROTATE0(Ray, i, pfAngles[i]); +		ROTATE0(DetS, i, pfAngles[i]); +		ROTATE0(DetU, i, pfAngles[i]); + +		if (pfExtraOffsets) { +			float d = pfExtraOffsets[i]; +			p[i].fDetSX -= d * p[i].fDetUX; +			p[i].fDetSY -= d * p[i].fDetUY; +		} +	} + +#undef ROTATE0 + +	return p; +} + + +SFanProjection* genFanProjections(unsigned int iProjAngles, +                                  unsigned int iProjDets, +                                  double fOriginSource, double fOriginDetector, +                                  double fDetSize, +                                  const float *pfAngles) +//                                  const float *pfExtraOffsets) +{ +	SFanProjection *pProjs = new SFanProjection[iProjAngles]; + +	float fSrcX0 = 0.0f; +	float fSrcY0 = -fOriginSource; +	float fDetUX0 = fDetSize; +	float fDetUY0 = 0.0f; +	float fDetSX0 = iProjDets * fDetUX0 / -2.0f; +	float fDetSY0 = fOriginDetector; + +#define ROTATE0(name,i,alpha) do { pProjs[i].f##name##X = f##name##X0 * cos(alpha) - f##name##Y0 * sin(alpha); pProjs[i].f##name##Y = f##name##X0 * sin(alpha) + f##name##Y0 * cos(alpha); } while(0) +	for (unsigned int i = 0; i < iProjAngles; ++i) { +		ROTATE0(Src, i, pfAngles[i]); +		ROTATE0(DetS, i, pfAngles[i]); +		ROTATE0(DetU, i, pfAngles[i]); +	} + +#undef ROTATE0 + +	return pProjs; +} + +// Convert a SParProjection back into its set of "standard" circular parallel +// beam parameters. This is always possible. +bool getParParameters(const SParProjection &proj, unsigned int iProjDets, float &fAngle, float &fDetSize, float &fOffset) +{ +	// Take part of DetU orthogonal to Ray +	double ux = proj.fDetUX; +	double uy = proj.fDetUY; + +	double t = (ux * proj.fRayX + uy * proj.fRayY) / (proj.fRayX * proj.fRayX + proj.fRayY * proj.fRayY); + +	ux -= t * proj.fRayX; +	uy -= t * proj.fRayY; + +	double angle = atan2(uy, ux); + +	fAngle = (float)angle; + +	double norm2 = uy * uy + ux * ux; + +	fDetSize = (float)sqrt(norm2); + +	// CHECKME: SIGNS? +	fOffset = (float)(-0.5*iProjDets - (proj.fDetSY*uy + proj.fDetSX*ux) / norm2); + +	return true; +} + +// Convert a SFanProjection back into its set of "standard" circular fan beam +// parameters. This will return false if it can not be represented in this way. +bool getFanParameters(const SFanProjection &proj, unsigned int iProjDets, float &fAngle, float &fOriginSource, float &fOriginDetector, float &fDetSize, float &fOffset) +{ +	// angle +	// det size +	// offset +	// origin-source +	// origin-detector + +	// Need to check if line source-origin is orthogonal to vector ux,uy +	// (including the case source==origin) + +	// (equivalent: source and origin project to same point on detector) + +	double dp = proj.fSrcX * proj.fDetUX + proj.fSrcY * proj.fDetUY; + +	double rel = (proj.fSrcX*proj.fSrcX + proj.fSrcY*proj.fSrcY) * (proj.fDetUX*proj.fDetUX + proj.fDetUY*proj.fDetUY); +	rel = sqrt(rel); + +	if (std::abs(dp) > rel * 0.0001) +		return false; + +	fOriginSource = sqrt(proj.fSrcX*proj.fSrcX + proj.fSrcY*proj.fSrcY); + +	fDetSize = sqrt(proj.fDetUX*proj.fDetUX + proj.fDetUY*proj.fDetUY); + +	// project origin on detector line ( == project source on detector line) + +	double t = (- proj.fDetSX) * proj.fDetUX + (- proj.fDetSY) * proj.fDetUY; + +	fOffset = (float)t - 0.5*iProjDets; + +	// TODO: CHECKME +	fOriginDetector = sqrt((proj.fDetSX + t * proj.fDetUX)*(proj.fDetSX + t * proj.fDetUX) + (proj.fDetSY + t * proj.fDetUY)*(proj.fDetSY + t * proj.fDetUY)); + +	//float fAngle = atan2(proj.fDetSX + t * proj.fDetUX - proj.fSrcX, proj.fDetSY + t * proj.fDetUY); // TODO: Fix order + sign +	fAngle = atan2(proj.fDetUY, proj.fDetUX); // TODO: Check order + sign + +	return true; +} + + +} diff --git a/src/ParallelBeamBlobKernelProjector2D.cpp b/src/ParallelBeamBlobKernelProjector2D.cpp index 5cc9174..7ff13e9 100644 --- a/src/ParallelBeamBlobKernelProjector2D.cpp +++ b/src/ParallelBeamBlobKernelProjector2D.cpp @@ -101,7 +101,7 @@ bool CParallelBeamBlobKernelProjector2D::_check()  	// check base class  	ASTRA_CONFIG_CHECK(CProjector2D::_check(), "ParallelBeamBlobKernelProjector2D", "Error in Projector2D initialization"); -	ASTRA_CONFIG_CHECK(dynamic_cast<CParallelProjectionGeometry2D*>(m_pProjectionGeometry), "ParallelBeamBlobKernelProjector2D", "Unsupported projection geometry"); +	ASTRA_CONFIG_CHECK(dynamic_cast<CParallelProjectionGeometry2D*>(m_pProjectionGeometry) || dynamic_cast<CParallelVecProjectionGeometry2D*>(m_pProjectionGeometry), "ParallelBeamBlobKernelProjector2D", "Unsupported projection geometry");  	ASTRA_CONFIG_CHECK(m_iBlobSampleCount > 0, "ParallelBeamBlobKernelProjector2D", "m_iBlobSampleCount should be strictly positive.");  	ASTRA_CONFIG_CHECK(m_pfBlobValues, "ParallelBeamBlobKernelProjector2D", "Invalid Volume Geometry Object."); @@ -154,17 +154,6 @@ bool CParallelBeamBlobKernelProjector2D::initialize(const Config& _cfg)  		for (int i = 0; i < m_iBlobSampleCount; i++) {  			m_pfBlobValues[i] = values[i];  		} - -		// Required: KernelValues -		node2 = node.getSingleNode("KernelValuesNeg"); -		ASTRA_CONFIG_CHECK(node2, "BlobProjector", "No Kernel/KernelValuesNeg tag specified."); -		vector<float32> values2 = node2.getContentNumericalArray(); -		ASTRA_CONFIG_CHECK(values2.size() == (unsigned int)m_iBlobSampleCount, "BlobProjector", "Number of specified values doesn't match SampleCount."); -		m_pfBlobValuesNeg = new float32[m_iBlobSampleCount]; -		for (int i = 0; i < m_iBlobSampleCount; i++) { -			m_pfBlobValuesNeg[i] = values2[i]; -		} -  	}  	// success @@ -227,44 +216,44 @@ void CParallelBeamBlobKernelProjector2D::computeSingleRayWeights(int _iProjectio  // Splat a single point  std::vector<SDetector2D> CParallelBeamBlobKernelProjector2D::projectPoint(int _iRow, int _iCol)  { -	float32 x = m_pVolumeGeometry->pixelColToCenterX(_iCol); -	float32 y = m_pVolumeGeometry->pixelRowToCenterY(_iRow); - -	std::vector<SDetector2D> res; -	// loop projectors and detectors -	for (int iProjection = 0; iProjection < m_pProjectionGeometry->getProjectionAngleCount(); ++iProjection) { - -		// get projection angle -		float32 theta = m_pProjectionGeometry->getProjectionAngle(iProjection); -		if (theta >= 7*PIdiv4) theta -= 2*PI; -		bool inverse = false; -		if (theta >= 3*PIdiv4) { -			theta -= PI; -			inverse = true; -		} - -		// calculate distance from the center of the voxel to the ray though the origin -		float32 t = x * cos(theta) + y * sin(theta); -		if (inverse) t *= -1.0f; - -		// calculate the offset on the detectorarray (in indices) -		float32 d = m_pProjectionGeometry->detectorOffsetToIndexFloat(t); -		int dmin = (int)ceil(d - m_fBlobSize); -		int dmax = (int)floor(d + m_fBlobSize); - -		// add affected detectors to the list -		for (int i = dmin; i <= dmax; ++i) { -			if (d >= 0 && d < m_pProjectionGeometry->getDetectorCount()) { -				SDetector2D det; -				det.m_iAngleIndex = iProjection; -				det.m_iDetectorIndex = i; -				det.m_iIndex = iProjection * getProjectionGeometry()->getDetectorCount() + i; -				res.push_back(det); -			} -		} -	} - -	// return result vector -	return res; - +	// float32 x = m_pVolumeGeometry->pixelColToCenterX(_iCol); +	// float32 y = m_pVolumeGeometry->pixelRowToCenterY(_iRow); + +	// std::vector<SDetector2D> res; +	// // loop projectors and detectors +	// for (int iProjection = 0; iProjection < m_pProjectionGeometry->getProjectionAngleCount(); ++iProjection) { + +	// 	// get projection angle +	// 	float32 theta = m_pProjectionGeometry->getProjectionAngle(iProjection); +	// 	if (theta >= 7*PIdiv4) theta -= 2*PI; +	// 	bool inverse = false; +	// 	if (theta >= 3*PIdiv4) { +	// 		theta -= PI; +	// 		inverse = true; +	// 	} + +	// 	// calculate distance from the center of the voxel to the ray though the origin +	// 	float32 t = x * cos(theta) + y * sin(theta); +	// 	if (inverse) t *= -1.0f; + +	// 	// calculate the offset on the detectorarray (in indices) +	// 	float32 d = m_pProjectionGeometry->detectorOffsetToIndexFloat(t); +	// 	int dmin = (int)ceil(d - m_fBlobSize); +	// 	int dmax = (int)floor(d + m_fBlobSize); + +	// 	// add affected detectors to the list +	// 	for (int i = dmin; i <= dmax; ++i) { +	// 		if (d >= 0 && d < m_pProjectionGeometry->getDetectorCount()) { +	// 			SDetector2D det; +	// 			det.m_iAngleIndex = iProjection; +	// 			det.m_iDetectorIndex = i; +	// 			det.m_iIndex = iProjection * getProjectionGeometry()->getDetectorCount() + i; +	// 			res.push_back(det); +	// 		} +	// 	} +	// } + +	// // return result vector +	// return res; +	return std::vector<SDetector2D>();  } diff --git a/src/ParallelBeamLineKernelProjector2D.cpp b/src/ParallelBeamLineKernelProjector2D.cpp index a5f46a7..a7d72d4 100644 --- a/src/ParallelBeamLineKernelProjector2D.cpp +++ b/src/ParallelBeamLineKernelProjector2D.cpp @@ -87,9 +87,9 @@ bool CParallelBeamLineKernelProjector2D::_check()  	// check base class  	ASTRA_CONFIG_CHECK(CProjector2D::_check(), "ParallelBeamLineKernelProjector2D", "Error in Projector2D initialization"); -	ASTRA_CONFIG_CHECK(dynamic_cast<CParallelProjectionGeometry2D*>(m_pProjectionGeometry), "ParallelBeamLineKernelProjector2D", "Unsupported projection geometry"); +	ASTRA_CONFIG_CHECK(dynamic_cast<CParallelProjectionGeometry2D*>(m_pProjectionGeometry) || dynamic_cast<CParallelVecProjectionGeometry2D*>(m_pProjectionGeometry), "ParallelBeamLineKernelProjector2D", "Unsupported projection geometry"); -	ASTRA_CONFIG_CHECK(m_pVolumeGeometry->getPixelLengthX() == m_pVolumeGeometry->getPixelLengthY(), "ParallelBeamLineKernelProjector2D", "Pixel height must equal pixel width."); +	ASTRA_CONFIG_CHECK(abs(m_pVolumeGeometry->getPixelLengthX() / m_pVolumeGeometry->getPixelLengthY()) - 1 < eps, "ParallelBeamLineKernelProjector2D", "Pixel height must equal pixel width.");  	// success  	return true; @@ -161,61 +161,63 @@ void CParallelBeamLineKernelProjector2D::computeSingleRayWeights(int _iProjectio  // Project Point  std::vector<SDetector2D> CParallelBeamLineKernelProjector2D::projectPoint(int _iRow, int _iCol)  { -	float32 xUL = m_pVolumeGeometry->pixelColToCenterX(_iCol) - m_pVolumeGeometry->getPixelLengthX() * 0.5f; -	float32 yUL = m_pVolumeGeometry->pixelRowToCenterY(_iRow) - m_pVolumeGeometry->getPixelLengthY() * 0.5f; -	float32 xUR = m_pVolumeGeometry->pixelColToCenterX(_iCol) + m_pVolumeGeometry->getPixelLengthX() * 0.5f; -	float32 yUR = m_pVolumeGeometry->pixelRowToCenterY(_iRow) - m_pVolumeGeometry->getPixelLengthY() * 0.5f; -	float32 xLL = m_pVolumeGeometry->pixelColToCenterX(_iCol) - m_pVolumeGeometry->getPixelLengthX() * 0.5f; -	float32 yLL = m_pVolumeGeometry->pixelRowToCenterY(_iRow) + m_pVolumeGeometry->getPixelLengthY() * 0.5f; -	float32 xLR = m_pVolumeGeometry->pixelColToCenterX(_iCol) + m_pVolumeGeometry->getPixelLengthX() * 0.5f; -	float32 yLR = m_pVolumeGeometry->pixelRowToCenterY(_iRow) + m_pVolumeGeometry->getPixelLengthY() * 0.5f; -  	std::vector<SDetector2D> res; -	// loop projectors and detectors -	for (int iProjection = 0; iProjection < m_pProjectionGeometry->getProjectionAngleCount(); ++iProjection) { - -		// get projection angle -		float32 theta = m_pProjectionGeometry->getProjectionAngle(iProjection); -		if (theta >= 7*PIdiv4) theta -= 2*PI; -		bool inverse = false; -		if (theta >= 3*PIdiv4) { -			theta -= PI; -			inverse = true; -		} - -		// calculate distance from the center of the voxel to the ray though the origin -		float32 tUL = xUL * cos(theta) + yUL * sin(theta); -		float32 tUR = xUR * cos(theta) + yUR * sin(theta); -		float32 tLL = xLL * cos(theta) + yLL * sin(theta); -		float32 tLR = xLR * cos(theta) + yLR * sin(theta); -		if (inverse) { -			tUL *= -1.0f; -			tUR *= -1.0f; -			tLL *= -1.0f; -			tLR *= -1.0f; -		} -		float32 tMin = min(tUL, min(tUR, min(tLL,tLR))); -		float32 tMax = max(tUL, max(tUR, max(tLL,tLR))); - -		// calculate the offset on the detectorarray (in indices) -		int dmin = (int)floor(m_pProjectionGeometry->detectorOffsetToIndexFloat(tMin)); -		int dmax = (int)ceil(m_pProjectionGeometry->detectorOffsetToIndexFloat(tMax)); - -		// add affected detectors to the list -		for (int i = dmin; i <= dmax; ++i) { -			if (i >= 0 && i < m_pProjectionGeometry->getDetectorCount()) { -				SDetector2D det; -				det.m_iAngleIndex = iProjection; -				det.m_iDetectorIndex = i; -				det.m_iIndex = iProjection * getProjectionGeometry()->getDetectorCount() + i; -				res.push_back(det); -			} -		} -	} - -	// return result vector  	return res; +	// float32 xUL = m_pVolumeGeometry->pixelColToCenterX(_iCol) - m_pVolumeGeometry->getPixelLengthX() * 0.5f; +	// float32 yUL = m_pVolumeGeometry->pixelRowToCenterY(_iRow) - m_pVolumeGeometry->getPixelLengthY() * 0.5f; +	// float32 xUR = m_pVolumeGeometry->pixelColToCenterX(_iCol) + m_pVolumeGeometry->getPixelLengthX() * 0.5f; +	// float32 yUR = m_pVolumeGeometry->pixelRowToCenterY(_iRow) - m_pVolumeGeometry->getPixelLengthY() * 0.5f; +	// float32 xLL = m_pVolumeGeometry->pixelColToCenterX(_iCol) - m_pVolumeGeometry->getPixelLengthX() * 0.5f; +	// float32 yLL = m_pVolumeGeometry->pixelRowToCenterY(_iRow) + m_pVolumeGeometry->getPixelLengthY() * 0.5f; +	// float32 xLR = m_pVolumeGeometry->pixelColToCenterX(_iCol) + m_pVolumeGeometry->getPixelLengthX() * 0.5f; +	// float32 yLR = m_pVolumeGeometry->pixelRowToCenterY(_iRow) + m_pVolumeGeometry->getPixelLengthY() * 0.5f; + +	// std::vector<SDetector2D> res; +	// // loop projectors and detectors +	// for (int iProjection = 0; iProjection < m_pProjectionGeometry->getProjectionAngleCount(); ++iProjection) { + +	// 	// get projection angle +	// 	float32 theta = m_pProjectionGeometry->getProjectionAngle(iProjection); +	// 	if (theta >= 7*PIdiv4) theta -= 2*PI; +	// 	bool inverse = false; +	// 	if (theta >= 3*PIdiv4) { +	// 		theta -= PI; +	// 		inverse = true; +	// 	} + +	// 	// calculate distance from the center of the voxel to the ray though the origin +	// 	float32 tUL = xUL * cos(theta) + yUL * sin(theta); +	// 	float32 tUR = xUR * cos(theta) + yUR * sin(theta); +	// 	float32 tLL = xLL * cos(theta) + yLL * sin(theta); +	// 	float32 tLR = xLR * cos(theta) + yLR * sin(theta); +	// 	if (inverse) { +	// 		tUL *= -1.0f; +	// 		tUR *= -1.0f; +	// 		tLL *= -1.0f; +	// 		tLR *= -1.0f; +	// 	} +	// 	float32 tMin = min(tUL, min(tUR, min(tLL,tLR))); +	// 	float32 tMax = max(tUL, max(tUR, max(tLL,tLR))); + +	// 	// calculate the offset on the detectorarray (in indices) +	// 	int dmin = (int)floor(m_pProjectionGeometry->detectorOffsetToIndexFloat(tMin)); +	// 	int dmax = (int)ceil(m_pProjectionGeometry->detectorOffsetToIndexFloat(tMax)); + +	// 	// add affected detectors to the list +	// 	for (int i = dmin; i <= dmax; ++i) { +	// 		if (i >= 0 && i < m_pProjectionGeometry->getDetectorCount()) { +	// 			SDetector2D det; +	// 			det.m_iAngleIndex = iProjection; +	// 			det.m_iDetectorIndex = i; +	// 			det.m_iIndex = iProjection * getProjectionGeometry()->getDetectorCount() + i; +	// 			res.push_back(det); +	// 		} +	// 	} +	// } + +	// // return result vector +	// return res;  }  //---------------------------------------------------------------------------------------- diff --git a/src/ParallelBeamLinearKernelProjector2D.cpp b/src/ParallelBeamLinearKernelProjector2D.cpp index e9034bf..98946a8 100644 --- a/src/ParallelBeamLinearKernelProjector2D.cpp +++ b/src/ParallelBeamLinearKernelProjector2D.cpp @@ -88,10 +88,10 @@ 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."); +	ASTRA_CONFIG_CHECK(abs(m_pVolumeGeometry->getPixelLengthX() / m_pVolumeGeometry->getPixelLengthY()) - 1 < eps, "ParallelBeamLinearKernelProjector2D", "Pixel height must equal pixel width.");  	// success  	return true; diff --git a/src/ParallelBeamStripKernelProjector2D.cpp b/src/ParallelBeamStripKernelProjector2D.cpp index ab4e49e..5a0767b 100644 --- a/src/ParallelBeamStripKernelProjector2D.cpp +++ b/src/ParallelBeamStripKernelProjector2D.cpp @@ -87,9 +87,9 @@ bool CParallelBeamStripKernelProjector2D::_check()  	// check base class  	ASTRA_CONFIG_CHECK(CProjector2D::_check(), "ParallelBeamStripKernelProjector2D", "Error in Projector2D initialization"); -	ASTRA_CONFIG_CHECK(dynamic_cast<CParallelProjectionGeometry2D*>(m_pProjectionGeometry), "ParallelBeamStripKernelProjector2D", "Unsupported projection geometry"); +	ASTRA_CONFIG_CHECK(dynamic_cast<CParallelProjectionGeometry2D*>(m_pProjectionGeometry) || dynamic_cast<CParallelVecProjectionGeometry2D*>(m_pProjectionGeometry), "ParallelBeamStripKernelProjector2D", "Unsupported projection geometry"); -	ASTRA_CONFIG_CHECK(m_pVolumeGeometry->getPixelLengthX() == m_pVolumeGeometry->getPixelLengthY(), "ParallelBeamStripKernelProjector2D", "Pixel height must equal pixel width."); +	ASTRA_CONFIG_CHECK(abs(m_pVolumeGeometry->getPixelLengthX() / m_pVolumeGeometry->getPixelLengthY()) - 1 < eps, "ParallelBeamStripKernelProjector2D", "Pixel height must equal pixel width.");  	// success  	return true; @@ -163,57 +163,57 @@ void CParallelBeamStripKernelProjector2D::computeSingleRayWeights(int _iProjecti  // Splat a single point  std::vector<SDetector2D> CParallelBeamStripKernelProjector2D::projectPoint(int _iRow, int _iCol)  { -	float32 xUL = m_pVolumeGeometry->pixelColToCenterX(_iCol) - m_pVolumeGeometry->getPixelLengthX() * 0.5f; -	float32 yUL = m_pVolumeGeometry->pixelRowToCenterY(_iRow) - m_pVolumeGeometry->getPixelLengthY() * 0.5f; -	float32 xUR = m_pVolumeGeometry->pixelColToCenterX(_iCol) + m_pVolumeGeometry->getPixelLengthX() * 0.5f; -	float32 yUR = m_pVolumeGeometry->pixelRowToCenterY(_iRow) - m_pVolumeGeometry->getPixelLengthY() * 0.5f; -	float32 xLL = m_pVolumeGeometry->pixelColToCenterX(_iCol) - m_pVolumeGeometry->getPixelLengthX() * 0.5f; -	float32 yLL = m_pVolumeGeometry->pixelRowToCenterY(_iRow) + m_pVolumeGeometry->getPixelLengthY() * 0.5f; -	float32 xLR = m_pVolumeGeometry->pixelColToCenterX(_iCol) + m_pVolumeGeometry->getPixelLengthX() * 0.5f; -	float32 yLR = m_pVolumeGeometry->pixelRowToCenterY(_iRow) + m_pVolumeGeometry->getPixelLengthY() * 0.5f; +	// float32 xUL = m_pVolumeGeometry->pixelColToCenterX(_iCol) - m_pVolumeGeometry->getPixelLengthX() * 0.5f; +	// float32 yUL = m_pVolumeGeometry->pixelRowToCenterY(_iRow) - m_pVolumeGeometry->getPixelLengthY() * 0.5f; +	// float32 xUR = m_pVolumeGeometry->pixelColToCenterX(_iCol) + m_pVolumeGeometry->getPixelLengthX() * 0.5f; +	// float32 yUR = m_pVolumeGeometry->pixelRowToCenterY(_iRow) - m_pVolumeGeometry->getPixelLengthY() * 0.5f; +	// float32 xLL = m_pVolumeGeometry->pixelColToCenterX(_iCol) - m_pVolumeGeometry->getPixelLengthX() * 0.5f; +	// float32 yLL = m_pVolumeGeometry->pixelRowToCenterY(_iRow) + m_pVolumeGeometry->getPixelLengthY() * 0.5f; +	// float32 xLR = m_pVolumeGeometry->pixelColToCenterX(_iCol) + m_pVolumeGeometry->getPixelLengthX() * 0.5f; +	// float32 yLR = m_pVolumeGeometry->pixelRowToCenterY(_iRow) + m_pVolumeGeometry->getPixelLengthY() * 0.5f;  	std::vector<SDetector2D> res; -	// loop projectors and detectors -	for (int iProjection = 0; iProjection < m_pProjectionGeometry->getProjectionAngleCount(); ++iProjection) { - -		// get projection angle -		float32 theta = m_pProjectionGeometry->getProjectionAngle(iProjection); -		if (theta >= 7*PIdiv4) theta -= 2*PI; -		bool inverse = false; -		if (theta >= 3*PIdiv4) { -			theta -= PI; -			inverse = true; -		} - -		// calculate distance from the center of the voxel to the ray though the origin -		float32 tUL = xUL * cos(theta) + yUL * sin(theta); -		float32 tUR = xUR * cos(theta) + yUR * sin(theta); -		float32 tLL = xLL * cos(theta) + yLL * sin(theta); -		float32 tLR = xLR * cos(theta) + yLR * sin(theta); -		if (inverse) { -			tUL *= -1.0f; -			tUR *= -1.0f; -			tLL *= -1.0f; -			tLR *= -1.0f; -		} -		float32 tMin = min(tUL, min(tUR, min(tLL,tLR))); -		float32 tMax = max(tUL, max(tUR, max(tLL,tLR))); - -		// calculate the offset on the detectorarray (in indices) -		int dmin = (int)floor(m_pProjectionGeometry->detectorOffsetToIndexFloat(tMin)); -		int dmax = (int)ceil(m_pProjectionGeometry->detectorOffsetToIndexFloat(tMax)); - -		// add affected detectors to the list -		for (int i = dmin; i <= dmax; ++i) { -			if (i >= 0 && i < m_pProjectionGeometry->getDetectorCount()) { -				SDetector2D det; -				det.m_iAngleIndex = iProjection; -				det.m_iDetectorIndex = i; -				det.m_iIndex = iProjection * getProjectionGeometry()->getDetectorCount() + i; -				res.push_back(det); -			} -		} -	} +	// // loop projectors and detectors +	// for (int iProjection = 0; iProjection < m_pProjectionGeometry->getProjectionAngleCount(); ++iProjection) { + +	// 	// get projection angle +	// 	float32 theta = m_pProjectionGeometry->getProjectionAngle(iProjection); +	// 	if (theta >= 7*PIdiv4) theta -= 2*PI; +	// 	bool inverse = false; +	// 	if (theta >= 3*PIdiv4) { +	// 		theta -= PI; +	// 		inverse = true; +	// 	} + +	// 	// calculate distance from the center of the voxel to the ray though the origin +	// 	float32 tUL = xUL * cos(theta) + yUL * sin(theta); +	// 	float32 tUR = xUR * cos(theta) + yUR * sin(theta); +	// 	float32 tLL = xLL * cos(theta) + yLL * sin(theta); +	// 	float32 tLR = xLR * cos(theta) + yLR * sin(theta); +	// 	if (inverse) { +	// 		tUL *= -1.0f; +	// 		tUR *= -1.0f; +	// 		tLL *= -1.0f; +	// 		tLR *= -1.0f; +	// 	} +	// 	float32 tMin = min(tUL, min(tUR, min(tLL,tLR))); +	// 	float32 tMax = max(tUL, max(tUR, max(tLL,tLR))); + +	// 	// calculate the offset on the detectorarray (in indices) +	// 	int dmin = (int)floor(m_pProjectionGeometry->detectorOffsetToIndexFloat(tMin)); +	// 	int dmax = (int)ceil(m_pProjectionGeometry->detectorOffsetToIndexFloat(tMax)); + +	// 	// add affected detectors to the list +	// 	for (int i = dmin; i <= dmax; ++i) { +	// 		if (i >= 0 && i < m_pProjectionGeometry->getDetectorCount()) { +	// 			SDetector2D det; +	// 			det.m_iAngleIndex = iProjection; +	// 			det.m_iDetectorIndex = i; +	// 			det.m_iIndex = iProjection * getProjectionGeometry()->getDetectorCount() + i; +	// 			res.push_back(det); +	// 		} +	// 	} +	// }  	// return result vector  	return res; diff --git a/src/ParallelProjectionGeometry2D.cpp b/src/ParallelProjectionGeometry2D.cpp index f73df50..3cc506a 100644 --- a/src/ParallelProjectionGeometry2D.cpp +++ b/src/ParallelProjectionGeometry2D.cpp @@ -27,6 +27,8 @@ along with the ASTRA Toolbox. If not, see <http://www.gnu.org/licenses/>.  #include "astra/ParallelProjectionGeometry2D.h" +#include "astra/GeometryUtil2D.h" +  #include <cstring>  using namespace std; @@ -47,15 +49,13 @@ CParallelProjectionGeometry2D::CParallelProjectionGeometry2D() :  CParallelProjectionGeometry2D::CParallelProjectionGeometry2D(int _iProjectionAngleCount,   															 int _iDetectorCount,   															 float32 _fDetectorWidth,  -															 const float32* _pfProjectionAngles, -															 const float32* _pfExtraDetectorOffsets) +															 const float32* _pfProjectionAngles)  {  	_clear();  	initialize(_iProjectionAngleCount,  				_iDetectorCount,   				_fDetectorWidth,  -				_pfProjectionAngles, -				_pfExtraDetectorOffsets); +				_pfProjectionAngles);  }  //---------------------------------------------------------------------------------------- @@ -65,8 +65,7 @@ CParallelProjectionGeometry2D::CParallelProjectionGeometry2D(const CParallelProj  	initialize(_projGeom.m_iProjectionAngleCount,  				_projGeom.m_iDetectorCount,   				_projGeom.m_fDetectorWidth,  -				_projGeom.m_pfProjectionAngles, -				_projGeom.m_pfExtraDetectorOffset); +				_projGeom.m_pfProjectionAngles);  }  //---------------------------------------------------------------------------------------- @@ -115,14 +114,12 @@ bool CParallelProjectionGeometry2D::initialize(const Config& _cfg)  bool CParallelProjectionGeometry2D::initialize(int _iProjectionAngleCount,   											   int _iDetectorCount,   											   float32 _fDetectorWidth,  -											   const float32* _pfProjectionAngles, -											   const float32* _pfExtraDetectorOffsets) +											   const float32* _pfProjectionAngles)  {  	_initialize(_iProjectionAngleCount,   			    _iDetectorCount,   			    _fDetectorWidth,  -			    _pfProjectionAngles, -				_pfExtraDetectorOffsets); +			    _pfProjectionAngles);  	// success  	m_bInitialized = _check(); @@ -178,15 +175,10 @@ Config* CParallelProjectionGeometry2D::getConfiguration() const  	cfg->self.addChildNode("DetectorCount", getDetectorCount());  	cfg->self.addChildNode("DetectorWidth", getDetectorWidth());  	cfg->self.addChildNode("ProjectionAngles", m_pfProjectionAngles, m_iProjectionAngleCount); -	if(m_pfExtraDetectorOffset!=NULL){ -		XMLNode opt = cfg->self.addChildNode("Option"); -		opt.addAttribute("key","ExtraDetectorOffset"); -		opt.setContent(m_pfExtraDetectorOffset, m_iProjectionAngleCount); -	}  	return cfg;  } -//---------------------------------------------------------------------------------------- +//----------------------------------------------------------------------------------------  CVector3D CParallelProjectionGeometry2D::getProjectionDirection(int _iProjectionIndex, int _iDetectorIndex /* = 0 */)  {  	CVector3D vOutput; @@ -200,4 +192,18 @@ CVector3D CParallelProjectionGeometry2D::getProjectionDirection(int _iProjection  	return vOutput;  } +//---------------------------------------------------------------------------------------- +CParallelVecProjectionGeometry2D* CParallelProjectionGeometry2D::toVectorGeometry() +{ +	SParProjection* vectors = genParProjections(m_iProjectionAngleCount, +	                                            m_iDetectorCount, +	                                            m_fDetectorWidth, +	                                            m_pfProjectionAngles, 0); +	// TODO: ExtraOffsets? +	CParallelVecProjectionGeometry2D* vecGeom = new CParallelVecProjectionGeometry2D(); +	vecGeom->initialize(m_iProjectionAngleCount, m_iDetectorCount, vectors); +	delete[] vectors; +	return vecGeom; +} +  } // end namespace astra diff --git a/src/ParallelVecProjectionGeometry2D.cpp b/src/ParallelVecProjectionGeometry2D.cpp new file mode 100644 index 0000000..1503076 --- /dev/null +++ b/src/ParallelVecProjectionGeometry2D.cpp @@ -0,0 +1,233 @@ +/* +----------------------------------------------------------------------- +Copyright: 2010-2015, iMinds-Vision Lab, University of Antwerp +           2014-2015, CWI, Amsterdam + +Contact: astra@uantwerpen.be +Website: http://sf.net/projects/astra-toolbox + +This file is part of the ASTRA Toolbox. + + +The ASTRA Toolbox is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +The ASTRA Toolbox is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with the ASTRA Toolbox. If not, see <http://www.gnu.org/licenses/>. + +----------------------------------------------------------------------- +$Id$ +*/ + +#include "astra/ParallelVecProjectionGeometry2D.h" + +#include <cstring> +#include <sstream> +#include <boost/lexical_cast.hpp> + +using namespace std; + +namespace astra +{ + +//---------------------------------------------------------------------------------------- +// Default constructor. Sets all variables to zero.  +CParallelVecProjectionGeometry2D::CParallelVecProjectionGeometry2D() +{ +	_clear(); +	m_pProjectionAngles = 0; +} + +//---------------------------------------------------------------------------------------- +// Constructor. +CParallelVecProjectionGeometry2D::CParallelVecProjectionGeometry2D(int _iProjectionAngleCount,  +                                                                 int _iDetectorCount,  +                                                                 const SParProjection* _pProjectionAngles) +{ +	this->initialize(_iProjectionAngleCount,  +	                 _iDetectorCount,  +	                 _pProjectionAngles); +} + +//---------------------------------------------------------------------------------------- +// Copy Constructor +CParallelVecProjectionGeometry2D::CParallelVecProjectionGeometry2D(const CParallelVecProjectionGeometry2D& _projGeom) +{ +	_clear(); +	this->initialize(_projGeom.m_iProjectionAngleCount, +	                 _projGeom.m_iDetectorCount, +	                 _projGeom.m_pProjectionAngles); +} + +//---------------------------------------------------------------------------------------- +// Destructor. +CParallelVecProjectionGeometry2D::~CParallelVecProjectionGeometry2D() +{ +	// TODO +	delete[] m_pProjectionAngles; +} + + +//---------------------------------------------------------------------------------------- +// Initialization. +bool CParallelVecProjectionGeometry2D::initialize(int _iProjectionAngleCount,  +											  int _iDetectorCount,  +											  const SParProjection* _pProjectionAngles) +{ +	m_iProjectionAngleCount = _iProjectionAngleCount; +	m_iDetectorCount = _iDetectorCount; +	m_pProjectionAngles = new SParProjection[m_iProjectionAngleCount]; +	for (int i = 0; i < m_iProjectionAngleCount; ++i) +		m_pProjectionAngles[i] = _pProjectionAngles[i]; + +	// TODO: check? + +	// success +	m_bInitialized = _check(); +	return m_bInitialized; +} + +//---------------------------------------------------------------------------------------- +// Initialization with a Config object +bool CParallelVecProjectionGeometry2D::initialize(const Config& _cfg) +{ +	ASTRA_ASSERT(_cfg.self); +	ConfigStackCheck<CProjectionGeometry2D> CC("ParallelVecProjectionGeometry2D", this, _cfg);	 + +	// TODO: Fix up class hierarchy... this class doesn't fit very well. +	// initialization of parent class +	//CProjectionGeometry2D::initialize(_cfg); + +	// Required: DetectorCount +	XMLNode node = _cfg.self.getSingleNode("DetectorCount"); +	ASTRA_CONFIG_CHECK(node, "ParallelVecProjectionGeometry2D", "No DetectorRowCount tag specified."); +	m_iDetectorCount = boost::lexical_cast<int>(node.getContent()); +	CC.markNodeParsed("DetectorCount"); + +	// Required: Vectors +	node = _cfg.self.getSingleNode("Vectors"); +	ASTRA_CONFIG_CHECK(node, "ParallelVecProjectionGeometry2D", "No Vectors tag specified."); +	vector<float32> data = node.getContentNumericalArray(); +	CC.markNodeParsed("Vectors"); +	ASTRA_CONFIG_CHECK(data.size() % 6 == 0, "ParallelVecProjectionGeometry2D", "Vectors doesn't consist of 6-tuples."); +	m_iProjectionAngleCount = data.size() / 6; +	m_pProjectionAngles = new SParProjection[m_iProjectionAngleCount]; + +	for (int i = 0; i < m_iProjectionAngleCount; ++i) { +		SParProjection& p = m_pProjectionAngles[i]; +		p.fRayX  = data[6*i +  0]; +		p.fRayY  = data[6*i +  1]; +		p.fDetUX = data[6*i +  4]; +		p.fDetUY = data[6*i +  5]; + +		// The backend code currently expects the corner of the detector, while +		// the matlab interface supplies the center +		p.fDetSX = data[6*i +  2] - 0.5f * m_iDetectorCount * p.fDetUX; +		p.fDetSY = data[6*i +  3] - 0.5f * m_iDetectorCount * p.fDetUY; +	} + +	// success +	m_bInitialized = _check(); +	return m_bInitialized; +} + +//---------------------------------------------------------------------------------------- +// Clone +CProjectionGeometry2D* CParallelVecProjectionGeometry2D::clone() +{ +	return new CParallelVecProjectionGeometry2D(*this); +} + +//---------------------------------------------------------------------------------------- +// is equal +bool CParallelVecProjectionGeometry2D::isEqual(CProjectionGeometry2D* _pGeom2) const +{ +	if (_pGeom2 == NULL) return false; + +	// try to cast argument to CParallelVecProjectionGeometry2D +	CParallelVecProjectionGeometry2D* pGeom2 = dynamic_cast<CParallelVecProjectionGeometry2D*>(_pGeom2); +	if (pGeom2 == NULL) return false; + +	// both objects must be initialized +	if (!m_bInitialized || !pGeom2->m_bInitialized) return false; + +	// check all values +	if (m_iProjectionAngleCount != pGeom2->m_iProjectionAngleCount) return false; +	if (m_iDetectorCount != pGeom2->m_iDetectorCount) return false; +	 +	for (int i = 0; i < m_iProjectionAngleCount; ++i) { +		if (memcmp(&m_pProjectionAngles[i], &pGeom2->m_pProjectionAngles[i], sizeof(m_pProjectionAngles[i])) != 0) return false; +	} + +	return true; +} + +//---------------------------------------------------------------------------------------- +// Is of type +bool CParallelVecProjectionGeometry2D::isOfType(const std::string& _sType) +{ +	return (_sType == "parallel_vec"); +} + +//---------------------------------------------------------------------------------------- + +CVector3D CParallelVecProjectionGeometry2D::getProjectionDirection(int _iProjectionIndex, int _iDetectorIndex /* = 0 */) +{ +	CVector3D vOutput(0.0f, 0.0f, 0.0f); + +	// not implemented +	ASTRA_ASSERT(false); + +	return vOutput; +} + +//---------------------------------------------------------------------------------------- + +void CParallelVecProjectionGeometry2D::getRayParams(int _iRow, int _iColumn, float32& _fT, float32& _fTheta) const +{ +	// not implemented +	ASTRA_ASSERT(false); +} + +//---------------------------------------------------------------------------------------- + +bool CParallelVecProjectionGeometry2D::_check() +{ +	// TODO +	return true; +} + + +//---------------------------------------------------------------------------------------- +// Get the configuration object +Config* CParallelVecProjectionGeometry2D::getConfiguration() const  +{ +	Config* cfg = new Config(); +	cfg->initialize("ProjectionGeometry2D"); +	cfg->self.addAttribute("type", "parallel_vec"); +	cfg->self.addChildNode("DetectorCount", getDetectorCount()); +	std::string vectors = ""; +	for (int i = 0; i < m_iProjectionAngleCount; ++i) { +		SParProjection& p = m_pProjectionAngles[i]; +		vectors += boost::lexical_cast<string>(p.fRayX) + ","; +		vectors += boost::lexical_cast<string>(p.fRayY) + ","; +		vectors += boost::lexical_cast<string>(p.fDetSX + 0.5f * m_iDetectorCount * p.fDetUX) + ","; +		vectors += boost::lexical_cast<string>(p.fDetSY + 0.5f * m_iDetectorCount * p.fDetUY) + ","; +		vectors += boost::lexical_cast<string>(p.fDetUX) + ","; +		vectors += boost::lexical_cast<string>(p.fDetUY); +		if (i < m_iProjectionAngleCount-1) vectors += ';'; +	} +	cfg->self.addChildNode("Vectors", vectors); +	return cfg; +} +//---------------------------------------------------------------------------------------- + + +} // namespace astra diff --git a/src/ProjectionGeometry2D.cpp b/src/ProjectionGeometry2D.cpp index e9f08ec..54605a7 100644 --- a/src/ProjectionGeometry2D.cpp +++ b/src/ProjectionGeometry2D.cpp @@ -44,11 +44,10 @@ CProjectionGeometry2D::CProjectionGeometry2D() : configCheckData(0)  CProjectionGeometry2D::CProjectionGeometry2D(int _iAngleCount,   											 int _iDetectorCount,   											 float32 _fDetectorWidth,  -											 const float32* _pfProjectionAngles, -											 const float32* _pfExtraDetectorOffsets) : configCheckData(0) +											 const float32* _pfProjectionAngles) : configCheckData(0)  {  	_clear(); -	_initialize(_iAngleCount, _iDetectorCount, _fDetectorWidth, _pfProjectionAngles,_pfExtraDetectorOffsets); +	_initialize(_iAngleCount, _iDetectorCount, _fDetectorWidth, _pfProjectionAngles);  }  //---------------------------------------------------------------------------------------- @@ -69,7 +68,6 @@ void CProjectionGeometry2D::_clear()  	m_iDetectorCount = 0;  	m_fDetectorWidth = 0.0f;  	m_pfProjectionAngles = NULL; -	m_pfExtraDetectorOffset = NULL;  	m_bInitialized = false;  } @@ -82,10 +80,8 @@ void CProjectionGeometry2D::clear()  	m_fDetectorWidth = 0.0f;  	if (m_bInitialized){  		delete[] m_pfProjectionAngles; -		delete[] m_pfExtraDetectorOffset;  	}  	m_pfProjectionAngles = NULL; -	m_pfExtraDetectorOffset = NULL;  	m_bInitialized = false;  } @@ -144,19 +140,6 @@ bool CProjectionGeometry2D::initialize(const Config& _cfg)  	}  	CC.markNodeParsed("ProjectionAngles"); -	vector<float32> offset = _cfg.self.getOptionNumericalArray("ExtraDetectorOffset"); -	m_pfExtraDetectorOffset = new float32[m_iProjectionAngleCount]; -	if (offset.size() == (size_t)m_iProjectionAngleCount) { -		for (int i = 0; i < m_iProjectionAngleCount; i++) { -			m_pfExtraDetectorOffset[i] = offset[i]; -		} -	} else { -		for (int i = 0; i < m_iProjectionAngleCount; i++) { -			m_pfExtraDetectorOffset[i] = 0.0f; -		}	 -	} -	CC.markOptionParsed("ExtraDetectorOffset"); -  	// some checks  	ASTRA_CONFIG_CHECK(m_iDetectorCount > 0, "ProjectionGeometry2D", "DetectorCount should be positive.");  	ASTRA_CONFIG_CHECK(m_fDetectorWidth > 0.0f, "ProjectionGeometry2D", "DetectorWidth should be positive."); @@ -171,8 +154,7 @@ bool CProjectionGeometry2D::initialize(const Config& _cfg)  bool CProjectionGeometry2D::_initialize(int _iProjectionAngleCount,   									    int _iDetectorCount,   									    float32 _fDetectorWidth,  -									    const float32* _pfProjectionAngles, -										const float32* _pfExtraDetectorOffsets) +									    const float32* _pfProjectionAngles)  {  	if (m_bInitialized) {  		clear(); @@ -183,10 +165,8 @@ bool CProjectionGeometry2D::_initialize(int _iProjectionAngleCount,  	m_iDetectorCount = _iDetectorCount;  	m_fDetectorWidth = _fDetectorWidth;  	m_pfProjectionAngles = new float32[m_iProjectionAngleCount]; -	m_pfExtraDetectorOffset = new float32[m_iProjectionAngleCount];  	for (int i = 0; i < m_iProjectionAngleCount; i++) {  		m_pfProjectionAngles[i] = _pfProjectionAngles[i];		 -		m_pfExtraDetectorOffset[i] = _pfExtraDetectorOffsets ? _pfExtraDetectorOffsets[i]:0;  	}  	// Interface class, so don't set m_bInitialized to true diff --git a/src/Projector2D.cpp b/src/Projector2D.cpp index 78412e6..ced5b84 100644 --- a/src/Projector2D.cpp +++ b/src/Projector2D.cpp @@ -27,6 +27,7 @@ along with the ASTRA Toolbox. If not, see <http://www.gnu.org/licenses/>.  #include "astra/Projector2D.h" +#include "astra/ParallelVecProjectionGeometry2D.h"  #include "astra/FanFlatProjectionGeometry2D.h"  #include "astra/FanFlatVecProjectionGeometry2D.h"  #include "astra/SparseMatrixProjectionGeometry2D.h" @@ -130,6 +131,10 @@ bool CProjector2D::initialize(const Config& _cfg)  		CFanFlatVecProjectionGeometry2D* pFanFlatVecProjectionGeometry = new CFanFlatVecProjectionGeometry2D();  		pFanFlatVecProjectionGeometry->initialize(Config(node));  		m_pProjectionGeometry = pFanFlatVecProjectionGeometry; +	} else if (type == "parallel_vec") { +		CParallelVecProjectionGeometry2D* pParallelVecProjectionGeometry = new CParallelVecProjectionGeometry2D(); +		pParallelVecProjectionGeometry->initialize(Config(node)); +		m_pProjectionGeometry = pParallelVecProjectionGeometry;  	} else {  		m_pProjectionGeometry = new CParallelProjectionGeometry2D();  		m_pProjectionGeometry->initialize(Config(node)); diff --git a/src/VolumeGeometry2D.cpp b/src/VolumeGeometry2D.cpp index dd056ae..75d0dfc 100644 --- a/src/VolumeGeometry2D.cpp +++ b/src/VolumeGeometry2D.cpp @@ -41,16 +41,16 @@ bool CVolumeGeometry2D::_check()  	ASTRA_CONFIG_CHECK(m_fWindowMinX < m_fWindowMaxX, "VolumeGeometry2D", "WindowMinX should be lower than WindowMaxX.");  	ASTRA_CONFIG_CHECK(m_fWindowMinY < m_fWindowMaxY, "VolumeGeometry2D", "WindowMinY should be lower than WindowMaxY."); -	ASTRA_CONFIG_CHECK(m_iGridTotCount == (m_iGridColCount * m_iGridRowCount), "VolumeGeometry2D", "Internal configuration error."); -	ASTRA_CONFIG_CHECK(m_fWindowLengthX == (m_fWindowMaxX - m_fWindowMinX), "VolumeGeometry2D", "Internal configuration error."); -	ASTRA_CONFIG_CHECK(m_fWindowLengthY == (m_fWindowMaxY - m_fWindowMinY), "VolumeGeometry2D", "Internal configuration error."); -	ASTRA_CONFIG_CHECK(m_fWindowArea == (m_fWindowLengthX * m_fWindowLengthY), "VolumeGeometry2D", "Internal configuration error."); -	ASTRA_CONFIG_CHECK(m_fPixelLengthX == (m_fWindowLengthX / (float32)m_iGridColCount), "VolumeGeometry2D", "Internal configuration error."); -	ASTRA_CONFIG_CHECK(m_fPixelLengthY == (m_fWindowLengthY / (float32)m_iGridRowCount), "VolumeGeometry2D", "Internal configuration error."); - -	ASTRA_CONFIG_CHECK(m_fPixelArea == (m_fPixelLengthX * m_fPixelLengthY), "VolumeGeometry2D", "Internal configuration error."); -	ASTRA_CONFIG_CHECK(fabsf(m_fDivPixelLengthX * m_fPixelLengthX - 1.0f) < eps, "VolumeGeometry2D", "Internal configuration error."); -	ASTRA_CONFIG_CHECK(fabsf(m_fDivPixelLengthY * m_fPixelLengthY - 1.0f) < eps, "VolumeGeometry2D", "Internal configuration error."); +	ASTRA_CONFIG_CHECK(fabsf(m_iGridTotCount - (m_iGridColCount * m_iGridRowCount)) < eps, "VolumeGeometry2D", "Internal configuration error (m_iGridTotCount)."); +	ASTRA_CONFIG_CHECK(fabsf(m_fWindowLengthX - (m_fWindowMaxX - m_fWindowMinX)) < eps, "VolumeGeometry2D", "Internal configuration error (m_fWindowLengthX)."); +	ASTRA_CONFIG_CHECK(fabsf(m_fWindowLengthY - (m_fWindowMaxY - m_fWindowMinY)) < eps, "VolumeGeometry2D", "Internal configuration error (m_fWindowLengthY)."); +	ASTRA_CONFIG_CHECK(fabsf(m_fWindowArea - (m_fWindowLengthX * m_fWindowLengthY)) < eps, "VolumeGeometry2D", "Internal configuration error (m_fWindowArea)."); +	ASTRA_CONFIG_CHECK(fabsf(m_fPixelLengthX - (m_fWindowLengthX / (float32)m_iGridColCount)) < eps, "VolumeGeometry2D", "Internal configuration error (m_fPixelLengthX)."); +	ASTRA_CONFIG_CHECK(fabsf(m_fPixelLengthY - (m_fWindowLengthY / (float32)m_iGridRowCount)) < eps, "VolumeGeometry2D", "Internal configuration error (m_fPixelLengthY)."); + +	ASTRA_CONFIG_CHECK(fabsf(m_fPixelArea - (m_fPixelLengthX * m_fPixelLengthY)) < eps, "VolumeGeometry2D", "Internal configuration error (m_fPixelArea)."); +	ASTRA_CONFIG_CHECK(fabsf(m_fDivPixelLengthX * m_fPixelLengthX - 1.0f) < eps, "VolumeGeometry2D", "Internal configuration error (m_fDivPixelLengthX)."); +	ASTRA_CONFIG_CHECK(fabsf(m_fDivPixelLengthY * m_fPixelLengthY - 1.0f) < eps, "VolumeGeometry2D", "Internal configuration error (m_fDivPixelLengthY).");  	return true;  }  | 
