Add math function for radial Zernike

This commit is contained in:
Zhuoran Han 2018-08-03 12:42:18 -05:00
parent 6f99f1ae18
commit cdfa3565c9
3 changed files with 62 additions and 0 deletions

View file

@ -11,6 +11,7 @@ module math
public :: calc_pn
public :: calc_rn
public :: calc_zn
public :: calc_zn_rad
public :: evaluate_legendre
public :: rotate_angle
public :: maxwell_spectrum
@ -70,6 +71,15 @@ module math
real(C_DOUBLE), intent(out) :: zn(((n + 1) * (n + 2)) / 2)
end subroutine calc_zn
pure subroutine calc_zn_rad(n, rho, phi, zn_rad) bind(C, name='calc_zn_rad_c')
use ISO_C_BINDING
implicit none
integer(C_INT), value, intent(in) :: n
real(C_DOUBLE), value, intent(in) :: rho
real(C_DOUBLE), value, intent(in) :: phi
real(C_DOUBLE), intent(out) :: zn_rad((n / 2) + 1)
end subroutine calc_zn
subroutine rotate_angle_c_intfc(uvw, mu, phi) bind(C, name='rotate_angle_c')
use ISO_C_BINDING
implicit none

View file

@ -587,6 +587,35 @@ void calc_zn_c(int n, double rho, double phi, double zn[]) {
}
void calc_zn_rad_c(int n, double rho, double phi, double zn_rad[]) {
// Calculate R_p0(rho) as Zn_p0(rho)
// Set up the array of the coefficients
int length = int(n/2) + 1;
double zn_rad[length];
double q = 0;
// R_00 is always 1
zn_rad[0] = 1;
// Fill in the rest of the array (Eq 3.8 and Eq 3.10 in Chong)
for (int p = 2; p <= n; p += 2) {
int index = int(p/2);
if (p == 2) {
// Setting up R_22 to calculate R_20 (Eq 3.10 in Chong)
R_22 = std::pow(rho, 2);
zn_rad[index] = 2 * R_22 - zn_rad[0]
}
else {
double k1 = ((p + q) * (p - q) * (p - 2)) / 2.;
double k2 = 2 * p * (p - 1) * (p - 2);
double k3 = -q * q * (p - 1) - p * (p - 1) * (p - 2);
double k4 = (-p * (p + q - 2) * (p - q - 2)) / 2.;
zn_rad[index] =
((k2 * rho * rho + k3) * zn_rad[index-1] + k4 * zn_rad[index-2]) / k1;
}
}
}
void rotate_angle_c(double uvw[3], double mu, double* phi) {
// Copy original directional cosines

View file

@ -91,6 +91,29 @@ extern "C" void calc_rn_c(int n, const double uvw[3], double rn[]);
extern "C" void calc_zn_c(int n, double rho, double phi, double zn[]);
//==============================================================================
//! Calculate only the even radial components of n-th order modified Zernike
//! polynomial moment with azimuthal dependency m = 0 for a given angle
//! (rho, theta) location on the unit disk.
//!
//! Since m = 0, n could only be even orders. Z_q0 = R_q0
//!
//! This procedure uses the modified Kintner's method for calculating Zernike
//! polynomials as outlined in Chong, C. W., Raveendran, P., & Mukundan,
//! R. (2003). A comparative analysis of algorithms for fast computation of
//! Zernike moments. Pattern Recognition, 36(3), 731-742.
//! The normalization of the polynomials is such that the integral of Z_pq^2
//! over the unit disk is exactly pi.
//!
//! @param n The maximum order requested
//! @param rho The radial parameter to specify location on the unit disk
//! @param phi The angle parameter to specify location on the unit disk
//! @param zn_rad The requested moments of order 0 to n (inclusive)
//! evaluated at rho and phi when m = 0.
//==============================================================================
extern "C" void calc_zn_rad_c(int n, double rho, double phi, double zn_rad[]);
//==============================================================================
//! Rotate the direction cosines through a polar angle whose cosine is mu and
//! through an azimuthal angle sampled uniformly.