Exemplo n.º 1
0
def interactive_define_ellipse(plotter):
    '''
    Interactive routine to define center and radii of an ellipse.
    '''
    from chiplotle.hpgl.compound.rectangle import Ellipse

    points = []

    print "Interactive define Rectangle:"
    print "Move pen to lower, left corner and press enter."

    input = raw_input()
    lower_left = Coordinate(plotter.actual_position[0].x,
                            plotter.actual_position[0].y)
    print "lower_left:"
    print lower_left

    print "Move pen to upper, right corner and press enter."
    input = raw_input()
    upper_right = Coordinate(plotter.actual_position[0].x,
                             plotter.actual_position[0].y)
    print "upper_right:"
    print upper_right

    rectangle = Rectangle([lower_left], upper_right.x, upper_right.y)

    return rectangle
Exemplo n.º 2
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
Exemplo n.º 3
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)
Exemplo n.º 4
0
def get_bounding_box(arg):
    '''Returns the pair of coordinate pairs outlining the bounding box of
    the given HPGL drawing.'''
    if not isinstance(arg, (list, tuple)):
        raise TypeError('arg must be list or tuple')

    min_x = min_y = 1000000.0
    max_x = max_y = -1000000.0

    coords = get_all_coordinates(arg)

    if len(coords) == 0:
        return None

    for c in coords:
        ## x...
        if c.x > max_x:
            max_x = c.x
        if c.x < min_x:
            min_x = c.x
        ## y...
        if c.y > max_y:
            max_y = c.y
        if c.y < min_y:
            min_y = c.y

    return (Coordinate(min_x, min_y), Coordinate(max_x, max_y))
def instantiate_virtual_plotter(
        left_bottom=Coordinate(0, 0),
        right_top=Coordinate(10320, 7920), type=None):
    '''
   Instantiates a virtual plotter with 8.5x11" (ANSI A) paper.
   If you have a default plotter defined in your config.py file
   we will use that plotter definition file (ignoring the serial
   port setting).
   '''

    which_plotter = type

    if type is None:
        map = get_config_value('serial_port_to_plotter_map')
        ## if user has set fixed port to plotter mapping...
        if map is not None:
            for k, v in map.items():
                which_plotter = v
        else:
            which_plotter = "Plotter"

    ser = VirtualSerialPort(left_bottom, right_top)
    plotter = instantiate_plotter_from_id(ser, which_plotter)
    print "\nInstantiated plotter %s:" % plotter
    coords = plotter.margins.soft.all_coordinates
    print "   Drawing limits: (left %s; bottom %s; right %s; top %s)" % coords
    print "   Buffer Size: %s" % plotter.buffer_size

    return plotter
 def minmax(self):
     """Returns the minimum and maximum coordinates."""
     if len(self._data) == 0:
         return None
     coords = [list(c) for c in self._data]
     mx = np.max(coords, 0).tolist()
     mn = np.min(coords, 0).tolist()
     return (Coordinate(*mn), Coordinate(*mx))
Exemplo n.º 7
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])
Exemplo n.º 8
0
def test_path_radd_03():
    """A Coordinate and a Path can be added."""
    a = Path([(1, 2), (3, 4)])
    t = Coordinate(1, 2) + a
    assert t is not a
    assert isinstance(t, Path)
    assert t == Path([(2, 4), (4, 6)])
Exemplo n.º 9
0
def test_path_add_03():
    """A Path and a Coordinate can be added."""
    a = Path([(1, 2), (3, 4)])
    t = a + Coordinate(1, 2)
    assert t is not a
    assert isinstance(t, Path)
    assert t == Path([(2, 4), (4, 6)])
Exemplo n.º 10
0
def supershape(
    width,
    height,
    m,
    n1,
    n2,
    n3,
    point_count=100,
    percentage=1.0,
    a=1.0,
    b=1.0,
    travel=None,
):
    """Supershape, generated using the superformula first proposed
    by Johan Gielis.

    - `points_count` is the total number of points to compute.
    - `travel` is the length of the outline drawn in radians.
        3.1416 * 2 is a complete cycle.
    """
    travel = travel or (math.pi * 2)

    ## compute points...
    phis = [i * travel / point_count for i in range(int(point_count * percentage))]
    points = [superformula(a, b, m, n1, n2, n3, x) for x in phis]

    ## scale and transpose...
    path = []
    for x, y in points:
        x *= width
        y *= height
        path.append(Coordinate(x, y))

    return Path(path)
Exemplo n.º 11
0
def test_path_rsub_03():
    """A Coordinate can substract a Path."""
    a = Path([(1, 2), (3, 4)])
    t = Coordinate(1, 2) - a
    assert t is not a
    assert isinstance(t, Path)
    assert t == Path([(0, 0), (-2, -2)])
