From c7081c5c67f7f1beb9ecee9c4bf6d1d35eb0f86b Mon Sep 17 00:00:00 2001 From: Farid Yagubbayli Date: Tue, 23 Apr 2024 18:29:09 +0200 Subject: [PATCH 1/8] Refactor make_line --- kwave/utils/mapgen.py | 352 +++++++++--------------------------------- 1 file changed, 70 insertions(+), 282 deletions(-) diff --git a/kwave/utils/mapgen.py b/kwave/utils/mapgen.py index 3c957be96..bd1679d7d 100644 --- a/kwave/utils/mapgen.py +++ b/kwave/utils/mapgen.py @@ -1010,313 +1010,101 @@ def make_line( # ========================================================================= if linetype == "AtoB": - # a and b must be different points if np.all(a == b): raise ValueError("The first and last points cannot be the same.") - - # end point must be a two-element row vector if len(b) != 2: - raise ValueError("endpoint should be a two-element vector.") - - # a and b must be within the grid - xx = np.array([a[0], b[0]], dtype=int) - yy = np.array([a[1], b[1]], dtype=int) - if np.any(a < 0) or np.any(b < 0) or np.any(xx > grid_size.x - 1) or np.any(yy > grid_size.y - 1): + raise ValueError("Endpoint should be a two-element vector.") + + # Ensure a and b are within the grid bounds + if np.any(np.array(a) < 0) or np.any(np.array(b) < 0) or \ + np.any(np.array([a[0], b[0]]) >= grid_size.x) or \ + np.any(np.array([a[1], b[1]]) >= grid_size.y): raise ValueError("Both the start and end points must lie within the grid.") if linetype == "angled": - # angle must lie between -np.pi and np.pi - angle = angle % (2 * np.pi) - if angle > np.pi: - angle = angle - (2 * np.pi) - elif angle < -np.pi: - angle = angle + (2 * np.pi) + # Normalize the angle to be within -np.pi and np.pi + angle = (angle + np.pi) % (2 * np.pi) - np.pi # ========================================================================= # CALCULATE A LINE FROM A TO B # ========================================================================= if linetype == "AtoB": - # define an empty grid to hold the line - line = np.zeros(grid_size, dtype=bool) - - # find the equation of the line - m = (b[1] - a[1]) / (b[0] - a[0]) # gradient of the line - c = a[1] - m * a[0] # where the line crosses the y axis - - if abs(m) < 1: - # start at the end with the smallest value of x - if a[0] < b[0]: - x, y = a - x_end = b[0] - else: - x, y = b - x_end = a[0] - - # fill in the first point - line[x, y] = 1 - - while x < x_end: - # next points to try are - poss_x = [x, x, x + 1, x + 1, x + 1] - poss_y = [y - 1, y + 1, y - 1, y, y + 1] - - # find the point closest to the line - true_y = m * poss_x + c - diff = (poss_y - true_y) ** 2 - index = matlab_find(diff == min(diff))[0] - - # the next point - x = poss_x[index[0] - 1] - y = poss_y[index[0] - 1] - - # add the point to the line - line[x - 1, y - 1] = 1 - - elif not np.isinf(abs(m)): - # start at the end with the smallest value of y - if a[1] < b[1]: - x = a[0] - y = a[1] - y_end = b[1] - else: - x = b[0] - y = b[1] - y_end = a[1] - - # fill in the first point - line[x, y] = 1 - - while y < y_end: - # next points to try are - poss_y = [y, y, y + 1, y + 1, y + 1] - poss_x = [x - 1, x + 1, x - 1, x, x + 1] - - # find the point closest to the line - true_x = (poss_y - c) / m - diff = (poss_x - true_x) ** 2 - index = matlab_find(diff == min(diff))[0] - - # the next point - x = poss_x[index[0] - 1] - y = poss_y[index[0] - 1] - - # add the point to the line - line[x, y] = 1 - - else: # m = +-Inf - # start at the end with the smallest value of y - if a[1] < b[1]: - x = a[0] - y = a[1] - y_end = b[1] + line = np.zeros(grid_size, dtype=bool) # Initialize the grid + m = (b[1] - a[1]) / (b[0] - a[0]) # Calculate the gradient + c = a[1] - m * a[0] # Calculate the y-intercept + + def get_point_sequence(start, end, horizontal=True): + points = [] + if horizontal: + x, y = start + x_end = end[0] + while x != x_end: + y = round(m * x + c) + points.append((x, y)) + x += 1 if x < x_end else -1 else: - x = b[0] - y = b[1] - y_end = a[1] - - # fill in the first point - line[x, y] = 1 - - while y < y_end: - # next point - y = y + 1 + x, y = start + y_end = end[1] + while y != y_end: + x = round((y - c) / m) + points.append((x, y)) + y += 1 if y < y_end else -1 + return points + + # Determine the direction based on slope + if np.isinf(m): + smaller, larger = sorted([a, b], key=lambda p: p[1]) # Sort by y value + points = get_point_sequence(smaller, larger, horizontal=False) + elif abs(m) < 1: + smaller, larger = sorted([a, b], key=lambda p: p[0]) # Sort by x value + points = get_point_sequence(smaller, larger, horizontal=True) + else: + smaller, larger = sorted([a, b], key=lambda p: p[1]) # Sort by y value for steep slopes + points = get_point_sequence(smaller, larger, horizontal=False) - # add the point to the line - line[x, y] = 1 + # Plot the points on the line + for x, y in points: + line[x, y] = True # Set grid position to True to mark the line # ========================================================================= # CALCULATE AN ANGLED LINE # ========================================================================= elif linetype == "angled": - # define an empty grid to hold the line - line = np.zeros(grid_size, dtype=bool) - - # start at the atart - x, y = startpoint + line = np.zeros(grid_size, dtype=bool) # Initialize the grid + x, y = startpoint # Start point - # fill in the first point - line[x - 1, y - 1] = 1 - - # initialise the current length of the line + line[x-1, y-1] = True # Set the first point line_length = 0 + # Directional increments based on the angle + dx, dy = 0, 0 if abs(angle) == np.pi: - while line_length < linelength: - # next point - y = y + 1 - - # stop the points incrementing at the edges - if y > grid_size.y: - break - - # add the point to the line - line[x - 1, y - 1] = 1 - - # calculate the current length of the line - line_length = np.sqrt((x - startpoint[0]) ** 2 + (y - startpoint[1]) ** 2) - - elif (angle < np.pi) and (angle > np.pi / 2): - # define the equation of the line - m = -np.tan(angle - np.pi / 2) # gradient of the line - c = y - m * x # where the line crosses the y axis - - while line_length < linelength: - # next points to try are - poss_x = np.array([x - 1, x - 1, x]) - poss_y = np.array([y, y + 1, y + 1]) - - # find the point closest to the line - true_y = m * poss_x + c - diff = (poss_y - true_y) ** 2 - index = matlab_find(diff == min(diff))[0] - - # the next point - x = poss_x[index[0] - 1] - y = poss_y[index[0] - 1] - - # stop the points incrementing at the edges - if (x < 0) or (y > grid_size.y - 1): - break - - # add the point to the line - line[x - 1, y - 1] = 1 - - # calculate the current length of the line - line_length = np.sqrt((x - startpoint[0]) ** 2 + (y - startpoint[1]) ** 2) - - elif angle == np.pi / 2: - while line_length < linelength: - # next point - x = x - 1 - - # stop the points incrementing at the edges - if x < 1: - break - - # add the point to the line - line[x - 1, y - 1] = 1 - - # calculate the current length of the line - line_length = np.sqrt((x - startpoint[0]) ** 2 + (y - startpoint[1]) ** 2) - - elif (angle < np.pi / 2) and (angle > 0): - # define the equation of the line - m = np.tan(np.pi / 2 - angle) # gradient of the line - c = y - m * x # where the line crosses the y axis - - while line_length < linelength: - # next points to try are - poss_x = np.array([x - 1, x - 1, x]) - poss_y = np.array([y, y - 1, y - 1]) - - # find the point closest to the line - true_y = m * poss_x + c - diff = (poss_y - true_y) ** 2 - index = matlab_find(diff == min(diff))[0] - - # the next point - x = poss_x[index[0] - 1] - y = poss_y[index[0] - 1] - - # stop the points incrementing at the edges - if (x < 1) or (y < 1): - break - - # add the point to the line - line[x - 1, y - 1] = 1 - - # calculate the current length of the line - line_length = np.sqrt((x - startpoint[0]) ** 2 + (y - startpoint[1]) ** 2) - - elif angle == 0: - while line_length < linelength: - # next point - y = y - 1 - - # stop the points incrementing at the edges - if y < 1: - break - - # add the point to the line - line[x - 1, y - 1] = 1 - - # calculate the current length of the line - line_length = np.sqrt((x - startpoint[0]) ** 2 + (y - startpoint[1]) ** 2) - - elif (angle < 0) and (angle > -np.pi / 2): - # define the equation of the line - m = -np.tan(np.pi / 2 + angle) # gradient of the line - c = y - m * x # where the line crosses the y axis - - while line_length < linelength: - # next points to try are - poss_x = np.array([x + 1, x + 1, x]) - poss_y = np.array([y, y - 1, y - 1]) - - # find the point closest to the line - true_y = m * poss_x + c - diff = (poss_y - true_y) ** 2 - index = matlab_find(diff == min(diff))[0] - - # the next point - x = poss_x[index[0] - 1] - y = poss_y[index[0] - 1] - - # stop the points incrementing at the edges - if (x > grid_size.x) or (y < 1): - break - - # add the point to the line - line[x - 1, y - 1] = 1 - - # calculate the current length of the line - line_length = np.sqrt((x - startpoint[0]) ** 2 + (y - startpoint[1]) ** 2) - - elif angle == -np.pi / 2: - while line_length < linelength: - # next point - x = x + 1 - - # stop the points incrementing at the edges - if x > grid_size.x: - break - - # add the point to the line - line[x - 1, y - 1] = 1 - - # calculate the current length of the line - line_length = np.sqrt((x - startpoint[0]) ** 2 + (y - startpoint[1]) ** 2) - - elif (angle < -np.pi / 2) and (angle > -np.pi): - # define the equation of the line - m = np.tan(-angle - np.pi / 2) # gradient of the line - c = y - m * x # where the line crosses the y axis - - while line_length < linelength: - # next points to try are - poss_x = np.array([x + 1, x + 1, x]) - poss_y = np.array([y, y + 1, y + 1]) - - # find the point closest to the line - true_y = m * poss_x + c - diff = (poss_y - true_y) ** 2 - index = matlab_find(diff == min(diff))[0] - - # the next point - x = poss_x[index[0] - 1] - y = poss_y[index[0] - 1] - - # stop the points incrementing at the edges - if (x > grid_size.x) or (y > grid_size.y): - break - - # add the point to the line - line[x - 1, y - 1] = 1 + dy = 1 + elif angle == np.pi / 2 or angle == -np.pi / 2: + dx = -1 if angle == np.pi / 2 else 1 + elif (angle < np.pi and angle > np.pi / 2) or (angle < -np.pi / 2 and angle > -np.pi): + m = -np.tan(angle - np.sign(angle) * np.pi / 2) # Gradient of the line + c = y - m * x # Y-intercept of the line + dx, dy = (1 if angle < 0 else -1), round(m) + elif (angle < np.pi / 2 and angle > 0) or (angle < 0 and angle > -np.pi / 2): + m = np.tan(np.pi / 2 - abs(angle)) # Gradient of the line + c = y - m * x # Y-intercept of the line + dx, dy = (-1 if angle > 0 else 1), round(m) + + # Draw the line according to the specified angle + while line_length < linelength: + x += dx + y += dy + + # Check boundary conditions + if not (0 <= x < grid_size.x and 0 <= y < grid_size.y): + break + + line[x-1, y-1] = True # Set point + line_length = np.sqrt((x - startpoint[0])**2 + (y - startpoint[1])**2) # Update line length - # calculate the current length of the line - line_length = np.sqrt((x - startpoint[0]) ** 2 + (y - startpoint[1]) ** 2) return line From 0a1f4b5eac846e80c0e689f6fc799f7f15e3d21f Mon Sep 17 00:00:00 2001 From: Farid Yagubbayli Date: Tue, 23 Apr 2024 19:35:35 +0200 Subject: [PATCH 2/8] Revert --- kwave/utils/mapgen.py | 352 +++++++++++++++++++++++++++++++++--------- 1 file changed, 282 insertions(+), 70 deletions(-) diff --git a/kwave/utils/mapgen.py b/kwave/utils/mapgen.py index bd1679d7d..3c957be96 100644 --- a/kwave/utils/mapgen.py +++ b/kwave/utils/mapgen.py @@ -1010,101 +1010,313 @@ def make_line( # ========================================================================= if linetype == "AtoB": + # a and b must be different points if np.all(a == b): raise ValueError("The first and last points cannot be the same.") + + # end point must be a two-element row vector if len(b) != 2: - raise ValueError("Endpoint should be a two-element vector.") - - # Ensure a and b are within the grid bounds - if np.any(np.array(a) < 0) or np.any(np.array(b) < 0) or \ - np.any(np.array([a[0], b[0]]) >= grid_size.x) or \ - np.any(np.array([a[1], b[1]]) >= grid_size.y): + raise ValueError("endpoint should be a two-element vector.") + + # a and b must be within the grid + xx = np.array([a[0], b[0]], dtype=int) + yy = np.array([a[1], b[1]], dtype=int) + if np.any(a < 0) or np.any(b < 0) or np.any(xx > grid_size.x - 1) or np.any(yy > grid_size.y - 1): raise ValueError("Both the start and end points must lie within the grid.") if linetype == "angled": - # Normalize the angle to be within -np.pi and np.pi - angle = (angle + np.pi) % (2 * np.pi) - np.pi + # angle must lie between -np.pi and np.pi + angle = angle % (2 * np.pi) + if angle > np.pi: + angle = angle - (2 * np.pi) + elif angle < -np.pi: + angle = angle + (2 * np.pi) # ========================================================================= # CALCULATE A LINE FROM A TO B # ========================================================================= if linetype == "AtoB": - line = np.zeros(grid_size, dtype=bool) # Initialize the grid - m = (b[1] - a[1]) / (b[0] - a[0]) # Calculate the gradient - c = a[1] - m * a[0] # Calculate the y-intercept - - def get_point_sequence(start, end, horizontal=True): - points = [] - if horizontal: - x, y = start - x_end = end[0] - while x != x_end: - y = round(m * x + c) - points.append((x, y)) - x += 1 if x < x_end else -1 + # define an empty grid to hold the line + line = np.zeros(grid_size, dtype=bool) + + # find the equation of the line + m = (b[1] - a[1]) / (b[0] - a[0]) # gradient of the line + c = a[1] - m * a[0] # where the line crosses the y axis + + if abs(m) < 1: + # start at the end with the smallest value of x + if a[0] < b[0]: + x, y = a + x_end = b[0] else: - x, y = start - y_end = end[1] - while y != y_end: - x = round((y - c) / m) - points.append((x, y)) - y += 1 if y < y_end else -1 - return points - - # Determine the direction based on slope - if np.isinf(m): - smaller, larger = sorted([a, b], key=lambda p: p[1]) # Sort by y value - points = get_point_sequence(smaller, larger, horizontal=False) - elif abs(m) < 1: - smaller, larger = sorted([a, b], key=lambda p: p[0]) # Sort by x value - points = get_point_sequence(smaller, larger, horizontal=True) - else: - smaller, larger = sorted([a, b], key=lambda p: p[1]) # Sort by y value for steep slopes - points = get_point_sequence(smaller, larger, horizontal=False) + x, y = b + x_end = a[0] + + # fill in the first point + line[x, y] = 1 + + while x < x_end: + # next points to try are + poss_x = [x, x, x + 1, x + 1, x + 1] + poss_y = [y - 1, y + 1, y - 1, y, y + 1] + + # find the point closest to the line + true_y = m * poss_x + c + diff = (poss_y - true_y) ** 2 + index = matlab_find(diff == min(diff))[0] + + # the next point + x = poss_x[index[0] - 1] + y = poss_y[index[0] - 1] + + # add the point to the line + line[x - 1, y - 1] = 1 + + elif not np.isinf(abs(m)): + # start at the end with the smallest value of y + if a[1] < b[1]: + x = a[0] + y = a[1] + y_end = b[1] + else: + x = b[0] + y = b[1] + y_end = a[1] + + # fill in the first point + line[x, y] = 1 + + while y < y_end: + # next points to try are + poss_y = [y, y, y + 1, y + 1, y + 1] + poss_x = [x - 1, x + 1, x - 1, x, x + 1] + + # find the point closest to the line + true_x = (poss_y - c) / m + diff = (poss_x - true_x) ** 2 + index = matlab_find(diff == min(diff))[0] + + # the next point + x = poss_x[index[0] - 1] + y = poss_y[index[0] - 1] + + # add the point to the line + line[x, y] = 1 + + else: # m = +-Inf + # start at the end with the smallest value of y + if a[1] < b[1]: + x = a[0] + y = a[1] + y_end = b[1] + else: + x = b[0] + y = b[1] + y_end = a[1] + + # fill in the first point + line[x, y] = 1 - # Plot the points on the line - for x, y in points: - line[x, y] = True # Set grid position to True to mark the line + while y < y_end: + # next point + y = y + 1 + + # add the point to the line + line[x, y] = 1 # ========================================================================= # CALCULATE AN ANGLED LINE # ========================================================================= elif linetype == "angled": - line = np.zeros(grid_size, dtype=bool) # Initialize the grid - x, y = startpoint # Start point + # define an empty grid to hold the line + line = np.zeros(grid_size, dtype=bool) + + # start at the atart + x, y = startpoint - line[x-1, y-1] = True # Set the first point + # fill in the first point + line[x - 1, y - 1] = 1 + + # initialise the current length of the line line_length = 0 - # Directional increments based on the angle - dx, dy = 0, 0 if abs(angle) == np.pi: - dy = 1 - elif angle == np.pi / 2 or angle == -np.pi / 2: - dx = -1 if angle == np.pi / 2 else 1 - elif (angle < np.pi and angle > np.pi / 2) or (angle < -np.pi / 2 and angle > -np.pi): - m = -np.tan(angle - np.sign(angle) * np.pi / 2) # Gradient of the line - c = y - m * x # Y-intercept of the line - dx, dy = (1 if angle < 0 else -1), round(m) - elif (angle < np.pi / 2 and angle > 0) or (angle < 0 and angle > -np.pi / 2): - m = np.tan(np.pi / 2 - abs(angle)) # Gradient of the line - c = y - m * x # Y-intercept of the line - dx, dy = (-1 if angle > 0 else 1), round(m) - - # Draw the line according to the specified angle - while line_length < linelength: - x += dx - y += dy - - # Check boundary conditions - if not (0 <= x < grid_size.x and 0 <= y < grid_size.y): - break - - line[x-1, y-1] = True # Set point - line_length = np.sqrt((x - startpoint[0])**2 + (y - startpoint[1])**2) # Update line length + while line_length < linelength: + # next point + y = y + 1 + + # stop the points incrementing at the edges + if y > grid_size.y: + break + + # add the point to the line + line[x - 1, y - 1] = 1 + + # calculate the current length of the line + line_length = np.sqrt((x - startpoint[0]) ** 2 + (y - startpoint[1]) ** 2) + + elif (angle < np.pi) and (angle > np.pi / 2): + # define the equation of the line + m = -np.tan(angle - np.pi / 2) # gradient of the line + c = y - m * x # where the line crosses the y axis + + while line_length < linelength: + # next points to try are + poss_x = np.array([x - 1, x - 1, x]) + poss_y = np.array([y, y + 1, y + 1]) + + # find the point closest to the line + true_y = m * poss_x + c + diff = (poss_y - true_y) ** 2 + index = matlab_find(diff == min(diff))[0] + + # the next point + x = poss_x[index[0] - 1] + y = poss_y[index[0] - 1] + + # stop the points incrementing at the edges + if (x < 0) or (y > grid_size.y - 1): + break + + # add the point to the line + line[x - 1, y - 1] = 1 + + # calculate the current length of the line + line_length = np.sqrt((x - startpoint[0]) ** 2 + (y - startpoint[1]) ** 2) + + elif angle == np.pi / 2: + while line_length < linelength: + # next point + x = x - 1 + + # stop the points incrementing at the edges + if x < 1: + break + + # add the point to the line + line[x - 1, y - 1] = 1 + + # calculate the current length of the line + line_length = np.sqrt((x - startpoint[0]) ** 2 + (y - startpoint[1]) ** 2) + + elif (angle < np.pi / 2) and (angle > 0): + # define the equation of the line + m = np.tan(np.pi / 2 - angle) # gradient of the line + c = y - m * x # where the line crosses the y axis + + while line_length < linelength: + # next points to try are + poss_x = np.array([x - 1, x - 1, x]) + poss_y = np.array([y, y - 1, y - 1]) + + # find the point closest to the line + true_y = m * poss_x + c + diff = (poss_y - true_y) ** 2 + index = matlab_find(diff == min(diff))[0] + + # the next point + x = poss_x[index[0] - 1] + y = poss_y[index[0] - 1] + + # stop the points incrementing at the edges + if (x < 1) or (y < 1): + break + + # add the point to the line + line[x - 1, y - 1] = 1 + + # calculate the current length of the line + line_length = np.sqrt((x - startpoint[0]) ** 2 + (y - startpoint[1]) ** 2) + + elif angle == 0: + while line_length < linelength: + # next point + y = y - 1 + + # stop the points incrementing at the edges + if y < 1: + break + + # add the point to the line + line[x - 1, y - 1] = 1 + + # calculate the current length of the line + line_length = np.sqrt((x - startpoint[0]) ** 2 + (y - startpoint[1]) ** 2) + + elif (angle < 0) and (angle > -np.pi / 2): + # define the equation of the line + m = -np.tan(np.pi / 2 + angle) # gradient of the line + c = y - m * x # where the line crosses the y axis + + while line_length < linelength: + # next points to try are + poss_x = np.array([x + 1, x + 1, x]) + poss_y = np.array([y, y - 1, y - 1]) + + # find the point closest to the line + true_y = m * poss_x + c + diff = (poss_y - true_y) ** 2 + index = matlab_find(diff == min(diff))[0] + + # the next point + x = poss_x[index[0] - 1] + y = poss_y[index[0] - 1] + + # stop the points incrementing at the edges + if (x > grid_size.x) or (y < 1): + break + + # add the point to the line + line[x - 1, y - 1] = 1 + + # calculate the current length of the line + line_length = np.sqrt((x - startpoint[0]) ** 2 + (y - startpoint[1]) ** 2) + + elif angle == -np.pi / 2: + while line_length < linelength: + # next point + x = x + 1 + + # stop the points incrementing at the edges + if x > grid_size.x: + break + + # add the point to the line + line[x - 1, y - 1] = 1 + + # calculate the current length of the line + line_length = np.sqrt((x - startpoint[0]) ** 2 + (y - startpoint[1]) ** 2) + + elif (angle < -np.pi / 2) and (angle > -np.pi): + # define the equation of the line + m = np.tan(-angle - np.pi / 2) # gradient of the line + c = y - m * x # where the line crosses the y axis + + while line_length < linelength: + # next points to try are + poss_x = np.array([x + 1, x + 1, x]) + poss_y = np.array([y, y + 1, y + 1]) + + # find the point closest to the line + true_y = m * poss_x + c + diff = (poss_y - true_y) ** 2 + index = matlab_find(diff == min(diff))[0] + + # the next point + x = poss_x[index[0] - 1] + y = poss_y[index[0] - 1] + + # stop the points incrementing at the edges + if (x > grid_size.x) or (y > grid_size.y): + break + + # add the point to the line + line[x - 1, y - 1] = 1 + # calculate the current length of the line + line_length = np.sqrt((x - startpoint[0]) ** 2 + (y - startpoint[1]) ** 2) return line From d6d1e4aeba894b8d96d8b53e90aaee7a62f9ddae Mon Sep 17 00:00:00 2001 From: Farid Yagubbayli Date: Tue, 23 Apr 2024 19:46:31 +0200 Subject: [PATCH 3/8] Split to angled and straight --- kwave/utils/mapgen.py | 590 +++++++++++++++++++++--------------------- 1 file changed, 299 insertions(+), 291 deletions(-) diff --git a/kwave/utils/mapgen.py b/kwave/utils/mapgen.py index 3c957be96..31394a706 100644 --- a/kwave/utils/mapgen.py +++ b/kwave/utils/mapgen.py @@ -954,371 +954,379 @@ def create_pixel_dim(Nx: int, origin_size: float, shift: float) -> Tuple[np.ndar @typechecker -def make_line( +def make_line_straight( grid_size: Vector, startpoint: Union[Tuple[Int[kt.ScalarLike, ""], Int[kt.ScalarLike, ""]], Int[np.ndarray, "2"]], endpoint: Optional[Union[Tuple[Int[kt.ScalarLike, ""], Int[kt.ScalarLike, ""]], Int[np.ndarray, "2"]]] = None, - angle: Optional[Float[kt.ScalarLike, ""]] = None, - length: Optional[Int[kt.ScalarLike, ""]] = None, ) -> kt.NP_ARRAY_BOOL_2D: - """ - Generate a line shape with a given start and end point, angle, or length. + a, b = startpoint, endpoint + + # Addition => Fix Matlab2Python indexing + a -= 1 + b -= 1 + + # a and b must be different points + if np.all(a == b): + raise ValueError("The first and last points cannot be the same.") + + # end point must be a two-element row vector + if len(b) != 2: + raise ValueError("endpoint should be a two-element vector.") + + # a and b must be within the grid + xx = np.array([a[0], b[0]], dtype=int) + yy = np.array([a[1], b[1]], dtype=int) + if np.any(a < 0) or np.any(b < 0) or np.any(xx > grid_size.x - 1) or np.any(yy > grid_size.y - 1): + raise ValueError("Both the start and end points must lie within the grid.") + + # define an empty grid to hold the line + line = np.zeros(grid_size, dtype=bool) + + # find the equation of the line + m = (b[1] - a[1]) / (b[0] - a[0]) # gradient of the line + c = a[1] - m * a[0] # where the line crosses the y axis + + if abs(m) < 1: + # start at the end with the smallest value of x + if a[0] < b[0]: + x, y = a + x_end = b[0] + else: + x, y = b + x_end = a[0] - Args: - grid_size: The size of the grid in pixels. - startpoint: The start point of the line, given as a tuple of x and y coordinates. - endpoint: The end point of the line, given as a tuple of x and y coordinates. - If not specified, the line is drawn from the start point at a given angle and length. - angle: The angle of the line in radians, measured counterclockwise from the x-axis. - If not specified, the line is drawn from the start point to the end point. - length: The length of the line in pixels. - If not specified, the line is drawn from the start point to the end point. + # fill in the first point + line[x, y] = 1 + + while x < x_end: + # next points to try are + poss_x = [x, x, x + 1, x + 1, x + 1] + poss_y = [y - 1, y + 1, y - 1, y, y + 1] + + # find the point closest to the line + true_y = m * poss_x + c + diff = (poss_y - true_y) ** 2 + index = matlab_find(diff == min(diff))[0] + + # the next point + x = poss_x[index[0] - 1] + y = poss_y[index[0] - 1] + + # add the point to the line + line[x - 1, y - 1] = 1 + + elif not np.isinf(abs(m)): + # start at the end with the smallest value of y + if a[1] < b[1]: + x = a[0] + y = a[1] + y_end = b[1] + else: + x = b[0] + y = b[1] + y_end = a[1] - Returns: - line: A 2D array of the same size as the input parameters, - with a value of 1 for pixels that are part of the line and 0 for pixels that are not. - """ - assert len(grid_size) == 2, "Grid size must be a 2-element vector." + # fill in the first point + line[x, y] = 1 - startpoint = np.array(startpoint, dtype=int) - if endpoint is not None: - endpoint = np.array(endpoint, dtype=int) + while y < y_end: + # next points to try are + poss_y = [y, y, y + 1, y + 1, y + 1] + poss_x = [x - 1, x + 1, x - 1, x, x + 1] - if len(startpoint) != 2: - raise ValueError("startpoint should be a two-element vector.") + # find the point closest to the line + true_x = (poss_y - c) / m + diff = (poss_x - true_x) ** 2 + index = matlab_find(diff == min(diff))[0] - if np.any(startpoint < 1) or startpoint[0] > grid_size.x or startpoint[1] > grid_size.y: - ValueError("The starting point must lie within the grid, between [1 1] and [grid_size.x grid_size.y].") + # the next point + x = poss_x[index[0] - 1] + y = poss_y[index[0] - 1] - # ========================================================================= - # LINE BETWEEN TWO POINTS OR ANGLED LINE? - # ========================================================================= + # add the point to the line + line[x, y] = 1 - if endpoint is not None: - linetype = "AtoB" - a, b = startpoint, endpoint + else: # m = +-Inf + # start at the end with the smallest value of y + if a[1] < b[1]: + x = a[0] + y = a[1] + y_end = b[1] + else: + x = b[0] + y = b[1] + y_end = a[1] - # Addition => Fix Matlab2Python indexing - a -= 1 - b -= 1 - else: - linetype = "angled" - angle, linelength = angle, length + # fill in the first point + line[x, y] = 1 - # ========================================================================= - # MORE INPUT CHECKING - # ========================================================================= + while y < y_end: + # next point + y = y + 1 - if linetype == "AtoB": - # a and b must be different points - if np.all(a == b): - raise ValueError("The first and last points cannot be the same.") - - # end point must be a two-element row vector - if len(b) != 2: - raise ValueError("endpoint should be a two-element vector.") - - # a and b must be within the grid - xx = np.array([a[0], b[0]], dtype=int) - yy = np.array([a[1], b[1]], dtype=int) - if np.any(a < 0) or np.any(b < 0) or np.any(xx > grid_size.x - 1) or np.any(yy > grid_size.y - 1): - raise ValueError("Both the start and end points must lie within the grid.") - - if linetype == "angled": - # angle must lie between -np.pi and np.pi - angle = angle % (2 * np.pi) - if angle > np.pi: - angle = angle - (2 * np.pi) - elif angle < -np.pi: - angle = angle + (2 * np.pi) + # add the point to the line + line[x, y] = 1 + + return line - # ========================================================================= - # CALCULATE A LINE FROM A TO B - # ========================================================================= - if linetype == "AtoB": - # define an empty grid to hold the line - line = np.zeros(grid_size, dtype=bool) +@typechecker +def make_line_angled( + grid_size: Vector, + startpoint: Union[Tuple[Int[kt.ScalarLike, ""], Int[kt.ScalarLike, ""]], Int[np.ndarray, "2"]], + angle: Optional[Float[kt.ScalarLike, ""]] = None, + length: Optional[Int[kt.ScalarLike, ""]] = None, +) -> kt.NP_ARRAY_BOOL_2D: + angle, linelength = angle, length - # find the equation of the line - m = (b[1] - a[1]) / (b[0] - a[0]) # gradient of the line - c = a[1] - m * a[0] # where the line crosses the y axis + # angle must lie between -np.pi and np.pi + angle = angle % (2 * np.pi) + if angle > np.pi: + angle = angle - (2 * np.pi) + elif angle < -np.pi: + angle = angle + (2 * np.pi) - if abs(m) < 1: - # start at the end with the smallest value of x - if a[0] < b[0]: - x, y = a - x_end = b[0] - else: - x, y = b - x_end = a[0] + # define an empty grid to hold the line + line = np.zeros(grid_size, dtype=bool) - # fill in the first point - line[x, y] = 1 + # start at the atart + x, y = startpoint - while x < x_end: - # next points to try are - poss_x = [x, x, x + 1, x + 1, x + 1] - poss_y = [y - 1, y + 1, y - 1, y, y + 1] - - # find the point closest to the line - true_y = m * poss_x + c - diff = (poss_y - true_y) ** 2 - index = matlab_find(diff == min(diff))[0] - - # the next point - x = poss_x[index[0] - 1] - y = poss_y[index[0] - 1] - - # add the point to the line - line[x - 1, y - 1] = 1 - - elif not np.isinf(abs(m)): - # start at the end with the smallest value of y - if a[1] < b[1]: - x = a[0] - y = a[1] - y_end = b[1] - else: - x = b[0] - y = b[1] - y_end = a[1] + # fill in the first point + line[x - 1, y - 1] = 1 - # fill in the first point - line[x, y] = 1 + # initialise the current length of the line + line_length = 0 - while y < y_end: - # next points to try are - poss_y = [y, y, y + 1, y + 1, y + 1] - poss_x = [x - 1, x + 1, x - 1, x, x + 1] - - # find the point closest to the line - true_x = (poss_y - c) / m - diff = (poss_x - true_x) ** 2 - index = matlab_find(diff == min(diff))[0] - - # the next point - x = poss_x[index[0] - 1] - y = poss_y[index[0] - 1] - - # add the point to the line - line[x, y] = 1 - - else: # m = +-Inf - # start at the end with the smallest value of y - if a[1] < b[1]: - x = a[0] - y = a[1] - y_end = b[1] - else: - x = b[0] - y = b[1] - y_end = a[1] + if abs(angle) == np.pi: + while line_length < linelength: + # next point + y = y + 1 - # fill in the first point - line[x, y] = 1 + # stop the points incrementing at the edges + if y > grid_size.y: + break - while y < y_end: - # next point - y = y + 1 + # add the point to the line + line[x - 1, y - 1] = 1 - # add the point to the line - line[x, y] = 1 + # calculate the current length of the line + line_length = np.sqrt((x - startpoint[0]) ** 2 + (y - startpoint[1]) ** 2) - # ========================================================================= - # CALCULATE AN ANGLED LINE - # ========================================================================= + elif (angle < np.pi) and (angle > np.pi / 2): + # define the equation of the line + m = -np.tan(angle - np.pi / 2) # gradient of the line + c = y - m * x # where the line crosses the y axis - elif linetype == "angled": - # define an empty grid to hold the line - line = np.zeros(grid_size, dtype=bool) + while line_length < linelength: + # next points to try are + poss_x = np.array([x - 1, x - 1, x]) + poss_y = np.array([y, y + 1, y + 1]) - # start at the atart - x, y = startpoint + # find the point closest to the line + true_y = m * poss_x + c + diff = (poss_y - true_y) ** 2 + index = matlab_find(diff == min(diff))[0] - # fill in the first point - line[x - 1, y - 1] = 1 + # the next point + x = poss_x[index[0] - 1] + y = poss_y[index[0] - 1] - # initialise the current length of the line - line_length = 0 + # stop the points incrementing at the edges + if (x < 0) or (y > grid_size.y - 1): + break - if abs(angle) == np.pi: - while line_length < linelength: - # next point - y = y + 1 + # add the point to the line + line[x - 1, y - 1] = 1 - # stop the points incrementing at the edges - if y > grid_size.y: - break + # calculate the current length of the line + line_length = np.sqrt((x - startpoint[0]) ** 2 + (y - startpoint[1]) ** 2) - # add the point to the line - line[x - 1, y - 1] = 1 + elif angle == np.pi / 2: + while line_length < linelength: + # next point + x = x - 1 - # calculate the current length of the line - line_length = np.sqrt((x - startpoint[0]) ** 2 + (y - startpoint[1]) ** 2) + # stop the points incrementing at the edges + if x < 1: + break - elif (angle < np.pi) and (angle > np.pi / 2): - # define the equation of the line - m = -np.tan(angle - np.pi / 2) # gradient of the line - c = y - m * x # where the line crosses the y axis + # add the point to the line + line[x - 1, y - 1] = 1 - while line_length < linelength: - # next points to try are - poss_x = np.array([x - 1, x - 1, x]) - poss_y = np.array([y, y + 1, y + 1]) + # calculate the current length of the line + line_length = np.sqrt((x - startpoint[0]) ** 2 + (y - startpoint[1]) ** 2) - # find the point closest to the line - true_y = m * poss_x + c - diff = (poss_y - true_y) ** 2 - index = matlab_find(diff == min(diff))[0] + elif (angle < np.pi / 2) and (angle > 0): + # define the equation of the line + m = np.tan(np.pi / 2 - angle) # gradient of the line + c = y - m * x # where the line crosses the y axis - # the next point - x = poss_x[index[0] - 1] - y = poss_y[index[0] - 1] + while line_length < linelength: + # next points to try are + poss_x = np.array([x - 1, x - 1, x]) + poss_y = np.array([y, y - 1, y - 1]) - # stop the points incrementing at the edges - if (x < 0) or (y > grid_size.y - 1): - break + # find the point closest to the line + true_y = m * poss_x + c + diff = (poss_y - true_y) ** 2 + index = matlab_find(diff == min(diff))[0] - # add the point to the line - line[x - 1, y - 1] = 1 + # the next point + x = poss_x[index[0] - 1] + y = poss_y[index[0] - 1] - # calculate the current length of the line - line_length = np.sqrt((x - startpoint[0]) ** 2 + (y - startpoint[1]) ** 2) + # stop the points incrementing at the edges + if (x < 1) or (y < 1): + break - elif angle == np.pi / 2: - while line_length < linelength: - # next point - x = x - 1 + # add the point to the line + line[x - 1, y - 1] = 1 - # stop the points incrementing at the edges - if x < 1: - break - - # add the point to the line - line[x - 1, y - 1] = 1 + # calculate the current length of the line + line_length = np.sqrt((x - startpoint[0]) ** 2 + (y - startpoint[1]) ** 2) - # calculate the current length of the line - line_length = np.sqrt((x - startpoint[0]) ** 2 + (y - startpoint[1]) ** 2) + elif angle == 0: + while line_length < linelength: + # next point + y = y - 1 - elif (angle < np.pi / 2) and (angle > 0): - # define the equation of the line - m = np.tan(np.pi / 2 - angle) # gradient of the line - c = y - m * x # where the line crosses the y axis + # stop the points incrementing at the edges + if y < 1: + break - while line_length < linelength: - # next points to try are - poss_x = np.array([x - 1, x - 1, x]) - poss_y = np.array([y, y - 1, y - 1]) + # add the point to the line + line[x - 1, y - 1] = 1 - # find the point closest to the line - true_y = m * poss_x + c - diff = (poss_y - true_y) ** 2 - index = matlab_find(diff == min(diff))[0] + # calculate the current length of the line + line_length = np.sqrt((x - startpoint[0]) ** 2 + (y - startpoint[1]) ** 2) - # the next point - x = poss_x[index[0] - 1] - y = poss_y[index[0] - 1] + elif (angle < 0) and (angle > -np.pi / 2): + # define the equation of the line + m = -np.tan(np.pi / 2 + angle) # gradient of the line + c = y - m * x # where the line crosses the y axis - # stop the points incrementing at the edges - if (x < 1) or (y < 1): - break + while line_length < linelength: + # next points to try are + poss_x = np.array([x + 1, x + 1, x]) + poss_y = np.array([y, y - 1, y - 1]) - # add the point to the line - line[x - 1, y - 1] = 1 + # find the point closest to the line + true_y = m * poss_x + c + diff = (poss_y - true_y) ** 2 + index = matlab_find(diff == min(diff))[0] - # calculate the current length of the line - line_length = np.sqrt((x - startpoint[0]) ** 2 + (y - startpoint[1]) ** 2) + # the next point + x = poss_x[index[0] - 1] + y = poss_y[index[0] - 1] - elif angle == 0: - while line_length < linelength: - # next point - y = y - 1 + # stop the points incrementing at the edges + if (x > grid_size.x) or (y < 1): + break - # stop the points incrementing at the edges - if y < 1: - break + # add the point to the line + line[x - 1, y - 1] = 1 - # add the point to the line - line[x - 1, y - 1] = 1 + # calculate the current length of the line + line_length = np.sqrt((x - startpoint[0]) ** 2 + (y - startpoint[1]) ** 2) - # calculate the current length of the line - line_length = np.sqrt((x - startpoint[0]) ** 2 + (y - startpoint[1]) ** 2) + elif angle == -np.pi / 2: + while line_length < linelength: + # next point + x = x + 1 - elif (angle < 0) and (angle > -np.pi / 2): - # define the equation of the line - m = -np.tan(np.pi / 2 + angle) # gradient of the line - c = y - m * x # where the line crosses the y axis + # stop the points incrementing at the edges + if x > grid_size.x: + break - while line_length < linelength: - # next points to try are - poss_x = np.array([x + 1, x + 1, x]) - poss_y = np.array([y, y - 1, y - 1]) + # add the point to the line + line[x - 1, y - 1] = 1 - # find the point closest to the line - true_y = m * poss_x + c - diff = (poss_y - true_y) ** 2 - index = matlab_find(diff == min(diff))[0] + # calculate the current length of the line + line_length = np.sqrt((x - startpoint[0]) ** 2 + (y - startpoint[1]) ** 2) - # the next point - x = poss_x[index[0] - 1] - y = poss_y[index[0] - 1] + elif (angle < -np.pi / 2) and (angle > -np.pi): + # define the equation of the line + m = np.tan(-angle - np.pi / 2) # gradient of the line + c = y - m * x # where the line crosses the y axis - # stop the points incrementing at the edges - if (x > grid_size.x) or (y < 1): - break + while line_length < linelength: + # next points to try are + poss_x = np.array([x + 1, x + 1, x]) + poss_y = np.array([y, y + 1, y + 1]) - # add the point to the line - line[x - 1, y - 1] = 1 + # find the point closest to the line + true_y = m * poss_x + c + diff = (poss_y - true_y) ** 2 + index = matlab_find(diff == min(diff))[0] - # calculate the current length of the line - line_length = np.sqrt((x - startpoint[0]) ** 2 + (y - startpoint[1]) ** 2) + # the next point + x = poss_x[index[0] - 1] + y = poss_y[index[0] - 1] - elif angle == -np.pi / 2: - while line_length < linelength: - # next point - x = x + 1 + # stop the points incrementing at the edges + if (x > grid_size.x) or (y > grid_size.y): + break - # stop the points incrementing at the edges - if x > grid_size.x: - break + # add the point to the line + line[x - 1, y - 1] = 1 - # add the point to the line - line[x - 1, y - 1] = 1 + # calculate the current length of the line + line_length = np.sqrt((x - startpoint[0]) ** 2 + (y - startpoint[1]) ** 2) - # calculate the current length of the line - line_length = np.sqrt((x - startpoint[0]) ** 2 + (y - startpoint[1]) ** 2) + return line - elif (angle < -np.pi / 2) and (angle > -np.pi): - # define the equation of the line - m = np.tan(-angle - np.pi / 2) # gradient of the line - c = y - m * x # where the line crosses the y axis - while line_length < linelength: - # next points to try are - poss_x = np.array([x + 1, x + 1, x]) - poss_y = np.array([y, y + 1, y + 1]) +@typechecker +def make_line( + grid_size: Vector, + startpoint: Union[Tuple[Int[kt.ScalarLike, ""], Int[kt.ScalarLike, ""]], Int[np.ndarray, "2"]], + endpoint: Optional[Union[Tuple[Int[kt.ScalarLike, ""], Int[kt.ScalarLike, ""]], Int[np.ndarray, "2"]]] = None, + angle: Optional[Float[kt.ScalarLike, ""]] = None, + length: Optional[Int[kt.ScalarLike, ""]] = None, +) -> kt.NP_ARRAY_BOOL_2D: + """ + Generate a line shape with a given start and end point, angle, or length. - # find the point closest to the line - true_y = m * poss_x + c - diff = (poss_y - true_y) ** 2 - index = matlab_find(diff == min(diff))[0] + Args: + grid_size: The size of the grid in pixels. + startpoint: The start point of the line, given as a tuple of x and y coordinates. + endpoint: The end point of the line, given as a tuple of x and y coordinates. + If not specified, the line is drawn from the start point at a given angle and length. + angle: The angle of the line in radians, measured counterclockwise from the x-axis. + If not specified, the line is drawn from the start point to the end point. + length: The length of the line in pixels. + If not specified, the line is drawn from the start point to the end point. - # the next point - x = poss_x[index[0] - 1] - y = poss_y[index[0] - 1] + Returns: + line: A 2D array of the same size as the input parameters, + with a value of 1 for pixels that are part of the line and 0 for pixels that are not. + """ + assert len(grid_size) == 2, "Grid size must be a 2-element vector." - # stop the points incrementing at the edges - if (x > grid_size.x) or (y > grid_size.y): - break + startpoint = np.array(startpoint, dtype=int) + if endpoint is not None: + endpoint = np.array(endpoint, dtype=int) - # add the point to the line - line[x - 1, y - 1] = 1 + if len(startpoint) != 2: + raise ValueError("startpoint should be a two-element vector.") - # calculate the current length of the line - line_length = np.sqrt((x - startpoint[0]) ** 2 + (y - startpoint[1]) ** 2) + if np.any(startpoint < 1) or startpoint[0] > grid_size.x or startpoint[1] > grid_size.y: + ValueError("The starting point must lie within the grid, between [1 1] and [grid_size.x grid_size.y].") - return line + if endpoint is not None: + return make_line_straight( + grid_size=grid_size, + startpoint=startpoint, + endpoint=endpoint + ) + else: + return make_line_angled( + grid_size=grid_size, + startpoint=startpoint, + angle=angle, + length=length + ) @typechecker From f6a5e42ab5d7d8239577d7543f1365bf85e920d5 Mon Sep 17 00:00:00 2001 From: Farid Yagubbayli Date: Tue, 23 Apr 2024 19:56:52 +0200 Subject: [PATCH 4/8] WIP --- kwave/utils/mapgen.py | 141 ++++++++---------------------------------- 1 file changed, 26 insertions(+), 115 deletions(-) diff --git a/kwave/utils/mapgen.py b/kwave/utils/mapgen.py index 31394a706..6079e8fb2 100644 --- a/kwave/utils/mapgen.py +++ b/kwave/utils/mapgen.py @@ -959,114 +959,31 @@ def make_line_straight( startpoint: Union[Tuple[Int[kt.ScalarLike, ""], Int[kt.ScalarLike, ""]], Int[np.ndarray, "2"]], endpoint: Optional[Union[Tuple[Int[kt.ScalarLike, ""], Int[kt.ScalarLike, ""]], Int[np.ndarray, "2"]]] = None, ) -> kt.NP_ARRAY_BOOL_2D: - a, b = startpoint, endpoint + a, b = np.array(startpoint) - 1, np.array(endpoint) - 1 # Adjust for zero-based indexing - # Addition => Fix Matlab2Python indexing - a -= 1 - b -= 1 - - # a and b must be different points if np.all(a == b): raise ValueError("The first and last points cannot be the same.") - - # end point must be a two-element row vector if len(b) != 2: - raise ValueError("endpoint should be a two-element vector.") - - # a and b must be within the grid - xx = np.array([a[0], b[0]], dtype=int) - yy = np.array([a[1], b[1]], dtype=int) - if np.any(a < 0) or np.any(b < 0) or np.any(xx > grid_size.x - 1) or np.any(yy > grid_size.y - 1): + raise ValueError("Endpoint should be a two-element vector.") + if not (0 <= a).all() or not (b < grid_size).all(): raise ValueError("Both the start and end points must lie within the grid.") - - # define an empty grid to hold the line - line = np.zeros(grid_size, dtype=bool) - - # find the equation of the line - m = (b[1] - a[1]) / (b[0] - a[0]) # gradient of the line - c = a[1] - m * a[0] # where the line crosses the y axis - - if abs(m) < 1: - # start at the end with the smallest value of x - if a[0] < b[0]: - x, y = a - x_end = b[0] - else: - x, y = b - x_end = a[0] - - # fill in the first point - line[x, y] = 1 - - while x < x_end: - # next points to try are - poss_x = [x, x, x + 1, x + 1, x + 1] - poss_y = [y - 1, y + 1, y - 1, y, y + 1] - # find the point closest to the line - true_y = m * poss_x + c - diff = (poss_y - true_y) ** 2 - index = matlab_find(diff == min(diff))[0] - - # the next point - x = poss_x[index[0] - 1] - y = poss_y[index[0] - 1] - - # add the point to the line - line[x - 1, y - 1] = 1 - - elif not np.isinf(abs(m)): - # start at the end with the smallest value of y - if a[1] < b[1]: - x = a[0] - y = a[1] - y_end = b[1] - else: - x = b[0] - y = b[1] - y_end = a[1] - - # fill in the first point - line[x, y] = 1 - - while y < y_end: - # next points to try are - poss_y = [y, y, y + 1, y + 1, y + 1] - poss_x = [x - 1, x + 1, x - 1, x, x + 1] + line = np.zeros(grid_size, dtype=bool) # Initialize the grid to hold the line + m = (b[1] - a[1]) / (b[0] - a[0]) if b[0] != a[0] else np.inf # Calculate gradient, handle vertical line + c = a[1] - m * a[0] if np.isfinite(m) else 0 # Calculate y-intercept if m is finite + + # Generate line points based on slope + if abs(m) < 1 or np.isinf(m): # Handle more horizontal or perfectly vertical lines + x_start, x_end = sorted([a[0], b[0]]) + for x in range(x_start, x_end + 1): + y = round(m * x + c) if np.isfinite(m) else a[1] + line[x, y] = True + else: # Handle more vertical lines + y_start, y_end = sorted([a[1], b[1]]) + for y in range(y_start, y_end + 1): + x = round((y - c) / m) + line[x, y] = True - # find the point closest to the line - true_x = (poss_y - c) / m - diff = (poss_x - true_x) ** 2 - index = matlab_find(diff == min(diff))[0] - - # the next point - x = poss_x[index[0] - 1] - y = poss_y[index[0] - 1] - - # add the point to the line - line[x, y] = 1 - - else: # m = +-Inf - # start at the end with the smallest value of y - if a[1] < b[1]: - x = a[0] - y = a[1] - y_end = b[1] - else: - x = b[0] - y = b[1] - y_end = a[1] - - # fill in the first point - line[x, y] = 1 - - while y < y_end: - # next point - y = y + 1 - - # add the point to the line - line[x, y] = 1 - return line @@ -1099,20 +1016,14 @@ def make_line_angled( line_length = 0 if abs(angle) == np.pi: - while line_length < linelength: - # next point - y = y + 1 - - # stop the points incrementing at the edges - if y > grid_size.y: - break - - # add the point to the line - line[x - 1, y - 1] = 1 - - # calculate the current length of the line - line_length = np.sqrt((x - startpoint[0]) ** 2 + (y - startpoint[1]) ** 2) - + # Calculate and draw the line to the maximum allowed y position within the grid and line length constraints + max_y = min(y + linelength, grid_size.y) + line[x - 1, y:max_y - 1] = True + + # Update y to the last position and calculate the actual length of the line + y = max_y - 1 + line_length = np.hypot(x - startpoint[0], y - startpoint[1]) + elif (angle < np.pi) and (angle > np.pi / 2): # define the equation of the line m = -np.tan(angle - np.pi / 2) # gradient of the line From 8d2464ef66ef289c60c2f3549b378581c08943eb Mon Sep 17 00:00:00 2001 From: Walter Simson Date: Sun, 23 Jun 2024 21:08:14 -0700 Subject: [PATCH 5/8] dimension check covered by typing --- kwave/utils/mapgen.py | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/kwave/utils/mapgen.py b/kwave/utils/mapgen.py index 6079e8fb2..4b8a76a1d 100644 --- a/kwave/utils/mapgen.py +++ b/kwave/utils/mapgen.py @@ -963,8 +963,6 @@ def make_line_straight( if np.all(a == b): raise ValueError("The first and last points cannot be the same.") - if len(b) != 2: - raise ValueError("Endpoint should be a two-element vector.") if not (0 <= a).all() or not (b < grid_size).all(): raise ValueError("Both the start and end points must lie within the grid.") @@ -1018,12 +1016,12 @@ def make_line_angled( if abs(angle) == np.pi: # Calculate and draw the line to the maximum allowed y position within the grid and line length constraints max_y = min(y + linelength, grid_size.y) - line[x - 1, y:max_y - 1] = True + line[x - 1, y : max_y - 1] = True # Update y to the last position and calculate the actual length of the line y = max_y - 1 line_length = np.hypot(x - startpoint[0], y - startpoint[1]) - + elif (angle < np.pi) and (angle > np.pi / 2): # define the equation of the line m = -np.tan(angle - np.pi / 2) # gradient of the line @@ -1226,18 +1224,9 @@ def make_line( ValueError("The starting point must lie within the grid, between [1 1] and [grid_size.x grid_size.y].") if endpoint is not None: - return make_line_straight( - grid_size=grid_size, - startpoint=startpoint, - endpoint=endpoint - ) + return make_line_straight(grid_size=grid_size, startpoint=startpoint, endpoint=endpoint) else: - return make_line_angled( - grid_size=grid_size, - startpoint=startpoint, - angle=angle, - length=length - ) + return make_line_angled(grid_size=grid_size, startpoint=startpoint, angle=angle, length=length) @typechecker From befffa0b52ba513478fa9a1bd15a15c403ab2da5 Mon Sep 17 00:00:00 2001 From: Walter Simson Date: Sun, 23 Jun 2024 21:11:21 -0700 Subject: [PATCH 6/8] add vertical and horizontal test cases --- .../matlab_collectors/collect_makeLine.m | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/matlab_test_data_collectors/matlab_collectors/collect_makeLine.m b/tests/matlab_test_data_collectors/matlab_collectors/collect_makeLine.m index 6936243ed..b8a03bfba 100644 --- a/tests/matlab_test_data_collectors/matlab_collectors/collect_makeLine.m +++ b/tests/matlab_test_data_collectors/matlab_collectors/collect_makeLine.m @@ -2,6 +2,8 @@ all_params = { ... {20, 20, [1, 1], [19, 19]}, ... {20, 20, [1, 1], [5, 5]}, ... + {20, 20, [1, 0], [5, 0]}, ... + {20, 20, [0, 1], [0, 1]}, ... {10, 20, [4, 15], [10, 1]}, ... {20, 20, [15, 15], 0.75 * pi, 5}, ... {20, 20, [15, 15], 0.75 * pi, -5}, ... From 0262f229d4c81dd9ddde694f38ae2fb8d71ed7e9 Mon Sep 17 00:00:00 2001 From: Walter Simson Date: Sun, 23 Jun 2024 21:11:45 -0700 Subject: [PATCH 7/8] test value errors --- .../python_testers/makeLine_test.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/matlab_test_data_collectors/python_testers/makeLine_test.py b/tests/matlab_test_data_collectors/python_testers/makeLine_test.py index 7197dccc3..3b98fe99b 100644 --- a/tests/matlab_test_data_collectors/python_testers/makeLine_test.py +++ b/tests/matlab_test_data_collectors/python_testers/makeLine_test.py @@ -3,6 +3,7 @@ from pathlib import Path import numpy as np +import pytest from scipy.io import loadmat from kwave.data import Vector @@ -43,3 +44,17 @@ def test_makeLine(): assert np.allclose(expected_line, line) logging.log(logging.INFO, "make_line(..) works as expected!") + + +def test_start_greater_grid_size(): + with np.testing.assert_raises(ValueError): + make_line(Vector([1, 1]), (-10, 10), (10, 10)) + + +def test_a_b_same(): + with np.testing.assert_raises(ValueError): + make_line(Vector([1, 1]), (10, 10), (10, 10)) + + +if __name__ == "__main__": + pytest.main([__file__]) From 34d5764327124fa233370ced963d293c7e4adea0 Mon Sep 17 00:00:00 2001 From: Walter Simson Date: Sun, 23 Jun 2024 21:19:25 -0700 Subject: [PATCH 8/8] fix point index --- .../matlab_collectors/collect_makeLine.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/matlab_test_data_collectors/matlab_collectors/collect_makeLine.m b/tests/matlab_test_data_collectors/matlab_collectors/collect_makeLine.m index b8a03bfba..1bb2a2037 100644 --- a/tests/matlab_test_data_collectors/matlab_collectors/collect_makeLine.m +++ b/tests/matlab_test_data_collectors/matlab_collectors/collect_makeLine.m @@ -2,8 +2,8 @@ all_params = { ... {20, 20, [1, 1], [19, 19]}, ... {20, 20, [1, 1], [5, 5]}, ... - {20, 20, [1, 0], [5, 0]}, ... - {20, 20, [0, 1], [0, 1]}, ... + {20, 20, [1, 1], [5, 1]}, ... + {20, 20, [1, 1], [1, 5]}, ... {10, 20, [4, 15], [10, 1]}, ... {20, 20, [15, 15], 0.75 * pi, 5}, ... {20, 20, [15, 15], 0.75 * pi, -5}, ...