def closest_in_cell(self, vector): """ Return the closest object to the passed vector in vectors cell. """ objs = self.all_in_cell(vector) if not objs: return None return min(objs, key=lambda o: euclidean_dist_square(vector, o.vector))
def _closest_path(segments, point, paths_dict, order_path): min_path, min_point, min_point_id, min_d, min_segment = None, None, None, None, None for segment in segments: path = paths_dict[segment[0]] point_id = None if _is_closed_segment(segment): # segment p, d, point_id = closest_point_on_edge(path[segment[1]], path[segment[2]], point) else: # point p = path[segment[1]] d = euclidean_dist_square(p, point) if min_d is None or d < min_d: min_path, min_point, min_d, min_segment, min_point_id = path, p, d, segment, point_id if order_path: if _is_closed_segment(min_segment): if min_point_id is 2: # order contour so that the projection point is the starting point min_path = np.concatenate( (to_ndarray([min_point]), min_path[min_segment[2]:], min_path[:min_segment[2]])) else: # closest point is part of the path, rotate the path # around that point if min_segment[1] is 0: # proper contour start, do nothing pass else: min_path = np.roll(min_path, min_segment[min_point_id], axis=0) elif min_segment[1] < 0: # reverse open path if it ends on the end point denoted as -1 min_path = min_path[::-1] return min_path, min_segment[0]
def _closest_path(segments, point, paths_dict, order_path): min_path, min_point, min_point_id, min_d, min_segment = None, None, None, None, None for segment in segments: path = paths_dict[segment[0]] point_id = None if _is_closed_segment(segment): # segment p, d, point_id = closest_point_on_edge(path[segment[1]], path[segment[2]], point) else: # point p = path[segment[1]] d = euclidean_dist_square(p, point) if min_d is None or d < min_d: min_path, min_point, min_d, min_segment, min_point_id = path, p, d, segment, point_id if order_path: if _is_closed_segment(min_segment): if min_point_id is 2: # order contour so that the projection point is the starting point min_path = np.concatenate((to_ndarray([min_point]), min_path[min_segment[2]:], min_path[:min_segment[2]])) else: # closest point is part of the path, rotate the path # around that point if min_segment[1] is 0: # proper contour start, do nothing pass else: min_path = np.roll(min_path, min_segment[min_point_id], axis=0) elif min_segment[1] < 0: # reverse open path if it ends on the end point denoted as -1 min_path = min_path[::-1] return min_path, min_segment[0]
def _connect_lines(lines, delta, theta, center, max_connection_dist): # lines are np arrays of np arrays tha represent vertices connected_lines = [] # lines should be aligned left-right and be parallel to X-axis lines_by_y = {} d_lines = [] for line in lines: # align left to right if line[0][0] > line[-1][0]: line = line[::-1] # line should be a list of np arrays that represent vertices line = list(line) d_lines.append(line) lines_by_y.setdefault(line[0][1], []).append(line) y_positions = sorted(lines_by_y.keys()) dist_squared = max_connection_dist ** 2 while len(lines_by_y) > 0: prev_y = y_positions[0] # line has to be a list, not a np array # because points will be added to it line = lines_by_y[prev_y].pop() # used y-positions to be removed from line collections used_ys = [prev_y] for y in y_positions[1:]: if not prev_y < y < prev_y + (2 * delta): # > prev_y and np.isclose(y, prev_y + delta): break # find if any of lines at the next y is close enough to connect next_line_connection_side = 0 if ((len(line) % 4) is 0) else -1 current_line_connection_vertex = line[-1] for line_idx, l in enumerate(lines_by_y[y]): next_line_vertex = l[next_line_connection_side] # TODO: maybe do a clip in the square between points and if resulting number of polygons # is 1 than we cont need the euclidean dist -> just put that polygon into line if euclidean_dist_square(current_line_connection_vertex, next_line_vertex) < dist_squared: del lines_by_y[y][line_idx] used_ys.append(y) # properly orient the line if next_line_connection_side is -1: l = l[::-1] line.extend(list(l)) # go for next y position break prev_y = y for y in used_ys: if len(lines_by_y[y]) is 0: del lines_by_y[y] y_positions.remove(y) # convert back to np array connected_lines.append(rotate_xy(to_ndarray(line), theta, center)) return connected_lines