Source code for simple_gyro

# SPDX-FileCopyrightText: Copyright (c) 2023 Jose D. Montoya
#
# SPDX-License-Identifier: MIT
"""
`simple_gyro`
================================================================================

Displayio Gyro representation


* Author(s): Jose D. Montoya


"""
# pylint: disable=too-many-arguments, unused-variable, too-many-locals, too-many-statements
# pylint: disable=too-many-instance-attributes
from math import pi, cos, sin
import displayio
from bitmaptools import draw_circle, rotozoom
from vectorio import Polygon


__version__ = "0.0.0+auto.0"
__repo__ = "https://github.com/jposada202020/CircuitPython_SIMPLE_GYRO.git"


DEG_TO_RAD = pi / 180


[docs]class Gyro: """ Gyro Graphical Representation """ def __init__( self, posx=100, posy=100, radius=50, padding=10, line_roll_height=10, color_circle=0x440044, color_needle=0x123456, color_indicator=0x112299, color_tick_indicator=0xFF0000, ): self.posx = posx self.posy = posy self.radius = radius self.padding = padding self._line_roll_height = line_roll_height self._line_roll_length = (2 * self.radius - 2 * self.padding) // 2 self.group = displayio.Group() self._palette = displayio.Palette(6) self._palette.make_transparent(0) self._palette[1] = color_circle self._palette[2] = color_needle self._palette[3] = color_indicator self._palette[4] = color_tick_indicator self._palette[5] = 0xFFFF00 self.dial_bitmap = displayio.Bitmap(2 * radius + 1, 2 * radius + 1, 10) background = displayio.TileGrid( self.dial_bitmap, pixel_shader=self._palette, x=posx - radius, y=posy - self.radius, ) self._draw_level() self._draw_inclination_line() self._draw_indicator() self.group.append(background) self.group.append(self.level) self.group.append(self.needle) self.group.append(self.indicator) draw_circle(self.dial_bitmap, radius, radius, radius, 1) self._draw_tick_indicator() self._draw_ticks_level() def _draw_inclination_line(self): points_polygono = [ (0, 0), (self._line_roll_length, 0), (self._line_roll_length, self._line_roll_height), (-self._line_roll_length, self._line_roll_height), (-self._line_roll_length, 0), ] self.needle = Polygon( points=points_polygono, pixel_shader=self._palette, x=self.posx, y=self.posy, color_index=2, ) self.original_values = self.needle.points def _draw_indicator(self): points_indicator = [(0, 0), (20, 0), (20, -6), (0, -6)] self.indicator = Polygon( pixel_shader=self._palette, points=points_indicator, x=self.posx - 5, y=self.posy - 30, color_index=3, ) self.indicator_original_values = self.indicator.points self.indix, self.indiy = self.indicator.location self.update_roll(0) def _draw_tick_indicator(self): tick_stroke = 1 tick_length = 30 tick_bitmap = displayio.Bitmap(tick_stroke, tick_length, 5) tick_bitmap.fill(4) pos = [-90, -80, -70, -60, -100, -110, -120] for i in pos: this_angle = i * DEG_TO_RAD target_position_x = self.radius + self.radius * cos(this_angle) target_position_y = self.radius + self.radius * sin(this_angle) rotozoom( self.dial_bitmap, ox=round(target_position_x), oy=round(target_position_y), source_bitmap=tick_bitmap, px=round(tick_bitmap.width / 2), py=0, angle=this_angle + 90 * DEG_TO_RAD, # in radians ) def _draw_level(self, padding_level=10): points_level = [ (0, 0), (self._line_roll_length - padding_level, 0), (self._line_roll_length - padding_level, self._line_roll_height // 3), (-self._line_roll_length + padding_level, self._line_roll_height // 3), (-self._line_roll_length + padding_level, 0), ] self.level = Polygon( pixel_shader=self._palette, points=points_level, x=self.posx, y=self.posy - self._line_roll_height // 2, color_index=1, ) self.level_origin_y = self.level.y def _draw_ticks_level(self): tick2_stroke = 2 tick2_length = 30 tick2_bitmap = displayio.Bitmap(tick2_length, tick2_stroke, 5) tick2_bitmap.fill(5) pos = [0, 15, 30, -15, -30] for i in pos: this_angle = i * DEG_TO_RAD target_position_x = ( (self.radius * cos(this_angle)) + self.radius - tick2_length ) target_position_y = (self.radius * sin(this_angle)) + self.radius rotozoom( self.dial_bitmap, ox=round(target_position_x), oy=round(target_position_y), source_bitmap=tick2_bitmap, px=0, py=0, angle=0, # in radians ) pos = [150, 165, 180, 195, 210] for i in pos: this_angle = i * DEG_TO_RAD target_position_x = (self.radius * cos(this_angle)) + self.radius target_position_y = (self.radius * sin(this_angle)) + self.radius rotozoom( self.dial_bitmap, ox=round(target_position_x), oy=round(target_position_y), source_bitmap=tick2_bitmap, px=0, py=0, angle=0, # in radians )
[docs] def update_roll(self, angle): """ update roll/pitch """ starting_angle = -90 * DEG_TO_RAD angle = (angle * DEG_TO_RAD) + starting_angle deltax = round((self.radius - 2 * self.padding) * cos(angle)) deltay = round((self.radius - 2 * self.padding) * sin(angle)) self.indicator.location = (self.indix + deltax + 5, self.indiy + deltay + 30) dummy = [(0, 0), (0, 0), (0, 0), (0, 0)] for j, element in enumerate(self.indicator.points): dummy[j] = round( self.indicator_original_values[j][0] * cos(angle) - self.indicator_original_values[j][1] * sin(angle) ), round( self.indicator_original_values[j][1] * cos(angle) + self.indicator_original_values[j][0] * sin(angle) ) self.indicator.points = dummy
[docs] def update_pitch(self, angle): """ Update pitch/roll """ angle = angle * 0.017 dummy = [(0, 0), (0, 0), (0, 0), (0, 0), (0, 0)] for j, element in enumerate(self.needle.points): dummy[j] = round( self.original_values[j][0] * cos(angle) - self.original_values[j][1] * sin(angle) ), round( self.original_values[j][1] * cos(angle) + self.original_values[j][0] * sin(angle) ) self.needle.points = dummy
[docs] def update_tilt(self, value): """ update roll/pitch """ self.level.y = value + self.level_origin_y