Example #1
0
    def scale_example():
        s1 = shapes.star_outline(100, 100, 4)
        transforms.offset(s1, (300, 0))
        transforms.rotate(s1, -math.pi / 4)
        s2 = shapes.star_outline(100, 100, 6)
        transforms.offset(s2, (300, 0))
        transforms.rotate(s2, -math.pi / 2)
        s3 = shapes.star_outline(100, 100, 9)
        transforms.offset(s3, (300, 0))
        transforms.rotate(s3, -math.pi * 3 / 4)

        tl = TransformLock([s1, s2], ["scale"])
        start = Group([tl, s3])

        mid = copy.deepcopy(start)
        end = copy.deepcopy(start)

        formatters.Pen(3)(start)
        formatters.Pen(2)(mid)
        formatters.Pen(1)(end)
        transforms.scale(mid, 2)
        transforms.scale(end, 3)

        o = shapes.circle(100)
        return Group([start, mid, end, o])
Example #2
0
 def __init__(self, shapes, lock_transforms):
     Group.__init__(self, shapes=shapes)
     self.lock_transforms = set(lock_transforms)
     self.transform_map = {
         "scale": self.scale_to_offset,
         "rotate": self.rotate_to_offset,
     }
Example #3
0
def test_transformlock_transforms_scale_02():
    '''Locks work within groups.'''
    t = scale_locked_rectangle_pair()
    g = Group([Group([t])])
    transforms.scale(g, 2)
    assert_scaling_preserves_diff(g)
    assert_scaling_changes_coords(g)
Example #4
0
def sort1(group):
    # dumb sort. find closest endpoint to current endpoint, append, rinse, repeat
    sortedgroup = Group()
    original = group[:]
    
    sortedgroup.append(original[0])
    del original[0]
    
    while original:
        p1 = sortedgroup[-1].points.xy[-1]
        bestvalue = 99999999999999999999 # i know this is stupid. ugh.
        bestindex = 0
        reverseflag = False
        
        for index in range(len(original)):
            distance = distance_between(p1, original[index].points.xy[0])
            if distance < bestvalue:
                bestvalue = distance
                bestindex = index
                reverseflag = False
                
            distance = distance_between(p1, original[index].points.xy[-1])
            if distance < bestvalue:
                bestvalue = distance
                bestindex = index
                reverseflag = True
        
        if reverseflag:
            original[bestindex].points.xy.reverse()

        sortedgroup.append(original[bestindex])
        del original[bestindex]

    return sortedgroup
Example #5
0
def test_transformlock_transforms_rotate_02():
    '''Locks work within groups.'''
    t = rotation_locked_rectangle_pair()
    g = Group([Group([t])])
    transforms.offset(g, (200, 0))
    assert_rotation_preserves_diff(g)
    assert_rotation_changes_coords(g)
Example #6
0
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
Example #7
0
def radial_ruler(radius,
                 start_angle,
                 end_angle,
                 units,
                 min_tick_height,
                 symmetric=True):

    length = end_angle - start_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:
                r1, a1 = tick_height / 2, unit * t + start_angle
                r2, a2 = -tick_height / 2, unit * t + start_angle
            else:
                r1, a1 = 0, unit * t + start_angle
                r2, a2 = -tick_height, unit * t + start_angle
            xy1 = p2c(Coordinate(r1, a1) + Coordinate(radius, 0))
            xy2 = p2c(Coordinate(r2, a2) + Coordinate(radius, 0))
            tick = line(xy1, xy2)
            result.append(tick)
    return Group(result)
Example #8
0
def pupd_to_paths(hpgl):
    # slurp in PUs and PDs, and convert to a group of simple paths
    # probably fragile, but works fine on the output of pstoedit -f hpgl
    results = Group()
    builder = []
    
    for command in hpgl:
        if isinstance(command, PU):
            if builder:
                # must be starting a new path, so stash the last
                coords = get_all_coordinates(builder)
                results.append(Path(coords))
                builder = []
            builder.append(command)
        elif isinstance(command, PD):
            builder.append(command)
            
    return results
Example #9
0
def cross(width, height):
    '''Draws a cross shape.

    - `width` is the length of the horizontal line.
    - `height` is the length of the vertical line..
    '''

    l1 = Path([Coordinate(-width / 2.0, 0), Coordinate(width / 2.0, 0)])
    l2 = Path([Coordinate(0, -height / 2.0), Coordinate(0, height / 2.0)])
    return Group([l1, l2])
