Skip to content

Commit

Permalink
Merge pull request #5 from tekktrik/match-repos
Browse files Browse the repository at this point in the history
Merge in code from Adafruit_CircuitPython_DisplayIO_Layout v1.17.0
  • Loading branch information
FoamyGuy authored Feb 19, 2022
2 parents 3a2389b + 890ee2c commit cef9af2
Show file tree
Hide file tree
Showing 4 changed files with 246 additions and 56 deletions.
235 changes: 181 additions & 54 deletions displayio_cartesian.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,9 @@

try:
import bitmaptools
except NameError:
except ImportError:
pass

try:
from typing import Tuple
except ImportError:
Expand Down Expand Up @@ -73,6 +74,7 @@ class Cartesian(Widget):
:param int nudge_y: movement in pixels in the y direction to move the origin.
Defaults to 0
:param bool verbose: print debugging information in some internal functions. Default to False
**Quickstart: Importing and using Cartesian**
Expand Down Expand Up @@ -180,11 +182,14 @@ def __init__(
subticks: bool = False,
nudge_x: int = 0,
nudge_y: int = 0,
verbose: bool = False,
**kwargs,
) -> None:

super().__init__(**kwargs)

self._verbose = verbose

self._background_color = background_color

self._axes_line_color = axes_color
Expand Down Expand Up @@ -249,8 +254,8 @@ def __init__(
self._axesy_bitmap = displayio.Bitmap(self._axesy_width, self.height, 4)
self._axesy_bitmap.fill(0)

self._screen_bitmap = displayio.Bitmap(self.width, self.height, 5)
self._screen_bitmap.fill(5)
self._plot_bitmap = displayio.Bitmap(self.width, self.height, 5)
self.clear_plot_lines()
self._screen_palette = displayio.Palette(6)
self._screen_palette.make_transparent(0)
self._screen_palette[1] = self._tick_color
Expand Down Expand Up @@ -292,7 +297,7 @@ def __init__(
)

self._screen_tilegrid = displayio.TileGrid(
self._screen_bitmap,
self._plot_bitmap,
pixel_shader=self._screen_palette,
x=0,
y=0,
Expand All @@ -309,11 +314,8 @@ def __init__(
self.append(self._screen_tilegrid)
self.append(self._corner_tilegrid)

self._update_line = True

self._pointer = None
self._circle_palette = None
self._pointer_vector_shape = None
self.plot_line_point = None

@staticmethod
Expand Down Expand Up @@ -389,10 +391,12 @@ def _draw_ticks(self) -> None:

if self._subticks:
if i in subticks:
# calc subtick_line_height; force min lineheigt to 1.
subtick_line_height = max(1, self._tick_line_height // 2)
rectangle_helper(
text_dist,
self._axes_line_thickness,
self._tick_line_height // 2,
subtick_line_height,
1,
self._axesx_bitmap,
1,
Expand Down Expand Up @@ -448,18 +452,138 @@ def _draw_ticks(self) -> None:
)

def _draw_pointers(self, x: int, y: int) -> None:
self._pointer = vectorio.Circle(self._pointer_radius)
self._circle_palette = displayio.Palette(2)
self._circle_palette.make_transparent(0)
self._circle_palette[1] = self._pointer_color

self._pointer_vector_shape = vectorio.VectorShape(
shape=self._pointer,
pixel_shader=self._circle_palette,
x=x,
y=y,

self._circle_palette = displayio.Palette(1)
self._circle_palette[0] = self._pointer_color
self._pointer = vectorio.Circle(
radius=self._pointer_radius, x=x, y=y, pixel_shader=self._circle_palette
)
self.append(self._pointer_vector_shape)

self.append(self._pointer)

def _calc_local_xy(self, x: int, y: int) -> Tuple[int, int]:
local_x = (
int((x - self._xrange[0]) * self._factorx * self._valuex) + self._nudge_x
)
# details on `+ (self.height - 1)` :
# the bitmap is set to self.width & self.height
# but we are only allowed to draw to pixels 0..height-1 and 0..width-1
local_y = (
int((self._yrange[0] - y) * self._factory * self._valuey)
+ (self.height - 1)
+ self._nudge_y
)
return (local_x, local_y)

def _check_local_x_in_range(self, local_x):
return 0 <= local_x < self.width

def _check_local_y_in_range(self, local_y):
return 0 <= local_y < self.height

def _check_local_xy_in_range(self, local_x, local_y):
return self._check_local_x_in_range(local_x) and self._check_local_y_in_range(
local_y
)

def _check_x_in_range(self, x):
return self._xrange[0] <= x <= self._xrange[1]

def _check_y_in_range(self, y):
return self._yrange[0] <= y <= self._yrange[1]

def _check_xy_in_range(self, x, y):
return self._check_x_in_range(x) and self._check_y_in_range(y)

def _add_point(self, x: int, y: int) -> None:
"""_add_point function
helper function to add a point to the graph in the plane
:param int x: ``x`` coordinate in the local plane
:param int y: ``y`` coordinate in the local plane
:return: None
rtype: None
"""
local_x, local_y = self._calc_local_xy(x, y)
if self._verbose:
print("")
print(
"xy: ({: >4}, {: >4}) "
"_xrange: ({: >4}, {: >4}) "
"_yrange: ({: >4}, {: >4}) "
"".format(
x,
y,
self._xrange[0],
self._xrange[1],
self._yrange[0],
self._yrange[1],
)
)
print(
"local_*: ({: >4}, {: >4}) "
" width: ({: >4}, {: >4}) "
" height: ({: >4}, {: >4}) "
"".format(
local_x,
local_y,
0,
self.width,
0,
self.height,
)
)
if self._check_xy_in_range(x, y):
if self._check_local_xy_in_range(local_x, local_y):
if self.plot_line_point is None:
self.plot_line_point = []
self.plot_line_point.append((local_x, local_y))
else:
# for better error messages we check in detail what failed...
# this should never happen:
# we already checked the range of the input values.
# but in case our calculation is wrong we handle this case to..
if not self._check_local_x_in_range(local_x):
raise ValueError(
"local_x out of range: "
"local_x:{: >4}; _xrange({: >4}, {: >4})"
"".format(
local_x,
0,
self.width,
)
)
if not self._check_local_y_in_range(local_y):
raise ValueError(
"local_y out of range: "
"local_y:{: >4}; _yrange({: >4}, {: >4})"
"".format(
local_y,
0,
self.height,
)
)
else:
# for better error messages we check in detail what failed...
if not self._check_x_in_range(x):
raise ValueError(
"x out of range: "
"x:{: >4}; xrange({: >4}, {: >4})"
"".format(
x,
self._xrange[0],
self._xrange[1],
)
)
if not self._check_y_in_range(y):
raise ValueError(
"y out of range: "
"y:{: >4}; yrange({: >4}, {: >4})"
"".format(
y,
self._yrange[0],
self._yrange[1],
)
)

def update_pointer(self, x: int, y: int) -> None:
"""updater_pointer function
Expand All @@ -469,46 +593,49 @@ def update_pointer(self, x: int, y: int) -> None:
:return: None
rtype: None
"""
local_x = int((x - self._xrange[0]) * self._factorx) + self._nudge_x
local_y = (
int((self._yrange[0] - y) * self._factory) + self.height + self._nudge_y
)
self._add_point(x, y)
if not self._pointer:
self._draw_pointers(
self.plot_line_point[-1][0],
self.plot_line_point[-1][1],
)
else:
self._pointer.x = self.plot_line_point[-1][0]
self._pointer.y = self.plot_line_point[-1][1]

if local_x >= 0 or local_y <= 100:
if self._update_line:
self._draw_pointers(local_x, local_y)
self._update_line = False
else:
self._pointer_vector_shape.x = local_x
self._pointer_vector_shape.y = local_y
def add_plot_line(self, x: int, y: int) -> None:
"""add_plot_line function.
def _set_plotter_line(self) -> None:
self.plot_line_point = list()
add line to the plane.
multiple calls create a line-plot graph.
def update_line(self, x: int, y: int) -> None:
"""updater_line function
helper function to update pointer in the plane
:param int x: ``x`` coordinate in the local plane
:param int y: ``y`` coordinate in the local plane
:return: None
rtype: None
"""
local_x = int((x - self._xrange[0]) * self._factorx) + self._nudge_x
local_y = (
int((self._yrange[0] - y) * self._factory) + self.height + self._nudge_y
)
if x < self._xrange[1] and y < self._yrange[1]:
if local_x > 0 or local_y < 100:
if self._update_line:
self._set_plotter_line()
self.plot_line_point.append((local_x, local_y))
self._update_line = False
else:
bitmaptools.draw_line(
self._screen_bitmap,
self.plot_line_point[-1][0],
self.plot_line_point[-1][1],
local_x,
local_y,
1,
)
self._add_point(x, y)
if len(self.plot_line_point) > 1:
bitmaptools.draw_line(
self._plot_bitmap,
self.plot_line_point[-2][0],
self.plot_line_point[-2][1],
self.plot_line_point[-1][0],
self.plot_line_point[-1][1],
1,
)

def clear_plot_lines(self, palette_index=5):
"""clear_plot_lines function.
clear all added lines
(clear line-plot graph)
:param int palette_index: color palett index. Defaults to 5
:return: None
rtype: None
"""
self.plot_line_point = None
self._plot_bitmap.fill(palette_index)
2 changes: 1 addition & 1 deletion examples/displayio_cartesian_advanced_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import board
import displayio
import terminalio
from adafruit_displayio_layout.widgets.cartesian import Cartesian
from displayio_cartesian import Cartesian

# Fonts used for the Dial tick labels
tick_font = terminalio.FONT
Expand Down
63 changes: 63 additions & 0 deletions examples/displayio_cartesian_lineplot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# SPDX-FileCopyrightText: 2021 Stefan Krüger
#
# SPDX-License-Identifier: MIT
#############################
"""
This is a basic demonstration of a Cartesian widget for line-ploting
"""

import time
import board
import displayio
from displayio_cartesian import Cartesian

# create the display on the PyPortal or Clue or PyBadge(for example)
display = board.DISPLAY
# otherwise change this to setup the display
# for display chip driver and pinout you have (e.g. ILI9341)

# pybadge display: 160x128
# Create a Cartesian widget
# https://circuitpython.readthedocs.io/projects/displayio-layout/en/latest/api.html#module-adafruit_displayio_layout.widgets.cartesian
my_plane = Cartesian(
x=15, # x position for the plane
y=2, # y plane position
width=140, # display width
height=105, # display height
xrange=(0, 10), # x range
yrange=(0, 10), # y range
)

my_group = displayio.Group()
my_group.append(my_plane)
display.show(my_group) # add high level Group to the display

data = [
# (0, 0), # we do this point manually - so we have no wait...
(1, 1),
(2, 1),
(2, 2),
(3, 3),
(4, 3),
(4, 4),
(5, 5),
(6, 5),
(6, 6),
(7, 7),
(8, 7),
(8, 8),
(9, 9),
(10, 9),
(10, 10),
]

print("examples/displayio_layout_cartesian_lineplot.py")

# first point without a wait.
my_plane.add_plot_line(0, 0)
for x, y in data:
my_plane.add_plot_line(x, y)
time.sleep(0.5)

while True:
pass
2 changes: 1 addition & 1 deletion examples/displayio_cartesian_simpletest.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import board
import displayio
import terminalio
from adafruit_displayio_layout.widgets.cartesian import Cartesian
from displayio_cartesian import Cartesian

# Fonts used for the Dial tick labels
tick_font = terminalio.FONT
Expand Down

0 comments on commit cef9af2

Please sign in to comment.