Beispiel #1
0
    def draw_2point_arc(self, point1, point2, radius, direction):
        """Draw an arc given two points and a radius."""
        if point1 is None:
            point1 = self.cart

        Display.debug_circle(point1, radius)
        Display.debug_circle(point2, radius)
        if point1 == point2:
            if direction == CW:
                center_point = Cartesian(point1.x + radius, point1.y)
                start_angle = Radians(math.pi)
            else:
                center_point = Cartesian(point1.x - radius, point1.y)
                start_angle = Radians(0.0)
            end_angle = Radians(start_angle + math.tau)
            Display.debug_point(center_point, 'purple')

        else:
            center_point = arc_center(point1, point2, radius, direction)
            Display.debug_point(center_point, 'blue')

            start_angle = calculate_angle(center_point, point1) % math.tau
            # TODO: This needs direct to choose end angle.
            end_angle = calculate_angle(center_point, point2) % math.tau

        self.draw_multi_point_arc(point1, point2, center_point, radius,
                                  start_angle, end_angle)
Beispiel #2
0
    def __init__(self, shape, translation=None, rotation=None):
        self.shape = shape
        if translation is None:
            translation = Cartesian(0.0, 0.0)
        self.translation = translation
        if rotation is None:
            rotation = Radians(0.0)
        self.rotation = rotation

        self.pivot = Cartesian(0.0, 0.0)
Beispiel #3
0
    def __init__(self):
        """Set the HUD elements."""
        if Pen.canvas is None:
            Pen.canvas = turtle_global.getscreen().getcanvas()

        self._transform = Cartesian(0.866666666, -0.866666666).pixels()

        self.pen_down = False
        self.color = 'black'
        self._internal_position = Cartesian(0.0, 0.0)
Beispiel #4
0
    def __init__(self, controller):
        """Init."""
        self.c = controller

        self._previous_cart = Cartesian(0.0, 0.0)
        self._cart = Cartesian(0.0, 0.0)
        self.cart_error = Cartesian(0.0, 0.0)
        self.grid_size = CartesianResolution(Millimeters(0.01),
                                             Millimeters(0.01))

        self.offset_to_origin = Cartesian(0.0, 0.0)
Beispiel #5
0
    def __init__(self, controller):
        """Init."""
        self.display = Display()
        self.c = controller

        self.polar = Polar(0.0, 0.0)
        self.polar_error = Polar(0.0, 0.0)

        self.cart = Cartesian(0.0, 0.0)
        self.cart_error = Cartesian(0.0, 0.0)
        self.grid_size = self.c.grid_size

        self.direction = CCW
Beispiel #6
0
    def draw_polar_line(self, *args):
        """Draw line between absolute points using polor interpolation."""
        if len(args) == 4:
            start_point = Cartesian(*args[:2])
            end_point = Cartesian(*args[2:])
        elif len(args) == 2:
            start_point, end_point = args
        else:
            raise RuntimeError('Incorrect arguments.')
        print 'draw_polar_line {} => {}'.format(start_point, end_point)

        # turtle.up()
        self.set_controller_pos(start_point)
        # turtle.down()
        self.set_controller_pos(end_point)
Beispiel #7
0
    def draw_polygon(self, center_point, radius, edge_count, start_angle=None):
        """Draw a polygon."""
        if start_angle is None:
            # Set the starting angle for the circle to be close to our current location.
            if center_point == Cartesian(0.0, 0.0):
                start_angle = 0.0
            else:
                base = center_point - self.cart
                start_angle = Cartesian(1.0, 0.0).angle(base)
                if self.cart.x < center_point.x or self.cart.y < center_point.y:
                    start_angle += math.pi

        print 'draw_polygon centered on {} radius {} edges {}'.format(
            center_point, radius, edge_count)
        end_angle = Radians(start_angle + (math.tau))
        direction = CCW
        return self.draw_polygon_arc(center_point, radius, edge_count,
                                     start_angle, end_angle, direction)