def convert_relatives_to_absolutes(lst):
    if not isinstance(lst, (list, tuple)):
        raise TypeError("`lst` must be a list or tuple.")

    lst = pens_updown_to_papr(lst)

    result = []
    last_position = Coordinate(0, 0)
    for e in lst:
        ## if has absolute position, keep track of last point...
        if is_primitive_absolute(e):
            if isinstance(e.xy, CoordinateArray):
                last_position = e.xy[-1]
            else:
                last_position = e.xy

        ## handle each HPGL command type...
        if isinstance(e, PR):
            command = pr_to_pa(e, last_position)
            last_position = command.xy[-1]
        elif isinstance(e, ER):
            command = EA(last_position + e.xy)
            last_position = command.xy
        elif isinstance(e, RR):
            command = RA(last_position + e.xy)
            last_position = command.xy
        elif isinstance(e, AR):
            command = AA(last_position + e.xy, e.angle, e.chordtolerance)
            last_position = command.xy
        else:
            command = e

        result.append(command)
    return result
 def center(self):
     """"center" is defined as being half way between the top/bottom
     and left/right-most points. This will be different from the
     centroid, which takes the distribution of the points into
     consideration.
     """
     return sum(self.minmax, Coordinate(0, 0)) / 2.0
Exemplo n.º 14
0
 def __init__(self, left_bottom, right_top):
     left_bottom = Coordinate(*left_bottom)
     right_top = Coordinate(*right_top)
     #print "I am a virtual serial port!"
     self._received_commands_string = ""
     self._next_query_value = ''
     self.commanded_x = 0
     self.commanded_y = 0
     #pen_status: 0 == up, 1 == down
     self.pen_status = 0
     self.left = left_bottom.x
     self.right = right_top.x
     self.bottom = left_bottom.y
     self.top = right_top.y
     self.buffer_size = maxint
     self.portstr = "VirtualSerialPort"
Exemplo n.º 15
0
def test_path_sub_03():
    """A Path can substract a Coordinate."""
    a = Path([(1, 2), (3, 4)])
    t = a - Coordinate(1, 2)
    assert t is not a
    assert isinstance(t, Path)
    assert t == Path([(0, 0), (2, 2)])
Exemplo n.º 16
0
def interactive_define_polygon_simple(plotter):
    '''
    Interactive routine to define points in a PolygonSimple object.
    '''
    from chiplotle.hpgl.compound.polygon_simple import PolygonSimple

    points = []

    print "Interactive define PolygonSimple:"
    print "Move pen to each point and press enter. Press x when finished adding points."
    print "The final point (a duplicate of first point) will be added automatically."
    while True:
        input = raw_input()
        if input is 'x':
            break

        point = Coordinate(plotter.actual_position[0].x,
                           plotter.actual_position[0].y)
        points.append(point)
        print "added:"
        print point

    poly = PolygonSimple([0, 0], points)

    return poly
Exemplo n.º 17
0
def xy_to_polar(args):
    """Converts cartesian to polar coordinates.
    Argument may be two coordinates x, y, a tuple (x, y),
    or a Coordinate(x, y).

    Returns an (r, a) tuple, where `r` is the magnitude, `a` is the angle
    in radians.
    """
    x, y = tuple(Coordinate(*args))

    r = math.sqrt(x ** 2 + y ** 2)
    x = x or 1E-10
    a = math.atan(y / x)

    if x >= 0:
        if y >= 0:
            pass
        else:
            a += 2 * math.pi
    else:
        a += math.pi
    #      if y >= 0:
    #         a += math.pi
    #      else:
    #         a = math.pi / 2 * 3 - a

    return r, a
 def cumsum(self):
     """Returns the cumulative sum."""
     dimensions = len(self[0])
     result = [Coordinate(*([0] * dimensions))]
     for coord in self:
         result.append(result[-1] + coord)
     return type(self)(result)
Exemplo n.º 19
0
def path_interpolated(points, curvature, interpolation_count=50):
    """Returns a Path with bezier interpolation between the given `points`.
    The interpolation is computed so that the resulting path touches the
    given points.

    - `points` the key points from which to interpolate.
    - `curvature` the smoothness of the curve [0, 1].
    - `interpolation_count` is the number of points to add by interpolation,
        per segment.
    """

    if not (0 <= curvature <= 1):
        raise ValueError("`curvature` must be between 0 and 1 inclusive.")

    if curvature == 0:
        return Path(points)

    ## else we have a curve...
    points = CoordinateArray(points)

    curvature = 4 + (1.0 - curvature) * 40
    bi = [0, -0.25]
    a = [Coordinate(0, 0), (points[2] - points[0] - Coordinate(0, 0)) / 4.0]

    ## compute bi and a...
    for i in range(2, len(points) - 1):
        bi.append(-1 / (curvature + bi[i - 1]))
        a.append(-(points[i + 1] - points[i - 1] - a[i - 1]) * bi[i])

    ## compute dxy...
    dxy = [Coordinate(0, 0)]
    for i in reversed(list(range(len(points) - 1))):
        dxy.insert(0, a[i] + dxy[0] * bi[i])

    ## compute interpolated points...
    plot_points = []
    for i in range(len(points) - 1):
        control_points = [
            points[i],
            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)
