def is_within(self, pi_object, resolution=0.0001): if isinstance(pi_object, pi_point.Point): # uses ray casting algorithm to solve point in polygon inf_point = pi_point.Point( pi_object.x + self.rect_info.top_left.x + self.rect_info.width + 10, pi_object.y) ray_line = pi_line.Line(pi_object, inf_point) intersecting_points = self.get_intersecting_points(ray_line) if len(intersecting_points) % 2 == 0: return False elif len(intersecting_points) == 1: if intersecting_points[i].equal(pi_object): # it's just touching return False return True elif isinstance(pi_object, pi_line.Line): points = self.get_intersecting_points(pi_object) if (len(points)) == 1: if (self.is_touching(pi_object.start) and not (pi_object.start.equal(points[0]))): return True elif (self.is_touching(pi_object.end) and not (pi_object.end.equal(points[0]))): return True elif len(points) == 2: other_points = [pi_object.start, pi_object.end] sorted(other_points, key=self.__filter_x_function) sorted(other_points, key=self.__filter_x_function) dx_0 = other_points[0].x - points[0].x dx_1 = other_points[1].x - points[1].x resolution = -1.0 * resolution return (dx_0 >= resolution) and (dx_1 >= resolution) if self.is_within(pi_object.start) or self.is_within( pi_object.end): return True elif self.is_touching(pi_object.start) and self.is_touching( pi_object.end): return True else: return False return False
def is_touching(self, pi_object): if isinstance(pi_object, pi_point.Point): # uses raying casting algorithm to solve point in polygon inf_point = pi_point.Point( pi_object.x + self.rect_info.top_left.x + self.rect_info.width + 10, pi_object.y) ray_line = pi_line.Line(pi_object, inf_point) intersecting_points = self.get_intersecting_points(ray_line) return not (len(intersecting_points) % 2 == 0) elif isinstance(pi_object, pi_line.Line): points = self.get_intersecting_points(pi_object) return self.is_touching(pi_object.start) or self.is_touching( pi_object.end) or (len(points) > 0) else: return False return False
def get_intersecting_lines(self, spacing=10.0, angle=0.0): padding = max(rect_info.width, rect_info.height) lines = self.get_shading_lines(spacing, angle, padding) intersecting_lines = [] for i in range(len(lines)): line = lines[i] intersecting_points = self.get_intersecting_points(line) sorted(intersecting_points, key=self.__filter_x_function) for j in range(0, max(len(intersecting_points) - 1, 0), 2): start = intersecting_points[i] end = intersecting_points[j + 1] line = pi_line.Line(start, end) intersecting_lines.append(line) return intersecting_lines
def calculate(self): if not self.closed: self.data_points.append(self.data_points[0]) for i in range(len(self.data_points)): point = self.data_points[i] self.xs.append(point.x) self.ys.append(point.y) self.boundary_lines = [] perimeter = 0 for i in range(len(self.data_points) - 1): start = self.data_points[i] end = self.data_points[i + 1] self.line = pi_line.Line(start, end) self.boundary_lines.append(self.line) perimeter += abs(self.line.get_length()) self.rect_info.top_left = pi_point.Point(min(self.xs), min(self.ys)) self.rect_info.width = max(self.xs) - self.rect_info.top_left.x self.rect_info.height = max(self.ys) - self.rect_info.top_left.y self.rect_info.bottom_right = pi_point.Point( self.rect_info.top_left.x + self.rect_info.width, self.rect_info.top_left.y + self.rect_info.height) self.rect_info.area = self.rect_info.width * self.rect_info.height self.rect_info.radius = math.sqrt( pow(self.rect_info.width / 2.0, 2) + pow(self.rect_info.height / 2.0, 2)) / 2.0 self.rect_info.center = pi_point.Point( self.rect_info.top_left.x + (self.rect_info.width / 2.0), self.rect_info.top_left.y + (self.rect_info.height / 2.0)) self.rect_info.perimeter = perimeter mn = min(self.rect_info.width, self.rect_info.height) mx = max(self.rect_info.width, self.rect_info.height) self.ratio = 0 if ((mn <= 0) or (mx <= 0)) else mn / mx return True
def count_edges(self, angle_threshold): count = 1 def _get_angle(a, b, c): return math.acos(((b**2) + (a**2) - (c**2)) / (2.0 * b * a)) for i in range(len(self.boundary_lines) - 1): current_line = self.boundary_lines[i] next_line = self.boundary_lines[i + 1] a = current_line.length b = next_line.length c = pi_line.Line(current_line.start, next_line.end).length if min(a, b, c) <= 0: continue angle = _get_angle(a, b, c) if abs(angle) > angle_threshold: count += 1 return count
def get_shading_lines(self, spacing=10.0, angle=0.0, padding=0.0): lines = [] min_x = self.rect_info.top_left.x - padding min_y = self.rect_info.top_left.y - padding max_x = self.rect_info.bottom_right.x + padding max_y = self.rect_info.bottom_right.y + padding cx = (max_x - min_x) / 2.0 + min_x cy = (max_y - min_y) / 2.0 + min_y about_point = pi_point.Point(cx, cy) for y in range(min_y, max_y, spacing): start = pi_point.Point(min_x, y) end = pi_point.Point(max_x, y) line = pi_line.Line(start, end) line.rotate(angle, about_point) lines.append(line) return lines