Example #10
0
def frame(width, height, inset):
    '''A frame (rectangle within a rectangle) with a width, height, and inset.

    - `width` is the width of the frame.
    - `height` is the height of the frame.
    - `inset` is the distance to inset the inner rectangle from the outer.
    '''

    r1 = rectangle(width, height)
    r2 = rectangle(width - (inset * 2), height - (inset * 2))
    return Group([r1, r2])
Example #11
0
    def rotation_example():
        r1 = shapes.rectangle(100, 100)
        r2 = shapes.rectangle(200, 200)
        transforms.offset(r2, (400, 0))
        r3 = shapes.rectangle(300, 300)
        transforms.offset(r3, (800, 0))

        tl = TransformLock([r1, r2], ["rotate"])
        start = Group([tl, r3])
        transforms.offset(start, (500, 0))

        mid = copy.deepcopy(start)
        end = copy.deepcopy(start)

        formatters.Pen(3)(start)
        formatters.Pen(2)(mid)
        formatters.Pen(1)(end)
        transforms.rotate(mid, math.pi / 6, (0, 0))
        transforms.rotate(end, math.pi / 3, (0, 0))

        o = shapes.circle(100)
        return Group([start, mid, end, o])
Example #12
0
    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
Example #13
0
    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
Example #14
0
def grid(width, height, width_divisions,height_divisions):
    '''Rectangular grid.

    - `width` : ``int`` or ``float``, width of the rectangle.
    - `height` : ``int`` or ``float``, height of the rectangle.
    - `width_divisions` : ``int``, number of horizontal equidistant partitions.
    - `height_divisions` : ``int``, number of vertical equidistant partitions.

    '''

    ul_x = width
    bl_x = ul_x
    ur_x = ul_x + width

    ul_y = height
    ur_y = ul_y
    bl_y = ul_y - height

    x_step_size = width / width_divisions
    y_step_size = height / height_divisions

    g = Group()

    ## add horizontal lines
    for i in range(height_divisions + 1):
        step_y = y_step_size * i
        l = line((ul_x, ul_y - step_y), (ur_x, ur_y - step_y))
        g.append(l)
    ## add vertical lines

    for i in range(width_divisions + 1):
        step_x = x_step_size * i
        l = line((ul_x + step_x, ul_y), (bl_x + step_x, bl_y))
        g.append(l)

    return g
Example #15
0
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])
Example #16
0
def donut(width, height, inset, segments=100):
    """
        A donut (ellipse within ellipse) with a width, height, inset, segments.

        segments is how many lines should be used to draw ellipse. More
        segments create a smoother ellipse, but will take longer to draw.

        inset is the distance to inset the inner ellipse from the outer.

        The donut is drawn with the current pen location as the center.
        offset may be used to shift this around, for example, to draw from
        the lower, left corner.
    """

    e1 = ellipse(width, height, segments)
    e2 = ellipse(width - (inset * 2), height - (inset * 2), segments)
    return Group([e1, e2])
Example #17
0
def target(outer_radius, inner_radius, circles_count, segments=36):
    """
    Creates `circles_count` concentric circles.
    Can be used to create radially filled circles.
    """

    if not outer_radius > inner_radius:
        raise ValueError("outer_radius must be > inner_radius.")
    if not circles_count > 1:
        raise ValueError("circles_count must be >= 2.")

    result = []
    radius_delta = (outer_radius - inner_radius) / float(circles_count)
    for i in range(circles_count):
        result.append(circle(inner_radius + radius_delta * i, segments))

    return Group(result)
Example #18
0
def grid(width, height, width_divisions, height_divisions):
    '''Rectangular grid.

    - `width` : ``int`` or ``float``, width of the rectangle.
    - `height` : ``int`` or ``float``, height of the rectangle.
    - `width_divisions` : ``int``, number of horizontal equidistant partitions.
    - `height_divisions` : ``int``, number of vertical equidistant partitions.

    '''

    ul_x = width
    bl_x = ul_x
    ur_x = ul_x + width

    ul_y = height
    ur_y = ul_y
    bl_y = ul_y - height

    x_step_size = width / width_divisions
    y_step_size = height / height_divisions

    g = Group()

    ## add horizontal lines
    for i in range(height_divisions + 1):
        step_y = y_step_size * i
        l = line((ul_x, ul_y - step_y), (ur_x, ur_y - step_y))
        g.append(l)
    ## add vertical lines

    for i in range(width_divisions + 1):
        step_x = x_step_size * i
        l = line((ul_x + step_x, ul_y), (bl_x + step_x, bl_y))
        g.append(l)

    return g
