def ruler(start_coord, end_coord, units, min_tick_height, symmetric=False): """ A measuring ruler. - `units` is a list of units on which to put marks, from smaller to larger. e.g., (10, 20, 40). - `min_tick_height` is the height of the marks for the smallest units. The hight of the other units are multiples of this. - `symmetric` set to True to draw the tick lines symmetrically around the invisible center-line. """ start_coord = Coordinate(*start_coord) end_coord = Coordinate(*end_coord) length = (end_coord - start_coord).magnitude angle = (end_coord - start_coord).angle result = [] for i, unit in enumerate(units): ticks = int(math.ceil(length / unit)) for t in range(ticks): tick_height = min_tick_height * (i + 1) if symmetric: x1, y1 = unit * t, tick_height / 2 x2, y2 = unit * t, -tick_height / 2 else: x1, y1 = unit * t, 0 x2, y2 = unit * t, -tick_height tick = line((x1, y1), (x2, y2)) result.append(tick) g = Group(result) rotate(g, angle, (0, 0)) offset(g, start_coord) return g
def ruler(start_coord, end_coord, units, min_tick_height, symmetric=False): ''' A measuring ruler. - `units` is a list of units on which to put marks, from smaller to larger. e.g., (10, 20, 40). - `min_tick_height` is the height of the marks for the smallest units. The hight of the other units are multiples of this. - `symmetric` set to True to draw the tick lines symmetrically around the invisible center-line. ''' start_coord = Coordinate(*start_coord) end_coord = Coordinate(*end_coord) length = (end_coord - start_coord).magnitude angle = (end_coord - start_coord).angle result = [ ] for i, unit in enumerate(units): ticks = int(math.ceil(length / unit)) for t in range(ticks): tick_height = min_tick_height * (i + 1) if symmetric: x1, y1 = unit * t, tick_height / 2 x2, y2 = unit * t, -tick_height / 2 else: x1, y1 = unit * t, 0 x2, y2 = unit * t, -tick_height tick = line((x1, y1), (x2, y2)) result.append(tick) g = Group(result) rotate(g, angle, (0, 0)) offset(g, start_coord) return g
def arrange_shapes_on_path(shapes, path): if not isinstance(path, Path): raise TypeError if len(shapes) != len(path): raise ValueError('len(shapes) == len(path) must be true.') for shape, coord in zip(shapes, path.points): offset(shape, coord)
def arrange_shapes_on_path(shapes, path): if not isinstance(path, Path): raise TypeError if len(shapes) != len(path): raise ValueError("len(shapes) == len(path) must be true.") for shape, coord in zip(shapes, path.points): offset(shape, coord)
def _annotate_properties(self): cr = " center: %s" % self.shape.center cd = "centroid: %s" % self.shape.centroid mn, mx = self.shape.minmax_coordinates mn = " min: %s" % mn mx = " max: %s" % mx ws = " width: %.2f" % self.shape.width hs = " height: %.2f" % self.shape.height fields = "\n\r".join([cr, cd, mn, mx, ws, hs]) label = Label(fields, self.charwidth, self.charheight) offset(label, self.shape.bottom_left) return label
def _annotate_properties(self): cr = ' center: %s' % self.shape.center cd = 'centroid: %s' % self.shape.centroid mn, mx = self.shape.minmax_coordinates mn = ' min: %s' % mn mx = ' max: %s' % mx ws = ' width: %.2f' % self.shape.width hs = ' height: %.2f' % self.shape.height fields = '\n\r'.join([cr, cd, mn, mx, ws, hs, ]) label = Label(fields, self.charwidth, self.charheight) offset(label, self.shape.bottom_left) return label
def arrow(path, headwidth, headheight, filled=False): '''Returns an arrow shape. - `path` is a Path object. - `headwidth` is the width of the arrow head. - `headheight` is the height of the arrow head. ''' ## make arow head... r, a = xy_to_polar((path.points[-1] - path.points[-2])) head = isosceles(headwidth, headheight, filled) offset(head, (0, -headheight)) rotate(head, a - math.pi / 2, (0, 0)) offset(head, path.points[-1]) return Group([head, path])
def _annotate_centroid(self): coord = self.shape.centroid label = Label("\n\rcentroid: " + str(coord), self.charwidth, self.charheight, origin="top-center") r = rectangle(20, 20) cr = cross(50, 50) mark = Group([r, cr, label]) offset(label, coord) offset(r, coord) offset(cr, coord) return mark
def _annotate_center(self): coord = self.shape.center label = Label("\n\rcenter: " + str(coord), self.charwidth, self.charheight, origin="top-center") c = circle(20) cr = cross(50, 50) mark = Group([c, cr, label]) offset(label, coord) offset(c, coord) offset(cr, coord) return mark
def _annotate_centroid(self): coord = self.shape.centroid label = Label('\n\rcentroid: ' + str(coord), self.charwidth, self.charheight, origin = 'top-center') r = rectangle(20, 20) cr = cross(50, 50) mark = Group([r, cr, label]) offset(label, coord) offset(r, coord) offset(cr, coord) return mark
def _annotate_center(self): coord = self.shape.center label = Label('\n\rcenter: ' + str(coord), self.charwidth, self.charheight, origin = 'top-center') c = circle(20) cr = cross(50, 50) mark = Group([c, cr, label]) offset(label, coord) offset(c, coord) offset(cr, coord) return mark
def center_at(shape, coord): """Centers shape at the given coordinate.""" offset(shape, -shape.center + Coordinate(*coord))
return mark @property def annotation(self): result = [] result.append(self._annotate_center()) result.append(self._annotate_centroid()) result.append(self._annotate_properties()) return Group(result) ## demo if __name__ == "__main__": from chiplotle import * from chiplotle.hpgl.formatters import Pen from random import randint coords = [(randint(0, 4000), randint(0, 4000)) for i in range(20)] p = bezier_path(coords, 1) r = rectangle(1000, 400) offset(r, (-2000, 1000)) g1 = Group([r, p]) an = annotation(g1) Pen(2)(an) g2 = Group([g1, an]) Pen(1)(g2) io.view(g2)
def center_at(shape, coord): '''Centers shape at the given coordinate.''' offset(shape, -shape.center + Coordinate(*coord))
return Path(plot_points) ## RUN DEMO CODE if __name__ == "__main__": from chiplotle.tools import io from chiplotle.geometry.shapes.group import group from chiplotle.geometry.shapes.cross import cross from chiplotle.geometry.transforms.offset import offset t_base = 4000 points = [(-t_base / 2, 0), (0, t_base * 0.8660), (t_base / 2, 0)] ## a list containing different sets of weights for the middle point weights = [[1, 1, 1], [1, 2, 1], [1, 0.5, 1], [1, 0, 1], [1, -0.5, 1]] c = group([]) ## draws a cross at each control point for i in points: r = cross(100, 100) offset(r, i) c.append(r) ## draws the rational bezier curve for each weight set for w in weights: b = path_bezier(points, weight=w) c.append(b) io.view(c)
return result ## RUN DEMO CODE if __name__ == '__main__': from chiplotle.geometry.core.group import Group from chiplotle.geometry.transforms.offset import offset from chiplotle.geometry.transforms.rotate import rotate from chiplotle.tools import io #one of each main spiral type s1 = spiral_archimedean(500, wrapping_constant=1) s2 = spiral_archimedean(500, wrapping_constant=2, direction="ccw") offset(s2, (0, -1000)) #these two are long, so we'll rotate them and move them to the side #of the others s3 = spiral_archimedean(1800, wrapping_constant=-1, direction="ccw") rotate(s3, math.pi * 1.5) offset(s3, (650, 400)) s4 = spiral_archimedean(1500, wrapping_constant=-2, direction="ccw") rotate(s4, math.pi * .6) offset(s4, (1000, -1100)) g = Group([s1, s2, s3, s4]) io.view(g)
path_points = catmull_interpolation(points, interpolation_count) return Path(path_points) ## DEMO if __name__ == '__main__': from chiplotle.tools import io from chiplotle.geometry.shapes.cross import cross from chiplotle.geometry.core.group import Group from chiplotle.geometry.transforms.offset import offset import random points = [ ] for i in range(10): x, y = random.randint(-100, 100), random.randint(-100, 100) points.append((x, y)) crosses = [ ] for point in points: c = cross(15, 15) offset(c, point) crosses.append(c) path = catmull_path(points) g = Group([path] + crosses) io.view(g)
## RUN DEMO CODE if __name__ == '__main__': from chiplotle.tools import io from chiplotle.geometry.shapes.group import group from chiplotle.geometry.shapes.cross import cross from chiplotle.geometry.transforms.offset import offset t_base = 4000 points = [(-t_base/2,0),(0,t_base*0.8660),(t_base/2,0)] ## a list containing different sets of weights for the middle point weights = [[1,1,1],[1,2,1],[1,0.5,1],[1,0,1],[1,-0.5,1]] c = group([]) ## draws a cross at each control point for i in points: r = cross(100,100) offset(r, i) c.append(r) ## draws the rational bezier curve for each weight set for w in weights: b = path_bezier(points, weight=w) c.append(b) io.view(c)
return result ## RUN DEMO CODE if __name__ == "__main__": from chiplotle.geometry.core.group import Group from chiplotle.geometry.transforms.offset import offset from chiplotle.geometry.transforms.rotate import rotate from chiplotle.tools import io # one of each main spiral type s1 = spiral_archimedean(500, wrapping_constant=1) s2 = spiral_archimedean(500, wrapping_constant=2, direction="ccw") offset(s2, (0, -1000)) # these two are long, so we'll rotate them and move them to the side # of the others s3 = spiral_archimedean(1800, wrapping_constant=-1, direction="ccw") rotate(s3, math.pi * 1.5) offset(s3, (650, 400)) s4 = spiral_archimedean(1500, wrapping_constant=-2, direction="ccw") rotate(s4, math.pi * 0.6) offset(s4, (1000, -1100)) g = Group([s1, s2, s3, s4]) io.view(g)
from chiplotle.geometry.core.transformlock import TransformLock from chiplotle.geometry.core.shape import _Shape def lock_group(shapes, lock_transforms): t = TransformLock(shapes, lock_transforms) return t ## ~~~~~~~~~~~~~~~~~~~~~~~ if __name__ == '__main__': from chiplotle.geometry.shapes.square import square from chiplotle.geometry.core.group import Group from chiplotle.geometry.transforms.rotate import rotate from chiplotle.geometry.transforms.offset import offset from chiplotle import io import math r1 = square(100) r2 = square(150) l = lock_group([r2], ['rotate']) g = Group([r1, l]) offset(g, (200, 0)) rotate(g, math.pi / 4) io.view(g)
point_order = [] for i in range(0, num_points): point_num = (i * jump_size) % num_points point_order.append(point_num) corners = [corners[i] for i in point_order] return Polygon(corners) ## RUN DEMO CODE if __name__ == "__main__": from chiplotle.tools import io from chiplotle.geometry.shapes.star_crisscross import star_crisscross from chiplotle.geometry.core.group import Group from chiplotle.geometry.transforms.offset import offset gr1 = Group() for points in range(5, 26): for i in range(1, points): s = star_crisscross(1000, 1000, num_points=points, jump_size=i, find_valid_jump_size=False) offset(s, ((i - 1) * 1000, -(points - 5) * 1000)) gr1.append(s) io.view(gr1)
def catmull_path(points, interpolation_count=50): '''Path with Catmull-Rom spline interpolation.''' path_points = catmull_interpolation(points, interpolation_count) return Path(path_points) ## DEMO if __name__ == '__main__': from chiplotle.tools import io from chiplotle.geometry.shapes.cross import cross from chiplotle.geometry.core.group import Group from chiplotle.geometry.transforms.offset import offset import random points = [] for i in range(10): x, y = random.randint(-100, 100), random.randint(-100, 100) points.append((x, y)) crosses = [] for point in points: c = cross(15, 15) offset(c, point) crosses.append(c) path = catmull_path(points) g = Group([path] + crosses) io.view(g)
point_order = [] for i in range(0, num_points): point_num = (i * jump_size) % num_points point_order.append(point_num) corners = [corners[i] for i in point_order] return Polygon(corners) ## RUN DEMO CODE if __name__ == '__main__': from chiplotle.tools import io from chiplotle.geometry.shapes.star_crisscross import star_crisscross from chiplotle.geometry.core.group import Group from chiplotle.geometry.transforms.offset import offset gr1 = Group() for points in range(5, 26): for i in range(1, points): s = star_crisscross(1000, 1000, num_points = points, jump_size = i, find_valid_jump_size = False) offset(s, ((i - 1) * 1000, -(points - 5) * 1000)) gr1.append(s) io.view(gr1)
return mark @property def annotation(self): result = [ ] result.append(self._annotate_center( )) result.append(self._annotate_centroid( )) result.append(self._annotate_properties( )) return Group(result) ## demo if __name__ == '__main__': from chiplotle import * from chiplotle.hpgl.formatters import Pen from random import randint coords = [(randint(0, 4000), randint(0, 4000)) for i in range(20)] p = bezier_path(coords, 1) r = rectangle(1000, 400) offset(r, (-2000, 1000)) g1 = Group([r, p]) an = annotation(g1) Pen(2)(an) g2 = Group([g1, an]) Pen(1)(g2) io.view(g2)