def setup_positions(): radius = 20 spacing = 2 d0 = Vec(0, radius) result = [] d = d0 theta = 2 * math.atan2(spacing, (2 * radius)) theta *= 180 / math.pi for i in range(8): phi = (3.5 - i) * theta p = Mat.rotz(phi) * d - d0 print(p) result.append((p, phi - 90)) d -= Vec(0, 2 * spacing) theta = 2 * math.atan2(2 * spacing, (2 * radius)) theta *= 180 / math.pi for i in range(2): phi = (.5 - i) * theta p = Mat.rotz(phi) * d - d0 print(p) result.append((p, -90)) d -= Vec(0, 1.5 * spacing) for i in range(1): phi = 0 p = Mat.rotz(phi) * d - d0 print(p) result.append((p, -90)) return result
def trace_grid(self, camera_name: str, p0: Vec, p1: Vec): step_size = min(self.get_pixel_size()) / 4.0 epsilon = step_size / 2.0 # to avoid array out of bounds p0 = p0.clamp(self.xmin, self.ymin, self.xmax - epsilon, self.ymax - epsilon) p1 = p1.clamp(self.xmin, self.ymin, self.xmax - epsilon, self.ymax - epsilon) to = p1 - p0 length = to.abs() if length < step_size: return dx = to.x / length * step_size dy = to.y / length * step_size pos_x, pos_y = p0.x, p0.y steps = int(length / step_size) g = self.get_grid(camera_name) self._trace_steps(g, pos_x, pos_y, dx, dy, steps)
def circumcenter_centroid_lerp(ratio: float, triangle: List[Tuple]) -> Tuple: p0 = Vec(*circumcenter(triangle)) p1 = Vec(*centroid(triangle)) u = p1 - p0 result = p0 + u.scale(ratio) return result.point2
def square_points(center: Vec, d: float, theta: float) -> List[Vec]: m = Mat.rotz(theta) i = m * Vec(1, 0) j = m * Vec(0, 1) result = list(reversed([ center + d * i - d * j, center + d * i + d * j, center - d * i + d * j, center - d * i - d * j, ])) return result
def main(): random.seed(46) grid = Grid(-10, -10, 10, 10, (400, 400), installation=None, spawner=False) g1 = grid.get_grid("camera-01") ct = g1.ctypes print("\n".join(a for a in dir(ct) if not a.startswith("_"))) print(list(ct.strides)) for i in range(1000): grid.trace_grid("camera-01", Vec(rand(), rand()), Vec(rand(), rand())) print(np.sum(g1))
def poly_line_intersection(svg: svgwrite.Drawing, poly, line: Line2D) -> Vec: # note: this assumes an intersection will take place poly = [Vec(*p) for p in poly] results = [] for p0, p1 in doubles(poly): segment = Line2D.from_points(p0, p1) d = (p1 - p0).abs() try: s = segment.intersect_distance(line) except NoIntersection: continue if 0 <= s < d: t = line.intersect_distance(segment) if t > 0: # svg.add(svg.line(p0.point2, p1.point2, stroke="green", stroke_width=0.5)) # svg.add(svg.circle(p1.point2, 0.5, fill="magenta")) q = segment.p + s * segment.u # svg.add(svg.circle(q.point2, 0.5, fill="yellow")) # svg.save() results.append((q.abs(), q)) return min(results)[1]
def line(self, p0: Vec, p1: Vec, stroke='black'): if p0.point2 == p1.point2: return self.svg.debug( self.svg.svg.line( (p0 + Vec(5.0, 5.0)).point2, (p1 + Vec(5.0, 5.0)).point2, stroke=stroke, stroke_width=0.5, )) self.svg.debug(self.svg.svg.circle(p1.point2, 0.25, fill='magenta')) if len(self._current_shape) == 0: self._current_shape.append(p0) self._current_shape.append(p1)
def build_wall(p0, p1, depth): v0, v1 = Vec(*p0), Vec(*p1) to = v1 - v0 n = to.cross(Vec(0.0, 0.0, 1.0)).unit().point3 a = [*v0.point2, 0.0] b = [*v1.point2, 0.0] c = [*v1.point2, depth] t0 = [*n, *a, *b, *c] a = [*v0.point2, 0.0] b = [*v1.point2, depth] c = [*v0.point2, depth] t1 = [*n, *a, *b, *c] return t0, t1
def motion_detected(self, camera_name: str, position: Vec): # perhaps not the best place for this function to live cam = self.inst.cameras.get(camera_name) if cam is None: log.error("Unknown camera", camera=camera_name) return p0 = Vec(0, 0) p1 = Mat.rotz(position) * Vec(10, 0) p0 = cam.stand.m * cam.m * p0 p1 = cam.stand.m * cam.m * p1 self.broadcast("motion-line", p0=[p0.x, p0.y], p1=[p1.x, p1.y]) self.grid.trace(camera_name, p0, p1) # sync focal points grid_fps = {fp.id: fp for fp in self.grid.focal_points} grid_ids = set(grid_fps.keys()) my_ids = set(self._focal_points.keys()) new = grid_ids - my_ids removed = my_ids - grid_ids existing = grid_ids & my_ids for name in new: fp = grid_fps[name] self._add_focal_point(fp.id, fp.pos) for name in removed: self._remove_focal_point(name) for name in existing: grid_fp = grid_fps[name] mine = self._focal_points[name] mine.pos = grid_fp.pos mine.ttl = 5.0 self._publish_focal_points()
def star_points(center, scale, theta_0) -> List[Vec]: # http://mathworld.wolfram.com/Pentagram.html R = 0.200811 rho = 0.525731 pi = math.pi R *= scale rho *= scale incr = -2 * pi / 5 theta = pi / 2 - incr + theta_0 outer = [] for i in range(5): print(theta * 180 / pi) x = rho * cos(theta) y = rho * sin(theta) outer.append((x, y)) theta += incr theta = - pi / 2 - 3 * incr + theta_0 inner = [] for i in range(5): print(theta * 180 / pi) x = R * cos(theta) y = R * sin(theta) inner.append((x, y)) theta += incr print(outer) print(inner) result = [] for i in range(5): result.append(Vec(*outer[i]) + center) result.append(Vec(*inner[i]) + center) return result
def handle_kinect_motion(self, msg: Dict): data = msg['data'] simplified_bodies: List = data['simplifiedBodies'] for body in simplified_bodies: if not body['tracked']: continue joints = body.get('joints', []) for joint in joints: x = joint.get('globalX') y = joint.get('globalY') if x is not None and y is not None: name = joint.get('name') self._add_focal_point(name, Vec(x, y))
def mitchell(cfg, seed: int): wall = Wall(f"mitchell-{seed}", cfg) output = subprocess.check_output(["mitchell/mitchell", str(seed)]) circles = json.loads(output) for circle in circles: center = Vec(circle['x'], circle['y']) r = circle['r'] points = circle_points(center, r, 20) poly = Polygon.Polygon([p.point2 for p in points]) & wall.window wall.result = wall.result + poly wall.result = wall.wall - wall.result wall.make_stl()
def interpolate_poly_circle(svg: svgwrite.Drawing, poly, center, radius, t): center = Vec(*center) points = circle_points(center, radius, 40) result = [] for p in points: # svg.add(svg.circle(p.point2, 0.3, fill="magenta")) line = Line2D.from_points(center, p) q = poly_line_intersection(svg, poly, line) w = t * q + (1 - t) * p result.append(w) svg.add(svg.circle(q.point2, 0.3, fill="blue")) # svg.add(svg.line(center.point2, q.point2, stroke="grey", stroke_width=0.3)) return result
def fun_circles(cfg, seed: int): random.seed(seed) wall = Wall(f"fun-circles-{seed}", cfg) points = poisson_disc_samples(width=cfg.width * 3, height=cfg.height * 3, r=cfg.r * 0.80) radii = {} for i in range(len(points)): radii[i] = min( distance(points[i], points[j]) for j in range(len(points)) if i != j) / 2 for i, point in enumerate(points): r = radii[i] * 0.95 center = Vec(*point) points = circle_points(center, r, 20) poly = Polygon.Polygon([p.point2 for p in points]) & wall.window wall.result = wall.result + poly wall.result = wall.wall - wall.result wall.make_stl()
def process_cmd(self, cmd, *args): print(cmd, " ".join(str(a) for a in args)) if cmd in 'Mm': p1 = Vec(*args) self.set_pos(p1) elif cmd == 'c': dx1, dy1, dx2, dy2, dx, dy = args p0 = self.pos p1 = p0 + Vec(dx1, dy1) p2 = p0 + Vec(dx2, dy2) p3 = p0 + Vec(dx, dy) STEPS = 10 p_bgn = p0 for i in range(1, STEPS + 1): t = i / STEPS p_new = cubic_bezier(p0, p1, p2, p3, t) self.line(p_bgn, p_new, stroke=self._color) p_bgn = p_new self.set_pos(p_new) elif cmd == 'C': x1, y1, x2, y2, x, y = args p0 = self.pos p1 = Vec(x1, y1) p2 = Vec(x2, y2) p3 = Vec(x, y) STEPS = 10 p_bgn = p0 for i in range(1, STEPS + 1): t = i / STEPS p_new = cubic_bezier(p0, p1, p2, p3, t) self.line(p_bgn, p_new, stroke=self._color) p_bgn = p_new self.set_pos(p_new) elif cmd == 's': dx2, dy2, dx, dy = args p0 = self.pos p1 = p0 + Vec(dx, dy) self.line(p0, p1) self.set_pos(p1) elif cmd in 'Zz': p0 = self.pos p1 = self._first self.line(p0, p1) self.finish_shape() elif cmd in 'h': dx = args[0] p0 = self.pos p1 = p0 + Vec(dx, 0) self.line(p0, p1) self.set_pos(p1) elif cmd in 'H': x = args[0] p0 = self.pos p1 = Vec(x, p0.y) self.line(p0, p1) self.set_pos(p1) elif cmd in 'L': x, y = args p0 = self.pos p1 = Vec(x, y) self.line(p0, p1) self.set_pos(p1) elif cmd in 'S': _, _, x, y = args p0 = self.pos p1 = Vec(x, y) self.line(p0, p1) self.set_pos(p1) elif cmd in 'A': rx, ry, x_rot, lrg, sweep, x, y = args assert rx == ry assert x_rot == 0 assert lrg == 0 assert sweep == 0 print("A:", args) assert 0 else: assert 0, f"unknown command {cmd}"
def manual_focal_point(self, name: str, x: float, y: float): self._add_focal_point(name, Vec(x, y), ttl=60.0)
def circle(center: Vec, radius: float, t: float) -> Vec: return ( center + radius * cos(2 * pi * t) * Vec(1.0, 0) + radius * sin(2 * pi * t) * Vec(0, 1.0) )
def focus(self) -> Tuple[Vec, float]: g = self.combined() m = np.argmax(g, axis=None) idx = np.unravel_index(m, g.shape) value = g[idx] return Vec(*self.idx_to_xy(idx)), value
def make_wall(cfg, points, name, debug_svg, x_offset, total_x): wall = Wall(name, cfg, x_offset=x_offset, y_offset=25) radii = {} for i in range(len(points)): radii[i] = min( distance(points[i], points[j]) for j in range(len(points)) if i != j) / 2 cut = Polygon.Polygon() def map_angle(x_in: float, y_in: float) -> float: a0 = 30 * math.pi / 180 f0 = 0.009 c = total_x phi = x_in / c * 2 * math.pi r = c / (2 * math.pi) x = r * math.cos(phi) y = r * math.cos(phi) z = y_in return a0 * noise.snoise3( f0 * x, f0 * y, f0 * z, ) + 0.25 * a0 * noise.snoise3( 2 * f0 * x + 1000, 2 * f0 * y + 1000, 2 * f0 * z + 1000, ) + 0.0 * a0 * (random.random() - 0.5) for i, point in enumerate(points): r = radii[i] * 2.5 center = Vec(*point) theta = map_angle(center.x, center.y) points: List[Vec] = star_points(center, r, theta) debug_svg.add( debug_svg.polygon([p.point2 for p in points], fill_opacity=0, stroke="black", stroke_width=0.25)) poly = Polygon.Polygon([p.point2 for p in points]) cut |= poly mask = wall.window & cut wall.result = wall.wall - mask wall.make_stl() debug_svg.add( debug_svg.polygon(wall.window.contour(0), fill_opacity=0, stroke="black", stroke_width=0.25)) debug_svg.add( debug_svg.polygon(wall.wall.contour(0), fill_opacity=0, stroke="black", stroke_width=0.25))
def make(self, prod_svg, debug_svg): x0, y0 = self.x0, self.y0 x1, y1 = self.x1, self.y1 b0 = (x1 - x0) / 2 - (6.125 + 7.5) block = Polygon.Polygon([ (x0 + b0, y0 + 0), (x1 - b0, y0 + 0), (x1 - b0, y0 + 14.25 + 7.5), (x0 + b0, y0 + 14.25 + 7.5), ]) b1 = (x1 - x0) / 2 - 6.125 tunnel = Polygon.Polygon([ (x0 + b1, y0 + -10), (x1 - b1, y0 + -10), (x1 - b1, y0 + 14.25), (x0 + b1, y0 + 14.25), ]) width = (x1 - x0) + 150 height = (y1 - y0) + 150 points = poisson_disc_samples(width=width, height=height, r=self.cfg.r) points = [(p[0] + x0 - 75, y1 - p[1] + 75) for p in points] # for p in points: # prod_svg.add(prod_svg.circle(p, 0.5, fill="green")) dely = DelaunayTri(points) cells = spooky_cells(dely) wx0 = min(p[0] for p in self.window[0]) wx1 = max(p[0] for p in self.window[0]) wy0 = min(p[1] for p in self.window[0]) wy1 = max(p[1] for p in self.window[0]) g0 = Graph(prod_svg, (wx0, wx1), (10, 10 + 30), (0.0, 1.0), "darkblue") g1 = Graph(prod_svg, (wx0, wx1), (10 + 30 + 5, 10 + 30 + 5 + 30), (0.0, 1.0), "darkgreen") for i, cell in sorted(cells.items()): inbounds = all(x0 - 50 < x < x1 + 50 and y0 - 50 < y < y1 + 50 for (x, y) in cell) if not inbounds: continue fixed = make_convex(cell) cx, cy = centroid(fixed) t = cx / (wx1 - wx0) s = cy / (wy1 - wy0) v = 0.73 * ( 0.5 + noise.snoise2(0.5 * s, 0.25 * t) + 0.5 * noise.snoise2(1 * s, 0.5 * t + 100) + 0.25 * noise.snoise2(2 * s, 1 * t + 200) ) v = geom.clamp(0, v, 1) g0.plot(cx, v) boost = inset_boost(v) g1.plot(cx, boost) inset_amount = self.cfg.line_width / 2.0 + boost p = inset(fixed, inset_amount) if p is None: continue cell = Polygon.Polygon(p) if len(cell & self.wall) == 0: continue c = centroid(cell.contour(0)) a = cell.area(0) r = (a / pi) ** 0.5 circle = Polygon.Polygon([p.point2 for p in circle_points(Vec(*c), r, 20)]) debug_svg.add(debug_svg.polygon(cell.contour(0), fill_opacity=0, stroke="black", stroke_width=0.25)) debug_svg.add(debug_svg.circle(c, r, fill_opacity=0, stroke="black", stroke_width=0.25)) # svg.save() new = geom.interpolate_poly_circle(debug_svg, cell.contour(0), c, r, 1 - v) new = Polygon.Polygon([p.point2 for p in new]) debug_svg.add(debug_svg.polygon(new.contour(0), fill_opacity=0, stroke="orange", stroke_width=0.25)) cell &= self.window circle &= self.window new &= self.window self.result += new debug_svg.add(debug_svg.polygon(self.window.contour(0), fill_opacity=0, stroke="black", stroke_width=0.25)) debug_svg.add(debug_svg.polygon(self.wall.contour(0), fill_opacity=0, stroke="black", stroke_width=0.25)) self.result = self.wall - self.result