Example #19
0
def test_shapes_group__init__01():
    """A Group can be empty."""
    t = Group([])
    assert len(t) == 0
Example #20
0
    rads_incr = segmentation_map[segmentation_mode.lower()]()
    rads = start_angle
    arc = []
    while rads < end_angle:
        coord = Coordinate(math.cos(rads), math.sin(rads))
        coord = coord * Coordinate(width / 2.0, height / 2.0)
        rads += rads_incr
        arc.append(coord)
    ## NOTE: this is better than using rads <= end_angle since
    ## the equality does not always work as expected with floats
    ## due to rounding.
    last = Coordinate(math.cos(end_angle), math.sin(end_angle))
    last *= Coordinate(width / 2.0, height / 2.0)
    arc.append(last)
    return Path(arc)


## RUN DEMO CODE

if __name__ == '__main__':
    from chiplotle.tools import io
    from chiplotle.geometry.core.group import Group

    gr = Group()
    for radius in range(100, 1000, 10):
        ae = arc_ellipse(radius, radius * 2, 0, math.pi / 2, 5, 'arc')
        gr.append(ae)

    io.view(gr)
Example #21
0
 def __init__(self, shapes, name):
     Group.__init__(self, shapes = shapes)
     self.name = name
Example #22
0
            points[i] + dxy[i],
            points[i + 1] - dxy[i + 1],
            points[i + 1],
        ]
        plot_points += bezier_interpolation(control_points,
                                            interpolation_count, 1)[:-1]

    return Path(plot_points)


## RUN DEMO CODE

if __name__ == "__main__":
    from chiplotle.geometry.core.group import Group
    from chiplotle.tools import io

    points = [
        (0, 0),
        (1000, 1000),
        (-1000, 1000),
        (-1000, -1000),
        (1000, -1000),
        (0, 0),
    ]
    e1 = path_interpolated(points, 1)
    e2 = path_interpolated(points, 0.5)
    e3 = path_interpolated(points, 0)
    assert isinstance(e1, Path)

    io.view(Group([e1, e2, e3]))
Example #23
0
from chiplotle.geometry.core.coordinate import Coordinate
from chiplotle.geometry.transforms.transformvisitor import TransformVisitor


def offset(shape, value):
    '''In place offsetting.

    - `shape` is the shape to be rotated.
    - `value` is the offset value. Can be a scalar or an (x, y) coordinate.
    '''
    if isinstance(value, (list, tuple)):
        value = Coordinate(*value)

    def offset(coords, value):
        return coords + value

    t = TransformVisitor(offset)
    t.visit(shape, value)


## RUN DEMO CODE
if __name__ == "__main__":
    from chiplotle.geometry.shapes.rectangle import rectangle
    from chiplotle.tools import io
    r0 = rectangle(1000, 400)
    r1 = rectangle(1000, 400)
    r2 = rectangle(1000, 400)
    offset(r1, (0, 1500))
    offset(r2, (100, 200))
    io.view(Group([r0, r1, r2]))
Example #24
0
    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)
Example #25
0
        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)


Example #26
0
 def __init__(self, shapes, name):
     Group.__init__(self, shapes=shapes)
     self.name = name
def test_shapes_group__init__04():
    '''A Group can be initialized with another Group.'''
    t = Group([Group([]), Path([(1, 2), (3, 4)])])
    assert len(t) == 2
    assert t[0] == Group([])
    assert t[1] == Path([(1, 2), (3, 4)])
def test_shapes_group__init__02():
    '''A Group can take no parameters.'''
    t = Group()
    assert len(t) == 0
Example #29
0
    else:
        #No collision
        return None



## DEMO
if __name__ == '__main__':
    from chiplotle.geometry.shapes.line import line
    from chiplotle.geometry.core.group import Group
    from chiplotle.tools import io
    from random import randrange

    #draw a bunch of lines that do not intersect

    no_intersections = Group()

    line_1 = line([randrange(0, 4000), randrange(0, 4000)],
        [randrange(0, 4000), randrange(0, 4000)])
    no_intersections.append(line_1)

    while len(no_intersections) < 300:
        new_line = line([randrange(0, 4000), randrange(0, 4000)],
            [randrange(0, 4000), randrange(0, 4000)])

        intersection = False

        for l in no_intersections:
            if get_line_intersection(new_line, l) != None:
                intersection = True
                break
