def bound(self, state): c, r, a = self.center_radius_angle(state.m) # Use derivative of ellipse equation to find angle of min max points tx = dmath.atan2(-r[1] * dmath.sin(a[0]), -r[0] * dmath.cos(a[0])) ty = dmath.atan2(r[1] * dmath.cos(a[0]), -r[0] * dmath.sin(a[0])) # plug those numbers back into the ellipse equations dx = dmath.fabs(r[0] * dmath.cos(tx) * dmath.cos(a[0]) - r[1] * dmath.sin(tx) * dmath.sin(a[0])) dy = dmath.fabs(r[0] * dmath.cos(ty) * dmath.sin(a[0]) + r[1] * dmath.sin(ty) * dmath.cos(a[0])) return ((c[0] - dx, c[1] - dy), (c[0] + dx, c[1] + dy))
def center_radius_angle(self, m): points = xform(m, self.points) c = points[0] r, a = [], [] for p in points[1:]: dx, dy = p[0] - c[0], p[1] - c[1] r.append(dmath.hypot(dx, dy)) a.append(dmath.atan2(-dy, dx)) return c, r, a
def rect_pad(self, name, points, rounded, state): m = [] ret = [] for i in range(len(points)): p0, p1 = points[i], points[(i + 1) % len(points)] m.append(((p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2)) dim0 = dmath.hypot(m[2][0] - m[0][0], m[2][1] - m[0][1]) dim1 = dmath.hypot(m[3][0] - m[1][0], m[3][1] - m[1][1]) c = ((m[0][0] + m[2][0]) / 2, (m[0][1] + m[2][1]) / 2) if dim0.quantize(D("0.000001")) == dim1.quantize(D("0.000001")): if rounded: ret.append(circ_pad(name, c, dim0 / 2), state) else: ret += self.rect_pad(name, [ points[0], points[1], m[1], m[3] ], False, state) ret += self.rect_pad(name, [ m[3], m[1], points[2], points[3] ], False, state) return ret if dim0 > dim1: angle = dmath.atan2(m[2][1] - m[0][1], m[2][0] - m[0][0]) else: angle = dmath.atan2(m[3][1] - m[1][1], m[3][0] - m[1][0]) flags = [] if not rounded: flags.append("square") if state.get_onsolder(): flags.append("onsolder") if not state.get_paste(): flags.append("nopaste") thickness = min(dim0, dim1) / 2 width = max(dim0, dim1) - thickness * 2 p = [] p.append((c[0] + dmath.cos(angle) * width / 2, c[1] + dmath.sin(angle) * width / 2)) p.append((c[0] - dmath.cos(angle) * width / 2, c[1] - dmath.sin(angle) * width / 2)) ret.append("""Pad [ %s %s %s %s %s %s %s "%s" "%s" "%s" ]""" % ( P(p[0][0]), P(p[0][1]), P(p[1][0]), P(p[1][1]), P(thickness * 2), P(self.clearance * 2), P((self.mask + thickness) * 2), name, name, ",".join(flags))) return ret
D2 = Decimal(2) Vec = namedtuple("Vec", "x y") vcross = lambda (a, b), (c, d): a*d - b*c vdot = lambda (a, b), (c, d): a*c + b*d vadd = lambda (a, b), (c, d): Vec(a + c, b + d) vsub = lambda (a, b), (c, d): Vec(a - c, b - d) vlen = lambda x: sqrt(vdot(x, x)) vdist = lambda a, b: vlen(vsub(a, b)) vscale = lambda s, (x, y): Vec(x * s, y * s) def vnorm(v): l = vlen(v) return Vec(v.x / l, v.y / l) vangle = lambda (x, y): atan2(y, x) def anorm(a): if a > pi: return a - pi * D2 if a < -pi: return a + pi * D2 return a Circle = namedtuple("Circle", "x y r") def circle_cross((x0, y0, r0), (x1, y1, r1)): d = vdist(Vec(x0, y0), Vec(x1, y1)) if d >= r0 + r1 or d <= abs(r0 - r1): return [] s = (r0 + r1 + d) / D2 a = sqrt(s * (s - d) * (s - r0) * (s - r1))