@@ -51,9 +51,9 @@ class ComputeGradient {
5151
5252// Gradient computation
5353
54- template <typename T, typename S>
54+ template <typename S>
5555 void
56- calc_bspline_fd_ds_mag (MeshData<T > &input, MeshData<S> &grad, const float hx, const float hy, const float hz);
56+ calc_bspline_fd_ds_mag (const MeshData<S > &input, MeshData<S> &grad, const float hx, const float hy, const float hz);
5757
5858 template <typename T,typename S>
5959 void mask_gradient (MeshData<T>& grad_ds,MeshData<S>& temp_ds,MeshData<T>& temp_full,APRParameters& par);
@@ -721,13 +721,16 @@ void ComputeGradient::get_smooth_bspline_3D(MeshData<T>& input,APRParameters& pa
721721 spline_timer.stop_timer ();
722722}
723723
724- template <typename T,typename S>
725- void ComputeGradient::calc_bspline_fd_ds_mag (MeshData<T> &input, MeshData<S> &grad, const float hx, const float hy,const float hz) {
726- //
727- // Bevan Cheeseman 2016
728- //
729- // Calculate fd filt, for xgrad with bsplines
730-
724+ /* *
725+ * Calculates downsampled gradient (maximum magnitude) with 'replicate' boundary approach (nearest border value)
726+ * @param input - input mesh
727+ * @param grad - output gradient (must be initialized)
728+ * @param hx - step in x dir
729+ * @param hy - step in y dir
730+ * @param hz - step in z dir
731+ */
732+ template <typename S>
733+ void ComputeGradient::calc_bspline_fd_ds_mag (const MeshData<S> &input, MeshData<S> &grad, const float hx, const float hy,const float hz) {
731734 const size_t z_num = input.z_num ;
732735 const size_t x_num = input.x_num ;
733736 const size_t y_num = input.y_num ;
@@ -738,67 +741,65 @@ void ComputeGradient::calc_bspline_fd_ds_mag(MeshData<T> &input, MeshData<S> &gr
738741 std::vector<S> temp (y_num, 0 );
739742 const size_t xnumynum = x_num * y_num;
740743
741- // 4 4
742- // 2 1,3 ... 1 2 3 ...
743- // 5 5
744744 #ifdef HAVE_OPENMP
745- #pragma omp parallel for default(shared) firstprivate(temp)
745+ #pragma omp parallel for default(shared) firstprivate(temp)
746746 #endif
747- for (size_t j = 0 ; j < z_num; ++j) {
748- S *left = input.mesh .begin () + j * xnumynum + 1 * y_num;
749- S *center = input.mesh .begin () + j * xnumynum;
747+ for (size_t z = 0 ; z < z_num; ++z) {
748+ // Belows pointers up, down... are forming stencil in X (left <-> right) and Z ( up <-> down) direction and
749+ // are pointing to whole Y column. If out of bounds then 'replicate' (nearest array border value) approach is used.
750+ //
751+ // up
752+ // ... left center right ...
753+ // down
754+ const S *left = input.mesh .begin () + z * xnumynum + 0 * y_num; // boundary value is chosen
755+ const S *center = input.mesh .begin () + z * xnumynum + 0 * y_num;
750756
751757 // LHS boundary condition is accounted for wiht this initialization
752- const size_t j_m = j > 0 ? j - 1 : 0 ;
753- const size_t j_p = std::min (z_num - 1 , j + 1 );
754- float g[x_num][y_num];
755- for (size_t i = 0 ; i < x_num - 1 ; ++i) {
756- S *up = input.mesh .begin () + j_m * xnumynum + i * y_num;
757- S *down = input.mesh .begin () + j_p * xnumynum + i * y_num;
758- S *right = input.mesh .begin () + j * xnumynum + (i + 1 ) * y_num;
758+ const size_t zMinus = z > 0 ? z - 1 : 0 /* boundary */ ;
759+ const size_t zPlus = std::min (z + 1 , z_num - 1 /* boundary */ );
760+
761+ for (size_t x = 0 ; x < x_num; ++x) {
762+ const S *up = input.mesh .begin () + zMinus * xnumynum + x * y_num;
763+ const S *down = input.mesh .begin () + zPlus * xnumynum + x * y_num;
764+ const size_t xPlus = std::min (x + 1 , x_num - 1 /* boundary */ );
765+ const S *right = input.mesh .begin () + z * xnumynum + xPlus * y_num;
759766
760767 // compute the boundary values
761- temp[0 ] = sqrt (pow ((right[0 ] - left[0 ]) / (2 * hx), 2.0 ) + pow ((down[0 ] - up[0 ]) / (2 * hz), 2.0 ));
762- g[0 ][i] = temp[0 ];
763- // do the y gradient
764- #ifdef HAVE_OPENMP
765- #pragma omp simd
766- #endif
767- for (size_t k = 1 ; k < y_num - 1 ; ++k) {
768- temp[k] = sqrt (pow ((right[k] - left[k]) / (2 * hx), 2.0 ) + pow ((down[k] - up[k]) / (2 * hz), 2.0 ) +
769- pow ((center[k + 1 ] - center[k - 1 ]) / (2 * hy), 2.0 ));
770- g[k][i] = temp[k];
768+ if (y_num >= 2 ) {
769+ temp[0 ] = sqrt (pow ((right[0 ] - left[0 ]) / (2 * hx), 2.0 ) + pow ((down[0 ] - up[0 ]) / (2 * hz), 2.0 ) + pow ((center[1 ] - center[0 /* boundary */ ]) / (2 * hy), 2.0 ));
770+ temp[y_num - 1 ] = sqrt (pow ((right[y_num - 1 ] - left[y_num - 1 ]) / (2 * hx), 2.0 ) + pow ((down[y_num - 1 ] - up[y_num - 1 ]) / (2 * hz), 2.0 ) + pow ((center[y_num - 1 /* boundary */ ] - center[y_num - 2 ]) / (2 * hy), 2.0 ));
771+ }
772+ else {
773+ temp[0 ] = 0 ; // same values minus same values in x/y/z
771774 }
772775
773- temp[y_num - 1 ] = sqrt (pow ((right[y_num - 1 ] - left[y_num - 1 ]) / (2 * hx), 2.0 ) +
774- pow ((down[y_num - 1 ] - up[y_num - 1 ]) / (2 * hz), 2.0 ));
775- g[y_num - 1 ][i] = temp[y_num - 1 ];
776+ // do the y gradient in range 1..y_num-2
777+ #ifdef HAVE_OPENMP
778+ #pragma omp simd
779+ #endif
780+ for (size_t y = 1 ; y < y_num - 1 ; ++y) {
781+ temp[y] = sqrt (pow ((right[y] - left[y]) / (2 * hx), 2.0 ) + pow ((down[y] - up[y]) / (2 * hz), 2.0 ) + pow ((center[y + 1 ] - center[y - 1 ]) / (2 * hy), 2.0 ));
782+ }
776783
777- int64_t j_2 = j / 2 ;
778- int64_t i_2 = i / 2 ;
784+ // Set as a downsampled gradient maximum from 2x2x2 gradient cubes
785+ int64_t z_2 = z / 2 ;
786+ int64_t x_2 = x / 2 ;
779787 for (size_t k = 0 ; k < y_num_ds; ++k) {
780788 size_t k_s = std::min (2 * k + 1 , y_num - 1 );
781- const size_t idx = j_2 * x_num_ds * y_num_ds + i_2 * y_num_ds + k;
789+ const size_t idx = z_2 * x_num_ds * y_num_ds + x_2 * y_num_ds + k;
782790 grad.mesh [idx] = std::max (temp[2 * k], std::max (temp[k_s], grad.mesh [idx]));
783791 }
784792
785793 // move left, center to current center, right (both +1 to right)
786794 std::swap (left, center);
787795 std::swap (center, right);
788796 }
789- for (int y = 0 ; y < y_num; ++y) {
790- for (int x = 0 ; x < x_num; ++x) {
791- std::cout << g[y][x] << " " ;
792- }
793- std::cout << " \n " ;
794- }
795797 }
796798}
797799
798- /*
800+ /* *
799801 * Caclulation of signal value from B-Spline co-efficients
800802 */
801-
802803template <typename T>
803804void ComputeGradient::calc_inv_bspline_y (MeshData<T>& input){
804805 //
0 commit comments