Exemplo n.º 20
0
 def digitized_point(self):
     """Returns last digitized point. Returns a tuple
   [Coordinate(x, y), pen status]"""
     response = self._send_query(self._hpgl.OD()).split(b",")
     return [
         Coordinate(eval(response[0]), eval(response[1])),
         eval(response[2].strip(b"\r")),
     ]
Exemplo n.º 21
0
 def actual_position(self):
     """Output the actual position of the plotter pen. Returns a tuple
   (Coordinate(x, y), pen status)"""
     response = self._send_query(self._hpgl.OA()).split(b",")
     return [
         Coordinate(eval(response[0]), eval(response[1])),
         eval(response[2].strip(b"\r")),
     ]
Exemplo n.º 22
0
 def __setitem__(self, i, arg):
     if isinstance(i, int):
         if not isinstance(arg, Coordinate):
             raise TypeError
         self._data[i] = arg
     else:
         arg = [Coordinate(*list(coord)) for coord in arg]
         self._data[i.start:i.stop] = arg
Exemplo n.º 23
0
 def commanded_position(self):
     '''Output the commanded position of the plotter pen. Returns a tuple
   [Coordinate(x, y), pen status]'''
     response = self._send_query(self._hpgl.OC()).split(',')
     return [
         Coordinate(eval(response[0]), eval(response[1])),
         eval(response[2].strip('\r'))
     ]
Exemplo n.º 24
0
 def commanded_position(self):
     """Output the commanded position of the plotter pen. Returns a tuple
   [Coordinate(x, y), pen status]"""
     response = self._send_query(self._hpgl.OC()).split(b",")
     return [
         Coordinate(eval(response[0]), eval(response[1])),
         eval(response[2].strip(b"\r")),
     ]
Exemplo n.º 25
0
 def actual_position(self):
     '''Output the actual position of the plotter pen. Returns a tuple
   (Coordinate(x, y), pen status)'''
     response = self._send_query(self._hpgl.OA()).split(',')
     return [
         Coordinate(eval(response[0]), eval(response[1])),
         eval(response[2].strip('\r'))
     ]
Exemplo n.º 26
0
 def digitized_point(self):
     '''Returns last digitized point. Returns a tuple
   [Coordinate(x, y), pen status]'''
     response = self._send_query(self._hpgl.OD()).split(',')
     return [
         Coordinate(eval(response[0]), eval(response[1])),
         eval(response[2].strip('\r'))
     ]
Exemplo n.º 27
0
def rotate_2d(xy, angle, pivot=(0, 0)):
    '''2D rotation.

    - `xy` is an (x, y) coordinate pair or a list of coordinate pairs.
    - `angle` is the angle of rotation in radians.
    - `pivot` the point around which to rotate `xy`.

    Returns a Coordinate or a CoordinateArray.
    '''
    try:
        xy = Coordinate(*xy)
        pivot = Coordinate(*pivot)
        result = rotate_coordinate_2d(xy, angle, pivot)
    except:
        xy = CoordinateArray(xy)
        pivot = Coordinate(*pivot)
        result = rotate_coordinatearray_2d(xy, angle, pivot)
    return result
Exemplo n.º 28
0
def rotate_coordinate_2d(xy, angle, pivot):
    '''Coordinate 2D rotation.

    - `xy` is an (x, y) coordinate pair.
    - `angle` is the angle of rotation in radians.
    - `pivot` the point around which to rotate `xy`.

    Returns a Coordinate.
    '''
    pivot = Coordinate(*list(pivot))
    ## rotate counter-clockwise...
    angle = -angle
    #cp = Coordinate(xy)
    xy -= pivot
    x = xy.x * math.cos(angle) + xy.y * math.sin(angle)
    y = -xy.x * math.sin(angle) + xy.y * math.cos(angle)
    result = Coordinate(x, y) + pivot
    return result
Exemplo n.º 29
0
def get_centroid(arg):
    '''Returns the centroid of the given Chiplotle-HPGL shapes.'''
    arg = get_all_coordinates(arg)
    ## convert into a set to remove duplicate coordinates and to
    ## avoid giving more weight to these duplicate points...
    arg = set(arg)
    result = Coordinate(0, 0)
    for c in arg:
        result += c
    return result / len(arg)
Exemplo n.º 30
0
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)