def __nearest_distance(seg: LineSegment, p: Point): a = p.get_x() - seg.get_a().get_x() b = p.get_y() - seg.get_a().get_y() c = seg.get_b().get_x() - seg.get_a().get_x() d = seg.get_b().get_x() - seg.get_a().get_y() dot = a * c + b * d q = c ** 2 + d ** 2 param = -1 if q != 0: param = dot / q if param < 0: xx = seg.get_a().get_x() yy = seg.get_a().get_y() elif param > 1: xx = seg.get_b().get_x() yy = seg.get_b().get_y() else: xx = seg.get_a().get_x() + param * c yy = seg.get_a().get_y() + param * d dx = p.get_x() - xx dy = p.get_y() - yy return math.sqrt(dx ** 2 + dy ** 2)
def distance_between_two_points(pa: Point, pb: Point): """ Get a distance between two points :param pa - Point A :param pb - Point B :return distance between point A and B """ return math.sqrt(pow(pb.get_x() - pa.get_x(), 2) + pow(pb.get_y() - pa.get_y(), 2))
def __points_orientation(p: Point, q: Point, r: Point): value = (q.get_y() - p.get_y()) * (r.get_x() - q.get_x()) - (q.get_x() - p.get_x()) * (r.get_y() - q.get_y()) if value == 0: return 0 elif value > 0: return 1 else: return 2
def point_in_polygon(p: Point, polygon: Polygon): cn = 0 v = copy.deepcopy(polygon.get_list_points()) v.append(v[0]) for i in range(len(v)-1): if (v[i].get_y() <= p.get_y() and v[i+1].get_y() > p.get_y()) or \ (v[i].get_y() > p.get_y() and v[i+1].get_y() <= p.get_y()): vt = (p.get_y() - v[i].get_y()) / float(v[i+1].get_y() - v[i].get_y()) if p.get_x() < (v[i].get_x() + vt * (v[i+1].get_x() - v[i].get_x())): cn += 1 return True if (cn % 2) == 1 else False
def _make_circle_two_points(points: list, p: Point, q: Point): circ = make_diameter(p, q) left = None right = None px = p.get_x() py = p.get_y() qx = q.get_x() qy = q.get_y() # para cada ponto que nao está no circulo for r in points: if classics.side_of_circle(circ, r) >= 0: continue # Formar uma circunferência e classificá-la no lado esquerdo ou direito cross = _cross_product(px, py, qx, qy, r.get_x(), r.get_y()) c = make_circumcircle(p, q, r) if c is None: continue elif cross > 0.0 and (left is None or _cross_product(px, py, qx, qy, c.get_centre().get_x(), c.get_centre().get_y()) > _cross_product(px, py, qx, qy, left.get_centre().get_x(), left.get_centre().get_y())): left = c elif cross < 0.0 and (right is None or _cross_product(px, py, qx, qy, c.get_centre().get_x(), c.get_centre().get_y()) < _cross_product(px, py, qx, qy, right.get_centre().get_x(), right.get_centre().get_y())): right = c # selecionar qual circulo vai retornar if left is None and right is None: return circ elif left is None: return right elif right is None: return left else: return left if (left.get_radius() <= right.get_radius()) else right
def distance_between_one_line_and_one_point(p: Point, l: Line): """ Get a distance between one line and one point :param p: one point :param l: one line :return: distance between p and l """ return (math.fabs(l.get_a() * p.get_x() + l.get_a() * p.get_y() + l.get_c())) / \ math.sqrt(pow(l.get_a(), 2) + pow(l.get_b(), 2))
def orient_2d(a: Point, b: Point, c: Point): """ Orientation of tree points Algorithm based in http://www.geeksforgeeks.org/orientation-3-ordered-points/ :param a: point 1 :param b: point 2 :param c: point 3 :return: orientation """ first = (b.get_y() - a.get_y()) * (c.get_x() - b.get_x()) second = (c.get_y() - b.get_y()) * (b.get_x() - a.get_x()) det = first - second if det == 0: return 0 elif det > 0: return 1 else: return -1
def make_circumcircle(p0: Point, p1: Point, p2: Point): ax = p0.get_x() ay = p0.get_y() bx = p1.get_x() by = p1.get_y() cx = p2.get_x() cy = p2.get_y() ox = (min(ax, bx, cx) + max(ax, bx, cx)) / 2.0 oy = (min(ay, by, cy) + max(ay, by, cy)) / 2.0 ax -= ox ay -= oy bx -= ox by -= oy cx -= ox cy -= oy d = (ax * (by - cy) + bx * (cy - ay) + cx * (ay - by)) * 2.0 if d == 0.0: return None x = ox + ((ax * ax + ay * ay) * (by - cy) + (bx * bx + by * by) * (cy - ay) + (cx * cx + cy * cy) * (ay - by)) / d y = oy + ((ax * ax + ay * ay) * (cx - bx) + (bx * bx + by * by) * (ax - cx) + (cx * cx + cy * cy) * (bx - ax)) / d ra = math.hypot(x - p0.get_x(), y - p0.get_y()) rb = math.hypot(x - p1.get_x(), y - p1.get_y()) rc = math.hypot(x - p2.get_x(), y - p2.get_y()) return Circle(Point(x, y), max(ra, rb, rc))
def convex_polygon(poly: Polygon): if len(poly.get_list_points()) < 3: return False list_points = poly.get_list_points() res = 0 for i in range(len(list_points)): p = list_points[i] tmp = list_points[((i+1) % len(list_points))] vx = tmp.get_x() - p.get_x() vy = tmp.get_y() - p.get_y() v = Point(vx, vy) u = list_points[((i+2) % len(list_points))] if i == 0: res = u.get_x() * v.get_y() - u.get_y() * v.get_x() + v.get_x() * p.get_y() - v.get_y() * p.get_x() else: new_res = u.get_x() * v.get_y() - u.get_y() * v.get_x() + v.get_x() * p.get_y() - v.get_y() * p.get_x() if (new_res > 0 and res < 0) or (new_res < 0 and res > 0): return False return True
def __point_in_segment(p: Point, s: LineSegment): px = p.get_x() py = p.get_y() sa_x = s.get_a().get_x() sa_y = s.get_a().get_y() sb_x = s.get_b().get_x() sb_y = s.get_b().get_y() if px <= max(sa_x, sb_x) and px >= min(sa_x, sb_x) and \ py <= max(sa_y, sb_y) and py >= min(sa_y, sb_y): return True else: return False
def remove_point(self, p: Point): remove_seg = [] for i in self.__segments.get_iterator(): if i.get_a().comparable(i.get_a(), p) == 0 or i.get_b().comparable( i.get_b(), p) == 0: remove_seg.append(i) for i in remove_seg: self.__segments.delete(i) for i in self.__list_points: if i.get_x() == p.get_x() and i.get_y() == p.get_y(): self.__list_points.remove(i) break
def compare_y(p1: Point, p2: Point): return p1.get_y() - p2.get_y()
def onClick(self, event): if not self.LOCK: self.w.create_oval(event.x - self.RADIUS, event.y - self.RADIUS, event.x + self.RADIUS, event.y + self.RADIUS, fill="black") self.pts.append((event.x, event.y)) if self.btnCirculo['state'] == tk.NORMAL: if len(self.pts) == 2: p1 = Point(self.pts[0][0], self.pts[0][1]) p2 = Point(self.pts[1][0], self.pts[1][1]) distance = classics.distance_between_two_points(p1, p2) circle = Circle(p1, int(distance)) self.circles.append(circle) self.draw_circle(p1.get_x(), p1.get_y(), circle.get_radius()) nome = "Circ" + str(len(self.circles)) self.w.create_text(p1.get_x(), p1.get_y() + circle.get_radius() + 7, text=nome) self.liberaTodosBotoes() self.LOCK = True self.pts.clear() elif self.btnLinha['state'] == tk.NORMAL: if len(self.pts) == 2: p1 = Point(self.pts[0][0], self.pts[0][1]) p2 = Point(self.pts[1][0], self.pts[1][1]) line = Line.generate_by_two_points(p1, p2) self.lines.append(line) p1_x_canvas = line.get_x_from_y(0) p2_x_canvas = line.get_x_from_y(500) self.w.create_line(int(p1_x_canvas), 0, int(p2_x_canvas), 500, fill="RoyalBlue2") nome = "Lin" + str(len(self.lines)) self.w.create_text((p1_x_canvas + p2_x_canvas) / 2, (0 + 500) / 2, text=nome) self.liberaTodosBotoes() self.LOCK = True self.pts.clear() elif self.btnSegmento['state'] == tk.NORMAL: if len(self.pts) == 2: p1 = Point(self.pts[0][0], self.pts[0][1]) p2 = Point(self.pts[1][0], self.pts[1][1]) seg = LineSegment(p1, p2) self.segments.append(seg) self.w.create_line(p1.get_x(), p1.get_y(), p2.get_x(), p2.get_y(), fill='red') nome = "Seg" + str(len(self.segments)) self.w.create_text((p1.get_x() + p2.get_x()) / 2, (p1.get_y() + p2.get_y()) / 2, text=nome) self.liberaTodosBotoes() self.LOCK = True self.pts.clear() elif self.btnPonto['state'] == tk.NORMAL: p = Point(self.pts[0][0], self.pts[0][1]) self.points.append(p) nome = "Ptn" + str(len(self.points)) self.w.create_text(p.get_x(), p.get_y() + 10, text=nome) self.pts.clear() elif self.btnPolygon['state'] == tk.NORMAL: if len(self.pts) == 2: p1 = Point(self.pts[0][0], self.pts[0][1]) p2 = Point(self.pts[1][0], self.pts[1][1]) seg = LineSegment(p1, p2) self.polygons[len(self.polygons) - 1].add_segment(seg) self.w.create_line(p1.get_x(), p1.get_y(), p2.get_x(), p2.get_y(), fill='blue') del self.pts[0]
def make_diameter(p0: Point, p1: Point): cx = (p0.get_x() + p1.get_x()) / 2.0 cy = (p0.get_y() + p1.get_y()) / 2.0 r0 = math.hypot(cx - p0.get_x(), cy - p0.get_y()) r1 = math.hypot(cx - p1.get_x(), cy - p1.get_y()) return Circle(Point(cx, cy), max(r0, r1))