From cabd4bd49792d0a6b00871ca17ed835b86309a47 Mon Sep 17 00:00:00 2001 From: kradchen Date: Thu, 18 May 2023 10:58:43 +0800 Subject: [PATCH] Add Bresengam and DGradient(and test). --- .../reconstruction/buildMatrix/Bresenham.cpp | 208 ++++++ .../reconstruction/buildMatrix/Bresenham.h | 8 + .../reconstruction/buildMatrix/DGradient.cpp | 679 ++++++++++++++++++ .../reconstruction/buildMatrix/DGradient.h | 7 + test/Reconstruction_Test.cpp | 14 + 5 files changed, 916 insertions(+) create mode 100644 src/transmissionReconstruction/reconstruction/buildMatrix/Bresenham.cpp create mode 100644 src/transmissionReconstruction/reconstruction/buildMatrix/Bresenham.h create mode 100644 src/transmissionReconstruction/reconstruction/buildMatrix/DGradient.cpp create mode 100644 src/transmissionReconstruction/reconstruction/buildMatrix/DGradient.h diff --git a/src/transmissionReconstruction/reconstruction/buildMatrix/Bresenham.cpp b/src/transmissionReconstruction/reconstruction/buildMatrix/Bresenham.cpp new file mode 100644 index 0000000..a36375c --- /dev/null +++ b/src/transmissionReconstruction/reconstruction/buildMatrix/Bresenham.cpp @@ -0,0 +1,208 @@ +#include "Bresenham.h" +#include +#include +#include + +float* b3dMex(float *startPoint, float *endPoint,size_t &outputSize ) { + + /* Input arguments from MATLAB */ + // float *startPoint; // data + // float *endPoint; // reference data + + /* create a pointer to the real data in the input array */ + // startPoint = (float *)mxGetPr(prhs[0]); + // endPoint = (float *)mxGetPr(prhs[1]); + + std::vector points; + + float i, l, m, n, x_inc, y_inc, z_inc, err_1, err_2, dx2, dy2, dz2, x,y,z; + + x = startPoint[0]; + y = startPoint[1]; + z = startPoint[2]; + + float dx = endPoint[0] - x; + float dy = endPoint[1] - y; + float dz = endPoint[2] - z; + + x_inc = (dx < 0) ? -1 : 1; + l = abs(dx); + y_inc = (dy < 0) ? -1 : 1; + m = abs(dy); + z_inc = (dz < 0) ? -1 : 1; + n = abs(dz); + dx2 = l*2;// << 1; + dy2 = m*2;// << 1; + dz2 = n*2;// << 1; + + if ((l >= m) && (l >= n)) { + err_1 = dy2 - l; + err_2 = dz2 - l; + for (i = 0; i < l; i++) { + + points.push_back(x); + points.push_back(y); + points.push_back(z); + + if (err_1 > 0) { + y += y_inc; + err_1 -= dx2; + } + if (err_2 > 0) { + z += z_inc; + err_2 -= dx2; + } + err_1 += dy2; + err_2 += dz2; + x += x_inc; + + } + } else if ((m >= l) && (m >= n)) { + err_1 = dx2 - m; + err_2 = dz2 - m; + for (i = 0; i < m; i++) { + + points.push_back(x); + points.push_back(y); + points.push_back(z); + + if (err_1 > 0) { + x += x_inc; + err_1 -= dy2; + } + if (err_2 > 0) { + z += z_inc; + err_2 -= dy2; + } + err_1 += dx2; + err_2 += dz2; + y += y_inc; + + } + } else { + err_1 = dy2 - n; + err_2 = dx2 - n; + for (i = 0; i < n; i++) { + + points.push_back(x); + points.push_back(y); + points.push_back(z); + + if (err_1 > 0) { + y += y_inc; + err_1 -= dz2; + } + if (err_2 > 0) { + x += x_inc; + err_2 -= dz2; + } + err_1 += dy2; + err_2 += dx2; + z += z_inc; + + } + } + + float* output= new float[points.size()]{0}; + std::copy(points.begin(), points.end(), output); + outputSize = points.size(); + return output; +} + +double * b3dMexDouble(double *startPoint,double *endPoint, size_t& outputSize) { + + std::vector points; + + double i, l, m, n, x_inc, y_inc, z_inc, err_1, err_2, dx2, dy2, dz2, x,y,z; + + x = startPoint[0]; + y = startPoint[1]; + z = startPoint[2]; + + double dx = endPoint[0] - x; + double dy = endPoint[1] - y; + double dz = endPoint[2] - z; + + x_inc = (dx < 0) ? -1 : 1; + l = abs(dx); + y_inc = (dy < 0) ? -1 : 1; + m = abs(dy); + z_inc = (dz < 0) ? -1 : 1; + n = abs(dz); + dx2 = l*2;// << 1; + dy2 = m*2;// << 1; + dz2 = n*2;// << 1; + + if ((l >= m) && (l >= n)) { + err_1 = dy2 - l; + err_2 = dz2 - l; + for (i = 0; i < l; i++) { + + points.push_back(x); + points.push_back(y); + points.push_back(z); + + if (err_1 > 0) { + y += y_inc; + err_1 -= dx2; + } + if (err_2 > 0) { + z += z_inc; + err_2 -= dx2; + } + err_1 += dy2; + err_2 += dz2; + x += x_inc; + + } + } else if ((m >= l) && (m >= n)) { + err_1 = dx2 - m; + err_2 = dz2 - m; + for (i = 0; i < m; i++) { + + points.push_back(x); + points.push_back(y); + points.push_back(z); + + if (err_1 > 0) { + x += x_inc; + err_1 -= dy2; + } + if (err_2 > 0) { + z += z_inc; + err_2 -= dy2; + } + err_1 += dx2; + err_2 += dz2; + y += y_inc; + + } + } else { + err_1 = dy2 - n; + err_2 = dx2 - n; + for (i = 0; i < n; i++) { + + points.push_back(x); + points.push_back(y); + points.push_back(z); + + if (err_1 > 0) { + y += y_inc; + err_1 -= dz2; + } + if (err_2 > 0) { + x += x_inc; + err_2 -= dz2; + } + err_1 += dy2; + err_2 += dx2; + z += z_inc; + + } + } + + double* output = new double[points.size()]; + std::copy(points.begin(), points.end(), output); + outputSize = points.size(); + return output; +} diff --git a/src/transmissionReconstruction/reconstruction/buildMatrix/Bresenham.h b/src/transmissionReconstruction/reconstruction/buildMatrix/Bresenham.h new file mode 100644 index 0000000..bd5fd2d --- /dev/null +++ b/src/transmissionReconstruction/reconstruction/buildMatrix/Bresenham.h @@ -0,0 +1,8 @@ +#ifndef __B3DMEX_H__ +#define __B3DMEX_H__ +#include +namespace Recon { + float* b3dMex(float *startPoint, float *endPoint,std::size_t &outputSize ); + double * b3dMexDouble(double *startPoint,double *endPoint, size_t& outputSize); +} +#endif // __B3DMEX_H__ \ No newline at end of file diff --git a/src/transmissionReconstruction/reconstruction/buildMatrix/DGradient.cpp b/src/transmissionReconstruction/reconstruction/buildMatrix/DGradient.cpp new file mode 100644 index 0000000..f8d2b03 --- /dev/null +++ b/src/transmissionReconstruction/reconstruction/buildMatrix/DGradient.cpp @@ -0,0 +1,679 @@ +#include "DGradient.h" + +#include +#include +#include +#include +#include + +#include "Matrix.h" +#include "Function.h" +#include "Function3D.h" + + + +#ifndef MWSIZE_MAX +#define mwSize int // Defined in tmwtypes.h +#define mwIndex int +#define MWSIZE_MAX INT_FAST32_MAX +#endif + +#define ERR_HEAD "*** DGradient[mex]: " +#define ERR_ID "JSimon:DGradient:" + +// Prototypes: ----------------------------------------------------------------- +void CoreDim1Space1(double *X, const mwSize M, const mwSize nDX, double Space, + double *Y); +void CoreDimNSpace1(double *X, const mwSize step, const mwSize nX, + const mwSize nDX, double Space, double *Y); + +void WrapSpaceN(double *X, const mwSize Step, const mwSize nX, + const mwSize nDX, double *Factor, double *Y); +void GetFactor(double *Space, mwSize nDX, double *Factor); +void CoreDim1SpaceN(double *X, const mwSize M, const mwSize nDX, + double *Space, double *Y); +// void CoreDimNSpaceN(double *X, const mwSize step, const mwSize nX, +// const mwSize nDX, double *Space, double *Y); +void CoreDim1FactorN(double *X, const mwSize M, const mwSize nDX, + double *Factor, double *Y); +void CoreDimNFactorN(double *X, const mwSize Step, const mwSize nX, + const mwSize nDX, double *Factor, double *Y); + +void WrapSpaceNOrder2(double *X, const mwSize Step, const mwSize nX, + const mwSize nDX, double *Space, double *Y); +void GetFactorOrder2(double *Space, const mwSize nDX, + double *A, double *B, double *C); +void CoreDim1SpaceNOrder2(double *X, const mwSize nX, const mwSize nDX, + double *Space, double *Y); +void CoreDimNSpaceNOrder2(double *X, const mwSize Step, const mwSize nX, + const mwSize nDX, double *Space, double *Y); +void CoreDim1FactorNOrder2(double *X, const mwSize nX, const mwSize nDX, + double *A, double *B, double *C, double *Y); +void CoreDimNFactorNOrder2(double *X, const mwSize Step, const mwSize nX, + const mwSize nDX, double *A, double *B, double *C, double *Y); + +mwSize FirstNonSingeltonDim(const mwSize Xndim, const mwSize *Xdim); +mwSize GetStep(const mwSize *Xdim, const mwSize N); + +// Main function =============================================================== +Aurora::Matrix Recon::DGradient(const Aurora::Matrix aX,double aSpacing,double aDim) +{ + double *X, *Y, Nd, *Space, UnitSpace = 1.0; + mwSize nX, nDX, ndimX, N, Step, nSpace = 1; + const mwSize *dimX; + int Order2 = 0; + + // Pointers and dimension to input array: ------------------------------------ + X = aX.getData(); + nX = aX.getDataSize(); + ndimX = aX.getDims(); + dimX = new int[3]{aX.getDimSize(0), aX.getDimSize(1), aX.getDimSize(2)}; + + // Return fast on empty input matrix: + if (nX == 0) { + return aX; + } + + // Get spacing, if defined: -------------------------------------------------- + + Space = &aSpacing; + nSpace = 1; + if (nSpace == 0) { + nSpace = 1; + Space = &UnitSpace; + } + + + // Determine dimension to operate on: ---------------------------------------- + // 3rd input used: + + Nd = aDim; + N = (mwSize) Nd - 1; + if (Nd < 1.0 || Nd != floor(Nd)) { + std::cerr<= 1, operate on any dimension + CoreDimNSpace1(X, Step, nX, nDX, *Space, Y); + } + + } else if (Order2) { // Spacing defined as vector, 2nd order method: + if (nX == nDX) { // Single vector only - dynamic spacing factors: + CoreDim1SpaceNOrder2(X, nX, nDX, Space, Y); + } else { + WrapSpaceNOrder2(X, Step, nX, nDX, Space, Y); + } + + } else { // Spacing defined as vector, 1st order method: + if (nX == nDX) { // Single vector only - dynamic spacing factors: + CoreDim1SpaceN(X, nX, nDX, Space, Y); + } else { + WrapSpaceN(X, Step, nX, nDX, Space, Y); + } + } + + return Aurora::Matrix::fromRawData(Y, aX.getDimSize(0),aX.getDimSize(1), aX.getDimSize(2)); +} + +// Subroutines: ================================================================ +mwSize FirstNonSingeltonDim(const mwSize Xndim, const mwSize *Xdim) +{ + // Get first non-singelton dimension - zero based. + + mwSize N; + + for (N = 0; N < Xndim; N++) { + if (Xdim[N] != 1) { + return (N); + } + } + + return (0); // Use the first dimension if all dims are 1 +} + +// ============================================================================= +mwSize GetStep(const mwSize *Xdim, const mwSize N) +{ + // Get step size between elements of a subvector in the N'th dimension. + // This is the product of the leading dimensions. + + const mwSize *XdimEnd, *XdimP; + mwSize Step; + + Step = 1; + XdimEnd = Xdim + N; + for (XdimP = Xdim; XdimP < XdimEnd; Step *= *XdimP++) ; // empty loop + + return (Step); +} + +// ============================================================================= +void CoreDim1Space1(double *X, const mwSize nX, const mwSize nDX, double Space, + double *Y) +{ + // Operate on first dimension, scalar spacing, 1st order method. + + double x0, x1, x2, *Xf, *Xc, fac1, fac2; + + // Multiplication is faster than division: + fac1 = 1.0 / Space; + fac2 = 1.0 / (2.0 * Space); + + Xf = X + nX; // End of input array + while (X < Xf) { + Xc = X + nDX; + + x0 = *X++; // Forward difference: + x1 = *X++; + x2 = *X++; + *Y++ = (4 * x1 - x2 - 3 * x0) * fac2; + X--; + while (X < Xc) { // Central differences: + x2 = *X++; + //X++; + *Y++ = (x2 - x0) * fac2; + x0 = x1; + x1 = x2; + } + //going back in time + x0 = *(X-3); + x1 = *(X-2); + *Y++ = (-4*x1 + x0 + 3* x2) * fac2; // Backward difference + } + + return; +} + +// ============================================================================= +void CoreDimNSpace1(double *X, const mwSize Step, const mwSize nX, + const mwSize nDX, double Space, double *Y) +{ + // Operate on any dimension, scalar spacing, 1st order method. + // Column oriented approach: Process contiguous memory blocks of input and + // output. + + double *Xf, *X0, *X1, *X2, *X3, *Xc, fac1, fac2; + mwSize nDXStep; + + // Multiplication is faster than division: + fac1 = 1.0 / Space; + fac2 = 1.0 / (2.0 * Space); + + // Distance between first and last element of X in specified dim: + nDXStep = nDX * Step; + + Xf = X + nX; // End of the input array + while (X < Xf) { + X1 = X; // Forward differences: + X2 = X1 + Step; + X3 = X2 + Step; + Xc = X2; + while (X1 < Xc) { + *Y++ = (4* *X2++ -3* *X1++ - *X3++) * fac2; + } + + X1 = X; // Central differences: + Xc = X + nDXStep; + while (X2 < Xc) { + *Y++ = (*X2++ - *X1++) * fac2; + } + + X2 = X1 + Step; // Backward differences: + X0 = X1 - Step; + while (X2 < Xc) { + *Y++ = ( *X0++ + 3* *X2++ -4* *X1++) * fac2; + } + + X = Xc; // Move input pointer to the next chunk + } + + return; +} + +// ============================================================================= +void WrapSpaceN(double *X, const mwSize Step, const mwSize nX, const mwSize nDX, + double *Space, double *Y) +{ + // Call different methods depending of the dimensions ofthe input. + // X has more than 1 vector. Therefore precalculating the spacing factors is + // cheaper. + + double *Factor; + + // Precalculate spacing factors: + if ((Factor =Aurora::malloc(nDX )) == NULL) { + std::cerr<