Beispiel #8
0
    def draw_circle(self, center_point, radius):
        """Draw a circle with the given center and radius."""
        print 'draw_circle centered on {} radius {}'.format(
            center_point, radius)
        circumference = float(radius) * math.tau
        edges_per_mm = 0.5
        edge_count = circumference * float(edges_per_mm)
        edge_count = int(math.ceil(edge_count))

        # Set the starting angle for the circle to be close to our current location.
        if center_point == Cartesian(0.0, 0.0):
            start_angle = 0.0
        else:
            base = center_point - self.cart
            start_angle = Cartesian(1.0, 0.0).angle(base)
            if self.cart.x < center_point.x or self.cart.y < center_point.y:
                start_angle += math.pi

        self.draw_polygon(center_point, radius, edge_count, start_angle)
Beispiel #9
0
    def move_fast(self, delta):
        """Set our position using relative cartesian coordinates."""
        if delta == Cartesian(0, 0):
            return

        current = self.cart_error + delta
        whole = Steps(current // self.grid_size, cartesian=True)
        current = current % self.grid_size

        self.cart = self.cart + (self.grid_size * whole)
        self.set_controller_pos(self.cart)
        self.cart_error = current
Beispiel #10
0
    def koru(self):
        """A constant spiral."""
        turtle.up()
        start = Polar(0.0, 0.0)
        self.setpos(start)

        print 'koru'

        koru = Transform(Koru(), Cartesian(0.0, 150.0))

        turtle.down()
        for step in koru:
            self.setpos(step)
        turtle.up()
Beispiel #11
0
def arc_center(p1, p2, radius, direction):
	"""Return arc center based on start and end points, radius and arc direction (2=CW, 3=CCW).
	
	radius can be negative (for arcs over 180 degrees)
	via https://math.stackexchange.com/a/482049
	"""
	angle = 0.0
	additional_angle = 0.0
	l1 = 0.0
	l2 = 0.0
	diff = 0.0
	allowed_error = 0.002
	
	t1 = None
	t2 = None
	
	if direction == CW:
		t1 = p2
		t2 = p1
	else:
		t1 = p1
		t2 = p2
	
	# find angle arc covers
	angle = calculate_angle(t1, t2)

	l1 = point_distance(t1, t2) / 2.0
	diff = l1 - abs(radius)

	if abs(radius) < l1 and diff > allowed_error:
		raise RuntimeError('Wrong radius.')
	
	l2 = math.sqrt(abs(radius ** 2 - l1 ** 2))

	if l1 == 0:
		additional_angle = math.pi / 2.0
	else:
		additional_angle = math.atan(l2 / l1)  # atan2???

	# Add or subtract from angle (depending of radius sign)
	if radius < 0:
		angle -= additional_angle
	else:
		angle += additional_angle

	# calculate center (from t1)
	x = float(t1.x + abs(radius) * math.cos(angle))
	y = float(t1.y + abs(radius) * math.sin(angle))
	return Cartesian(x, y)
Beispiel #12
0
    def move(self, delta):
        """Set our position using relative cartesian coordinates."""
        if delta == Cartesian(0, 0):
            return

        steps_number = delta.max_abs_value()
        delta_step = delta / steps_number

        current = self.cart_error
        for r in range(int(steps_number) + 1):
            current += delta_step

            whole = Steps(current // self.grid_size, cartesian=True)
            current = current % self.grid_size

            # print '\t', r + 1, 'in', int(steps_number) + 1, whole
            self.cart = self.cart + (self.grid_size * whole)
            self.set_controller_pos(self.cart)

        self.cart_error = current
Beispiel #13
0
    def __init__(self, radius, speed=1.0):
        """Init.

		radius of the cog
		speed multiplies the turning rate relative to the parent.
		"""
        self.radius = Millimeters(radius)
        self.offset = None

        self.children = list()
        self.track = Polar(0.0, 0.0)

        self.theta = Radians(0.0)
        self.speed_boost = speed
        self.base_speed = 1.0
        self.center = Cartesian(0.0, 0.0)
        self.direction = 1.0

        self.parent_radius = None

        self.id = uuid.uuid4()
Beispiel #14
0
class Display(object):
	"""Abstraction that converts our polar motor signals to pixels on the screen."""

	c = DisplayPosition(0, 0)
	p = Polar(0, 0)
	c_pixels = DisplayPosition(0, 0)
	c_pixels_whole = DisplayPosition(0, 0)

	offset = Cartesian(0, 0)

	hud = None
	canvas = None

	debug_enabled = True
	debug_pen = None

	class HUD(threading.Thread):
		"""HUD manager."""

		def __init__(self):
			"""Setup the HUD elements."""
			super(Display.HUD, self).__init__()
			self.canvas = turtle.screen.getcanvas()
			
			self.hud_lines = dict()
			self.queues = dict()

			self.next_pos = TkSpace(-102.0, -98.0)

			self.stop = False
			self.daemon = True

		def __setitem__(self, queue_name, value):
			"""Set text on HUD item.

			Use a queue to make the value avaiable when we refresh the HUD.
			Passing new keys into here will create new HUD lines.
			"""
			if queue_name not in self.queues:
				self.queues[queue_name] = LifoQueue()
			if queue_name not in self.hud_lines:
				self.hud_lines[queue_name] = self.canvas.create_text(*self.next_pos, text='', fill='grey', anchor=tk.SW)
				self.next_pos.y += 5.0

			try:
				while True:
					self.queues[queue_name].get_nowait()
			except Empty:
				pass
			self.queues[queue_name].put_nowait(value)

		def run(self):
			"""Update the HUD text."""
			while not self.stop:
				for queue_name, q in self.queues.iteritems():
					try:
						self.canvas.itemconfig(self.hud_lines[queue_name], text=q.get_nowait())
					except Empty:
						pass
				time.sleep(0.5)

	def __init__(self):
		"""Set the HUD elements."""
		if Display.hud is None:
			Display.hud = Display.HUD()
			Display.hud.start()

		if Display.canvas is None:
			Display.canvas = turtle.screen.getcanvas()
			Display.debug_pen = Pen()

		self.pen = Pen()

	def setpos(self, polar):
		"""Set the position of of the polar coordinates to pixels on the screen."""
		self.p = polar
		self.c = self.p.cartesian()
		new_pixel_position = self.c.pixels().trunc(factor=10)
		if self.c_pixels != new_pixel_position:

			# a = new_pixel_position * 0.86666666666666666666666
			# self.pen.down()
			# self.pen.setpos(self.c)
			# self.pen.up()

			# TODO: What is going on here?!?
			# Some how my converion from mm to pixels that works everywhere else doesn't here.
			turtle.setpos(new_pixel_position * 0.86666666666666666 * 0.86666666666666666666666)
			if not FAST:
				turtle.setheading(polar.t.degrees())
			self.c_pixels = new_pixel_position

		# Post values to the HUD
		self.hud['hud_polar'] = self.p
		self.hud['hud_cartesian'] = self.c

	@classmethod
	def set_offset(cls, offset):
		"""Apply an offset to align with the real drawings."""
		cls.offset = offset

	@classmethod
	def debug_point(cls, point, color):
		"""Draw a colored dot."""
		if cls.debug_enabled:
			pen = Display.debug_pen
			pen.color = color
			if cls.offset:
				point = point + cls.offset

			pen.setpos(point)
			pen.down()
			pen.dot(5, color)
			pen.up()
	
	@classmethod
	def debug_line(cls, start_point, end_point, color='grey'):
		"""Draw a line."""
		if cls.debug_enabled:
			pen = Display.debug_pen
			if cls.offset:
				start_point = start_point + cls.offset
				end_point = end_point + cls.offset

			pen.down()
			pen.line(start_point, end_point)
			pen.up()

	@classmethod
	def debug_circle(cls, center_point, radius, color='grey'):
		"""Draw a line."""
		if cls.debug_enabled:
			pen = Display.debug_pen
			if cls.offset:
				center_point = center_point + cls.offset

			pen.down()
			pen.circle(center_point, radius, color)
			pen.up()

	@classmethod
	def debug_text(cls, point, text):
		"""Write some text."""
		pass
		# if cls.debug_enabled:
		# 	with DebugPen('grey', 1) as pen:
		# 		pen.setpos(point.pixels() * 0.86666666666666666 * 0.86666666666666666)
		# 		pen.write(text)
	
	@classmethod
	def debug_clear(cls):
		"""Clear all debug drawing."""
		if cls.debug_enabled:
			debug_pen.clear()