/* * Copyright (C) 2016 Karlsruhe Institute of Technology * * This file is part of Ufo. * * This library is free software: you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation, either * version 3 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #include #include #include "lamino-roi.h" static inline void swap (gint *first, gint *second) { gint tmp; tmp = *first; *first = *second; *second = tmp; } /** * Determine the left and right column to read from a projection at a given * tomographic angle. */ void determine_x_extrema (gfloat extrema[2], GValueArray *x_extrema, GValueArray *y_extrema, gfloat tomo_angle, gfloat x_center) { gfloat sin_tomo, cos_tomo; gint x_min, x_max, y_min, y_max; sin_tomo = sin (tomo_angle); cos_tomo = cos (tomo_angle); x_min = EXTRACT_INT (x_extrema, 0); /* The interval is right-opened when OpenCL indices for both x and y are generated, */ /* so the last index doesn't count */ x_max = EXTRACT_INT (x_extrema, 1) - 1; y_min = EXTRACT_INT (y_extrema, 0); y_max = EXTRACT_INT (y_extrema, 1) - 1; if (sin_tomo < 0) { swap (&y_min, &y_max); } if (cos_tomo < 0) { swap (&x_min, &x_max); } /* -1 to make sure the interpolation doesn't reach to uninitialized values*/ extrema[0] = cos_tomo * x_min + sin_tomo * y_min + x_center - 1; /* +1 because extrema[1] will be accessed by interpolation * but the region in copying is right-open */ extrema[1] = cos_tomo * x_max + sin_tomo * y_max + x_center + 1; } /** * Determine the top and bottom row to read from a projection at given * tomographic and laminographic angles. */ void determine_y_extrema (gfloat extrema[2], GValueArray *x_extrema, GValueArray *y_extrema, gfloat z_extrema[2], gfloat tomo_angle, gfloat lamino_angle, gfloat y_center) { gfloat sin_tomo, cos_tomo, sin_lamino, cos_lamino; gint x_min, x_max, y_min, y_max; sin_tomo = sin (tomo_angle); cos_tomo = cos (tomo_angle); sin_lamino = sin (lamino_angle); cos_lamino = cos (lamino_angle); x_min = EXTRACT_INT (x_extrema, 0); x_max = EXTRACT_INT (x_extrema, 1) - 1; y_min = EXTRACT_INT (y_extrema, 0); y_max = EXTRACT_INT (y_extrema, 1) - 1; if (sin_tomo < 0) { swap (&x_min, &x_max); } if (cos_tomo > 0) { swap (&y_min, &y_max); } extrema[0] = sin_tomo * x_min - cos_tomo * y_min; extrema[1] = sin_tomo * x_max - cos_tomo * y_max; extrema[0] = extrema[0] * cos_lamino + z_extrema[0] * sin_lamino + y_center - 1; extrema[1] = extrema[1] * cos_lamino + z_extrema[1] * sin_lamino + y_center + 1; } /** * clip: * @result: resulting clipped extrema * @extrema: (min, max) * @maximum: projection width or height * * Clip extrema to an allowed interval [0, projection width/height) */ void clip (gint result[2], gfloat extrema[2], gint maximum) { result[0] = (gint) floorf (extrema[0]); result[1] = (gint) ceilf (extrema[1]); if (result[0] < 0) { result[0] = 0; } if (result[0] > maximum) { result[0] = maximum; } if (result[1] < 0) { result[1] = 0; } if (result[1] > maximum) { result[1] = maximum; } if (result[0] == result[1]) { if (result[1] < maximum) { result[1]++; } else if (result[0] > 0) { result[0]--; } else { g_warning ("Cannot extend"); } } else if (result[0] > result[1]) { g_warning ("Invalid extrema: minimum larger than maximum"); } } /** * Determine the left and right column to read from a projection at a given * tomographic angle. The result is bound to [0, projection width) */ void determine_x_region (gint result[2], GValueArray *x_extrema, GValueArray *y_extrema, gfloat tomo_angle, gfloat x_center, gint width) { gfloat extrema[2]; determine_x_extrema (extrema, x_extrema, y_extrema, tomo_angle, x_center); clip (result, extrema, width); } /** * Determine the top and bottom column to read from a projection at given * tomographic and laminographic angles. The result is bound to * [0, projection height). */ void determine_y_region (gint result[2], GValueArray *x_extrema, GValueArray *y_extrema, gfloat z_extrema[2], gfloat tomo_angle, gfloat lamino_angle, gfloat y_center, gint height) { gfloat extrema[2]; determine_y_extrema (extrema, x_extrema, y_extrema, z_extrema, tomo_angle, lamino_angle, y_center); clip (result, extrema, height); }