def intersection(p0, p1, l): # get the intersection of two parabolas p = p0 if p0.x == p1.x: py = (p0.y + p1.y) / 2.0 elif p1.x == l: py = p1.y elif p0.x == l: py = p0.y p = p1 else: # use quadratic formula z0 = 2.0 * (p0.x - l) z1 = 2.0 * (p1.x - l) a = 1.0 / z0 - 1.0 / z1 b = -2.0 * (p0.y / z0 - p1.y / z1) c = 1.0 * (p0.y**2 + p0.x**2 - l**2) / z0 - 1.0 * (p1.y**2 + p1.x**2 - l**2) / z1 py = 1.0 * (-b - math.sqrt(b * b - 4 * a * c)) / (2 * a) px = 1.0 * (p.x**2 + (p.y - py)**2 - l**2) / (2 * p.x - 2 * l) res = Point(px, py) return res
def circle(self, a, b, c): if ((b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y)) > 0: return False, None, None # Joseph O'Rourke, Computational Geometry in C (2nd ed.) p.189 A = b.x - a.x B = b.y - a.y C = c.x - a.x D = c.y - a.y E = A * (a.x + b.x) + B * (a.y + b.y) F = C * (a.x + c.x) + D * (a.y + c.y) G = 2 * (A * (c.y - b.y) - B * (c.x - b.x)) if G == 0: return False, None, None # Points are co-linear # point o is the center of the circle ox = 1.0 * (D * E - B * F) / G oy = 1.0 * (A * F - C * E) / G # o.x plus radius equals max x coord x = ox + math.sqrt((a.x - ox)**2 + (a.y - oy)**2) o = Point(ox, oy) return True, x, o
def bresenham_line(p1, p2): x0 = p1.x x1 = p2.x y0 = p1.y y1 = p2.y dx = x1 - x0 dy = y1 - y0 xsign = 1 if dx > 0 else -1 ysign = 1 if dy > 0 else -1 dx = abs(dx) dy = abs(dy) if dx > dy: xx, xy, yx, yy = xsign, 0, 0, ysign else: dx, dy = dy, dx xx, xy, yx, yy = 0, ysign, xsign, 0 D = 2 * dy - dx y = 0 for x in range(dx + 1): yield Point(x0 + x * xx + y * yx, y0 + x * xy + y * yy) if D > 0: y += 1 D -= dx D += dy
def read_points(filename): book = open_workbook(filename) position_sheet = book.sheet_by_index(0) value_sheet = book.sheet_by_index(1) d = dict() for row in range(1, position_sheet.nrows): key = position_sheet.cell(row, 0).value x = position_sheet.cell(row, 1).value y = position_sheet.cell(row, 2).value d[key] = Point(key, x, y) for row in range(1, value_sheet.nrows): key = value_sheet.cell(row, 0).value val = value_sheet.cell(row, 1).value d[key].val = val return d.values()
def __init__(self, points, check=True): self.points = [Point(*x) for x in points] if len(self.points) < 3: raise ValueError('Not a polygon') self.edges = self.gen_edges() if check and not (self.check_convex() and self.check_self_intersection() and self.check_num_of_edges()): raise ValueError('Not convex') self.bbb = [] self.circles = None
def voronoi(self): test = set() for e in self.edges: i = 0 for u in bresenham_line(*e.points): if i % 20 == 0: test.add(u) i += 1 v = Voronoi(test) v.process() self.bbb = [] voronoi_res = [] ddd = {} for e in v.output: p01 = round(e.points[0].x), round(e.points[0].y) p02 = round(e.points[1].x), round(e.points[1].y) if p01 == p02: continue if p01 in ddd: ddd[p01] += 1 else: ddd[p01] = 1 p1 = Point(*p01) p2 = Point(*p02) voronoi_res.append(Segment(p1, p2)) for e in voronoi_res: p1 = e.points[0] p2 = e.points[1] if self.check_point_inside_polygon(p1) and \ self.check_point_inside_polygon(p2) and \ not self.check_point_on_edge(p1) and \ not self.check_point_on_edge(p2): self.bbb.append(e) self.filter_bbb(voronoi_res, ddd)
def arc_insert(self, p): if self.arc is None: self.arc = Arc(p) else: i = self.arc while i is not None: flag, z = self.intersect(p, i) if flag: flag, zz = self.intersect(p, i.pnext) if (i.pnext is not None) and (not flag): i.pnext.pprev = Arc(i.p, i, i.pnext) i.pnext = i.pnext.pprev else: i.pnext = Arc(i.p, i) i.pnext.s1 = i.s1 i.pnext.pprev = Arc(p, i, i.pnext) i.pnext = i.pnext.pprev i = i.pnext # now i points to the new arc seg = Segment(z, None) self.output.append(seg) i.pprev.s1 = i.s0 = seg seg = Segment(z, None) self.output.append(seg) i.pnext.s0 = i.s1 = seg self.check_circle_event(i) self.check_circle_event(i.pprev) self.check_circle_event(i.pnext) return i = i.pnext i = self.arc while i.pnext is not None: i = i.pnext i.pnext = Arc(p, i) # insert new segment between p and i x = self.x0 y = (i.pnext.p.y + i.p.y) / 2.0 start = Point(x, y) seg = Segment(start, None) i.s1 = i.pnext.s0 = seg self.output.append(seg)
def intersect(self, p, i): # check whether a new parabola at point p intersect with arc i if i is None: return False, None if i.p.x == p.x: return False, None a = 0.0 b = 0.0 if i.pprev is not None: a = (self.intersection(i.pprev.p, i.p, 1.0 * p.x)).y if i.pnext is not None: b = (self.intersection(i.p, i.pnext.p, 1.0 * p.x)).y if (((i.pprev is None) or (a <= p.y)) and ((i.pnext is None) or (p.y <= b))): py = p.y px = 1.0 * (i.p.x**2 + (i.p.y - py)**2 - p.x**2) / (2 * i.p.x - 2 * p.x) res = Point(px, py) return True, res return False, None