def reflect(shape, position, _angle, keep_original): """Mirrors and copies the geometry across an invisible axis.""" if shape is None: return None new_shape = shape.cloneAndClear() for contour in shape.contours: c = Contour() for point in contour.points: d = distance(point.x, point.y, position.x, position.y) a = angle(point.x, point.y, position.x, position.y) x, y = coordinates(position.x, position.y, d * cos(radians(a - _angle)), 180 + _angle) d = distance(point.x, point.y, x, y) a = angle(point.x, point.y, x, y) px, py = coordinates(point.x, point.y, d * 2, a) c.addPoint(Point(px, py, point.type)) if contour.closed: c.close() new_shape.add(c) if keep_original: g = Geometry() g.add(shape) g.add(new_shape) return g return new_shape
def draw(self, ctx): pos = self.getValue("position") x = pos.x y = pos.y a = self.getValue("angle") x1, y1 = coordinates(x, y, -1000, a) x2, y2 = coordinates(x, y, 1000, a) ctx.stroke(self.HANDLE_COLOR) ctx.line(x1, y1, x2, y2) CombinedHandle.draw(self, ctx)
def round_segments(path, d): points = path.points new_points = [] for i, pt in enumerate(points): prev = points[i - 1] next = points[(i + 1) % len(points)] a = angle(prev.x, prev.y, next.x, next.y) c1 = coordinates(pt.x, pt.y, -d, a) c2 = coordinates(pt.x, pt.y, d, a) new_points.append(Point(c1[0], c1[1])) new_points.append(pt) new_points.append(Point(c2[0], c2[1])) new_path = path.cloneAndClear() _construct_path(new_path, new_points) return new_path
def line_angle(position, angle, distance): p = Path() x1, y1 = coordinates(position.x, position.y, distance, angle) p.line(position.x, position.y, x1, y1) p.strokeColor = Color.BLACK p.strokeWidth = 1 return p
def polygon(position, radius, sides, align): """Draw a polygon.""" p = Path() x, y, r = position.x, position.y, radius sides = max(sides, 3) a = 360.0 / sides da = 0 if align: x0, y0 = coordinates(x, y, r, 0) x1, y1 = coordinates(x, y, r, a) da = -angle(x1, y1, x0, y0) for i in xrange(sides): x1, y1 = coordinates(x, y, r, (a * i) + da) if i == 0: p.moveto(x1, y1) else: p.lineto(x1, y1) p.close() return p
def polygon(position, radius, sides, align): """Draw a polygon.""" p = Path() x, y, r = position.x, position.y, radius sides = max(sides, 3) a = 360.0 / sides da = 0 if align: x0, y0 = coordinates(x, y, r, 0) x1, y1 = coordinates(x, y, r, a) da = -angle(x1, y1, x0, y0) for i in xrange(sides): x1, y1 = coordinates(x, y, r, (a*i) + da) if i == 0: p.moveto(x1, y1) else: p.lineto(x1, y1) p.close() return p
def polar_grid(distance, angle, radial, polar, full, position): if full: alpha = 360 / polar else: alpha = angle points = [] for p in xrange(polar): for r in xrange(radial): point = coordinates(position.x, position.y, r * distance, p * alpha) points.append(Point(point[0], point[1])) return points
def shape_intersects(distance): tx, ty = coordinates(0, 0, distance, angle) t = Transform() t.translate(tx, ty) translated_shape = t.map(shape) if use_bounding_box: b = Path() b.cornerRect(translated_shape.bounds) else: b = translated_shape # If the shape intersects it is too close (the distance is too low). if bounding_path.intersects(b): return -1 return 1
def quad_curve(pt1, pt2, t, distance): t /= 100.0 cx = pt1.x + t * (pt2.x - pt1.x) cy = pt1.y + t * (pt2.y - pt1.y) a = angle(pt1.x, pt1.y, pt2.x, pt2.y) + 90 qx, qy = coordinates(cx, cy, distance, a) p = Path() p.moveto(pt1.x, pt1.y) c1x = pt1.x + 2 / 3.0 * (qx - pt1.x) c1y = pt1.y + 2 / 3.0 * (qy - pt1.y) c2x = pt2.x + 2 / 3.0 * (qx - pt2.x) c2y = pt2.y + 2 / 3.0 * (qy - pt2.y) p.curveto(c1x, c1y, c2x, c2y, pt2.x, pt2.y) p.fill = None p.stroke = Color.BLACK p.strokeWidth = 1.0 return p
def quad_curve(pt1, pt2, t, distance): t /= 100.0 cx = pt1.x + t * (pt2.x - pt1.x) cy = pt1.y + t * (pt2.y - pt1.y) a = angle(pt1.x, pt1.y, pt2.x, pt2.y) + 90 qx, qy = coordinates(cx, cy, distance, a) p = Path() p.moveto(pt1.x, pt1.y) c1x = pt1.x + 2/3.0 * (qx - pt1.x) c1y = pt1.y + 2/3.0 * (qy - pt1.y) c2x = pt2.x + 2/3.0 * (qx - pt2.x) c2y = pt2.y + 2/3.0 * (qy - pt2.y) p.curveto(c1x, c1y, c2x, c2y, pt2.x, pt2.y) p.fill = None p.stroke = Color.BLACK p.strokeWidth = 1.0 return p
def shape_on_path(shapes, path, amount, alignment, spacing, margin, baseline_offset): if not shapes: return [] if path is None: return [] if alignment == "trailing": shapes = list(shapes) shapes.reverse() length = path.length - margin m = margin / path.length c = 0 new_shapes = [] for i in xrange(amount): for shape in shapes: if alignment == "distributed": p = length / ((amount * len(shapes)) - 1) pos = c * p / length pos = m + (pos * (1 - 2 * m)) else: pos = ((c * spacing) % length) / length pos = m + (pos * (1 - m)) if alignment == "trailing": pos = 1 - pos p1 = path.pointAt(pos) p2 = path.pointAt(pos + 0.0000001) a = angle(p1.x, p1.y, p2.x, p2.y) if baseline_offset: coords = coordinates(p1.x, p1.y, baseline_offset, a - 90) p1 = Point(*coords) t = Transform() t.translate(p1) t.rotate(a) new_shapes.append(t.map(shape)) c += 1 return new_shapes
def angle_pack(shapes, seed, limit, maximum_radius, angle_tries=1, use_bounding_box=False): if shapes is None: return None _seed(seed) def center_and_translate(shape, tx=0, ty=0): bx, by, bw, bh = list(shape.bounds) t = Transform() t.translate(-bw / 2 - bx, -bh / 2 - by) return t.map(shape) geo = Geometry() bounding_path = Path() # Center first shape first_shape = center_and_translate(shapes[0]) geo.add(first_shape) bounding_path.cornerRect(first_shape.bounds) for shape in shapes[1:]: centered_shape = center_and_translate(shape) angles = [] for i in range(angle_tries): a = uniform(0, 360) if use_bounding_box: d = try_angle(bounding_path, centered_shape, a, limit, maximum_radius, use_bounding_box) else: d = try_angle(geo, centered_shape, a, limit, maximum_radius, use_bounding_box) angles.append([d, a]) chosen_distance, chosen_angle = sorted(angles)[0] tx, ty = coordinates(0, 0, chosen_distance, chosen_angle) t = Transform() t.translate(tx, ty) translated_shape = t.map(centered_shape) bounding_path.cornerRect(translated_shape.bounds) geo.add(translated_shape) return geo