def extend_cpu_numba(sx, tx, sy, ty, xmin, xmax, ymin, ymax, x_start_i, x_flat, y_start_i, y_flat, *aggs_and_cols): nrows = len(x_start_i) x_flat_len = len(x_flat) y_flat_len = len(y_flat) for i in range(nrows): # Get x index range x_start_index = x_start_i[i] x_stop_index = (x_start_i[i + 1] if i < nrows - 1 else x_flat_len) # Get y index range y_start_index = y_start_i[i] y_stop_index = (y_start_i[i + 1] if i < nrows - 1 else y_flat_len) # Find line segment length as shorter of the two segments segment_len = min(x_stop_index - x_start_index, y_stop_index - y_start_index) for j in range(segment_len - 1): x0 = x_flat[x_start_index + j] y0 = y_flat[y_start_index + j] x1 = x_flat[x_start_index + j + 1] y1 = y_flat[y_start_index + j + 1] segment_start = ((j == 0) or isnull(x_flat[x_start_index + j - 1]) or isnull(y_flat[y_start_index + j] - 1)) draw_segment(i, sx, tx, sy, ty, xmin, xmax, ymin, ymax, segment_start, x0, x1, y0, y1, *aggs_and_cols)
def draw_segment( i, sx, tx, sy, ty, xmin, xmax, ymin, ymax, segment_start, x0, x1, y0, y1, *aggs_and_cols ): # NOTE: The slightly bizarre variable versioning herein for variables # x0, y0, y0, y1 is to deal with Numba not having SSA form prior to # version 0.49.0. The result of lack of SSA is that the type inference # algorithms would widen types that are multiply defined as would be the # case in code such as `x, y = function(x, y)` if the function returned # a wider type for x, y then the input x, y. skip = False # If any of the coordinates are NaN, there's a discontinuity. # Skip the entire segment. if isnull(x0) or isnull(y0) or isnull(x1) or isnull(y1): skip = True # Use Liang-Barsky to clip the segment to a bounding box x0_1, x1_1, y0_1, y1_1, skip, clipped_start, clipped_end = \ _liang_barsky(xmin, xmax, ymin, ymax, x0, x1, y0, y1, skip) if not skip: clipped = clipped_start or clipped_end segment_start = segment_start or clipped_start x0_2, y0_2 = map_onto_pixel( sx, tx, sy, ty, xmin, xmax, ymin, ymax, x0_1, y0_1 ) x1_2, y1_2 = map_onto_pixel( sx, tx, sy, ty, xmin, xmax, ymin, ymax, x1_1, y1_1 ) if antialias: _xiaolinwu(i, x0_2, x1_2, y0_2, y1_2, append, *aggs_and_cols) else: _bresenham(i, sx, tx, sy, ty, xmin, xmax, ymin, ymax, segment_start, x0_2, x1_2, y0_2, y1_2, clipped, append, *aggs_and_cols)
def perform_extend_line(i, j, sx, tx, sy, ty, xmin, xmax, ymin, ymax, plot_start, xs, ys, *aggs_and_cols): x0 = xs[i, j] y0 = ys[i, j] x1 = xs[i + 1, j] y1 = ys[i + 1, j] segment_start = (plot_start if i == 0 else (isnull(xs[i - 1, j]) or isnull(ys[i - 1, j]))) draw_segment(i, sx, tx, sy, ty, xmin, xmax, ymin, ymax, segment_start, x0, x1, y0, y1, *aggs_and_cols)
def perform_extend_line(i, j, sx, tx, sy, ty, xmin, xmax, ymin, ymax, xs, ys, *aggs_and_cols): x0 = xs[i, j] y0 = ys[j] x1 = xs[i, j + 1] y1 = ys[j + 1] segment_start = ((j == 0) or isnull(xs[i, j - 1]) or isnull(ys[j - 1])) draw_segment(i, sx, tx, sy, ty, xmin, xmax, ymin, ymax, segment_start, x0, x1, y0, y1, *aggs_and_cols)
def _append(x, y, m2, field, sum, count): # sum & count are the results of sum[y, x], count[y, x] before being # updated by field if not isnull(field): if count > 0: u1 = np.float64(sum) / count u = np.float64(sum + field) / (count + 1) m2[y, x] += (field - u1) * (field - u)
def draw_segment(i, sx, tx, sy, ty, xmin, xmax, ymin, ymax, segment_start, x0, x1, y0, y1, *aggs_and_cols): """Draw a line segment using Bresenham's algorithm This method plots a line segment with integer coordinates onto a pixel grid. """ skip = False # If any of the coordinates are NaN, there's a discontinuity. # Skip the entire segment. if isnull(x0) or isnull(y0) or isnull(x1) or isnull(y1): skip = True # Use Liang-Barsky (1992) to clip the segment to a bounding box # Check if line is fully outside viewport if x0 < xmin and x1 < xmin: skip = True elif x0 > xmax and x1 > xmax: skip = True elif y0 < ymin and y1 < ymin: skip = True elif y0 > ymax and y1 > ymax: skip = True t0, t1 = 0, 1 dx1 = x1 - x0 t0, t1, accept = _clipt(-dx1, x0 - xmin, t0, t1) if not accept: skip = True t0, t1, accept = _clipt(dx1, xmax - x0, t0, t1) if not accept: skip = True dy1 = y1 - y0 t0, t1, accept = _clipt(-dy1, y0 - ymin, t0, t1) if not accept: skip = True t0, t1, accept = _clipt(dy1, ymax - y0, t0, t1) if not accept: skip = True if t1 < 1: clipped_end = True x1 = x0 + t1 * dx1 y1 = y0 + t1 * dy1 else: clipped_end = False if t0 > 0: # If x0 is clipped, we need to plot the new start clipped_start = True x0 = x0 + t0 * dx1 y0 = y0 + t0 * dy1 else: clipped_start = False segment_start = segment_start or clipped_start if not skip: x0i, y0i = map_onto_pixel(sx, tx, sy, ty, xmin, xmax, ymin, ymax, x0, y0) x1i, y1i = map_onto_pixel(sx, tx, sy, ty, xmin, xmax, ymin, ymax, x1, y1) clipped = clipped_start or clipped_end dx = x1i - x0i ix = (dx > 0) - (dx < 0) dx = abs(dx) * 2 dy = y1i - y0i iy = (dy > 0) - (dy < 0) dy = abs(dy) * 2 # If vertices weren't clipped and are concurrent in integer space, # call append and return, so that the second vertex won't be hit below. if not clipped and not (dx | dy): append(i, x0i, y0i, *aggs_and_cols) return if segment_start: append(i, x0i, y0i, *aggs_and_cols) if dx >= dy: error = 2 * dy - dx while x0i != x1i: if error >= 0 and (error or ix > 0): error -= 2 * dx y0i += iy error += 2 * dy x0i += ix append(i, x0i, y0i, *aggs_and_cols) else: error = 2 * dx - dy while y0i != y1i: if error >= 0 and (error or iy > 0): error -= 2 * dy x0i += ix error += 2 * dx y0i += iy append(i, x0i, y0i, *aggs_and_cols)
def _append(x, y, agg, field): if isnull(agg[y, x]): agg[y, x] = field elif agg[y, x] < field: agg[y, x] = field
def _append(x, y, agg, field): if not isnull(field): if isnull(agg[y, x]): agg[y, x] = field else: agg[y, x] += field
def _append_cuda(x, y, agg, field): if not isnull(field): nb_cuda.atomic.add(agg, (y, x), field)
def _append(x, y, agg, field): if not isnull(field): agg[y, x] += field