Example #30
0
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)
Example #31
0
   rads_incr = segmentation_map[segmentation_mode.lower()]()
   rads = start_angle
   arc = []
   while rads < end_angle:
      coord = Coordinate(math.cos(rads), math.sin(rads))
      coord = coord * Coordinate(width / 2.0, height / 2.0)
      rads += rads_incr
      arc.append(coord)
   ## NOTE: this is better than using rads <= end_angle since
   ## the equality does not always work as expected with floats
   ## due to rounding.
   last = Coordinate(math.cos(end_angle), math.sin(end_angle))
   last *= Coordinate(width / 2.0, height / 2.0)
   arc.append(last)
   return Path(arc)


## RUN DEMO CODE

if __name__ == '__main__':
   from chiplotle.tools import io
   from chiplotle.geometry.core.group import Group

   gr = Group()
   for radius in range(100, 1000, 10):
       ae = arc_ellipse(radius, radius * 2, 0, math.pi/2, 5, 'arc')
       gr.append(ae)

   io.view(gr)

Example #32
0
def group(lst):
    return Group(lst)
def test_shapes_group__init__03():
    '''A Group can be initialized with a list of Paths.'''
    t = Group([Path([(1, 2), (3, 4)])])
    assert len(t) == 1
    assert t[0] == Path([(1, 2), (3, 4)])
Example #34
0
from chiplotle.geometry.core.coordinate import Coordinate
from chiplotle.geometry.transforms.transformvisitor import TransformVisitor


def scale(shape, value, pivot=Coordinate(0, 0)):
    """In place scaling.

    - `shape` is the shape to be rotated.
    - `value` is the scaling value. Can be a scalar or an (x, y) coordinate.
    - `pivot` is the Coordinate around which the shape will be scaled.
    """
    from chiplotle.tools.geometrytools.scale import scale

    t = TransformVisitor(scale)
    t.visit(shape, value, pivot)


## RUN DEMO CODE
if __name__ == "__main__":
    from chiplotle.geometry.shapes.rectangle import rectangle
    from chiplotle.tools import io

    r0 = rectangle(1000, 500)
    r1 = rectangle(1000, 500)
    r2 = rectangle(1000, 500)
    scale(r1, 5, (500, 250))
    scale(r2, (10, 20))
    g = Group([r0, r1, r2])
    print(g.format)
    io.view(g)
def test_shapes_group__init__01():
    '''A Group can be empty.'''
    t = Group([])
    assert len(t) == 0
Example #36
0
        x = math.cos(theta) * math.pow(math.e, (expansion_rate * theta))
        y = math.sin(theta) * math.pow(math.e, (expansion_rate * theta))

        if direction == "ccw":
            y *= -1.0

        spiral_points.append((x, y))
        theta += theta_incr

    return Path(spiral_points)


## RUN DEMO CODE

if __name__ == "__main__":
    from chiplotle.geometry.core.group import Group
    from chiplotle.geometry.shapes.line import line
    from chiplotle.tools import io

    s = spiral_logarithmic()

    # add some lines for scale
    line_right = line((0, 0), (500, 0))
    line_left = line((0, 0), (-500, 0))
    line_up = line((0, 0), (0, 500))
    line_down = line((0, 0), (0, -500))

    g = Group([s, line_right, line_left, line_up, line_down])

    io.view(g)
Example #37
0
   '''
   Constructs an arc from a circle with the given radius,
   and number of segments. Arc goes from start_angle to end_angle,
   both of which are in radians.

      - `segmentation_mode` : '2PI' or 'arc'. The first segments
         the whole circle into the given number of segments,
         the second segments the arc.
   '''
   radius = radius * 2.0
   return arc_ellipse(radius, radius,
                      start_angle, end_angle,
                      segments, segmentation_mode)



## RUN DEMO CODE

if __name__ == '__main__':
   from chiplotle.tools import io

   gr = Group()

   for radius in range(100, 1000, 100):
       ac = arc_circle(radius, 1.0, math.pi)
       assert isinstance(ac, Path)
       gr.append(ac)

   io.view(gr, 'png')

Example #38
0
        else:
            w_multi = quarter_width
            h_multi = quarter_height
            even = True

        point_x = (w_multi * cos_alpha);
        point_y = (h_multi * sin_alpha);

        corners.append((point_x, point_y))

        degrees += degrees_incr

    corners.append(corners[0])
    return Polygon(corners)



## RUN DEMO CODE
if __name__ == '__main__':
    from chiplotle.tools import io
    from chiplotle.geometry.shapes.star_outline import star_outline
    from chiplotle.geometry.core.group import Group

    gr1 = Group()

    for i in range(5, 10):
        st = star_outline(100 * (i * i * i), 100 * (i * i * i), num_points = i)
        gr1.append(st)

    io.view(gr1)