From 3133990d9002efb214489e7e4f171f5d1e7dc1a8 Mon Sep 17 00:00:00 2001 From: jposada202020 Date: Sun, 21 Mar 2021 15:21:06 -0400 Subject: [PATCH 01/36] Initial changes to include cartesian widget --- .../widgets/cartesian.py | 403 ++++++++++++++++++ .../displayio_layout_cartesian_simpletest.py | 40 ++ 2 files changed, 443 insertions(+) create mode 100644 adafruit_displayio_layout/widgets/cartesian.py create mode 100644 examples/displayio_layout_cartesian_simpletest.py diff --git a/adafruit_displayio_layout/widgets/cartesian.py b/adafruit_displayio_layout/widgets/cartesian.py new file mode 100644 index 0000000..88e869f --- /dev/null +++ b/adafruit_displayio_layout/widgets/cartesian.py @@ -0,0 +1,403 @@ +# SPDX-FileCopyrightText: 2021 Jose David Montoya +# +# SPDX-License-Identifier: MIT +""" + +`cartesian` +================================================================================ +A cartasian plane widget for displaying graphical information. + +* Author(s): Jose David Montoya + +Implementation Notes +-------------------- + +**Hardware:** + +**Software and Dependencies:** + +* Adafruit CircuitPython firmware for the supported boards: + https://github.com/adafruit/circuitpython/releases + +""" + +# pylint: disable=too-many-lines, too-many-instance-attributes, too-many-arguments +# pylint: disable=too-many-locals, too-many-statements + + +import math +import displayio +import board +import terminalio +from adafruit_displayio_layout.widgets.widget import Widget + +try: + import bitmaptools +except NameError: + pass # utilize the blit_rotate_scale function defined herein + + +class Cartesian(Widget): + """A cartesian widget. The origin is set using ``x`` and ``y``. + + :param int x: pixel position TODO + :param int y: pixel position TODO + + :param int width: requested width, in pixels TODO + :param int height: requested height, in pixels TODO + + """ + + def __init__( + self, + display_color=0x000000, + width: int = board.DISPLAY.width, + height: int = board.DISPLAY.height, + axes_color=0xFFFFFF, + axes_stroke=2, + tick_color=0xFFFFFF, + major_tick_stroke=1, + major_tick_length=10, + tick_label_font=terminalio.FONT, + tick_label_color=0xFFFFFF, + **kwargs, + ): + + super().__init__(**kwargs, max_size=3) + + self._margin = 10 + + self._display_color = display_color + self._display_width = width + self._display_height = height + + self._axes_line_color = axes_color + self._axes_line_thickness = axes_stroke + + self._tick_color = tick_color + self._tick_line_thickness = major_tick_stroke + self._tick_line_height = major_tick_length + self._font = tick_label_font + self._font_color = tick_label_color + + self._font_width = self._get_font_height(self._font, 1)[0] + self._font_height = self._get_font_height(self._font, 1)[1] + + self._usable_width = self._display_width - self._font_width - 2 * self._margin + self._usable_height = ( + self._display_height - self._font_height - 2 * self._margin + ) + self._tickx_separation = 2 * self._font_width + 2 + + self._tick_bitmap = displayio.Bitmap( + self._tick_line_thickness, self._tick_line_height, 3 + ) + self._tick_bitmap.fill(1) + + self._axesx_bitmap = displayio.Bitmap( + self._axes_line_thickness, self._usable_height, 3 + ) + self._axesx_bitmap.fill(2) + + self._axesy_bitmap = displayio.Bitmap( + self._usable_width, self._axes_line_thickness, 3 + ) + self._axesy_bitmap.fill(2) + + self._screen_bitmap = displayio.Bitmap( + self._usable_width, self._usable_height, 6 + ) + + self._screen_palette = displayio.Palette(6) + self._screen_palette[0] = 0x000000 + self._screen_palette[1] = self._tick_color + self._screen_palette[2] = self._axes_line_color + self._screen_palette[3] = 0x00FFFF + self._screen_palette[4] = 0xFFFFFF + self._screen_palette[5] = self._display_color + + self._screen_tilegrid = displayio.TileGrid( + self._screen_bitmap, + pixel_shader=self._screen_palette, + x=self._margin + self._font_width, + y=self._margin, + ) + + self._draw_axes() + self._draw_ticks() + self.append(self._screen_tilegrid) + + @staticmethod + def _get_font_height(font, scale): + if hasattr(font, "get_bounding_box"): + font_height = int(scale * font.get_bounding_box()[1]) + font_width = int(scale * font.get_bounding_box()[0]) + elif hasattr(font, "ascent"): + font_height = int(scale * font.ascent + font.ascent) + font_width = 12 + return font_width, font_height + + def _draw_axes(self): + bitmaptools.rotozoom( + self._screen_bitmap, + ox=self._margin - 1, + oy=self._usable_height, + source_bitmap=self._axesx_bitmap, + px=self._axesx_bitmap.width, + py=self._axesx_bitmap.height, + angle=0.0, # in radians + ) + + bitmaptools.rotozoom( + self._screen_bitmap, + ox=int(self._usable_width - self._margin / 2), + oy=self._usable_height, + source_bitmap=self._axesy_bitmap, + px=self._axesy_bitmap.width, + py=self._axesy_bitmap.height, + angle=0.0, + ) + + def _draw_ticks(self): + for i in range(self._margin, self._usable_width, self._tickx_separation): + if "rotozoom" in dir(bitmaptools): # if core function is available + bitmaptools.rotozoom( + self._screen_bitmap, + ox=i, + oy=self._usable_height, + source_bitmap=self._tick_bitmap, + px=int(self._tick_bitmap.width / 2), + py=self._tick_bitmap.height, + angle=0.0, # in radians + ) + else: + _blit_rotate_scale( # translate and rotate the tick into the target_bitmap + destination=self._screen_bitmap, + ox=i, + oy=0, + source=self._tick_bitmap, + px=int(self._tick_bitmap / 2), + py=self._tick_bitmap.height, + angle=0.0, # in radians + ) + + for i in range(self._margin, self._usable_height, self._tickx_separation): + if "rotozoom" in dir(bitmaptools): # if core function is available + bitmaptools.rotozoom( + self._screen_bitmap, + ox=self._margin, + oy=i, + source_bitmap=self._tick_bitmap, + px=int(self._tick_bitmap.width / 2), + py=int(self._tick_bitmap.height / 2), + angle=(90 * math.pi / 180), # in radians + ) + else: + _blit_rotate_scale( # translate and rotate the tick into the target_bitmap + destination=self._screen_bitmap, + ox=i, + oy=0, + source=self._tick_bitmap, + px=int(self._tick_bitmap.width / 2), + py=int(self._tick_bitmap.height / 2), + angle=(90 * math.pi / 180), # in radians + ) + + +# * Copyright (c) 2017 Werner Stoop +# * +# * Permission is hereby granted, free of charge, to any person obtaining a copy +# * of this software and associated documentation files (the "Software"), to deal +# * in the Software without restriction, including without limitation the rights +# * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# * copies of the Software, and to permit persons to whom the Software is +# * furnished to do so, subject to the following conditions: +# * +# * The above copyright notice and this permission notice shall be included in all +# * copies or substantial portions of the Software. +# * +# * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# * SOFTWARE. + + +# Credit from https://github.com/wernsey/bitmap +# MIT License from +# * Copyright (c) 2017 Werner Stoop +# +# /** +# * #### `void bm_rotate_blit(Bitmap *dst, int ox, int oy, Bitmap *src, int px, +# * int py, double angle, double scale);` +# * +# * Rotates a source bitmap `src` around a pivot point `px,py` and blits it +# * onto a destination bitmap `dst`. +# * +# * The bitmap is positioned such that the point `px,py` on the source is at +# * the offset `ox,oy` on the destination. +# * +# * The `angle` is clockwise, in radians. The bitmap is also scaled by the +# * factor `scale`. +# */ +# void bm_rotate_blit(Bitmap *dst, int ox, int oy, Bitmap *src, int px, +# int py, double angle, double scale); + + +# /* +# Reference: +# "Fast Bitmap Rotation and Scaling" By Steven Mortimer, Dr Dobbs' Journal, July 01, 2001 +# http://www.drdobbs.com/architecture-and-design/fast-bitmap-rotation-and-scaling/184416337 +# See also http://www.efg2.com/Lab/ImageProcessing/RotateScanline.htm +# */ + +# pylint: disable=invalid-name, too-many-branches, too-many-statements + +# This function is provided in case the bitmaptools.rotozoom function is not available +def _blit_rotate_scale( + destination, # destination bitmap + ox=None, + oy=None, # (ox, oy) is the destination point where the source (px,py) is placed + dest_clip0=None, + dest_clip1=None, # clip0,1 is (x,y) corners of clip window on the destination bitmap + source=None, # source bitmap + px=None, + py=None, # (px, py) is the rotation point of the source bitmap + source_clip0=None, + source_clip1=None, # clip0,1 is (x,y) corners of clip window on the source bitmap + angle=0, # in radians, clockwise + scale=1.0, # scale factor (float) + skip_index=None, # color index to ignore +): + + if source is None: + pass + + # Check the input limits + + if ox is None: + ox = destination.width / 2 + if oy is None: + oy = destination.height / 2 + if px is None: + px = source.width / 2 + if py is None: + py = source.height / 2 + + if dest_clip0 is None: + dest_clip0 = (0, 0) + if dest_clip1 is None: + dest_clip1 = (destination.width, destination.height) + + if source_clip0 is None: + source_clip0 = (0, 0) + if source_clip1 is None: + source_clip1 = (source.width, source.height) + + minx = dest_clip1[0] + miny = dest_clip1[1] + maxx = dest_clip0[0] + maxy = dest_clip0[1] + + sinAngle = math.sin(angle) + cosAngle = math.cos(angle) + + dx = -cosAngle * px * scale + sinAngle * py * scale + ox + dy = -sinAngle * px * scale - cosAngle * py * scale + oy + if dx < minx: + minx = int(round(dx)) + if dx > maxx: + maxx = int(round(dx)) + if dy < miny: + miny = int(round(dy)) + if dy > maxy: + maxy = int(dy) + dx = cosAngle * (source.width - px) * scale + sinAngle * py * scale + ox + dy = sinAngle * (source.width - px) * scale - cosAngle * py * scale + oy + if dx < minx: + minx = int(round(dx)) + if dx > maxx: + maxx = int(round(dx)) + if dy < miny: + miny = int(round(dy)) + if dy > maxy: + maxy = int(round(dy)) + + dx = ( + cosAngle * (source.width - px) * scale + - sinAngle * (source.height - py) * scale + + ox + ) + dy = ( + sinAngle * (source.width - px) * scale + + cosAngle * (source.height - py) * scale + + oy + ) + if dx < minx: + minx = int(round(dx)) + if dx > maxx: + maxx = int(round(dx)) + if dy < miny: + miny = int(round(dy)) + if dy > maxy: + maxy = int(round(dy)) + + dx = -cosAngle * px * scale - sinAngle * (source.height - py) * scale + ox + dy = -sinAngle * px * scale + cosAngle * (source.height - py) * scale + oy + if dx < minx: + minx = int(round(dx)) + if dx > maxx: + maxx = int(round(dx)) + if dy < miny: + miny = int(round(dy)) + if dy > maxy: + maxy = int(round(dy)) + + # /* Clipping */ + if minx < dest_clip0[0]: + minx = dest_clip0[0] + if maxx > dest_clip1[0] - 1: + maxx = dest_clip1[0] - 1 + if miny < dest_clip0[1]: + miny = dest_clip0[1] + if maxy > dest_clip1[1] - 1: + maxy = dest_clip1[1] - 1 + + dvCol = math.cos(angle) / scale + duCol = math.sin(angle) / scale + + duRow = dvCol + dvRow = -duCol + + startu = px - (ox * dvCol + oy * duCol) + startv = py - (ox * dvRow + oy * duRow) + + rowu = startu + miny * duCol + rowv = startv + miny * dvCol + + for y in range(miny, maxy + 1): # (y = miny, y <= maxy, y++) + u = rowu + minx * duRow + v = rowv + minx * dvRow + for x in range(minx, maxx + 1): # (x = minx, x <= maxx, x++) + if (source_clip0[0] <= u < source_clip1[0]) and ( + source_clip0[1] <= v < source_clip1[1] + ): + # get the pixel color (c) from the source bitmap at (u,v) + c = source[ + int(u) + source.width * int(v) + ] # direct index into bitmap is faster than tuple + # c = source[int(u), int(v)] + + if c != skip_index: # ignore any pixels with skip_index + # place the pixel color (c) into the destination bitmap at (x,y) + destination[ + x + y * destination.width + ] = c # direct index into bitmap is faster than tuple + # destination[x,y] = c + u += duRow + v += dvRow + + rowu += duCol + rowv += dvCol diff --git a/examples/displayio_layout_cartesian_simpletest.py b/examples/displayio_layout_cartesian_simpletest.py new file mode 100644 index 0000000..856ef72 --- /dev/null +++ b/examples/displayio_layout_cartesian_simpletest.py @@ -0,0 +1,40 @@ +# SPDX-FileCopyrightText: 2021 Jose David Montoya +# +# SPDX-License-Identifier: MIT +############################# +""" +This is a basic demonstration of a Cartesian widget. +""" + +import board +import displayio +import terminalio +from adafruit_displayio_layout.widgets.cartesian import Cartesian + +# Fonts used for the Dial tick labels +tick_font = terminalio.FONT + +display = board.DISPLAY # create the display on the PyPortal or Clue (for example) +# otherwise change this to setup the display +# for display chip driver and pinout you have (e.g. ILI9341) + + +# Create a Dial widget +my_plane = Cartesian( + width=display.width, # display width + height=display.height, # display height + axes_color=0xFFFFFF, # axes line color + axes_stroke=2, # axes lines width in pixels + tick_color=0xFFFFFF, # ticks color + major_tick_stroke=1, # ticks width in pixels + major_tick_length=10, # ticks length in pixels + tick_label_color=0xFFFFFF, # ticks line color + tick_label_font=tick_font, # the font used for the tick labels +) + +my_group = displayio.Group(max_size=3) +my_group.append(my_plane) +display.show(my_group) # add high level Group to the display + +while True: + pass From e5304e621ee3cb4c7157c3a7bed6ec5c2a8f3d37 Mon Sep 17 00:00:00 2001 From: jposada202020 Date: Sun, 21 Mar 2021 15:53:15 -0400 Subject: [PATCH 02/36] Moving _blip_rotate_scale to __init__ to avoid code repetition. --- adafruit_displayio_layout/widgets/__init__.py | 208 ++++++++++++++++++ .../widgets/cartesian.py | 200 +---------------- 2 files changed, 209 insertions(+), 199 deletions(-) diff --git a/adafruit_displayio_layout/widgets/__init__.py b/adafruit_displayio_layout/widgets/__init__.py index e69de29..ea90e78 100644 --- a/adafruit_displayio_layout/widgets/__init__.py +++ b/adafruit_displayio_layout/widgets/__init__.py @@ -0,0 +1,208 @@ +# SPDX-FileCopyrightText: Kevin Matocha +# +# SPDX-License-Identifier: MIT + +""" +`adafruit_displayio_layout.widgets` +======================= +""" + +import math + +# * Copyright (c) 2017 Werner Stoop +# * +# * Permission is hereby granted, free of charge, to any person obtaining a copy +# * of this software and associated documentation files (the "Software"), to deal +# * in the Software without restriction, including without limitation the rights +# * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# * copies of the Software, and to permit persons to whom the Software is +# * furnished to do so, subject to the following conditions: +# * +# * The above copyright notice and this permission notice shall be included in all +# * copies or substantial portions of the Software. +# * +# * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# * SOFTWARE. + + +# Credit from https://github.com/wernsey/bitmap +# MIT License from +# * Copyright (c) 2017 Werner Stoop +# +# /** +# * #### `void bm_rotate_blit(Bitmap *dst, int ox, int oy, Bitmap *src, int px, +# * int py, double angle, double scale);` +# * +# * Rotates a source bitmap `src` around a pivot point `px,py` and blits it +# * onto a destination bitmap `dst`. +# * +# * The bitmap is positioned such that the point `px,py` on the source is at +# * the offset `ox,oy` on the destination. +# * +# * The `angle` is clockwise, in radians. The bitmap is also scaled by the +# * factor `scale`. +# */ +# void bm_rotate_blit(Bitmap *dst, int ox, int oy, Bitmap *src, int px, +# int py, double angle, double scale); + + +# /* +# Reference: +# "Fast Bitmap Rotation and Scaling" By Steven Mortimer, Dr Dobbs' Journal, July 01, 2001 +# http://www.drdobbs.com/architecture-and-design/fast-bitmap-rotation-and-scaling/184416337 +# See also http://www.efg2.com/Lab/ImageProcessing/RotateScanline.htm +# */ +# This function is provided in case the bitmaptools.rotozoom function is not available + +# pylint: disable=invalid-name, too-many-branches, too-many-statements, too-many-locals +# pylint: disable=too-many-arguments +def _blit_rotate_scale( + destination, # destination bitmap + ox=None, + oy=None, # (ox, oy) is the destination point where the source (px,py) is placed + dest_clip0=None, + dest_clip1=None, # clip0,1 is (x,y) corners of clip window on the destination bitmap + source=None, # source bitmap + px=None, + py=None, # (px, py) is the rotation point of the source bitmap + source_clip0=None, + source_clip1=None, # clip0,1 is (x,y) corners of clip window on the source bitmap + angle=0, # in radians, clockwise + scale=1.0, # scale factor (float) + skip_index=None, # color index to ignore +): + + if source is None: + pass + + # Check the input limits + + if ox is None: + ox = destination.width / 2 + if oy is None: + oy = destination.height / 2 + if px is None: + px = source.width / 2 + if py is None: + py = source.height / 2 + + if dest_clip0 is None: + dest_clip0 = (0, 0) + if dest_clip1 is None: + dest_clip1 = (destination.width, destination.height) + + if source_clip0 is None: + source_clip0 = (0, 0) + if source_clip1 is None: + source_clip1 = (source.width, source.height) + + minx = dest_clip1[0] + miny = dest_clip1[1] + maxx = dest_clip0[0] + maxy = dest_clip0[1] + + sinAngle = math.sin(angle) + cosAngle = math.cos(angle) + + dx = -cosAngle * px * scale + sinAngle * py * scale + ox + dy = -sinAngle * px * scale - cosAngle * py * scale + oy + if dx < minx: + minx = int(round(dx)) + if dx > maxx: + maxx = int(round(dx)) + if dy < miny: + miny = int(round(dy)) + if dy > maxy: + maxy = int(dy) + dx = cosAngle * (source.width - px) * scale + sinAngle * py * scale + ox + dy = sinAngle * (source.width - px) * scale - cosAngle * py * scale + oy + if dx < minx: + minx = int(round(dx)) + if dx > maxx: + maxx = int(round(dx)) + if dy < miny: + miny = int(round(dy)) + if dy > maxy: + maxy = int(round(dy)) + + dx = ( + cosAngle * (source.width - px) * scale + - sinAngle * (source.height - py) * scale + + ox + ) + dy = ( + sinAngle * (source.width - px) * scale + + cosAngle * (source.height - py) * scale + + oy + ) + if dx < minx: + minx = int(round(dx)) + if dx > maxx: + maxx = int(round(dx)) + if dy < miny: + miny = int(round(dy)) + if dy > maxy: + maxy = int(round(dy)) + + dx = -cosAngle * px * scale - sinAngle * (source.height - py) * scale + ox + dy = -sinAngle * px * scale + cosAngle * (source.height - py) * scale + oy + if dx < minx: + minx = int(round(dx)) + if dx > maxx: + maxx = int(round(dx)) + if dy < miny: + miny = int(round(dy)) + if dy > maxy: + maxy = int(round(dy)) + + # /* Clipping */ + if minx < dest_clip0[0]: + minx = dest_clip0[0] + if maxx > dest_clip1[0] - 1: + maxx = dest_clip1[0] - 1 + if miny < dest_clip0[1]: + miny = dest_clip0[1] + if maxy > dest_clip1[1] - 1: + maxy = dest_clip1[1] - 1 + + dvCol = math.cos(angle) / scale + duCol = math.sin(angle) / scale + + duRow = dvCol + dvRow = -duCol + + startu = px - (ox * dvCol + oy * duCol) + startv = py - (ox * dvRow + oy * duRow) + + rowu = startu + miny * duCol + rowv = startv + miny * dvCol + + for y in range(miny, maxy + 1): # (y = miny, y <= maxy, y++) + u = rowu + minx * duRow + v = rowv + minx * dvRow + for x in range(minx, maxx + 1): # (x = minx, x <= maxx, x++) + if (source_clip0[0] <= u < source_clip1[0]) and ( + source_clip0[1] <= v < source_clip1[1] + ): + # get the pixel color (c) from the source bitmap at (u,v) + c = source[ + int(u) + source.width * int(v) + ] # direct index into bitmap is faster than tuple + # c = source[int(u), int(v)] + + if c != skip_index: # ignore any pixels with skip_index + # place the pixel color (c) into the destination bitmap at (x,y) + destination[ + x + y * destination.width + ] = c # direct index into bitmap is faster than tuple + # destination[x,y] = c + u += duRow + v += dvRow + + rowu += duCol + rowv += dvCol diff --git a/adafruit_displayio_layout/widgets/cartesian.py b/adafruit_displayio_layout/widgets/cartesian.py index 88e869f..977dd99 100644 --- a/adafruit_displayio_layout/widgets/cartesian.py +++ b/adafruit_displayio_layout/widgets/cartesian.py @@ -30,6 +30,7 @@ import board import terminalio from adafruit_displayio_layout.widgets.widget import Widget +from adafruit_displayio_layout.widgets import _blit_rotate_scale try: import bitmaptools @@ -202,202 +203,3 @@ def _draw_ticks(self): py=int(self._tick_bitmap.height / 2), angle=(90 * math.pi / 180), # in radians ) - - -# * Copyright (c) 2017 Werner Stoop -# * -# * Permission is hereby granted, free of charge, to any person obtaining a copy -# * of this software and associated documentation files (the "Software"), to deal -# * in the Software without restriction, including without limitation the rights -# * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# * copies of the Software, and to permit persons to whom the Software is -# * furnished to do so, subject to the following conditions: -# * -# * The above copyright notice and this permission notice shall be included in all -# * copies or substantial portions of the Software. -# * -# * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# * SOFTWARE. - - -# Credit from https://github.com/wernsey/bitmap -# MIT License from -# * Copyright (c) 2017 Werner Stoop -# -# /** -# * #### `void bm_rotate_blit(Bitmap *dst, int ox, int oy, Bitmap *src, int px, -# * int py, double angle, double scale);` -# * -# * Rotates a source bitmap `src` around a pivot point `px,py` and blits it -# * onto a destination bitmap `dst`. -# * -# * The bitmap is positioned such that the point `px,py` on the source is at -# * the offset `ox,oy` on the destination. -# * -# * The `angle` is clockwise, in radians. The bitmap is also scaled by the -# * factor `scale`. -# */ -# void bm_rotate_blit(Bitmap *dst, int ox, int oy, Bitmap *src, int px, -# int py, double angle, double scale); - - -# /* -# Reference: -# "Fast Bitmap Rotation and Scaling" By Steven Mortimer, Dr Dobbs' Journal, July 01, 2001 -# http://www.drdobbs.com/architecture-and-design/fast-bitmap-rotation-and-scaling/184416337 -# See also http://www.efg2.com/Lab/ImageProcessing/RotateScanline.htm -# */ - -# pylint: disable=invalid-name, too-many-branches, too-many-statements - -# This function is provided in case the bitmaptools.rotozoom function is not available -def _blit_rotate_scale( - destination, # destination bitmap - ox=None, - oy=None, # (ox, oy) is the destination point where the source (px,py) is placed - dest_clip0=None, - dest_clip1=None, # clip0,1 is (x,y) corners of clip window on the destination bitmap - source=None, # source bitmap - px=None, - py=None, # (px, py) is the rotation point of the source bitmap - source_clip0=None, - source_clip1=None, # clip0,1 is (x,y) corners of clip window on the source bitmap - angle=0, # in radians, clockwise - scale=1.0, # scale factor (float) - skip_index=None, # color index to ignore -): - - if source is None: - pass - - # Check the input limits - - if ox is None: - ox = destination.width / 2 - if oy is None: - oy = destination.height / 2 - if px is None: - px = source.width / 2 - if py is None: - py = source.height / 2 - - if dest_clip0 is None: - dest_clip0 = (0, 0) - if dest_clip1 is None: - dest_clip1 = (destination.width, destination.height) - - if source_clip0 is None: - source_clip0 = (0, 0) - if source_clip1 is None: - source_clip1 = (source.width, source.height) - - minx = dest_clip1[0] - miny = dest_clip1[1] - maxx = dest_clip0[0] - maxy = dest_clip0[1] - - sinAngle = math.sin(angle) - cosAngle = math.cos(angle) - - dx = -cosAngle * px * scale + sinAngle * py * scale + ox - dy = -sinAngle * px * scale - cosAngle * py * scale + oy - if dx < minx: - minx = int(round(dx)) - if dx > maxx: - maxx = int(round(dx)) - if dy < miny: - miny = int(round(dy)) - if dy > maxy: - maxy = int(dy) - dx = cosAngle * (source.width - px) * scale + sinAngle * py * scale + ox - dy = sinAngle * (source.width - px) * scale - cosAngle * py * scale + oy - if dx < minx: - minx = int(round(dx)) - if dx > maxx: - maxx = int(round(dx)) - if dy < miny: - miny = int(round(dy)) - if dy > maxy: - maxy = int(round(dy)) - - dx = ( - cosAngle * (source.width - px) * scale - - sinAngle * (source.height - py) * scale - + ox - ) - dy = ( - sinAngle * (source.width - px) * scale - + cosAngle * (source.height - py) * scale - + oy - ) - if dx < minx: - minx = int(round(dx)) - if dx > maxx: - maxx = int(round(dx)) - if dy < miny: - miny = int(round(dy)) - if dy > maxy: - maxy = int(round(dy)) - - dx = -cosAngle * px * scale - sinAngle * (source.height - py) * scale + ox - dy = -sinAngle * px * scale + cosAngle * (source.height - py) * scale + oy - if dx < minx: - minx = int(round(dx)) - if dx > maxx: - maxx = int(round(dx)) - if dy < miny: - miny = int(round(dy)) - if dy > maxy: - maxy = int(round(dy)) - - # /* Clipping */ - if minx < dest_clip0[0]: - minx = dest_clip0[0] - if maxx > dest_clip1[0] - 1: - maxx = dest_clip1[0] - 1 - if miny < dest_clip0[1]: - miny = dest_clip0[1] - if maxy > dest_clip1[1] - 1: - maxy = dest_clip1[1] - 1 - - dvCol = math.cos(angle) / scale - duCol = math.sin(angle) / scale - - duRow = dvCol - dvRow = -duCol - - startu = px - (ox * dvCol + oy * duCol) - startv = py - (ox * dvRow + oy * duRow) - - rowu = startu + miny * duCol - rowv = startv + miny * dvCol - - for y in range(miny, maxy + 1): # (y = miny, y <= maxy, y++) - u = rowu + minx * duRow - v = rowv + minx * dvRow - for x in range(minx, maxx + 1): # (x = minx, x <= maxx, x++) - if (source_clip0[0] <= u < source_clip1[0]) and ( - source_clip0[1] <= v < source_clip1[1] - ): - # get the pixel color (c) from the source bitmap at (u,v) - c = source[ - int(u) + source.width * int(v) - ] # direct index into bitmap is faster than tuple - # c = source[int(u), int(v)] - - if c != skip_index: # ignore any pixels with skip_index - # place the pixel color (c) into the destination bitmap at (x,y) - destination[ - x + y * destination.width - ] = c # direct index into bitmap is faster than tuple - # destination[x,y] = c - u += duRow - v += dvRow - - rowu += duCol - rowv += dvCol From 45bd92017ff256d09089d0fee3e852e8557b6b4b Mon Sep 17 00:00:00 2001 From: jposada202020 Date: Sun, 21 Mar 2021 18:08:55 -0400 Subject: [PATCH 03/36] inclusion the ability to select widget x,y coordinates, update function is working --- .../widgets/cartesian.py | 96 ++++++++++++++----- .../displayio_layout_cartesian_simpletest.py | 16 +++- 2 files changed, 84 insertions(+), 28 deletions(-) diff --git a/adafruit_displayio_layout/widgets/cartesian.py b/adafruit_displayio_layout/widgets/cartesian.py index 977dd99..53eaf77 100644 --- a/adafruit_displayio_layout/widgets/cartesian.py +++ b/adafruit_displayio_layout/widgets/cartesian.py @@ -24,13 +24,13 @@ # pylint: disable=too-many-lines, too-many-instance-attributes, too-many-arguments # pylint: disable=too-many-locals, too-many-statements - import math import displayio import board import terminalio from adafruit_displayio_layout.widgets.widget import Widget from adafruit_displayio_layout.widgets import _blit_rotate_scale +import vectorio try: import bitmaptools @@ -41,36 +41,55 @@ class Cartesian(Widget): """A cartesian widget. The origin is set using ``x`` and ``y``. - :param int x: pixel position TODO - :param int y: pixel position TODO + :param int x: x position of the plane origin + :param int y: y position of the plane origin + + :param int display_color: background color to use defaults to black (0x000000) + :param int width: requested width, in pixels defaults to screen width + :param int height: requested height, in pixels defaults to screen height + + :param int axes_color: axes lines color defaults to white (0xFFFFFF) + :param int axes_stroke: axes lines thickness in pixels defaults to 2 + + :param int major_tick_stroke: tick lines thickness in pixels dafaults to 1 + :param int major_tick_lenght: tick lines lenght in pixels defaults to 5 - :param int width: requested width, in pixels TODO - :param int height: requested height, in pixels TODO + :param int tick_label_font: tick label text font + :param int tick_label_color: tick label text color + + :param int pointer_radius: pointer radius in pixels defaults to 1 + :param int pointer_color: pointer color defaults to white (0xFFFFFF) """ def __init__( self, + x: int = 10, + y: int = board.DISPLAY.height - 10, display_color=0x000000, width: int = board.DISPLAY.width, height: int = board.DISPLAY.height, - axes_color=0xFFFFFF, - axes_stroke=2, - tick_color=0xFFFFFF, - major_tick_stroke=1, - major_tick_length=10, + axes_color: int = 0xFFFFFF, + axes_stroke: int = 2, + tick_color: int = 0xFFFFFF, + major_tick_stroke: int = 1, + major_tick_length: int = 5, tick_label_font=terminalio.FONT, - tick_label_color=0xFFFFFF, + tick_label_color: int = 0xFFFFFF, + pointer_radius: int = 1, + pointer_color: int = 0xFFFFFF, **kwargs, - ): + ) -> None: super().__init__(**kwargs, max_size=3) + self._origin_x = x + self._origin_y = y self._margin = 10 self._display_color = display_color - self._display_width = width - self._display_height = height + self._widget_width = width + self._widget_height = height self._axes_line_color = axes_color self._axes_line_thickness = axes_stroke @@ -78,16 +97,18 @@ def __init__( self._tick_color = tick_color self._tick_line_thickness = major_tick_stroke self._tick_line_height = major_tick_length + + self._pointer_radius = pointer_radius + self._pointer_color = pointer_color + self._font = tick_label_font self._font_color = tick_label_color self._font_width = self._get_font_height(self._font, 1)[0] self._font_height = self._get_font_height(self._font, 1)[1] - self._usable_width = self._display_width - self._font_width - 2 * self._margin - self._usable_height = ( - self._display_height - self._font_height - 2 * self._margin - ) + self._usable_width = self._widget_width - 2 * self._margin + self._usable_height = self._widget_height - 2 * self._margin self._tickx_separation = 2 * self._font_width + 2 self._tick_bitmap = displayio.Bitmap( @@ -106,11 +127,11 @@ def __init__( self._axesy_bitmap.fill(2) self._screen_bitmap = displayio.Bitmap( - self._usable_width, self._usable_height, 6 + self._usable_width, self._usable_height, 3 ) self._screen_palette = displayio.Palette(6) - self._screen_palette[0] = 0x000000 + self._screen_palette.make_transparent(0) self._screen_palette[1] = self._tick_color self._screen_palette[2] = self._axes_line_color self._screen_palette[3] = 0x00FFFF @@ -120,12 +141,14 @@ def __init__( self._screen_tilegrid = displayio.TileGrid( self._screen_bitmap, pixel_shader=self._screen_palette, - x=self._margin + self._font_width, - y=self._margin, + x=self._origin_x, + y=self._origin_y, ) self._draw_axes() self._draw_ticks() + self._draw_pointers() + self.append(self._pointer_vector_shape) self.append(self._screen_tilegrid) @staticmethod @@ -141,7 +164,7 @@ def _get_font_height(font, scale): def _draw_axes(self): bitmaptools.rotozoom( self._screen_bitmap, - ox=self._margin - 1, + ox=self._margin, oy=self._usable_height, source_bitmap=self._axesx_bitmap, px=self._axesx_bitmap.width, @@ -151,7 +174,7 @@ def _draw_axes(self): bitmaptools.rotozoom( self._screen_bitmap, - ox=int(self._usable_width - self._margin / 2), + ox=int(self._usable_width + self._margin), oy=self._usable_height, source_bitmap=self._axesy_bitmap, px=self._axesy_bitmap.width, @@ -203,3 +226,28 @@ def _draw_ticks(self): py=int(self._tick_bitmap.height / 2), angle=(90 * math.pi / 180), # in radians ) + + def _draw_pointers(self): + self._pointer = vectorio.Circle(3) + + self._circle_palette = displayio.Palette(2) + self._circle_palette.make_transparent(0) + self._circle_palette[1] = 0xFFFFFF + + self._pointer_vector_shape = vectorio.VectorShape( + shape=self._pointer, + pixel_shader=self._circle_palette, + x=0, + y=0, + ) + + def update_pointer(self, x: int, y: int): + """updater_pointer function + helper function to update pointer in the plane + :param x: x coordinate in the local plane + :param y: y coordinate in the local plane + :return: None + rtype: None + """ + self._pointer_vector_shape.x = self._origin_x + x + self._margin + self._pointer_vector_shape.y = self._origin_y + self._usable_height + y diff --git a/examples/displayio_layout_cartesian_simpletest.py b/examples/displayio_layout_cartesian_simpletest.py index 856ef72..ed2212d 100644 --- a/examples/displayio_layout_cartesian_simpletest.py +++ b/examples/displayio_layout_cartesian_simpletest.py @@ -6,6 +6,7 @@ This is a basic demonstration of a Cartesian widget. """ +import time import board import displayio import terminalio @@ -21,13 +22,15 @@ # Create a Dial widget my_plane = Cartesian( - width=display.width, # display width - height=display.height, # display height + x=150, # x position for the plane + y=100, # y plane position + width=100, # display width + height=100, # display height axes_color=0xFFFFFF, # axes line color axes_stroke=2, # axes lines width in pixels tick_color=0xFFFFFF, # ticks color major_tick_stroke=1, # ticks width in pixels - major_tick_length=10, # ticks length in pixels + major_tick_length=5, # ticks length in pixels tick_label_color=0xFFFFFF, # ticks line color tick_label_font=tick_font, # the font used for the tick labels ) @@ -36,5 +39,10 @@ my_group.append(my_plane) display.show(my_group) # add high level Group to the display +posx = 0 +posy = 0 + while True: - pass + my_plane.update_pointer(posx, posy) + display.show(my_group) + time.sleep(0.5) From e8e67c08d9ed55c00f6403d2697f7e06941939eb Mon Sep 17 00:00:00 2001 From: jposada202020 Date: Sun, 21 Mar 2021 21:40:39 -0400 Subject: [PATCH 04/36] # TODO Make axes, separate from data [X] # TODO Replace with drawline/vectorio [ ] # TODO Make a rectangle function [ ] # TODO Include functions to equal space ticks [ ] # TODO Make labels and text [ ] # TODO Make Styles applicable [ ] # TODO Animate when overflow [ ] --- adafruit_displayio_layout/widgets/__init__.py | 208 ------------------ .../widgets/cartesian.py | 103 ++++----- 2 files changed, 52 insertions(+), 259 deletions(-) diff --git a/adafruit_displayio_layout/widgets/__init__.py b/adafruit_displayio_layout/widgets/__init__.py index ea90e78..e69de29 100644 --- a/adafruit_displayio_layout/widgets/__init__.py +++ b/adafruit_displayio_layout/widgets/__init__.py @@ -1,208 +0,0 @@ -# SPDX-FileCopyrightText: Kevin Matocha -# -# SPDX-License-Identifier: MIT - -""" -`adafruit_displayio_layout.widgets` -======================= -""" - -import math - -# * Copyright (c) 2017 Werner Stoop -# * -# * Permission is hereby granted, free of charge, to any person obtaining a copy -# * of this software and associated documentation files (the "Software"), to deal -# * in the Software without restriction, including without limitation the rights -# * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# * copies of the Software, and to permit persons to whom the Software is -# * furnished to do so, subject to the following conditions: -# * -# * The above copyright notice and this permission notice shall be included in all -# * copies or substantial portions of the Software. -# * -# * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# * SOFTWARE. - - -# Credit from https://github.com/wernsey/bitmap -# MIT License from -# * Copyright (c) 2017 Werner Stoop -# -# /** -# * #### `void bm_rotate_blit(Bitmap *dst, int ox, int oy, Bitmap *src, int px, -# * int py, double angle, double scale);` -# * -# * Rotates a source bitmap `src` around a pivot point `px,py` and blits it -# * onto a destination bitmap `dst`. -# * -# * The bitmap is positioned such that the point `px,py` on the source is at -# * the offset `ox,oy` on the destination. -# * -# * The `angle` is clockwise, in radians. The bitmap is also scaled by the -# * factor `scale`. -# */ -# void bm_rotate_blit(Bitmap *dst, int ox, int oy, Bitmap *src, int px, -# int py, double angle, double scale); - - -# /* -# Reference: -# "Fast Bitmap Rotation and Scaling" By Steven Mortimer, Dr Dobbs' Journal, July 01, 2001 -# http://www.drdobbs.com/architecture-and-design/fast-bitmap-rotation-and-scaling/184416337 -# See also http://www.efg2.com/Lab/ImageProcessing/RotateScanline.htm -# */ -# This function is provided in case the bitmaptools.rotozoom function is not available - -# pylint: disable=invalid-name, too-many-branches, too-many-statements, too-many-locals -# pylint: disable=too-many-arguments -def _blit_rotate_scale( - destination, # destination bitmap - ox=None, - oy=None, # (ox, oy) is the destination point where the source (px,py) is placed - dest_clip0=None, - dest_clip1=None, # clip0,1 is (x,y) corners of clip window on the destination bitmap - source=None, # source bitmap - px=None, - py=None, # (px, py) is the rotation point of the source bitmap - source_clip0=None, - source_clip1=None, # clip0,1 is (x,y) corners of clip window on the source bitmap - angle=0, # in radians, clockwise - scale=1.0, # scale factor (float) - skip_index=None, # color index to ignore -): - - if source is None: - pass - - # Check the input limits - - if ox is None: - ox = destination.width / 2 - if oy is None: - oy = destination.height / 2 - if px is None: - px = source.width / 2 - if py is None: - py = source.height / 2 - - if dest_clip0 is None: - dest_clip0 = (0, 0) - if dest_clip1 is None: - dest_clip1 = (destination.width, destination.height) - - if source_clip0 is None: - source_clip0 = (0, 0) - if source_clip1 is None: - source_clip1 = (source.width, source.height) - - minx = dest_clip1[0] - miny = dest_clip1[1] - maxx = dest_clip0[0] - maxy = dest_clip0[1] - - sinAngle = math.sin(angle) - cosAngle = math.cos(angle) - - dx = -cosAngle * px * scale + sinAngle * py * scale + ox - dy = -sinAngle * px * scale - cosAngle * py * scale + oy - if dx < minx: - minx = int(round(dx)) - if dx > maxx: - maxx = int(round(dx)) - if dy < miny: - miny = int(round(dy)) - if dy > maxy: - maxy = int(dy) - dx = cosAngle * (source.width - px) * scale + sinAngle * py * scale + ox - dy = sinAngle * (source.width - px) * scale - cosAngle * py * scale + oy - if dx < minx: - minx = int(round(dx)) - if dx > maxx: - maxx = int(round(dx)) - if dy < miny: - miny = int(round(dy)) - if dy > maxy: - maxy = int(round(dy)) - - dx = ( - cosAngle * (source.width - px) * scale - - sinAngle * (source.height - py) * scale - + ox - ) - dy = ( - sinAngle * (source.width - px) * scale - + cosAngle * (source.height - py) * scale - + oy - ) - if dx < minx: - minx = int(round(dx)) - if dx > maxx: - maxx = int(round(dx)) - if dy < miny: - miny = int(round(dy)) - if dy > maxy: - maxy = int(round(dy)) - - dx = -cosAngle * px * scale - sinAngle * (source.height - py) * scale + ox - dy = -sinAngle * px * scale + cosAngle * (source.height - py) * scale + oy - if dx < minx: - minx = int(round(dx)) - if dx > maxx: - maxx = int(round(dx)) - if dy < miny: - miny = int(round(dy)) - if dy > maxy: - maxy = int(round(dy)) - - # /* Clipping */ - if minx < dest_clip0[0]: - minx = dest_clip0[0] - if maxx > dest_clip1[0] - 1: - maxx = dest_clip1[0] - 1 - if miny < dest_clip0[1]: - miny = dest_clip0[1] - if maxy > dest_clip1[1] - 1: - maxy = dest_clip1[1] - 1 - - dvCol = math.cos(angle) / scale - duCol = math.sin(angle) / scale - - duRow = dvCol - dvRow = -duCol - - startu = px - (ox * dvCol + oy * duCol) - startv = py - (ox * dvRow + oy * duRow) - - rowu = startu + miny * duCol - rowv = startv + miny * dvCol - - for y in range(miny, maxy + 1): # (y = miny, y <= maxy, y++) - u = rowu + minx * duRow - v = rowv + minx * dvRow - for x in range(minx, maxx + 1): # (x = minx, x <= maxx, x++) - if (source_clip0[0] <= u < source_clip1[0]) and ( - source_clip0[1] <= v < source_clip1[1] - ): - # get the pixel color (c) from the source bitmap at (u,v) - c = source[ - int(u) + source.width * int(v) - ] # direct index into bitmap is faster than tuple - # c = source[int(u), int(v)] - - if c != skip_index: # ignore any pixels with skip_index - # place the pixel color (c) into the destination bitmap at (x,y) - destination[ - x + y * destination.width - ] = c # direct index into bitmap is faster than tuple - # destination[x,y] = c - u += duRow - v += dvRow - - rowu += duCol - rowv += dvCol diff --git a/adafruit_displayio_layout/widgets/cartesian.py b/adafruit_displayio_layout/widgets/cartesian.py index 53eaf77..6a721d6 100644 --- a/adafruit_displayio_layout/widgets/cartesian.py +++ b/adafruit_displayio_layout/widgets/cartesian.py @@ -29,7 +29,6 @@ import board import terminalio from adafruit_displayio_layout.widgets.widget import Widget -from adafruit_displayio_layout.widgets import _blit_rotate_scale import vectorio try: @@ -80,6 +79,13 @@ def __init__( pointer_color: int = 0xFFFFFF, **kwargs, ) -> None: + # TODO Make axes, separate from data [X] + # TODO Replace with drawline/vectorio [ ] + # TODO Make a rectangle function [ ] + # TODO Include functions to equal space ticks [ ] + # TODO Make labels and text [ ] + # TODO Make Styles applicable [ ] + # TODO Animate when overflow [ ] super().__init__(**kwargs, max_size=3) self._origin_x = x @@ -116,15 +122,23 @@ def __init__( ) self._tick_bitmap.fill(1) - self._axesx_bitmap = displayio.Bitmap( - self._axes_line_thickness, self._usable_height, 3 + axesx_height = ( + 2 + + self._axes_line_thickness + + self._font_height + + self._tick_line_height // 2 ) - self._axesx_bitmap.fill(2) - - self._axesy_bitmap = displayio.Bitmap( - self._usable_width, self._axes_line_thickness, 3 + self._axesx_bitmap = displayio.Bitmap(self._usable_width, axesx_height, 4) + self._axesx_bitmap.fill(0) + + self._axesy_width = ( + 2 + + self._axes_line_thickness + + self._font_height + + self._tick_line_height // 2 ) - self._axesy_bitmap.fill(2) + self._axesy_bitmap = displayio.Bitmap(self._axesy_width, self._usable_height, 4) + self._axesy_bitmap.fill(0) self._screen_bitmap = displayio.Bitmap( self._usable_width, self._usable_height, 3 @@ -134,10 +148,24 @@ def __init__( self._screen_palette.make_transparent(0) self._screen_palette[1] = self._tick_color self._screen_palette[2] = self._axes_line_color - self._screen_palette[3] = 0x00FFFF + self._screen_palette[3] = 0x990099 self._screen_palette[4] = 0xFFFFFF self._screen_palette[5] = self._display_color + self._axesx_tilegrid = displayio.TileGrid( + self._axesx_bitmap, + pixel_shader=self._screen_palette, + x=self._origin_x, + y=self._origin_y + self._usable_height, + ) + + self._axesy_tilegrid = displayio.TileGrid( + self._axesy_bitmap, + pixel_shader=self._screen_palette, + x=self._origin_x - self._axesy_width, + y=self._origin_y, + ) + self._screen_tilegrid = displayio.TileGrid( self._screen_bitmap, pixel_shader=self._screen_palette, @@ -149,6 +177,8 @@ def __init__( self._draw_ticks() self._draw_pointers() self.append(self._pointer_vector_shape) + self.append(self._axesx_tilegrid) + self.append(self._axesy_tilegrid) self.append(self._screen_tilegrid) @staticmethod @@ -162,24 +192,15 @@ def _get_font_height(font, scale): return font_width, font_height def _draw_axes(self): - bitmaptools.rotozoom( - self._screen_bitmap, - ox=self._margin, - oy=self._usable_height, - source_bitmap=self._axesx_bitmap, - px=self._axesx_bitmap.width, - py=self._axesx_bitmap.height, - angle=0.0, # in radians - ) - - bitmaptools.rotozoom( - self._screen_bitmap, - ox=int(self._usable_width + self._margin), - oy=self._usable_height, - source_bitmap=self._axesy_bitmap, - px=self._axesy_bitmap.width, - py=self._axesy_bitmap.height, - angle=0.0, + y = self._tick_line_height // 2 + bitmaptools.draw_line(self._axesx_bitmap, 0, y, self._usable_width - 1, y, 3) + bitmaptools.draw_line( + self._axesy_bitmap, + self._axesy_width - 1, + 0, + self._axesy_width - 1, + self._usable_height - 1, + 3, ) def _draw_ticks(self): @@ -188,19 +209,9 @@ def _draw_ticks(self): bitmaptools.rotozoom( self._screen_bitmap, ox=i, - oy=self._usable_height, + oy=self._usable_height + self._tick_line_height // 2, source_bitmap=self._tick_bitmap, - px=int(self._tick_bitmap.width / 2), - py=self._tick_bitmap.height, - angle=0.0, # in radians - ) - else: - _blit_rotate_scale( # translate and rotate the tick into the target_bitmap - destination=self._screen_bitmap, - ox=i, - oy=0, - source=self._tick_bitmap, - px=int(self._tick_bitmap / 2), + px=int(self._tick_bitmap.width), py=self._tick_bitmap.height, angle=0.0, # in radians ) @@ -209,20 +220,10 @@ def _draw_ticks(self): if "rotozoom" in dir(bitmaptools): # if core function is available bitmaptools.rotozoom( self._screen_bitmap, - ox=self._margin, + ox=0, oy=i, source_bitmap=self._tick_bitmap, - px=int(self._tick_bitmap.width / 2), - py=int(self._tick_bitmap.height / 2), - angle=(90 * math.pi / 180), # in radians - ) - else: - _blit_rotate_scale( # translate and rotate the tick into the target_bitmap - destination=self._screen_bitmap, - ox=i, - oy=0, - source=self._tick_bitmap, - px=int(self._tick_bitmap.width / 2), + px=int(self._tick_bitmap.width), py=int(self._tick_bitmap.height / 2), angle=(90 * math.pi / 180), # in radians ) From e4aeb41fc734999be5b739a89643845ec3446e43 Mon Sep 17 00:00:00 2001 From: jposada202020 Date: Sun, 21 Mar 2021 21:46:03 -0400 Subject: [PATCH 05/36] # TODO Make axes, separate from data [X] - Import Order # TODO Replace with drawline/vectorio [ ] # TODO Make a rectangle function [ ] # TODO Include functions to equal space ticks [ ] # TODO Make labels and text [ ] # TODO Make Styles applicable [ ] # TODO Animate when overflow [ ] --- adafruit_displayio_layout/widgets/cartesian.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/adafruit_displayio_layout/widgets/cartesian.py b/adafruit_displayio_layout/widgets/cartesian.py index 6a721d6..2dd8042 100644 --- a/adafruit_displayio_layout/widgets/cartesian.py +++ b/adafruit_displayio_layout/widgets/cartesian.py @@ -28,9 +28,8 @@ import displayio import board import terminalio -from adafruit_displayio_layout.widgets.widget import Widget import vectorio - +from adafruit_displayio_layout.widgets.widget import Widget try: import bitmaptools except NameError: From 7f4e1b16a1885536f7c329aca4cc4d8ef21da1ba Mon Sep 17 00:00:00 2001 From: jposada202020 Date: Sun, 21 Mar 2021 21:51:19 -0400 Subject: [PATCH 06/36] # TODO Make axes, separate from data [X] - Black # TODO Replace with drawline/vectorio [ ] # TODO Make a rectangle function [ ] # TODO Include functions to equal space ticks [ ] # TODO Make labels and text [ ] # TODO Make Styles applicable [ ] # TODO Animate when overflow [ ] --- adafruit_displayio_layout/widgets/cartesian.py | 1 + 1 file changed, 1 insertion(+) diff --git a/adafruit_displayio_layout/widgets/cartesian.py b/adafruit_displayio_layout/widgets/cartesian.py index 2dd8042..9247b65 100644 --- a/adafruit_displayio_layout/widgets/cartesian.py +++ b/adafruit_displayio_layout/widgets/cartesian.py @@ -30,6 +30,7 @@ import terminalio import vectorio from adafruit_displayio_layout.widgets.widget import Widget + try: import bitmaptools except NameError: From 057a96c18d6cc1876c08fcb1b899d83cb5f0fac4 Mon Sep 17 00:00:00 2001 From: jposada202020 Date: Sun, 21 Mar 2021 23:19:44 -0400 Subject: [PATCH 07/36] # TODO Replace with drawline/vectorio [X] # TODO Make a rectangle function [ ] # TODO Include functions to equal space ticks [ ] # TODO Make labels and text [ ] # TODO Make Styles applicable [ ] # TODO Animate when overflow [ ] # TODO Add Subticks functionality [ ] --- .../widgets/cartesian.py | 35 +++++++------------ .../displayio_layout_cartesian_simpletest.py | 2 +- 2 files changed, 14 insertions(+), 23 deletions(-) diff --git a/adafruit_displayio_layout/widgets/cartesian.py b/adafruit_displayio_layout/widgets/cartesian.py index 9247b65..7c163b8 100644 --- a/adafruit_displayio_layout/widgets/cartesian.py +++ b/adafruit_displayio_layout/widgets/cartesian.py @@ -24,7 +24,6 @@ # pylint: disable=too-many-lines, too-many-instance-attributes, too-many-arguments # pylint: disable=too-many-locals, too-many-statements -import math import displayio import board import terminalio @@ -80,12 +79,13 @@ def __init__( **kwargs, ) -> None: # TODO Make axes, separate from data [X] - # TODO Replace with drawline/vectorio [ ] + # TODO Replace with drawline/vectorio [X] # TODO Make a rectangle function [ ] # TODO Include functions to equal space ticks [ ] # TODO Make labels and text [ ] # TODO Make Styles applicable [ ] # TODO Animate when overflow [ ] + # TODO Add Subticks functionality [ ] super().__init__(**kwargs, max_size=3) self._origin_x = x @@ -205,28 +205,19 @@ def _draw_axes(self): def _draw_ticks(self): for i in range(self._margin, self._usable_width, self._tickx_separation): - if "rotozoom" in dir(bitmaptools): # if core function is available - bitmaptools.rotozoom( - self._screen_bitmap, - ox=i, - oy=self._usable_height + self._tick_line_height // 2, - source_bitmap=self._tick_bitmap, - px=int(self._tick_bitmap.width), - py=self._tick_bitmap.height, - angle=0.0, # in radians - ) + bitmaptools.draw_line( + self._axesx_bitmap, i, self._tick_line_height // 2, i, 0, 2 + ) for i in range(self._margin, self._usable_height, self._tickx_separation): - if "rotozoom" in dir(bitmaptools): # if core function is available - bitmaptools.rotozoom( - self._screen_bitmap, - ox=0, - oy=i, - source_bitmap=self._tick_bitmap, - px=int(self._tick_bitmap.width), - py=int(self._tick_bitmap.height / 2), - angle=(90 * math.pi / 180), # in radians - ) + bitmaptools.draw_line( + self._axesy_bitmap, + (self._axesy_width - self._tick_line_height // 2) - 1, + i, + self._axesy_width - 1, + i, + 2, + ) def _draw_pointers(self): self._pointer = vectorio.Circle(3) diff --git a/examples/displayio_layout_cartesian_simpletest.py b/examples/displayio_layout_cartesian_simpletest.py index ed2212d..29323b0 100644 --- a/examples/displayio_layout_cartesian_simpletest.py +++ b/examples/displayio_layout_cartesian_simpletest.py @@ -20,7 +20,7 @@ # for display chip driver and pinout you have (e.g. ILI9341) -# Create a Dial widget +# Create a Cartesian widget my_plane = Cartesian( x=150, # x position for the plane y=100, # y plane position From 185e539dd4610b95f4f7d710dd6111b99cf30054 Mon Sep 17 00:00:00 2001 From: jposada202020 Date: Mon, 22 Mar 2021 05:49:36 -0400 Subject: [PATCH 08/36] =?UTF-8?q?#=20TODO=20Make=20a=20rectangle=20functio?= =?UTF-8?q?n=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20[=E2=88=9A]=20?= =?UTF-8?q?#=20TODO=20Include=20functions=20to=20equal=20space=20ticks=20?= =?UTF-8?q?=20=20[=20]=20#=20TODO=20Make=20labels=20and=20text=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20[=20]=20#=20?= =?UTF-8?q?TODO=20Make=20Styles=20applicable=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20[=20]=20#=20TODO=20Animate=20when=20?= =?UTF-8?q?overflow=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20[=20]=20#=20TODO=20Add=20Subticks=20functionality=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20[=20]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- adafruit_displayio_layout/widgets/__init__.py | 67 +++++++++++++++++++ .../widgets/cartesian.py | 7 +- 2 files changed, 71 insertions(+), 3 deletions(-) diff --git a/adafruit_displayio_layout/widgets/__init__.py b/adafruit_displayio_layout/widgets/__init__.py index e69de29..80825ac 100644 --- a/adafruit_displayio_layout/widgets/__init__.py +++ b/adafruit_displayio_layout/widgets/__init__.py @@ -0,0 +1,67 @@ +# SPDX-FileCopyrightText: 2021 Kevin Matocha, Tim C, Jose David M +# +# SPDX-License-Identifier: MIT + +""" +`adafruit_displayio_layout.widgets` +======================= +""" + +import vectorio + +try: + import bitmaptools +except NameError: + pass + + +# pylint: disable=invalid-name, too-many-arguments +def rectangle_helper( + x0: int, + y0: int, + height: int, + width: int, + bitmap, + color_index: int, + palette, + bitmaptool: bool = True, +) -> None: + """rectangle_helper function + Draws a rectangle to the bitmap given using ``bitmapstools.bitmap`` or + ``vectorio.rectangle`` functions + + :param int x0: rectangle lower corner x position + :param int y0: rectangle lower corner y position + + :param int width: rectangle upper corner x position + :param int height: rectangle upper corner y position + + :param int color_index: palette color index to be used + :param palette: palette object to be used to draw the rectangle + + :param bitmap: bitmap for the rectangle to be drawn + :param bool bitmaptool: uses :py:func:`~bitmaptools.draw_line` to draw the rectanlge. + when `False` uses :py:func:`~vectorio.Rectangle` + + :return: None + :rtype: None + + ┌───────────────────────┐ + │ │ + │ │ + (x0,y0) └───────────────────────┘ + + """ + if bitmaptool: + x1 = x0 + width + y1 = y0 + height + for row_pos in range(y0, y1, 1): + bitmaptools.draw_line(bitmap, x0, row_pos, x1, row_pos, color_index) + else: + rect = vectorio.Rectangle(width, height) + vectorio.VectorShape( + shape=rect, + pixel_shader=palette, + x=x0, + y=y0, + ) diff --git a/adafruit_displayio_layout/widgets/cartesian.py b/adafruit_displayio_layout/widgets/cartesian.py index 7c163b8..7183e1e 100644 --- a/adafruit_displayio_layout/widgets/cartesian.py +++ b/adafruit_displayio_layout/widgets/cartesian.py @@ -78,14 +78,15 @@ def __init__( pointer_color: int = 0xFFFFFF, **kwargs, ) -> None: - # TODO Make axes, separate from data [X] - # TODO Replace with drawline/vectorio [X] - # TODO Make a rectangle function [ ] + # TODO Make axes, separate from data [√] + # TODO Replace with drawline/vectorio [√] + # TODO Make a rectangle function [√] # TODO Include functions to equal space ticks [ ] # TODO Make labels and text [ ] # TODO Make Styles applicable [ ] # TODO Animate when overflow [ ] # TODO Add Subticks functionality [ ] + # TODO ticks evenly distributed [ ] super().__init__(**kwargs, max_size=3) self._origin_x = x From 2c1a3071161c41fcda0c69287ab4dd0396805061 Mon Sep 17 00:00:00 2001 From: jposada202020 Date: Mon, 22 Mar 2021 06:06:54 -0400 Subject: [PATCH 09/36] =?UTF-8?q?#=20TODO=20Make=20a=20rectangle=20functio?= =?UTF-8?q?n=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20[=E2=88=9A]=20?= =?UTF-8?q?-=20API=20Docs=20#=20TODO=20Include=20functions=20to=20equal=20?= =?UTF-8?q?space=20ticks=20=20=20[=20]=20#=20TODO=20Make=20labels=20and=20?= =?UTF-8?q?text=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20[=20]=20#=20TODO=20Make=20Styles=20applicable=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20[=20]=20#=20TODO?= =?UTF-8?q?=20Animate=20when=20overflow=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20[=20]=20#=20TODO=20Add=20Subticks=20?= =?UTF-8?q?functionality=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20[=20]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/api.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/api.rst b/docs/api.rst index 8f3cdae..8410864 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -33,3 +33,10 @@ .. automodule:: adafruit_displayio_layout.widgets.icon_widget :members: :member-order: bysource + +.. automodule:: adafruit_displayio_layout.widgets.cartesian + :members: + :member-order: bysource + :inherited-members: + +.. inheritance-diagram:: adafruit_displayio_layout.widgets.cartesian \ No newline at end of file From 5cecb031f18410ef5e0476c5eff535a597e57c54 Mon Sep 17 00:00:00 2001 From: jposada202020 Date: Mon, 22 Mar 2021 06:14:01 -0400 Subject: [PATCH 10/36] =?UTF-8?q?#=20TODO=20Make=20a=20rectangle=20functio?= =?UTF-8?q?n=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20[=E2=88=9A]=20?= =?UTF-8?q?-=20API=20Docs=20-=20End=20of=20line=20space=20#=20TODO=20Inclu?= =?UTF-8?q?de=20functions=20to=20equal=20space=20ticks=20=20=20[=20]=20#?= =?UTF-8?q?=20TODO=20Make=20labels=20and=20text=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20[=20]=20#=20TODO=20Make=20S?= =?UTF-8?q?tyles=20applicable=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20[=20]=20#=20TODO=20Animate=20when=20overflow=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20[=20]=20#?= =?UTF-8?q?=20TODO=20Add=20Subticks=20functionality=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20[=20]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/api.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api.rst b/docs/api.rst index 8410864..bacd0c2 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -39,4 +39,4 @@ :member-order: bysource :inherited-members: -.. inheritance-diagram:: adafruit_displayio_layout.widgets.cartesian \ No newline at end of file +.. inheritance-diagram:: adafruit_displayio_layout.widgets.cartesian From b129077b868161df56dd5cd13d82dad23e2c850f Mon Sep 17 00:00:00 2001 From: jposada202020 Date: Mon, 22 Mar 2021 06:24:48 -0400 Subject: [PATCH 11/36] =?UTF-8?q?#=20TODO=20Make=20a=20rectangle=20functio?= =?UTF-8?q?n=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20[=E2=88=9A]=20?= =?UTF-8?q?-=20board.Display=20reference=20#=20TODO=20Include=20functions?= =?UTF-8?q?=20to=20equal=20space=20ticks=20=20=20[=20]=20#=20TODO=20Make?= =?UTF-8?q?=20labels=20and=20text=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20[=20]=20#=20TODO=20Make=20Styles=20appl?= =?UTF-8?q?icable=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?[=20]=20#=20TODO=20Animate=20when=20overflow=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20[=20]=20#=20TODO=20Ad?= =?UTF-8?q?d=20Subticks=20functionality=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20[=20]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- adafruit_displayio_layout/widgets/cartesian.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/adafruit_displayio_layout/widgets/cartesian.py b/adafruit_displayio_layout/widgets/cartesian.py index 7183e1e..64c94c0 100644 --- a/adafruit_displayio_layout/widgets/cartesian.py +++ b/adafruit_displayio_layout/widgets/cartesian.py @@ -25,7 +25,6 @@ # pylint: disable=too-many-locals, too-many-statements import displayio -import board import terminalio import vectorio from adafruit_displayio_layout.widgets.widget import Widget @@ -43,8 +42,8 @@ class Cartesian(Widget): :param int y: y position of the plane origin :param int display_color: background color to use defaults to black (0x000000) - :param int width: requested width, in pixels defaults to screen width - :param int height: requested height, in pixels defaults to screen height + :param int width: requested width, in pixels defaults to 100 pixels + :param int height: requested height, in pixels defaults to 100 pixels :param int axes_color: axes lines color defaults to white (0xFFFFFF) :param int axes_stroke: axes lines thickness in pixels defaults to 2 @@ -63,10 +62,10 @@ class Cartesian(Widget): def __init__( self, x: int = 10, - y: int = board.DISPLAY.height - 10, + y: int = 10, display_color=0x000000, - width: int = board.DISPLAY.width, - height: int = board.DISPLAY.height, + width: int = 100, + height: int = 100, axes_color: int = 0xFFFFFF, axes_stroke: int = 2, tick_color: int = 0xFFFFFF, From a36b27ce2ad0166e080211a0a59d1c104f19d257 Mon Sep 17 00:00:00 2001 From: jposada202020 Date: Mon, 22 Mar 2021 11:46:13 -0400 Subject: [PATCH 12/36] =?UTF-8?q?#=20TODO=20Include=20functions=20to=20equ?= =?UTF-8?q?al=20space=20ticks=20=20=20[=E2=88=9A]=20#=20TODO=20Make=20labe?= =?UTF-8?q?ls=20and=20text=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20[=20]=20#=20TODO=20Make=20Styles=20applicable=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20[=20]=20#?= =?UTF-8?q?=20TODO=20Animate=20when=20overflow=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20[=20]=20#=20TODO=20Add=20Subti?= =?UTF-8?q?cks=20functionality=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20[=20]=20#=20TODO=20ticks=20evenly=20distributed=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20[=E2=88=9A]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../widgets/cartesian.py | 85 +++++++++++++++---- docs/examples.rst | 9 ++ 2 files changed, 79 insertions(+), 15 deletions(-) diff --git a/adafruit_displayio_layout/widgets/cartesian.py b/adafruit_displayio_layout/widgets/cartesian.py index 64c94c0..8c722b5 100644 --- a/adafruit_displayio_layout/widgets/cartesian.py +++ b/adafruit_displayio_layout/widgets/cartesian.py @@ -33,6 +33,10 @@ import bitmaptools except NameError: pass # utilize the blit_rotate_scale function defined herein +try: + from typing import Tuple +except ImportError: + pass class Cartesian(Widget): @@ -45,6 +49,9 @@ class Cartesian(Widget): :param int width: requested width, in pixels defaults to 100 pixels :param int height: requested height, in pixels defaults to 100 pixels + :param (int, int) axesx_range: X axes range + :param (int, int) axesy_range: Y axes range + :param int axes_color: axes lines color defaults to white (0xFFFFFF) :param int axes_stroke: axes lines thickness in pixels defaults to 2 @@ -57,6 +64,43 @@ class Cartesian(Widget): :param int pointer_radius: pointer radius in pixels defaults to 1 :param int pointer_color: pointer color defaults to white (0xFFFFFF) + **Quickstart: Importing and using Cartesian** + + Here is one way of importing the `Cartesian` class so you can use it as + the name ``Plane``: + + .. code-block:: python + + from adafruit_displayio_layout.widgets.cartesian import Cartesian as Plane + + Now you can create a plane at pixel position x=20, y=30 using: + + .. code-block:: python + + my_plane=Plane(x=20, y=30) # instance the switch at x=20, y=30 + + Once you setup your display, you can now add ``my_plane`` to your display using: + + .. code-block:: python + + display.show(my_plane) # add the group to the display + + If you want to have multiple display elements, you can create a group and then + append the switch and the other elements to the group. Then, you can add the full + group to the display as in this example: + + .. code-block:: python + + my_plane= Plane(20, 30) # instance the plane at x=20, y=30 + my_group = displayio.Group(max_size=10) # make a group that can hold 10 items + my_group.append(my_plane) # Add my_plane to the group + + # + # Append other display elements to the group + # + + display.show(my_group) # add the group to the display + """ def __init__( @@ -66,6 +110,8 @@ def __init__( display_color=0x000000, width: int = 100, height: int = 100, + xrange: Tuple[int, int] = (0, 100), + yrange: Tuple[int, int] = (0, 100), axes_color: int = 0xFFFFFF, axes_stroke: int = 2, tick_color: int = 0xFFFFFF, @@ -80,12 +126,12 @@ def __init__( # TODO Make axes, separate from data [√] # TODO Replace with drawline/vectorio [√] # TODO Make a rectangle function [√] - # TODO Include functions to equal space ticks [ ] + # TODO Include functions to equal space ticks [√] # TODO Make labels and text [ ] # TODO Make Styles applicable [ ] # TODO Animate when overflow [ ] # TODO Add Subticks functionality [ ] - # TODO ticks evenly distributed [ ] + # TODO ticks evenly distributed [√] super().__init__(**kwargs, max_size=3) self._origin_x = x @@ -113,9 +159,11 @@ def __init__( self._font_width = self._get_font_height(self._font, 1)[0] self._font_height = self._get_font_height(self._font, 1)[1] - self._usable_width = self._widget_width - 2 * self._margin - self._usable_height = self._widget_height - 2 * self._margin - self._tickx_separation = 2 * self._font_width + 2 + self._usable_width = self._widget_width + self._usable_height = self._widget_height + + self._tickx_separation = int(xrange[1] / self._usable_width * 10) + self._ticky_separation = int(yrange[1] / self._usable_height * 10) self._tick_bitmap = displayio.Bitmap( self._tick_line_thickness, self._tick_line_height, 3 @@ -134,7 +182,7 @@ def __init__( self._axesy_width = ( 2 + self._axes_line_thickness - + self._font_height + + self._font_width + self._tick_line_height // 2 ) self._axesy_bitmap = displayio.Bitmap(self._axesy_width, self._usable_height, 4) @@ -143,7 +191,7 @@ def __init__( self._screen_bitmap = displayio.Bitmap( self._usable_width, self._usable_height, 3 ) - + self._screen_bitmap.fill(0) self._screen_palette = displayio.Palette(6) self._screen_palette.make_transparent(0) self._screen_palette[1] = self._tick_color @@ -192,27 +240,34 @@ def _get_font_height(font, scale): return font_width, font_height def _draw_axes(self): - y = self._tick_line_height // 2 - bitmaptools.draw_line(self._axesx_bitmap, 0, y, self._usable_width - 1, y, 3) + # Draw x axes line + bitmaptools.draw_line(self._axesx_bitmap, 0, 0, self._usable_width - 1, 0, 2) + # Draw y axes line bitmaptools.draw_line( self._axesy_bitmap, self._axesy_width - 1, 0, self._axesy_width - 1, self._usable_height - 1, - 3, + 2, ) def _draw_ticks(self): - for i in range(self._margin, self._usable_width, self._tickx_separation): + # X axes ticks + + for i in range( + self._tickx_separation, self._usable_width, self._tickx_separation + ): bitmaptools.draw_line( - self._axesx_bitmap, i, self._tick_line_height // 2, i, 0, 2 + self._axesx_bitmap, i, self._tick_line_height, i, 0, 2 ) - - for i in range(self._margin, self._usable_height, self._tickx_separation): + # Y axes ticks + for i in range( + self._usable_height - 1 - self._ticky_separation, 0, -self._ticky_separation + ): bitmaptools.draw_line( self._axesy_bitmap, - (self._axesy_width - self._tick_line_height // 2) - 1, + (self._axesy_width - self._tick_line_height) - 1, i, self._axesy_width - 1, i, diff --git a/docs/examples.rst b/docs/examples.rst index bedc2c9..0c59f04 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -24,3 +24,12 @@ Create multiple sliding switch with various sizes and orientations. .. literalinclude:: ../examples/displayio_layout_switch_multiple.py :caption: examples/displayio_layout_switch_multiple.py :linenos: + +Cartesian plane simple test +--------------------------- + +Create a simple plot plane. + +.. literalinclude:: ../examples/displayio_layout_cartesian_simpletest.py + :caption: examples/displayio_layout_cartesian_simpletest.py + :linenos: From 5af4bf21e44fa0c8ac8301ec463d72429f8b7d18 Mon Sep 17 00:00:00 2001 From: jposada202020 Date: Mon, 22 Mar 2021 19:29:28 -0400 Subject: [PATCH 13/36] =?UTF-8?q?#=20TODO=20Make=20labels=20and=20text=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20[?= =?UTF-8?q?=E2=88=9A]=20#=20TODO=20Make=20Styles=20applicable=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20[=20]=20#=20TODO?= =?UTF-8?q?=20Animate=20when=20overflow=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20[=20]=20#=20TODO=20Add=20Subticks=20?= =?UTF-8?q?functionality=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20[=20]?= =?UTF-8?q?=20#=20TODO=20Updater=20to=20use=20local=20coordinates=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20[=20]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../widgets/cartesian.py | 114 ++++++++++++++---- .../displayio_layout_cartesian_simpletest.py | 6 +- 2 files changed, 97 insertions(+), 23 deletions(-) diff --git a/adafruit_displayio_layout/widgets/cartesian.py b/adafruit_displayio_layout/widgets/cartesian.py index 8c722b5..4778b42 100644 --- a/adafruit_displayio_layout/widgets/cartesian.py +++ b/adafruit_displayio_layout/widgets/cartesian.py @@ -1,11 +1,11 @@ -# SPDX-FileCopyrightText: 2021 Jose David Montoya +# SPDX-FileCopyrightText: 2021 Jose David M. # # SPDX-License-Identifier: MIT """ `cartesian` ================================================================================ -A cartasian plane widget for displaying graphical information. +A cartesian plane widget for displaying graphical information. * Author(s): Jose David Montoya @@ -28,6 +28,8 @@ import terminalio import vectorio from adafruit_displayio_layout.widgets.widget import Widget +from adafruit_displayio_layout.widgets import rectangle_helper +from adafruit_display_text import bitmap_label try: import bitmaptools @@ -56,7 +58,8 @@ class Cartesian(Widget): :param int axes_stroke: axes lines thickness in pixels defaults to 2 :param int major_tick_stroke: tick lines thickness in pixels dafaults to 1 - :param int major_tick_lenght: tick lines lenght in pixels defaults to 5 + :param int major_tick_length: tick lines length in pixels defaults to 5 + :param List[str] tick_labels: a list of strings for the tick text labels :param int tick_label_font: tick label text font :param int tick_label_color: tick label text color @@ -77,7 +80,7 @@ class Cartesian(Widget): .. code-block:: python - my_plane=Plane(x=20, y=30) # instance the switch at x=20, y=30 + my_plane=Plane(x=20, y=30) # instance the plane at x=20, y=30 Once you setup your display, you can now add ``my_plane`` to your display using: @@ -86,7 +89,7 @@ class Cartesian(Widget): display.show(my_plane) # add the group to the display If you want to have multiple display elements, you can create a group and then - append the switch and the other elements to the group. Then, you can add the full + append the plane and the other elements to the group. Then, you can add the full group to the display as in this example: .. code-block:: python @@ -113,7 +116,7 @@ def __init__( xrange: Tuple[int, int] = (0, 100), yrange: Tuple[int, int] = (0, 100), axes_color: int = 0xFFFFFF, - axes_stroke: int = 2, + axes_stroke: int = 1, tick_color: int = 0xFFFFFF, major_tick_stroke: int = 1, major_tick_length: int = 5, @@ -127,11 +130,13 @@ def __init__( # TODO Replace with drawline/vectorio [√] # TODO Make a rectangle function [√] # TODO Include functions to equal space ticks [√] - # TODO Make labels and text [ ] + # TODO Make labels and text [√] # TODO Make Styles applicable [ ] # TODO Animate when overflow [ ] # TODO Add Subticks functionality [ ] # TODO ticks evenly distributed [√] + # TODO Make Ticker lines [√] + # TODO Updater to use local coordinates [ ] super().__init__(**kwargs, max_size=3) self._origin_x = x @@ -162,8 +167,8 @@ def __init__( self._usable_width = self._widget_width self._usable_height = self._widget_height - self._tickx_separation = int(xrange[1] / self._usable_width * 10) - self._ticky_separation = int(yrange[1] / self._usable_height * 10) + self._tickx_separation = int(xrange[1] / self._usable_width * 10) + 3 + self._ticky_separation = int(yrange[1] / self._usable_height * 10) + 3 self._tick_bitmap = displayio.Bitmap( self._tick_line_thickness, self._tick_line_height, 3 @@ -237,34 +242,100 @@ def _get_font_height(font, scale): elif hasattr(font, "ascent"): font_height = int(scale * font.ascent + font.ascent) font_width = 12 + else: + font_height = 12 + font_width = 12 return font_width, font_height def _draw_axes(self): # Draw x axes line - bitmaptools.draw_line(self._axesx_bitmap, 0, 0, self._usable_width - 1, 0, 2) - # Draw y axes line - bitmaptools.draw_line( - self._axesy_bitmap, - self._axesy_width - 1, - 0, - self._axesy_width - 1, - self._usable_height - 1, - 2, - ) + if self._axes_line_thickness == 1: + bitmaptools.draw_line( + self._axesx_bitmap, 0, 0, self._usable_width - 1, 0, 2 + ) + # Draw y axes line + bitmaptools.draw_line( + self._axesy_bitmap, + self._axesy_width - 1, + 0, + self._axesy_width - 1, + self._usable_height - 1, + 2, + ) + else: + rectangle_helper( + 0, + 0, + self._axes_line_thickness, + self._axesx_bitmap.width - 1, + self._axesx_bitmap, + 2, + self._screen_palette, + True, + ) + rectangle_helper( + self._axesy_width - self._axes_line_thickness - 1, + 0, + self._axesy_bitmap.height, + self._axes_line_thickness, + self._axesy_bitmap, + 2, + self._screen_palette, + True, + ) def _draw_ticks(self): # X axes ticks - + tickcounter = 1 for i in range( self._tickx_separation, self._usable_width, self._tickx_separation ): + if tickcounter == 3: + tickcounter = 0 + shift_label_x = len(str(i)) * self._font_width + tick_text = bitmap_label.Label( + self._font, + text=str(i), + x=self._origin_x + (i - shift_label_x // 2), + y=self._origin_y + + self._usable_height + + self._axes_line_thickness + + self._tick_line_height + + self._font_height // 2 + + 1, + ) + self.append(tick_text) + bitmaptools.draw_line( - self._axesx_bitmap, i, self._tick_line_height, i, 0, 2 + self._axesx_bitmap, + i, + self._tick_line_height + self._axes_line_thickness, + i, + 0, + 2, ) + tickcounter = tickcounter + 1 + # Y axes ticks + tickcounter = 0 for i in range( self._usable_height - 1 - self._ticky_separation, 0, -self._ticky_separation ): + if tickcounter == 2: + tickcounter = 0 + shift_label_x = len(str(self._usable_height - i)) * self._font_width + tick_text = bitmap_label.Label( + self._font, + text=str(self._usable_height - i), + x=self._origin_x + - shift_label_x + - self._axes_line_thickness + - self._tick_line_height + - 2, + y=self._origin_y + i + self._font_height, + ) + self.append(tick_text) + bitmaptools.draw_line( self._axesy_bitmap, (self._axesy_width - self._tick_line_height) - 1, @@ -273,6 +344,7 @@ def _draw_ticks(self): i, 2, ) + tickcounter = tickcounter + 1 def _draw_pointers(self): self._pointer = vectorio.Circle(3) diff --git a/examples/displayio_layout_cartesian_simpletest.py b/examples/displayio_layout_cartesian_simpletest.py index 29323b0..0b54473 100644 --- a/examples/displayio_layout_cartesian_simpletest.py +++ b/examples/displayio_layout_cartesian_simpletest.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2021 Jose David Montoya +# SPDX-FileCopyrightText: 2021 Jose David M. # # SPDX-License-Identifier: MIT ############################# @@ -40,9 +40,11 @@ display.show(my_group) # add high level Group to the display posx = 0 -posy = 0 +posy = 100 while True: my_plane.update_pointer(posx, posy) display.show(my_group) time.sleep(0.5) + posx = posx + 2 + posy = posy - 2 From 66c7fcf7c5394db31b85a4b8e3b1bd7ce89ab426 Mon Sep 17 00:00:00 2001 From: jposada202020 Date: Mon, 22 Mar 2021 19:36:36 -0400 Subject: [PATCH 14/36] =?UTF-8?q?#=20TODO=20Make=20labels=20and=20text=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20[?= =?UTF-8?q?=E2=88=9A]=20-=20import=20order=20#=20TODO=20Make=20Styles=20ap?= =?UTF-8?q?plicable=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20[=20]=20#=20TODO=20Animate=20when=20overflow=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20[=20]=20#=20TODO?= =?UTF-8?q?=20Add=20Subticks=20functionality=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20[=20]=20#=20TODO=20Updater=20to=20use=20local=20?= =?UTF-8?q?coordinates=20=20=20=20=20=20=20=20=20[=20]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- adafruit_displayio_layout/widgets/cartesian.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adafruit_displayio_layout/widgets/cartesian.py b/adafruit_displayio_layout/widgets/cartesian.py index 4778b42..97972f5 100644 --- a/adafruit_displayio_layout/widgets/cartesian.py +++ b/adafruit_displayio_layout/widgets/cartesian.py @@ -27,9 +27,9 @@ import displayio import terminalio import vectorio +from adafruit_display_text import bitmap_label from adafruit_displayio_layout.widgets.widget import Widget from adafruit_displayio_layout.widgets import rectangle_helper -from adafruit_display_text import bitmap_label try: import bitmaptools From 57dd04d17eb2253732ffe0e815a84fc9898929dc Mon Sep 17 00:00:00 2001 From: jposada202020 Date: Mon, 22 Mar 2021 22:12:50 -0400 Subject: [PATCH 15/36] =?UTF-8?q?#=20TODO=20Make=20Styles=20applicable=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20[?= =?UTF-8?q?=E2=88=9A]=20#=20TODO=20Animate=20when=20overflow=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20[=20]=20#=20TOD?= =?UTF-8?q?O=20Add=20Subticks=20functionality=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20[=E2=88=9A]=20#=20TODO=20Updater=20to=20use?= =?UTF-8?q?=20local=20coordinates=20=20=20=20=20=20=20=20=20[=E2=88=9A]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../widgets/cartesian.py | 99 ++++++++++++++----- 1 file changed, 72 insertions(+), 27 deletions(-) diff --git a/adafruit_displayio_layout/widgets/cartesian.py b/adafruit_displayio_layout/widgets/cartesian.py index 97972f5..9e8f615 100644 --- a/adafruit_displayio_layout/widgets/cartesian.py +++ b/adafruit_displayio_layout/widgets/cartesian.py @@ -62,7 +62,7 @@ class Cartesian(Widget): :param List[str] tick_labels: a list of strings for the tick text labels :param int tick_label_font: tick label text font - :param int tick_label_color: tick label text color + :param int font_color: font color :param int pointer_radius: pointer radius in pixels defaults to 1 :param int pointer_color: pointer color defaults to white (0xFFFFFF) @@ -121,9 +121,10 @@ def __init__( major_tick_stroke: int = 1, major_tick_length: int = 5, tick_label_font=terminalio.FONT, - tick_label_color: int = 0xFFFFFF, + font_color: int = 0xFFFFFF, pointer_radius: int = 1, pointer_color: int = 0xFFFFFF, + subticks: bool = False, **kwargs, ) -> None: # TODO Make axes, separate from data [√] @@ -159,7 +160,7 @@ def __init__( self._pointer_color = pointer_color self._font = tick_label_font - self._font_color = tick_label_color + self._font_color = font_color self._font_width = self._get_font_height(self._font, 1)[0] self._font_height = self._get_font_height(self._font, 1)[1] @@ -175,6 +176,8 @@ def __init__( ) self._tick_bitmap.fill(1) + self._subticks = subticks + axesx_height = ( 2 + self._axes_line_thickness @@ -290,11 +293,23 @@ def _draw_ticks(self): for i in range( self._tickx_separation, self._usable_width, self._tickx_separation ): - if tickcounter == 3: + if self._subticks: + if tickcounter == 3: + bitmaptools.draw_line( + self._axesx_bitmap, + i, + self._tick_line_height // 2 + self._axes_line_thickness, + i, + self._axes_line_thickness, + 1, + ) + + if tickcounter == 5: tickcounter = 0 shift_label_x = len(str(i)) * self._font_width tick_text = bitmap_label.Label( self._font, + color=self._font_color, text=str(i), x=self._origin_x + (i - shift_label_x // 2), y=self._origin_y @@ -306,26 +321,38 @@ def _draw_ticks(self): ) self.append(tick_text) - bitmaptools.draw_line( - self._axesx_bitmap, - i, - self._tick_line_height + self._axes_line_thickness, - i, - 0, - 2, - ) + bitmaptools.draw_line( + self._axesx_bitmap, + i, + self._tick_line_height + self._axes_line_thickness, + i, + self._axes_line_thickness, + 1, + ) tickcounter = tickcounter + 1 # Y axes ticks - tickcounter = 0 + tickcounter = 1 for i in range( self._usable_height - 1 - self._ticky_separation, 0, -self._ticky_separation ): - if tickcounter == 2: + if self._subticks: + if tickcounter == 3: + bitmaptools.draw_line( + self._axesy_bitmap, + (self._axesy_width - self._tick_line_height // 2) - 1, + i, + self._axesy_width - 1, + i, + 1, + ) + + if tickcounter == 5: tickcounter = 0 shift_label_x = len(str(self._usable_height - i)) * self._font_width tick_text = bitmap_label.Label( self._font, + color=self._font_color, text=str(self._usable_height - i), x=self._origin_x - shift_label_x @@ -336,14 +363,14 @@ def _draw_ticks(self): ) self.append(tick_text) - bitmaptools.draw_line( - self._axesy_bitmap, - (self._axesy_width - self._tick_line_height) - 1, - i, - self._axesy_width - 1, - i, - 2, - ) + bitmaptools.draw_line( + self._axesy_bitmap, + (self._axesy_width - self._tick_line_height) - 1, + i, + self._axesy_width - 1, + i, + 1, + ) tickcounter = tickcounter + 1 def _draw_pointers(self): @@ -351,7 +378,7 @@ def _draw_pointers(self): self._circle_palette = displayio.Palette(2) self._circle_palette.make_transparent(0) - self._circle_palette[1] = 0xFFFFFF + self._circle_palette[1] = self._pointer_color self._pointer_vector_shape = vectorio.VectorShape( shape=self._pointer, @@ -363,10 +390,28 @@ def _draw_pointers(self): def update_pointer(self, x: int, y: int): """updater_pointer function helper function to update pointer in the plane - :param x: x coordinate in the local plane - :param y: y coordinate in the local plane + :param int x: x coordinate in the local plane + :param int y: y coordinate in the local plane :return: None rtype: None """ - self._pointer_vector_shape.x = self._origin_x + x + self._margin - self._pointer_vector_shape.y = self._origin_y + self._usable_height + y + local_x = self._origin_x + x + local_y = self._origin_y + self._usable_height - y + self._pointer_vector_shape.x = local_x + self._pointer_vector_shape.y = local_y + + def set_widget_style(self, new_style: str) -> None: + """set_widget_style function + Allows to set the widget style + :param str new_style: style for the widget + :return: None + """ + # import would change after library packaging + # pylint: disable=import-outside-toplevel + from adafruit_styles import get_hex + from adafruit_styles import styles + + colorset = styles.THEME + self._pointer_color = get_hex(colorset[new_style]["TEXT"]) + self._font_color = get_hex(colorset[new_style]["TEXT"]) + self._draw_ticks() From 0e39c397e2e3b6d8123f2b9c924fe1be5bfda381 Mon Sep 17 00:00:00 2001 From: jposada202020 Date: Tue, 23 Mar 2021 05:54:25 -0400 Subject: [PATCH 16/36] =?UTF-8?q?#=20UPDATE=20Ticks/Subticks=20Logic-Advan?= =?UTF-8?q?ced=20Example=20=20[=E2=88=9A]=20#=20TODO=20Animate=20when=20ov?= =?UTF-8?q?erflow=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20[=20]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../widgets/cartesian.py | 114 +++++++++--------- docs/examples.rst | 9 ++ ...isplayio_layout_cartesian_advanced_test.py | 75 ++++++++++++ .../displayio_layout_cartesian_simpletest.py | 6 +- 4 files changed, 143 insertions(+), 61 deletions(-) create mode 100644 examples/displayio_layout_cartesian_advanced_test.py diff --git a/adafruit_displayio_layout/widgets/cartesian.py b/adafruit_displayio_layout/widgets/cartesian.py index 9e8f615..52a7006 100644 --- a/adafruit_displayio_layout/widgets/cartesian.py +++ b/adafruit_displayio_layout/widgets/cartesian.py @@ -7,7 +7,7 @@ ================================================================================ A cartesian plane widget for displaying graphical information. -* Author(s): Jose David Montoya +* Author(s): Jose David M. Implementation Notes -------------------- @@ -34,7 +34,7 @@ try: import bitmaptools except NameError: - pass # utilize the blit_rotate_scale function defined herein + pass try: from typing import Tuple except ImportError: @@ -132,12 +132,12 @@ def __init__( # TODO Make a rectangle function [√] # TODO Include functions to equal space ticks [√] # TODO Make labels and text [√] - # TODO Make Styles applicable [ ] + # TODO Make Styles applicable [√] # TODO Animate when overflow [ ] - # TODO Add Subticks functionality [ ] + # TODO Add Subticks functionality [√] # TODO ticks evenly distributed [√] # TODO Make Ticker lines [√] - # TODO Updater to use local coordinates [ ] + # TODO Updater to use local coordinates [√] super().__init__(**kwargs, max_size=3) self._origin_x = x @@ -146,8 +146,9 @@ def __init__( self._margin = 10 self._display_color = display_color - self._widget_width = width - self._widget_height = height + + self._usable_width = width + self._usable_height = height self._axes_line_color = axes_color self._axes_line_thickness = axes_stroke @@ -165,11 +166,10 @@ def __init__( self._font_width = self._get_font_height(self._font, 1)[0] self._font_height = self._get_font_height(self._font, 1)[1] - self._usable_width = self._widget_width - self._usable_height = self._widget_height - - self._tickx_separation = int(xrange[1] / self._usable_width * 10) + 3 - self._ticky_separation = int(yrange[1] / self._usable_height * 10) + 3 + self._normx = xrange[1] / 100 + self._valuex = self._usable_width / 100 + self._normy = yrange[1] / 100 + self._valuey = self._usable_height / 100 self._tick_bitmap = displayio.Bitmap( self._tick_line_thickness, self._tick_line_height, 3 @@ -288,30 +288,20 @@ def _draw_axes(self): ) def _draw_ticks(self): + # ticks definition + ticks = [10, 30, 50, 70, 90] + subticks = [20, 40, 60, 80, 100] # X axes ticks - tickcounter = 1 - for i in range( - self._tickx_separation, self._usable_width, self._tickx_separation - ): - if self._subticks: - if tickcounter == 3: - bitmaptools.draw_line( - self._axesx_bitmap, - i, - self._tick_line_height // 2 + self._axes_line_thickness, - i, - self._axes_line_thickness, - 1, - ) - - if tickcounter == 5: - tickcounter = 0 - shift_label_x = len(str(i)) * self._font_width + for i in range(10, 100, 10): + text_tick = str(round(i * self._normx)) + text_dist = int(self._valuex * i) + if i in ticks: + shift_label_x = len(text_tick) * self._font_width tick_text = bitmap_label.Label( self._font, color=self._font_color, - text=str(i), - x=self._origin_x + (i - shift_label_x // 2), + text=text_tick, + x=self._origin_x + text_dist - (shift_label_x // 2), y=self._origin_y + self._usable_height + self._axes_line_thickness @@ -320,58 +310,66 @@ def _draw_ticks(self): + 1, ) self.append(tick_text) - bitmaptools.draw_line( self._axesx_bitmap, - i, + text_dist, self._tick_line_height + self._axes_line_thickness, - i, + text_dist, self._axes_line_thickness, 1, ) - tickcounter = tickcounter + 1 - - # Y axes ticks - tickcounter = 1 - for i in range( - self._usable_height - 1 - self._ticky_separation, 0, -self._ticky_separation - ): if self._subticks: - if tickcounter == 3: + if i in subticks: bitmaptools.draw_line( - self._axesy_bitmap, - (self._axesy_width - self._tick_line_height // 2) - 1, - i, - self._axesy_width - 1, - i, + self._axesx_bitmap, + text_dist, + self._tick_line_height // 2 + self._axes_line_thickness, + text_dist, + self._axes_line_thickness, 1, ) - if tickcounter == 5: - tickcounter = 0 - shift_label_x = len(str(self._usable_height - i)) * self._font_width + # Y axes ticks + for i in range(10, 100, 10): + text_tick = str(round(i * self._normy)) + text_dist = int(self._valuey * i) + if i in ticks: + shift_label_x = len(text_tick) * self._font_width tick_text = bitmap_label.Label( self._font, color=self._font_color, - text=str(self._usable_height - i), + text=text_tick, x=self._origin_x - shift_label_x - self._axes_line_thickness - self._tick_line_height - 2, - y=self._origin_y + i + self._font_height, + y=self._origin_y + self._usable_height - text_dist, ) self.append(tick_text) bitmaptools.draw_line( self._axesy_bitmap, - (self._axesy_width - self._tick_line_height) - 1, - i, - self._axesy_width - 1, - i, + self._axesy_width + - self._axes_line_thickness + - self._tick_line_height + - 1, + text_dist, + self._axesy_width - 1 - self._axes_line_thickness, + text_dist, 1, ) - tickcounter = tickcounter + 1 + + if self._subticks: + if i in subticks: + bitmaptools.draw_line( + self._axesy_bitmap, + self._axesy_width - 1 - self._tick_line_height // 2, + text_dist, + self._axesy_width - 1, + text_dist, + 1, + ) def _draw_pointers(self): self._pointer = vectorio.Circle(3) diff --git a/docs/examples.rst b/docs/examples.rst index 0c59f04..404ebb2 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -33,3 +33,12 @@ Create a simple plot plane. .. literalinclude:: ../examples/displayio_layout_cartesian_simpletest.py :caption: examples/displayio_layout_cartesian_simpletest.py :linenos: + +Cartesian plane advanced test +----------------------------- + +Create different cartesian planes in the scree + +.. literalinclude:: ../examples/displayio_layout_cartesian_advanced_test.py + :caption: examples/displayio_layout_cartesian_advanced_test.py + :linenos: diff --git a/examples/displayio_layout_cartesian_advanced_test.py b/examples/displayio_layout_cartesian_advanced_test.py new file mode 100644 index 0000000..10bd6a0 --- /dev/null +++ b/examples/displayio_layout_cartesian_advanced_test.py @@ -0,0 +1,75 @@ +# SPDX-FileCopyrightText: 2021 Jose David M. +# +# SPDX-License-Identifier: MIT +############################# +""" +This is a more advance demonstration of a Cartesian widget and some configurable +parameters. +""" + +import board +import displayio +import terminalio +from adafruit_displayio_layout.widgets.cartesian import Cartesian + +# Fonts used for the Dial tick labels +tick_font = terminalio.FONT + +display = board.DISPLAY # create the display on the PyPortal or Clue (for example) +# otherwise change this to setup the display +# for display chip driver and pinout you have (e.g. ILI9341) + + +# Create different Cartesian widgets +my_group = displayio.Group(max_size=10) + +car = Cartesian( + x=25, + y=10, + width=100, + height=100, + subticks=True, +) +my_group.append(car) + +car3 = Cartesian( + x=150, + y=10, + width=150, + height=100, + xrange=(0, 160), + axes_stroke=1, + axes_color=0x990099, + subticks=True, +) +my_group.append(car3) + +car4 = Cartesian( + x=30, + y=140, + width=80, + height=80, + axes_stroke=1, + tick_color=0xFFFFFF, + subticks=True, +) +car4.set_widget_style("LightGreen6") +my_group.append(car4) + +car5 = Cartesian( + x=180, + y=140, + width=70, + height=70, + xrange=(0, 120), + yrange=(0, 90), + tick_color=0x990099, + axes_stroke=3, + major_tick_length=10, +) +my_group.append(car5) + +display.show(my_group) + +while True: + pass diff --git a/examples/displayio_layout_cartesian_simpletest.py b/examples/displayio_layout_cartesian_simpletest.py index 0b54473..6ab4b4b 100644 --- a/examples/displayio_layout_cartesian_simpletest.py +++ b/examples/displayio_layout_cartesian_simpletest.py @@ -31,8 +31,8 @@ tick_color=0xFFFFFF, # ticks color major_tick_stroke=1, # ticks width in pixels major_tick_length=5, # ticks length in pixels - tick_label_color=0xFFFFFF, # ticks line color tick_label_font=tick_font, # the font used for the tick labels + font_color=0xFFFFFF, # ticks line color ) my_group = displayio.Group(max_size=3) @@ -40,11 +40,11 @@ display.show(my_group) # add high level Group to the display posx = 0 -posy = 100 +posy = 0 while True: my_plane.update_pointer(posx, posy) display.show(my_group) time.sleep(0.5) posx = posx + 2 - posy = posy - 2 + posy = posy + 2 From edccd8a5ec7f3a860609af689b9323f4a13d50b6 Mon Sep 17 00:00:00 2001 From: jposada202020 Date: Tue, 23 Mar 2021 14:33:20 -0400 Subject: [PATCH 17/36] =?UTF-8?q?#=20UPDATE=20widget=20group=20and=20coord?= =?UTF-8?q?inates=20=20=20=20=20=20=20=20=20=20=20[=E2=88=9A]=20#=20TODO?= =?UTF-8?q?=20Animate=20when=20overflow=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20[=20]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../widgets/cartesian.py | 58 +++++++------------ 1 file changed, 21 insertions(+), 37 deletions(-) diff --git a/adafruit_displayio_layout/widgets/cartesian.py b/adafruit_displayio_layout/widgets/cartesian.py index 52a7006..b23a0a9 100644 --- a/adafruit_displayio_layout/widgets/cartesian.py +++ b/adafruit_displayio_layout/widgets/cartesian.py @@ -108,11 +108,7 @@ class Cartesian(Widget): def __init__( self, - x: int = 10, - y: int = 10, display_color=0x000000, - width: int = 100, - height: int = 100, xrange: Tuple[int, int] = (0, 100), yrange: Tuple[int, int] = (0, 100), axes_color: int = 0xFFFFFF, @@ -140,16 +136,9 @@ def __init__( # TODO Updater to use local coordinates [√] super().__init__(**kwargs, max_size=3) - self._origin_x = x - self._origin_y = y - - self._margin = 10 self._display_color = display_color - self._usable_width = width - self._usable_height = height - self._axes_line_color = axes_color self._axes_line_thickness = axes_stroke @@ -167,9 +156,9 @@ def __init__( self._font_height = self._get_font_height(self._font, 1)[1] self._normx = xrange[1] / 100 - self._valuex = self._usable_width / 100 + self._valuex = self.width / 100 self._normy = yrange[1] / 100 - self._valuey = self._usable_height / 100 + self._valuey = self.height / 100 self._tick_bitmap = displayio.Bitmap( self._tick_line_thickness, self._tick_line_height, 3 @@ -184,7 +173,8 @@ def __init__( + self._font_height + self._tick_line_height // 2 ) - self._axesx_bitmap = displayio.Bitmap(self._usable_width, axesx_height, 4) + + self._axesx_bitmap = displayio.Bitmap(self.width, axesx_height, 4) self._axesx_bitmap.fill(0) self._axesy_width = ( @@ -193,12 +183,11 @@ def __init__( + self._font_width + self._tick_line_height // 2 ) - self._axesy_bitmap = displayio.Bitmap(self._axesy_width, self._usable_height, 4) + + self._axesy_bitmap = displayio.Bitmap(self._axesy_width, self.height, 4) self._axesy_bitmap.fill(0) - self._screen_bitmap = displayio.Bitmap( - self._usable_width, self._usable_height, 3 - ) + self._screen_bitmap = displayio.Bitmap(self.width, self.height, 3) self._screen_bitmap.fill(0) self._screen_palette = displayio.Palette(6) self._screen_palette.make_transparent(0) @@ -211,22 +200,22 @@ def __init__( self._axesx_tilegrid = displayio.TileGrid( self._axesx_bitmap, pixel_shader=self._screen_palette, - x=self._origin_x, - y=self._origin_y + self._usable_height, + x=0, + y=self.height, ) self._axesy_tilegrid = displayio.TileGrid( self._axesy_bitmap, pixel_shader=self._screen_palette, - x=self._origin_x - self._axesy_width, - y=self._origin_y, + x=-self._axesy_width, + y=0, ) self._screen_tilegrid = displayio.TileGrid( self._screen_bitmap, pixel_shader=self._screen_palette, - x=self._origin_x, - y=self._origin_y, + x=0, + y=0, ) self._draw_axes() @@ -253,16 +242,14 @@ def _get_font_height(font, scale): def _draw_axes(self): # Draw x axes line if self._axes_line_thickness == 1: - bitmaptools.draw_line( - self._axesx_bitmap, 0, 0, self._usable_width - 1, 0, 2 - ) + bitmaptools.draw_line(self._axesx_bitmap, 0, 0, self.width - 1, 0, 2) # Draw y axes line bitmaptools.draw_line( self._axesy_bitmap, self._axesy_width - 1, 0, self._axesy_width - 1, - self._usable_height - 1, + self.height - 1, 2, ) else: @@ -301,9 +288,8 @@ def _draw_ticks(self): self._font, color=self._font_color, text=text_tick, - x=self._origin_x + text_dist - (shift_label_x // 2), - y=self._origin_y - + self._usable_height + x=text_dist - (shift_label_x // 2), + y=self.height + self._axes_line_thickness + self._tick_line_height + self._font_height // 2 @@ -339,12 +325,11 @@ def _draw_ticks(self): self._font, color=self._font_color, text=text_tick, - x=self._origin_x - - shift_label_x + x=-shift_label_x - self._axes_line_thickness - self._tick_line_height - 2, - y=self._origin_y + self._usable_height - text_dist, + y=0 + self.height - text_dist, ) self.append(tick_text) @@ -373,7 +358,6 @@ def _draw_ticks(self): def _draw_pointers(self): self._pointer = vectorio.Circle(3) - self._circle_palette = displayio.Palette(2) self._circle_palette.make_transparent(0) self._circle_palette[1] = self._pointer_color @@ -393,8 +377,8 @@ def update_pointer(self, x: int, y: int): :return: None rtype: None """ - local_x = self._origin_x + x - local_y = self._origin_y + self._usable_height - y + local_x = x + local_y = self.height - y self._pointer_vector_shape.x = local_x self._pointer_vector_shape.y = local_y From e65ab90d6204abc67a87c36f63fce9e4c64de280 Mon Sep 17 00:00:00 2001 From: jposada202020 Date: Tue, 23 Mar 2021 23:32:41 -0400 Subject: [PATCH 18/36] =?UTF-8?q?#=20UPDATE=20scale=20and=20tickers,=20plo?= =?UTF-8?q?t=20limits=20=20=20=20=20=20=20=20=20[=E2=88=9A]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../widgets/cartesian.py | 135 ++++++++++++------ 1 file changed, 88 insertions(+), 47 deletions(-) diff --git a/adafruit_displayio_layout/widgets/cartesian.py b/adafruit_displayio_layout/widgets/cartesian.py index b23a0a9..d4cd060 100644 --- a/adafruit_displayio_layout/widgets/cartesian.py +++ b/adafruit_displayio_layout/widgets/cartesian.py @@ -59,7 +59,6 @@ class Cartesian(Widget): :param int major_tick_stroke: tick lines thickness in pixels dafaults to 1 :param int major_tick_length: tick lines length in pixels defaults to 5 - :param List[str] tick_labels: a list of strings for the tick text labels :param int tick_label_font: tick label text font :param int font_color: font color @@ -107,21 +106,21 @@ class Cartesian(Widget): """ def __init__( - self, - display_color=0x000000, - xrange: Tuple[int, int] = (0, 100), - yrange: Tuple[int, int] = (0, 100), - axes_color: int = 0xFFFFFF, - axes_stroke: int = 1, - tick_color: int = 0xFFFFFF, - major_tick_stroke: int = 1, - major_tick_length: int = 5, - tick_label_font=terminalio.FONT, - font_color: int = 0xFFFFFF, - pointer_radius: int = 1, - pointer_color: int = 0xFFFFFF, - subticks: bool = False, - **kwargs, + self, + display_color=0x000000, + xrange: Tuple[int, int] = (0, 100), + yrange: Tuple[int, int] = (0, 100), + axes_color: int = 0xFFFFFF, + axes_stroke: int = 1, + tick_color: int = 0xFFFFFF, + major_tick_stroke: int = 1, + major_tick_length: int = 5, + tick_label_font=terminalio.FONT, + font_color: int = 0xFFFFFF, + pointer_radius: int = 1, + pointer_color: int = 0xFFFFFF, + subticks: bool = False, + **kwargs, ) -> None: # TODO Make axes, separate from data [√] # TODO Replace with drawline/vectorio [√] @@ -155,10 +154,15 @@ def __init__( self._font_width = self._get_font_height(self._font, 1)[0] self._font_height = self._get_font_height(self._font, 1)[1] - self._normx = xrange[1] / 100 + self._xrange = xrange + self._normx = (self._xrange[1] - self._xrange[0]) / 100 self._valuex = self.width / 100 - self._normy = yrange[1] / 100 + self._factorx = 100 / (self._xrange[1] - self._xrange[0]) + + self._yrange = yrange + self._normy = (self._yrange[1] - self._yrange[0]) / 100 self._valuey = self.height / 100 + self._factory = 100 / (self._yrange[1] - self._yrange[0]) self._tick_bitmap = displayio.Bitmap( self._tick_line_thickness, self._tick_line_height, 3 @@ -168,27 +172,27 @@ def __init__( self._subticks = subticks axesx_height = ( - 2 - + self._axes_line_thickness - + self._font_height - + self._tick_line_height // 2 + 2 + + self._axes_line_thickness + + self._font_height + + self._tick_line_height // 2 ) self._axesx_bitmap = displayio.Bitmap(self.width, axesx_height, 4) self._axesx_bitmap.fill(0) self._axesy_width = ( - 2 - + self._axes_line_thickness - + self._font_width - + self._tick_line_height // 2 + 2 + + self._axes_line_thickness + + self._font_width + + self._tick_line_height // 2 ) 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, 3) - self._screen_bitmap.fill(0) + self._screen_bitmap = displayio.Bitmap(self.width, self.height, 5) + self._screen_bitmap.fill(5) self._screen_palette = displayio.Palette(6) self._screen_palette.make_transparent(0) self._screen_palette[1] = self._tick_color @@ -220,12 +224,13 @@ def __init__( self._draw_axes() self._draw_ticks() - self._draw_pointers() - self.append(self._pointer_vector_shape) + self.append(self._axesx_tilegrid) self.append(self._axesy_tilegrid) self.append(self._screen_tilegrid) + self._update_line = True + @staticmethod def _get_font_height(font, scale): if hasattr(font, "get_bounding_box"): @@ -280,7 +285,7 @@ def _draw_ticks(self): subticks = [20, 40, 60, 80, 100] # X axes ticks for i in range(10, 100, 10): - text_tick = str(round(i * self._normx)) + text_tick = str(round(self._xrange[0]) + round(i * self._normx)) text_dist = int(self._valuex * i) if i in ticks: shift_label_x = len(text_tick) * self._font_width @@ -290,10 +295,10 @@ def _draw_ticks(self): text=text_tick, x=text_dist - (shift_label_x // 2), y=self.height - + self._axes_line_thickness - + self._tick_line_height - + self._font_height // 2 - + 1, + + self._axes_line_thickness + + self._tick_line_height + + self._font_height // 2 + + 1, ) self.append(tick_text) bitmaptools.draw_line( @@ -317,7 +322,7 @@ def _draw_ticks(self): # Y axes ticks for i in range(10, 100, 10): - text_tick = str(round(i * self._normy)) + text_tick = str(round(self._yrange[0]) + round(i * self._normy)) text_dist = int(self._valuey * i) if i in ticks: shift_label_x = len(text_tick) * self._font_width @@ -326,9 +331,9 @@ def _draw_ticks(self): color=self._font_color, text=text_tick, x=-shift_label_x - - self._axes_line_thickness - - self._tick_line_height - - 2, + - self._axes_line_thickness + - self._tick_line_height + - 2, y=0 + self.height - text_dist, ) self.append(tick_text) @@ -356,7 +361,7 @@ def _draw_ticks(self): 1, ) - def _draw_pointers(self): + def _draw_pointers(self, x, y): self._pointer = vectorio.Circle(3) self._circle_palette = displayio.Palette(2) self._circle_palette.make_transparent(0) @@ -365,9 +370,10 @@ def _draw_pointers(self): self._pointer_vector_shape = vectorio.VectorShape( shape=self._pointer, pixel_shader=self._circle_palette, - x=0, - y=0, + x=x, + y=y, ) + self.append(self._pointer_vector_shape) def update_pointer(self, x: int, y: int): """updater_pointer function @@ -377,10 +383,45 @@ def update_pointer(self, x: int, y: int): :return: None rtype: None """ - local_x = x - local_y = self.height - y - self._pointer_vector_shape.x = local_x - self._pointer_vector_shape.y = local_y + local_x = int((x - self._xrange[0]) * self._factorx) + local_y = int((self._yrange[0] - y) * self._factory) + self.height + + 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 _set_plotter_line(self): + self.plot_line_point = list() + + def update_line(self, x: int, y: int): + """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) + local_y = int((self._yrange[0] - y) * self._factory) + self.height + 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, + ) def set_widget_style(self, new_style: str) -> None: """set_widget_style function @@ -396,4 +437,4 @@ def set_widget_style(self, new_style: str) -> None: colorset = styles.THEME self._pointer_color = get_hex(colorset[new_style]["TEXT"]) self._font_color = get_hex(colorset[new_style]["TEXT"]) - self._draw_ticks() + self._draw_ticks() \ No newline at end of file From b2104eacca3f035047950dce79f615b11d703de5 Mon Sep 17 00:00:00 2001 From: jposada202020 Date: Tue, 23 Mar 2021 23:36:42 -0400 Subject: [PATCH 19/36] =?UTF-8?q?#=20UPDATE=20scale=20and=20tickers,=20plo?= =?UTF-8?q?t=20limits=20=20=20=20=20=20=20=20=20[=E2=88=9A]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../widgets/cartesian.py | 78 +++++++++---------- 1 file changed, 36 insertions(+), 42 deletions(-) diff --git a/adafruit_displayio_layout/widgets/cartesian.py b/adafruit_displayio_layout/widgets/cartesian.py index d4cd060..97db59d 100644 --- a/adafruit_displayio_layout/widgets/cartesian.py +++ b/adafruit_displayio_layout/widgets/cartesian.py @@ -106,33 +106,22 @@ class Cartesian(Widget): """ def __init__( - self, - display_color=0x000000, - xrange: Tuple[int, int] = (0, 100), - yrange: Tuple[int, int] = (0, 100), - axes_color: int = 0xFFFFFF, - axes_stroke: int = 1, - tick_color: int = 0xFFFFFF, - major_tick_stroke: int = 1, - major_tick_length: int = 5, - tick_label_font=terminalio.FONT, - font_color: int = 0xFFFFFF, - pointer_radius: int = 1, - pointer_color: int = 0xFFFFFF, - subticks: bool = False, - **kwargs, + self, + display_color=0x000000, + xrange: Tuple[int, int] = (0, 100), + yrange: Tuple[int, int] = (0, 100), + axes_color: int = 0xFFFFFF, + axes_stroke: int = 1, + tick_color: int = 0xFFFFFF, + major_tick_stroke: int = 1, + major_tick_length: int = 5, + tick_label_font=terminalio.FONT, + font_color: int = 0xFFFFFF, + pointer_radius: int = 1, + pointer_color: int = 0xFFFFFF, + subticks: bool = False, + **kwargs, ) -> None: - # TODO Make axes, separate from data [√] - # TODO Replace with drawline/vectorio [√] - # TODO Make a rectangle function [√] - # TODO Include functions to equal space ticks [√] - # TODO Make labels and text [√] - # TODO Make Styles applicable [√] - # TODO Animate when overflow [ ] - # TODO Add Subticks functionality [√] - # TODO ticks evenly distributed [√] - # TODO Make Ticker lines [√] - # TODO Updater to use local coordinates [√] super().__init__(**kwargs, max_size=3) @@ -172,20 +161,20 @@ def __init__( self._subticks = subticks axesx_height = ( - 2 - + self._axes_line_thickness - + self._font_height - + self._tick_line_height // 2 + 2 + + self._axes_line_thickness + + self._font_height + + self._tick_line_height // 2 ) self._axesx_bitmap = displayio.Bitmap(self.width, axesx_height, 4) self._axesx_bitmap.fill(0) self._axesy_width = ( - 2 - + self._axes_line_thickness - + self._font_width - + self._tick_line_height // 2 + 2 + + self._axes_line_thickness + + self._font_width + + self._tick_line_height // 2 ) self._axesy_bitmap = displayio.Bitmap(self._axesy_width, self.height, 4) @@ -231,6 +220,11 @@ def __init__( self._update_line = True + self._pointer = None + self._circle_palette = None + self._pointer_vector_shape = None + self.plot_line_point = None + @staticmethod def _get_font_height(font, scale): if hasattr(font, "get_bounding_box"): @@ -295,10 +289,10 @@ def _draw_ticks(self): text=text_tick, x=text_dist - (shift_label_x // 2), y=self.height - + self._axes_line_thickness - + self._tick_line_height - + self._font_height // 2 - + 1, + + self._axes_line_thickness + + self._tick_line_height + + self._font_height // 2 + + 1, ) self.append(tick_text) bitmaptools.draw_line( @@ -331,9 +325,9 @@ def _draw_ticks(self): color=self._font_color, text=text_tick, x=-shift_label_x - - self._axes_line_thickness - - self._tick_line_height - - 2, + - self._axes_line_thickness + - self._tick_line_height + - 2, y=0 + self.height - text_dist, ) self.append(tick_text) @@ -437,4 +431,4 @@ def set_widget_style(self, new_style: str) -> None: colorset = styles.THEME self._pointer_color = get_hex(colorset[new_style]["TEXT"]) self._font_color = get_hex(colorset[new_style]["TEXT"]) - self._draw_ticks() \ No newline at end of file + self._draw_ticks() From b53cbfc60e421ee20c8785ce7fb3feeeefe429e1 Mon Sep 17 00:00:00 2001 From: jposada202020 Date: Wed, 24 Mar 2021 21:09:07 -0400 Subject: [PATCH 20/36] =?UTF-8?q?#=20TODO=20Pointer:=20(0,=200)=20AXISX=20?= =?UTF-8?q?vs=20AXISY=20=20=20=20=20=20=20=20[=20]=20#=20TODO=20major=5Fti?= =?UTF-8?q?ck=5Fstroke=20value=20is=20ignored=20=20=20=20[=20]=20#=20TODO?= =?UTF-8?q?=20pointer=5Fradiusvalue=20is=20ignored=20=20=20=20=20=20=20=20?= =?UTF-8?q?[=E2=88=9A]=20#=20TODO=20The=20y-axis=20width=20vs=20x-axis=20w?= =?UTF-8?q?idth.=20=20=20=20=20[=20]=20#=20TODO=20Use=20rectangle=20helper?= =?UTF-8?q?=20for=20all=20cases=20=20=20=20[=20]=20#=20TODO=20Docstrings?= =?UTF-8?q?=20Xrange=20-=20axis=5Frange=20=20=20=20=20=20=20=20[=E2=88=9A]?= =?UTF-8?q?=20#=20TODO=20Change=20background=5Fcolor=20name=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20[=E2=88=9A]=20#=20TODO=20Verify=20Errors=20Tick?= =?UTF-8?q?=20Lenght=20Selection=20=20=20[=20]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../widgets/cartesian.py | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/adafruit_displayio_layout/widgets/cartesian.py b/adafruit_displayio_layout/widgets/cartesian.py index 97db59d..1fdff00 100644 --- a/adafruit_displayio_layout/widgets/cartesian.py +++ b/adafruit_displayio_layout/widgets/cartesian.py @@ -47,12 +47,12 @@ class Cartesian(Widget): :param int x: x position of the plane origin :param int y: y position of the plane origin - :param int display_color: background color to use defaults to black (0x000000) + :param int background_color: background color to use defaults to black (0x000000) :param int width: requested width, in pixels defaults to 100 pixels :param int height: requested height, in pixels defaults to 100 pixels - :param (int, int) axesx_range: X axes range - :param (int, int) axesy_range: Y axes range + :param (int, int) xrange: X axes range + :param (int, int) yrange: Y axes range :param int axes_color: axes lines color defaults to white (0xFFFFFF) :param int axes_stroke: axes lines thickness in pixels defaults to 2 @@ -107,7 +107,7 @@ class Cartesian(Widget): def __init__( self, - display_color=0x000000, + background_color=0x000000, xrange: Tuple[int, int] = (0, 100), yrange: Tuple[int, int] = (0, 100), axes_color: int = 0xFFFFFF, @@ -123,9 +123,18 @@ def __init__( **kwargs, ) -> None: + # TODO Pointer: (0, 0) AXISX vs AXISY [ ] + # TODO major_tick_stroke value is ignored [ ] + # TODO pointer_radiusvalue is ignored [√] + # TODO The y-axis width vs x-axis width. [ ] + # TODO Use rectangle helper for all cases [ ] + # TODO Docstrings Xrange - axis_range [√] + # TODO Change background_color name [√] + # TODO Verify Errors Tick Lenght Selection [ ] + super().__init__(**kwargs, max_size=3) - self._display_color = display_color + self._background_color = background_color self._axes_line_color = axes_color self._axes_line_thickness = axes_stroke @@ -188,7 +197,7 @@ def __init__( self._screen_palette[2] = self._axes_line_color self._screen_palette[3] = 0x990099 self._screen_palette[4] = 0xFFFFFF - self._screen_palette[5] = self._display_color + self._screen_palette[5] = self._background_color self._axesx_tilegrid = displayio.TileGrid( self._axesx_bitmap, @@ -356,7 +365,7 @@ def _draw_ticks(self): ) def _draw_pointers(self, x, y): - self._pointer = vectorio.Circle(3) + 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 From ff46af0ab0b83db6873dcabe04c1646d4731c716 Mon Sep 17 00:00:00 2001 From: jposada202020 Date: Wed, 24 Mar 2021 23:05:43 -0400 Subject: [PATCH 21/36] =?UTF-8?q?=20=20=20=20=20=20=20=20#=20TODO=20major?= =?UTF-8?q?=5Ftick=5Fstroke=20value=20is=20ignored=20=20=20=20[=E2=88=9A]?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20#=20TODO=20Pointer:=20(0,=200)=20AXI?= =?UTF-8?q?SX=20vs=20AXISY=20=20=20=20=20=20=20=20[=20]=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20#=20TODO=20pointer=5Fradiusvalue=20is=20ignored=20=20?= =?UTF-8?q?=20=20=20=20=20=20[=E2=88=9A]=20=20=20=20=20=20=20=20=20#=20TOD?= =?UTF-8?q?O=20The=20y-axis=20width=20vs=20x-axis=20width.=20=20=20=20=20[?= =?UTF-8?q?=20]=20=20=20=20=20=20=20=20=20#=20TODO=20Use=20rectangle=20hel?= =?UTF-8?q?per=20for=20all=20cases=20=20=20=20[=E2=88=9A]=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20#=20TODO=20Docstrings=20Xrange=20-=20axis=5Frange?= =?UTF-8?q?=20=20=20=20=20=20=20=20[=E2=88=9A]=20=20=20=20=20=20=20=20=20#?= =?UTF-8?q?=20TODO=20Change=20background=5Fcolor=20name=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20[=E2=88=9A]=20=20=20=20=20=20=20=20=20#=20TODO=20Ve?= =?UTF-8?q?rify=20Errors=20Tick=20Lenght=20Selection=20=20=20[=E2=88=9A]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- adafruit_displayio_layout/widgets/__init__.py | 7 +- .../widgets/cartesian.py | 120 ++++++++++-------- 2 files changed, 68 insertions(+), 59 deletions(-) diff --git a/adafruit_displayio_layout/widgets/__init__.py b/adafruit_displayio_layout/widgets/__init__.py index 80825ac..a02e091 100644 --- a/adafruit_displayio_layout/widgets/__init__.py +++ b/adafruit_displayio_layout/widgets/__init__.py @@ -53,10 +53,9 @@ def rectangle_helper( """ if bitmaptool: - x1 = x0 + width - y1 = y0 + height - for row_pos in range(y0, y1, 1): - bitmaptools.draw_line(bitmap, x0, row_pos, x1, row_pos, color_index) + bitmaptools.fill_region( + bitmap, x0, y0, x0 + width - 1, y0 + height - 1, color_index + ) else: rect = vectorio.Rectangle(width, height) vectorio.VectorShape( diff --git a/adafruit_displayio_layout/widgets/cartesian.py b/adafruit_displayio_layout/widgets/cartesian.py index 1fdff00..22cbd7b 100644 --- a/adafruit_displayio_layout/widgets/cartesian.py +++ b/adafruit_displayio_layout/widgets/cartesian.py @@ -123,14 +123,14 @@ def __init__( **kwargs, ) -> None: + # TODO major_tick_stroke value is ignored [√] # TODO Pointer: (0, 0) AXISX vs AXISY [ ] - # TODO major_tick_stroke value is ignored [ ] # TODO pointer_radiusvalue is ignored [√] # TODO The y-axis width vs x-axis width. [ ] - # TODO Use rectangle helper for all cases [ ] + # TODO Use rectangle helper for all cases [√] # TODO Docstrings Xrange - axis_range [√] # TODO Change background_color name [√] - # TODO Verify Errors Tick Lenght Selection [ ] + # TODO Verify Errors Tick Lenght Selection [√] super().__init__(**kwargs, max_size=3) @@ -140,8 +140,17 @@ def __init__( self._axes_line_thickness = axes_stroke self._tick_color = tick_color - self._tick_line_thickness = major_tick_stroke - self._tick_line_height = major_tick_length + if major_tick_stroke not in range(1, 5): + print("tick thickness must be 1-4 pixels. Defaulting to 1") + self._tick_line_thickness = 1 + else: + self._tick_line_thickness = major_tick_stroke + + if major_tick_length not in range(1, 9): + print("tick lenght must be 1-10 pixels. Defaulting to 5") + self._tick_line_height = 5 + else: + self._tick_line_height = major_tick_length self._pointer_radius = pointer_radius self._pointer_color = pointer_color @@ -249,38 +258,28 @@ def _get_font_height(font, scale): def _draw_axes(self): # Draw x axes line - if self._axes_line_thickness == 1: - bitmaptools.draw_line(self._axesx_bitmap, 0, 0, self.width - 1, 0, 2) - # Draw y axes line - bitmaptools.draw_line( - self._axesy_bitmap, - self._axesy_width - 1, - 0, - self._axesy_width - 1, - self.height - 1, - 2, - ) - else: - rectangle_helper( - 0, - 0, - self._axes_line_thickness, - self._axesx_bitmap.width - 1, - self._axesx_bitmap, - 2, - self._screen_palette, - True, - ) - rectangle_helper( - self._axesy_width - self._axes_line_thickness - 1, - 0, - self._axesy_bitmap.height, - self._axes_line_thickness, - self._axesy_bitmap, - 2, - self._screen_palette, - True, - ) + rectangle_helper( + 0, + 0, + self._axes_line_thickness, + self.width, + self._axesx_bitmap, + 2, + self._screen_palette, + True, + ) + + # Draw y axes line + rectangle_helper( + self._axesy_width - self._axes_line_thickness, + 0, + self.height, + self._axes_line_thickness, + self._axesy_bitmap, + 2, + self._screen_palette, + True, + ) def _draw_ticks(self): # ticks definition @@ -304,23 +303,28 @@ def _draw_ticks(self): + 1, ) self.append(tick_text) - bitmaptools.draw_line( - self._axesx_bitmap, - text_dist, - self._tick_line_height + self._axes_line_thickness, + rectangle_helper( text_dist, self._axes_line_thickness, + self._tick_line_height, + self._tick_line_thickness, + self._axesx_bitmap, 1, + self._screen_palette, + True, ) + if self._subticks: if i in subticks: - bitmaptools.draw_line( - self._axesx_bitmap, - text_dist, - self._tick_line_height // 2 + self._axes_line_thickness, + rectangle_helper( text_dist, self._axes_line_thickness, + self._tick_line_height // 2, + 1, + self._axesx_bitmap, 1, + self._screen_palette, + True, ) # Y axes ticks @@ -340,28 +344,34 @@ def _draw_ticks(self): y=0 + self.height - text_dist, ) self.append(tick_text) - - bitmaptools.draw_line( - self._axesy_bitmap, + rectangle_helper( self._axesy_width - self._axes_line_thickness - self._tick_line_height - 1, text_dist, - self._axesy_width - 1 - self._axes_line_thickness, - text_dist, + self._tick_line_thickness, + self._tick_line_height, + self._axesy_bitmap, 1, + self._screen_palette, + True, ) if self._subticks: if i in subticks: - bitmaptools.draw_line( - self._axesy_bitmap, - self._axesy_width - 1 - self._tick_line_height // 2, - text_dist, - self._axesy_width - 1, + rectangle_helper( + self._axesy_width + - self._axes_line_thickness + - self._tick_line_height // 2 + - 1, text_dist, 1, + self._tick_line_height // 2, + self._axesy_bitmap, + 1, + self._screen_palette, + True, ) def _draw_pointers(self, x, y): From 95ac520eda1c3b94a64bfe31b7ee45d5112ead84 Mon Sep 17 00:00:00 2001 From: jposada202020 Date: Wed, 24 Mar 2021 23:40:28 -0400 Subject: [PATCH 22/36] =?UTF-8?q?#=20TODO=20Pointer:=20(0,=200)=20AXISX=20?= =?UTF-8?q?vs=20AXISY=20=20=20=20=20=20=20=20[=E2=88=9A]=20#=20TODO=20majo?= =?UTF-8?q?r=5Ftick=5Fstroke=20value=20is=20ignored=20=20=20=20[=E2=88=9A]?= =?UTF-8?q?=20#=20TODO=20The=20y-axis=20width=20vs=20x-axis=20width.=20=20?= =?UTF-8?q?=20=20=20[=E2=88=9A]=20#=20TODO=20Use=20rectangle=20helper=20fo?= =?UTF-8?q?r=20all=20cases=20=20=20=20[=E2=88=9A]=20#=20TODO=20Verify=20Er?= =?UTF-8?q?rors=20Tick=20Lenght=20Selection=20=20=20[=E2=88=9A]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- adafruit_displayio_layout/widgets/cartesian.py | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/adafruit_displayio_layout/widgets/cartesian.py b/adafruit_displayio_layout/widgets/cartesian.py index 22cbd7b..73315d2 100644 --- a/adafruit_displayio_layout/widgets/cartesian.py +++ b/adafruit_displayio_layout/widgets/cartesian.py @@ -123,15 +123,6 @@ def __init__( **kwargs, ) -> None: - # TODO major_tick_stroke value is ignored [√] - # TODO Pointer: (0, 0) AXISX vs AXISY [ ] - # TODO pointer_radiusvalue is ignored [√] - # TODO The y-axis width vs x-axis width. [ ] - # TODO Use rectangle helper for all cases [√] - # TODO Docstrings Xrange - axis_range [√] - # TODO Change background_color name [√] - # TODO Verify Errors Tick Lenght Selection [√] - super().__init__(**kwargs, max_size=3) self._background_color = background_color @@ -444,9 +435,11 @@ def set_widget_style(self, new_style: str) -> None: """ # import would change after library packaging # pylint: disable=import-outside-toplevel - from adafruit_styles import get_hex - from adafruit_styles import styles - + try: + from adafruit_styles import get_hex + from adafruit_styles import styles + except ImportError: + pass colorset = styles.THEME self._pointer_color = get_hex(colorset[new_style]["TEXT"]) self._font_color = get_hex(colorset[new_style]["TEXT"]) From dc34b07548328bf24ea04666961585e72374a3e0 Mon Sep 17 00:00:00 2001 From: jposada202020 Date: Thu, 25 Mar 2021 09:37:21 -0400 Subject: [PATCH 23/36] =?UTF-8?q?#=20UPDATE=20DOCS=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20[=E2=88=9A]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../widgets/cartesian.py | 51 +++++++++++++++--- docs/cartesian.gif | Bin 0 -> 1031 bytes docs/cartesian.gif.license | 3 ++ docs/cartesian_explanation.png | Bin 0 -> 5032 bytes docs/cartesian_explanation.png.license | 3 ++ docs/cartesian_zones.png | Bin 0 -> 4442 bytes docs/cartesian_zones.png.license | 3 ++ 7 files changed, 52 insertions(+), 8 deletions(-) create mode 100644 docs/cartesian.gif create mode 100644 docs/cartesian.gif.license create mode 100644 docs/cartesian_explanation.png create mode 100644 docs/cartesian_explanation.png.license create mode 100644 docs/cartesian_zones.png create mode 100644 docs/cartesian_zones.png.license diff --git a/adafruit_displayio_layout/widgets/cartesian.py b/adafruit_displayio_layout/widgets/cartesian.py index 73315d2..7765528 100644 --- a/adafruit_displayio_layout/widgets/cartesian.py +++ b/adafruit_displayio_layout/widgets/cartesian.py @@ -66,6 +66,7 @@ class Cartesian(Widget): :param int pointer_radius: pointer radius in pixels defaults to 1 :param int pointer_color: pointer color defaults to white (0xFFFFFF) + **Quickstart: Importing and using Cartesian** Here is one way of importing the `Cartesian` class so you can use it as @@ -103,6 +104,40 @@ class Cartesian(Widget): display.show(my_group) # add the group to the display + + .. figure:: cartesian.gif + :scale: 100 % + :figwidth: 50% + :align: center + :alt: Diagram of the cartesian widget with the pointer in motion. + + This is a diagram of a cartesian widget with the pointer moving in the + plot area. + + .. figure:: cartesian_zones.png + :scale: 100 % + :figwidth: 50% + :align: center + :alt: Diagram of the cartesian widget zones. + + This is a diagram of a cartesian widget showing the different zones. + + .. figure:: cartesian_zones.png + :scale: 100 % + :figwidth: 50% + :align: center + :alt: Diagram of the cartesian widget zones. + + This is a diagram of a cartesian widget showing the different zones. + + .. figure:: cartesian_explanation.png + :scale: 100 % + :figwidth: 50% + :align: center + :alt: Diagram of the cartesian widget localisation. + + This is a diagram of a cartesian widget showing localisation scheme. + """ def __init__( @@ -138,7 +173,7 @@ def __init__( self._tick_line_thickness = major_tick_stroke if major_tick_length not in range(1, 9): - print("tick lenght must be 1-10 pixels. Defaulting to 5") + print("tick length must be 1-10 pixels. Defaulting to 5") self._tick_line_height = 5 else: self._tick_line_height = major_tick_length @@ -235,7 +270,7 @@ def __init__( self.plot_line_point = None @staticmethod - def _get_font_height(font, scale): + def _get_font_height(font, scale: int) -> Tuple[int, int]: if hasattr(font, "get_bounding_box"): font_height = int(scale * font.get_bounding_box()[1]) font_width = int(scale * font.get_bounding_box()[0]) @@ -247,7 +282,7 @@ def _get_font_height(font, scale): font_width = 12 return font_width, font_height - def _draw_axes(self): + def _draw_axes(self) -> None: # Draw x axes line rectangle_helper( 0, @@ -272,7 +307,7 @@ def _draw_axes(self): True, ) - def _draw_ticks(self): + def _draw_ticks(self) -> None: # ticks definition ticks = [10, 30, 50, 70, 90] subticks = [20, 40, 60, 80, 100] @@ -365,7 +400,7 @@ def _draw_ticks(self): True, ) - def _draw_pointers(self, x, y): + 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) @@ -379,7 +414,7 @@ def _draw_pointers(self, x, y): ) self.append(self._pointer_vector_shape) - def update_pointer(self, x: int, y: int): + def update_pointer(self, x: int, y: int) -> None: """updater_pointer function helper function to update pointer in the plane :param int x: x coordinate in the local plane @@ -398,10 +433,10 @@ def update_pointer(self, x: int, y: int): self._pointer_vector_shape.x = local_x self._pointer_vector_shape.y = local_y - def _set_plotter_line(self): + def _set_plotter_line(self) -> None: self.plot_line_point = list() - def update_line(self, x: int, y: int): + 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 diff --git a/docs/cartesian.gif b/docs/cartesian.gif new file mode 100644 index 0000000000000000000000000000000000000000..3d6677967cabd9e86984488be47a354323587767 GIT binary patch literal 1031 zcmZ?wbhEHboW?MX;R6E*{P^=j@jthpYe=xOV}PrXo&hr>P*m|J3yT!Pe+C_p5|CmB zrvEMdD^I`WUp!~at?teD_Wb5=d*m_gS?97>r?$Q0KK{w)`nTTazog#myY-vX``|*s z5F0J?lS?mOs_|03xYD4(Heof}y3p`9t&;cj^JLEGol29IQh1lQJ@>K9JhkgnKd!6G zXJ7u6eTTF9^P^!qmh7mw^1^~e@~5$9W`$+x49(P&m5+Z$3Ts(8M@bcT{aUnZmErVd z+n#A%R=4oxzN|j`!mQa7w{yS#T`l;!J(|a)V~xWa8^ddNxc9C(>K!}x^P1i(wcmK9 z-kIff#h&ZRTNQVD-m7)o^Y#8$wNLl>Kdbij9R4}Ad9&=fzCAk9WIBOUuJMde(uSk0 z(!0%hw5@73WCri={;#G|a{Ky)I;k zCEwbdy>d(I0k_PZF5gaEa(!*Ud9Q76+ubc%Q+;ClE`{B@JM;b7g9rWe+cK-BY9}m+ zP&emWRs8xkTaj>?+>e{_FOJMMRI}~1+WPA1n&{npE;C=H&ik!&ecxM`&AB&s|9tfA z?C;KZ_chwt?fK?R-1szEyXV`rJvm=8;yohM-|gA*?d_fEQoY*Q>%&YR2~Kpc@qev+ z`ea?uwpRygf3N7Dv2eXsyYT_HLth>z$8*e9*v8RzKaurNse&Tg#b<|;H5^^%MGLNC zO^_`2(eQNsbFp2a=CiFuM>}uUi}?*FO_k?2sRt=5NjzLQeP(9A<|6SPeY@+ieOB*I zB=_6><4Bp{#OIkZ(M_&1Ws;ZPPgh1zx?`1MU}DfwWQbwl1VRQT{ubHtgKORj^d#7= z2)Or01ffQmA&Q_HRfY(HYSbCR2&&O!2qCCOn<0px8eN6}f@<^`{0OQsWbh%V#+bni Hml|sTnx~^= literal 0 HcmV?d00001 diff --git a/docs/cartesian.gif.license b/docs/cartesian.gif.license new file mode 100644 index 0000000..a879c67 --- /dev/null +++ b/docs/cartesian.gif.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: 2021 Jose David M. + +SPDX-License-Identifier: MIT \ No newline at end of file diff --git a/docs/cartesian_explanation.png b/docs/cartesian_explanation.png new file mode 100644 index 0000000000000000000000000000000000000000..985edc7c83691963d3f99655274d9d1aaa26d3de GIT binary patch literal 5032 zcma)8cQhQ{x*at-(IZL-GBIjM)GoZ=+UBuXoJyvqGk|`Ac)bT zj268cFTcC)eRsY8-udIKz1H`gbM{$hfBSsV&$Xe{6l@d#0DxLe^_eaJK%np!?~xJy zo$)#XasU7YQ=q<)x30C{Jr9_>z0+&Ed)@&acK7W3o$LVs|JnEq*Ys^5&9j>zCKR#4 zJu7LlUTIXgG2TqN!lEltUOcxN?JeU?F zN1k`CpNb=dC;ygUC6JSV6Z~*0pWq4RLQ~CF<0o2<@7>WC&A4=#_#Cr`v*kp38Whl0=>BjyAj@c zAUJf912)62MsY)ojyiY2D;5a%vI+sS2@z(v2wt2{lFhT1hfU-2AMPB)_t_v|k{kbq z<$zYd*u;0~c{8bl9<_E}7i`O+@gaJrJgXxmjgw?!(ZBl&I1;!-bWzv=PpT_+D zgk)X6J7YOuIF7&ln`L#@(0i2{*}kv*HoU$GlE-uHY5Pmdv(YchxEQFJ`CD?Ciqr^8 z!pu0@@>1A2`b=9D9a5@oNz_-_o45OONSn<8S>Uw&!A`U}_SY}7DnET&taHz$2Nc`C zH+5i~XmqE|-`r(z*S59EqSX)Jb;m`Q!DQ}f^0i=XZDdOX@dz+j0M)A5av_-B!{*=S zo0?tKwB0iWH0Y~bt^JOj7oW9A&~QSX^1!u-dQ=pizp8f7`HC{o;dIUZ0g5LGwQg7| z<+~qNb$d8Rm#!9;SF*@0h&>?0)M!VXvBpeqyJ-qcXXI z1iaNwx1!oI#69LpBXO}I$4#Rckdnza(4W2yX3;|Bnz!Xx$=6NBAlI};>sw2v~6uXISui|XM}hV*e45rMpsHs~X9 zGizs!a@Vgz&JLH6bV_~^@c}Nq&>+dcT`l#NHL2VM#JtSe|R}(GFLc>7ytIfC2#p{d=u3$A@ zB7R+m`?)2@>1FR&+H&pP1f~WBpQ@U)X;%}b7+etA@#=)V*&CWAcx0OzU7lksA|{dD zO<=Ffq&`DpMBxfl_j(~Zv!bi48;e^JcO;lEm2jhe=Kf@^m}<>qMJoLDb5VVBh|(i~ zmio#27V8g&uJ?`MWtfs8o4DpRsfb#=drYlulJu%-N0di?!-+vrE4PY$QFP7SzU>HXlWDmYH-_h)dk)|o{~lDrkj@yR** zrXNEzY4qG#(cw`YTLDfjI8(O-+)k6^-dn-^j$#qdz8_0p5X6W82a>Rn{J5i?JhIz| z3Ahu8&Sm=_t|esycIuGWnuqFr8nhGJ^ta{{7$kBI(dIc z+f~dpB`UC74}+_B*nXNw6&20hL(Z(Gs`BUK=Qy-j-w&E!Wn|#nRnpHBQTcYwVd1>M zjzG)Qt6{oCR%kttheRBm(Xr|KbEe^M_kCubO_s2;SM#@O^7#%E)yz6%Dw`99a zp^%+V;0F4;=mHLo;F+FdioF*O^C@ zKAh~`uUOVxX9#(pWTdM@>3>gL*ZBOd^=n zb|miL@D93cJb%i-+3Kza=j!wB@f6Irjk|>>_%AOXHR8acRYQSmuBn5(Ln>3_>6lwC z*5(pB^`HRbk1SPk5mMtr&llyc3L_VNS{ZV6>ZVjPnn3SZzY2ruGi_Sp@t#{HH#W1q zP@8X@xi*;o?yc0V0vDwsN{E$wpC_=A77ixjm*o~u;(7(S!$;{u?#MIvF>OF)jG;JI zt(+-(6gqiA{bSK(0p}|`CUX1Sz>xHy1vh~_6UaTG-#d2eOPY=$of>Sh6UAuvU{hsA zjA`aYDWCV?2xK}qExEzz{hFKJImFv^WKJpZPtE5Klohyohg=nxKSy!U{Xs`M-jfF) zGH2+n;J6dsQZ;uiL*~pboQlL_vY3S23kgP9cEO7%vP9X3aAc|8gCis8@FM%%Q}i(> z86x9i@H&(oGn`Zg8tJH&D1VZoD%VTRyrgs>4^%uOd9^pja{*e-=4Uev&CKJlWtUW4%ubu$A>-d`E)9{k{E4CmeTWFL>5&o*RB8Uq_p^O|@Kk z_S!W&?o|s@#3tE``kFT1o(OBAW`@fOjy^lJjI0*~M~m`oYuh%4>_MnOUNLUAjA*)e zd}GAh`5B5okiuHTOAs;x-qS--Lnx8wpsg71dGLFV+s z@9-tS#kvq#6W>V|$2OIOmyHz~*k6`mo4vFW{;4}$w<75) zT=6AEJ}6qCf4z{(A>U$TrnJh7d-=1V$k9?`Q^t~KP=N0V(0-OreOB={Y=0WIJQ*J9 z;=V0BPuVlfOl3|gOVZgP`7(}7FVzQJ{BmyLP8s4X!or(YW#e2#a_0gzS`_r*Z=Xoy zrKqM)Mn*Qbq_YSBkVDj-J=OQO*qImeU1?+{wOZp~F;P!ngfTDk*rAQlslugWin@X1 z#xWEuNQFqEl{bv9)c6(P3*+CCMV_kW^(k?t8%8%tsF-fXf2?@3@ZLl49w~pQ_-Hyjkte;{laa!-Ix3u61=h{W!+N zi?6fi4CC~o;7sUyb;A)qWS?d!_P43W(#W~{o^x8gh|XS{LCZ~= zS#FLVn(Q~&*s1wwUUg7RHWa3vrU>*weqe^49zl)IV3$8%O}O8_5%^;6%Dh-eN$t$l zMFP0n+(?v<)v=2C`6@SuHUXtL_UXs_@fj4Qi4IQ<^x8MS zg6BDX&~6xQ9j#82mE&M%V%QPyp6q5c>1WhsiFfsa=WT{Md(JQ6l5EU`7sJ455&I3V zitIGGxgf|8-+zL&<2lyQKFu~N4~-`#{q>Gn4|WBbDjRr|Pme<0Tc5O0a`Z7OZ`n>| ztQ{mrWh^Al!Ssjg6KQe?Q|Mu23&+tW{hD2$a{c^POlmQOtp=BtQ8Qad7l*j@VkT6O z(7xlHiDiSsoMV}ePtcZ7=mA~Zn9xqGoo1}*2$2vcPj`(WAr%pW6>BD-r~7124C7Wz z`!*)g7yhi5f?&5VXHKrRdcrE#d_%aIHGFhDtf?s#+m7G4?jgB*BX^y9GuVR(lWa`2 za4aBlM+Sa0B{m%@Q4f_|OJ$m_p`<2aSWNgm|1(TXh?td>zgtw4ATo?xlu9%7*5S@| zL$g3Ebj@q=OLJj(4$c3P_)q4pD&CcML9;LdaH<%1PE4??xPJ_{R4z=Wly01c8FHNV z7OLOE8fgStN7J--q~Es?$`ByHW(L`KQn!tP)z#7+zGK2blm;nKp} z>0MWw=ZB#!FwklCc^Ix+bE2Mo+qC8MDpCDbhHc;jk&bh{s_y-+kFk|?}`utd1n}uZ}tJtc_0+WKDz&s@{w*~yt2c(d%wL>M- z5e0}4tg>T@w8qx$81m7+J>=*UP-IDf33l}F&42i$PVy;Z4gU+~3fBDxf^0gpZ(ic_@ZVW-J)h_+wY`YUjaYl+1xd$Ju0rk+tbz-`$S+k4m9`IYcvox}d1s5XEd1 zCG|Q}Y3`*oWfhToW$l;#Ae&VP%>6uq-8?s$dC}tcX{wK20?kO&m+N9b`bBNVf!6)k z>FI4P^0GCyi#yVKlU;K4UZCADn)ccswy~q}!Eryb3s+Aj!btpWC*K*wzAl+{m;F`) z==l)5-cnJt&@1+j{H?8g3#_#~zXyb1zjfB%$Szr7_>A*!x)|z2WcIAg#-D!wciMkz zGbaLTakZ&fsgMS67sL{P3_=nk6So!ppf*mWMDDL2Ry&CVT5RSS>EpUP-uX?cwN1>> z0pq8`bOvyHy3CY9wym%eBg3JR@*+Tf!VP$aH)wy-mM_NEX0?*1!=Z<2KC9_+`8?yH zMg8h^Wt_1IpG-&o0rbU{)Jga>?lBlmBKJN)#)Er@l!aR8I#aSqPGC~Zvs>Au@aH3Y zwT2mkSUMj#J;+W9{GKPwvzxKMSUu3}L%qaJYr2@n1M^${b5`}dC_AcOI@1JL1C2+f z{oU7Odv?O}{+?AioP*RIrW@!*o0o`BLh?h>Da&RS zu6txC_Rf;4DX z$HEN*#eM=;w?R6*7hM|1J1|bt6&ZjzBT3H@KVB6xKSXdG@m~Y{*B`m-0GU=y8P4b( z=BgS%zn6Mskj{8N7UcE4IxnZX`7@mDre!)p_;gLf723l9r(;5B&0Q!(FnA#a|?BF=;RO6 z*b<(!226GgIE$g9O3WuVX*T~k71lTOGGD~_&O+S<%|^GZx7Ojqsra2E&g!i8*4@W9 zgf%5;D*E$NULYa^W~~Op=rrbhQ&5ZjyyrQqlVJ?Cq)$OhGd8u_*snZ3E)AvKCA0o` zi+PmbzkR?)yoh+s#`;{B9nK9Oh(`&IcMJJgS^Y{$+55MeT@H3HJiob%l_=}roA)3r4KC?Yq<`IF4^5Jh=@oRXPpf@vjZk?n zFL5E3xSwl%{a3h4f$?vX4g5?5>3^yJKat};;%6gkJKJjH=YLkHDQiEgR0m(o4Zj!bAq7y z)$#dRWuUc8U|(ghMOa|wb(<)$T6iL?a;&2|m*FX1h97PP%$Ym%@;}W9t%dsyF;V25 zD?FV8!(m(( zlF*6G0@Pk~JGU4meoF14vi7JUq?qCz%z~ItW`J|PZVVi}C?c^IoBP{;KbdLM(Q(w> zn$aYoq2FFiCQ-_*kR~8(+RRFE1NidtSUBgQyJTTCcsZnKqc(8{@P&yAQ4M@XEHeq% zRZ-{Wk5+zXv-sMrT{>VWn6I?cjE%rFQM6pa(#BzD08{2}vG*AQ@n!I;=}dHm`ij6G zhJhE)^fkh{drFth%hC@WDBXdK7b}P7w>XIlWKykUWU1OK+~VO?SV!Eg(d(P3ZKO^I~6G=0<7=MVl`w zQY`I`B``1Nygh1sf>yP>zWe7qC)hdu^17nQs(eNI78R21*co6h<1;4V6cObdyAXxbuL9+a_MlASQ>FVWN8>Z{0zFF>1KYF-m=vvW@qWOt!{D!#Sz+( z?Xv+S^m1k)<9i`Fu7<d!L%fv)X3-bz(djSaGAA?2QpP5kABex2v($5-u_HN^0Kfir zEhxQsaW$Tzq&x|^@Wl71#^}g%1oa7NDl7F+t8n^Onk*yw3l!T1f+oKoQ+fN>Gt1XO z(Dx#5b7fVFs|c@ zG2MswHC|-{xfIZ2-gOeGn&+$BY}q#-ZcE`~SWutZK#HiwUyLezt_lupIjtL_y3=;U z4FXd}K`~`Ve3C7@95xL@`7FHJ)>~gLe%wYg8!PJ}#+zY$kGO(rq|Vmk{knud#6qM$w?v0@qM1+}3Roh6$p!$pWz)XJB`_ryj^`_P7wui)gco( zaV8vcit|5OSc{;0icX{xQ{?Togo;Yl5L-o{y0iV)ZApnTTICq?ZLC+JPjpC&p=~dB z-A^&sFT54#u489WH#@n2uZ5ybOmdXfs!Jr)N7XBDv>?N7Y^3c`dBU<2tQ5uhi6Q3B z#uBQPse3u3LpUT!J=t+!_>R%5cFLoBu3b2>K_eSQRq)K#`^M3i;XZjqZDlGbGG6r= zO_z?Nmoy;#f&HDE?tYRc0lWupunX}vn~INrv+*da#uUwwNBfBi@;Hm0t(h`v`k2#l z!8q2 z*w~viN}q~l=aVXR$3d&r_cCW@feXcfK{?ExBr;Q%)kf0@dZ0?B9AQE{&fTGy3!uFB$ z@^^)!I!(;!EEn%}7VoCMiF&tpZJ1V7KY{ot+}{!l5T(I<|G9{gl!JmcK2BQ2Vi@@! zC5T08h-i2d!bc}-Hzn~=LNrV6?UySnoFUO>bL=6{Zy}ycqDycG9O_ zgYeC_l4a?LLV{;DTTeaYJ?o;O{IVu1TSKCKuQh5_HY${RBXCktT%KQXDybT!m$b=* zv0)lgbDvE5`34#PxIt_+dWyg4_*x)qT}ez`ng;Rs4-!%#Uebd_qPC=T>E?h+is$zU zL!wX~aAL0nZ5rd-G54c|l9@_vwiIgrfDAQPVJ&QpE&1EzAiC&qv%B9)2X$l0J7+So z>}eGqOYry%;$&Zii9S!iE|fS!v&M4{8i2@>>Oqfb52*|g^{Z+1ulQp1kOE6b87?f| zV=g*0G%-G7Tp~xOd*8Dk7{#m`GEpeqL^XN(B>oZCKI5%B8}*x;_dD;*_%z%Vxk!Zp zeLSaQixrCr1Zs!sdYGF7{xxg1Lreky9Qa}s_QE;H64lxLy6q#6zB53pSGyhUY14Jt zK=t%}(iP!M47dF*LCePd63IAgCZqJQ`A zscfUMc5L>SAvCCeE)T%slLM`{1X0b1ED4TB0Pd!^ApvpP^=$Vd2e+a;gnRCNQ)mL? zG&4ikQ6+_m`LBQRIg2>z*|Q$qh_MkZI1K8kqGIwAsd>PipZ9z6nwA<8!J;?Jsfgr+ zj0tl;*t1}M0cI9cSbtIiTj>*Czx85kZKNJhclmZwv5rNaCsstTZ}!aq4iYprEuX_i&rDxw``v2V2J`d=^)lr0-q>x=n5>dYidFzboIFgwFr+lK z-DP$1b_S=)y(4=hcuSLENo(B}yam>5`AkEWW!feDo08#g{CdEJ2KWNGF4Z}-Pqo8B za&)h7-rN?1xFNd<4OdPJtK^l0EFB^v?w zM4}p>jlOE`O@!gfuNMLmw9~zed5gsw7Ny=n_n=yh5Aqs*JH^e#ZrA;=6E0vXV=#6bPjR+=SGFt2FBravOC070MJUPeC6CI;MjF*<>G zvlZopiGtW)8;Ft{V1GzGbm@s(nT%j~!T!=$P46aKO*AEHXtCmL^s7}v8qWIRN?VDw zC?@q#V@&cnG*#@Q&8{%VL2Hc%V_x8@lR#$fm2k?GpsDmtcx<6PZ$kZ>lgKzofueL7 zgU{Y`*7YojZEgaIQZql&3 zciRIbD`@yZ?N%$LXPbkK2CX)gn&?f}U@40A`72rWUcG_EZ^&b~5eo!?KEH0B1nLTf zLvENk6ixQ;ln&^UT?scShQ?VQXfcs9rz)qsNqw`yL#tlmNz+}2K+b^ljBoR}N1C_0 z`wn)r^G>fy)3tjLIGc0?-jSx%!{3MfyWS5}sM-4PvCWPTo8)?PqGy{SyiQM_anmmI z1#y*1S2*T96;YyluW+2lvX4*b^%jPRD8~69$OX=st-?7#%WF_I7%3Q|f1iK<)Lq95 zEJm~jbc`{q6Qtbb7tuEaUHMaQnS^IIIw1(qjLR^f4D)9IwOu z{|QYk1iyJ(zidDO5QvXZbInnvsx?tuQa4$^r2J8{(Xd|xTW_jxMbmd%UnjC{lRCY9 zf=do&;2@ywi6?{#r_cGLZe0r)_XocRbI_PE-Xo=j-{-D5_giYegxp~t!Ldoq`kwd= z+~nV9SUVXavtdqX2w~Uis6e!?+j?hwZE0Lyp41u}KmHd>S9)Obpb+1I3|oM~EOX}M zFZgmq`Wj0&kCw=?Gqdsn81HZz( z4Hyvp5H1dvBYN!kT^ZnqfSSMgQw9_|X0hXNAP3>s8u08%o>=I61)<9a_{^)-<)YS6 zlE4+%vf!BospY{??$fg>;+5m|f_3(;1!=b9*JZ(rr9;0V$bm-dkWe*lEfn)3#pJa+RuD76l^d8|Cv%26|c!OsP$DjRR zpGl)Bu7UY$n}$s}I#>lTtn39W^D0YVvF}P}uJ+Pl0W8*ug@Ze>DRv+Kw*sX9J7^>} a#n)u-Sl$jNllQp%htyKjQ>{_9iTp2r`pl#N literal 0 HcmV?d00001 diff --git a/docs/cartesian_zones.png.license b/docs/cartesian_zones.png.license new file mode 100644 index 0000000..a879c67 --- /dev/null +++ b/docs/cartesian_zones.png.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: 2021 Jose David M. + +SPDX-License-Identifier: MIT \ No newline at end of file From ecf503684d3765c9c1f10550743afc628c6224cf Mon Sep 17 00:00:00 2001 From: jposada202020 Date: Thu, 25 Mar 2021 09:43:24 -0400 Subject: [PATCH 24/36] =?UTF-8?q?#=20UPDATE:=20End=20of=20license=20Files?= =?UTF-8?q?=20=20=20=20=20=20=20[=E2=88=9A]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/cartesian.gif.license | 2 +- docs/cartesian_explanation.png.license | 2 +- docs/cartesian_zones.png.license | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/cartesian.gif.license b/docs/cartesian.gif.license index a879c67..a55a809 100644 --- a/docs/cartesian.gif.license +++ b/docs/cartesian.gif.license @@ -1,3 +1,3 @@ SPDX-FileCopyrightText: 2021 Jose David M. -SPDX-License-Identifier: MIT \ No newline at end of file +SPDX-License-Identifier: MIT diff --git a/docs/cartesian_explanation.png.license b/docs/cartesian_explanation.png.license index a879c67..a55a809 100644 --- a/docs/cartesian_explanation.png.license +++ b/docs/cartesian_explanation.png.license @@ -1,3 +1,3 @@ SPDX-FileCopyrightText: 2021 Jose David M. -SPDX-License-Identifier: MIT \ No newline at end of file +SPDX-License-Identifier: MIT diff --git a/docs/cartesian_zones.png.license b/docs/cartesian_zones.png.license index a879c67..a55a809 100644 --- a/docs/cartesian_zones.png.license +++ b/docs/cartesian_zones.png.license @@ -1,3 +1,3 @@ SPDX-FileCopyrightText: 2021 Jose David M. -SPDX-License-Identifier: MIT \ No newline at end of file +SPDX-License-Identifier: MIT From 3b5d1f244a1e3edfab30a50fe5f0a5aec757342a Mon Sep 17 00:00:00 2001 From: jposada202020 Date: Thu, 25 Mar 2021 09:49:55 -0400 Subject: [PATCH 25/36] =?UTF-8?q?#=20UPDATE:=20Remove=20Duplicate=20graph?= =?UTF-8?q?=20=20=20=20=20=20[=E2=88=9A]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- adafruit_displayio_layout/widgets/cartesian.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/adafruit_displayio_layout/widgets/cartesian.py b/adafruit_displayio_layout/widgets/cartesian.py index 7765528..8c7374b 100644 --- a/adafruit_displayio_layout/widgets/cartesian.py +++ b/adafruit_displayio_layout/widgets/cartesian.py @@ -122,14 +122,6 @@ class Cartesian(Widget): This is a diagram of a cartesian widget showing the different zones. - .. figure:: cartesian_zones.png - :scale: 100 % - :figwidth: 50% - :align: center - :alt: Diagram of the cartesian widget zones. - - This is a diagram of a cartesian widget showing the different zones. - .. figure:: cartesian_explanation.png :scale: 100 % :figwidth: 50% From d35ffd6b8a8c6aad52855fb841c2fd9a4fdee157 Mon Sep 17 00:00:00 2001 From: jposada202020 Date: Thu, 25 Mar 2021 14:01:37 -0400 Subject: [PATCH 26/36] =?UTF-8?q?#=20UPDATE:=20spaces=20=20=20=20=20[?= =?UTF-8?q?=E2=88=9A]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- adafruit_displayio_layout/widgets/cartesian.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/adafruit_displayio_layout/widgets/cartesian.py b/adafruit_displayio_layout/widgets/cartesian.py index 8c7374b..6cf7657 100644 --- a/adafruit_displayio_layout/widgets/cartesian.py +++ b/adafruit_displayio_layout/widgets/cartesian.py @@ -409,8 +409,9 @@ def _draw_pointers(self, x: int, y: int) -> None: def update_pointer(self, x: int, y: int) -> None: """updater_pointer 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 + + :param int x: ``x`` coordinate in the local plane + :param int y: ``y`` coordinate in the local plane :return: None rtype: None """ @@ -431,9 +432,11 @@ def _set_plotter_line(self) -> None: 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 + + :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) From 7506b245768c0c2c035f8598f1f57a693cb9b5eb Mon Sep 17 00:00:00 2001 From: jposada202020 Date: Thu, 25 Mar 2021 14:09:36 -0400 Subject: [PATCH 27/36] =?UTF-8?q?#=20UPDATE:=20spaces=20=20=20=20=20[?= =?UTF-8?q?=E2=88=9A]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- adafruit_displayio_layout/widgets/cartesian.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/adafruit_displayio_layout/widgets/cartesian.py b/adafruit_displayio_layout/widgets/cartesian.py index 6cf7657..2a022cf 100644 --- a/adafruit_displayio_layout/widgets/cartesian.py +++ b/adafruit_displayio_layout/widgets/cartesian.py @@ -409,7 +409,6 @@ def _draw_pointers(self, x: int, y: int) -> None: def update_pointer(self, x: int, y: int) -> None: """updater_pointer 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 @@ -432,11 +431,9 @@ def _set_plotter_line(self) -> None: 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) From 40bb7a2f453f192a88d8cab571e791953da220db Mon Sep 17 00:00:00 2001 From: jposada202020 Date: Thu, 25 Mar 2021 15:35:11 -0400 Subject: [PATCH 28/36] =?UTF-8?q?#=20UPDATE:=20docsstrings=20=20=20=20=20[?= =?UTF-8?q?=E2=88=9A]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../widgets/cartesian.py | 48 ++++++++++++++----- 1 file changed, 35 insertions(+), 13 deletions(-) diff --git a/adafruit_displayio_layout/widgets/cartesian.py b/adafruit_displayio_layout/widgets/cartesian.py index 2a022cf..6430e79 100644 --- a/adafruit_displayio_layout/widgets/cartesian.py +++ b/adafruit_displayio_layout/widgets/cartesian.py @@ -48,23 +48,23 @@ class Cartesian(Widget): :param int y: y position of the plane origin :param int background_color: background color to use defaults to black (0x000000) - :param int width: requested width, in pixels defaults to 100 pixels - :param int height: requested height, in pixels defaults to 100 pixels + :param int width: requested width, in pixels. + :param int height: requested height, in pixels. - :param (int, int) xrange: X axes range - :param (int, int) yrange: Y axes range + :param (int, int) xrange: X axes range. Defaults to (0, 100) + :param (int, int) yrange: Y axes range. Defaults to (0, 100) :param int axes_color: axes lines color defaults to white (0xFFFFFF) :param int axes_stroke: axes lines thickness in pixels defaults to 2 - :param int major_tick_stroke: tick lines thickness in pixels dafaults to 1 + :param int major_tick_stroke: tick lines thickness in pixels defaults to 1 :param int major_tick_length: tick lines length in pixels defaults to 5 :param int tick_label_font: tick label text font - :param int font_color: font color + :param int font_color: font color. Defaults to white (0xFFFFFF) :param int pointer_radius: pointer radius in pixels defaults to 1 - :param int pointer_color: pointer color defaults to white (0xFFFFFF) + :param int pointer_color: pointer color. Defaults to white (0xFFFFFF) **Quickstart: Importing and using Cartesian** @@ -105,6 +105,27 @@ class Cartesian(Widget): display.show(my_group) # add the group to the display + **Summary: Cartesian Features and input variables** + + The `cartesian` widget has some options for controlling its position, visible appearance, + and scale through a collection of input variables: + + - **position**: ``x``, ``y`` or ``anchor_point`` and ``anchored_position`` + + - **size**: ``width`` and ``height`` + + - **color**: ``axes_color``, ``font_color``, ``tick_color``, ``pointer_color`` + + - **background color**: ``background_color`` + + - **linewidths**: ``axes_stroke`` and ``major_tick_stroke`` + + - **range**: ``xrange`` and ``yrange`` This is the range in absolute units. + For example, when using (20-90), the X axis will start at 20 finishing at 90. + However the height of the graph is given by the height parameter. The scale + is handled internal to provide a 1:1 experience when you update the graph. + + .. figure:: cartesian.gif :scale: 100 % :figwidth: 50% @@ -134,7 +155,7 @@ class Cartesian(Widget): def __init__( self, - background_color=0x000000, + background_color: int = 0x000000, xrange: Tuple[int, int] = (0, 100), yrange: Tuple[int, int] = (0, 100), axes_color: int = 0xFFFFFF, @@ -465,9 +486,10 @@ def set_widget_style(self, new_style: str) -> None: try: from adafruit_styles import get_hex from adafruit_styles import styles + + colorset = styles.THEME + self._pointer_color = get_hex(colorset[new_style]["TEXT"]) + self._font_color = get_hex(colorset[new_style]["TEXT"]) + self._draw_ticks() except ImportError: - pass - colorset = styles.THEME - self._pointer_color = get_hex(colorset[new_style]["TEXT"]) - self._font_color = get_hex(colorset[new_style]["TEXT"]) - self._draw_ticks() + print("This feature is not yet implemented") From 1377f4a14f226c1aada00f438dac44d5fd36b314 Mon Sep 17 00:00:00 2001 From: jposada202020 Date: Thu, 25 Mar 2021 16:25:31 -0400 Subject: [PATCH 29/36] =?UTF-8?q?#=20UPDATE:=20docstrings=20=20=20=20=20[?= =?UTF-8?q?=E2=88=9A]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- adafruit_displayio_layout/widgets/cartesian.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adafruit_displayio_layout/widgets/cartesian.py b/adafruit_displayio_layout/widgets/cartesian.py index 6430e79..fa0abc4 100644 --- a/adafruit_displayio_layout/widgets/cartesian.py +++ b/adafruit_displayio_layout/widgets/cartesian.py @@ -60,7 +60,7 @@ class Cartesian(Widget): :param int major_tick_stroke: tick lines thickness in pixels defaults to 1 :param int major_tick_length: tick lines length in pixels defaults to 5 - :param int tick_label_font: tick label text font + :param terminalio.FONT tick_label_font: tick label text font :param int font_color: font color. Defaults to white (0xFFFFFF) :param int pointer_radius: pointer radius in pixels defaults to 1 From 2db1bbf05d727667897cf0b342a2d0e61d0a32ff Mon Sep 17 00:00:00 2001 From: jposada202020 Date: Thu, 25 Mar 2021 22:33:30 -0400 Subject: [PATCH 30/36] =?UTF-8?q?#=20UPDATE:=20Corrections.=20Corner=20Bit?= =?UTF-8?q?map,=20Simpletest=20=20=20=20=20[=E2=88=9A]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../widgets/cartesian.py | 19 +++++++++++++++++++ .../displayio_layout_cartesian_simpletest.py | 7 ++----- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/adafruit_displayio_layout/widgets/cartesian.py b/adafruit_displayio_layout/widgets/cartesian.py index fa0abc4..1a82048 100644 --- a/adafruit_displayio_layout/widgets/cartesian.py +++ b/adafruit_displayio_layout/widgets/cartesian.py @@ -247,6 +247,24 @@ def __init__( self._screen_palette[4] = 0xFFFFFF self._screen_palette[5] = self._background_color + self._corner_bitmap = displayio.Bitmap(10, 10, 5) + rectangle_helper( + 0, + 0, + self._axes_line_thickness, + self._axes_line_thickness, + self._corner_bitmap, + 2, + self._screen_palette, + ) + + self._corner_tilegrid = displayio.TileGrid( + self._corner_bitmap, + pixel_shader=self._screen_palette, + x=-self._axes_line_thickness, + y=self.height, + ) + self._axesx_tilegrid = displayio.TileGrid( self._axesx_bitmap, pixel_shader=self._screen_palette, @@ -274,6 +292,7 @@ def __init__( self.append(self._axesx_tilegrid) self.append(self._axesy_tilegrid) self.append(self._screen_tilegrid) + self.append(self._corner_tilegrid) self._update_line = True diff --git a/examples/displayio_layout_cartesian_simpletest.py b/examples/displayio_layout_cartesian_simpletest.py index 6ab4b4b..ee5727f 100644 --- a/examples/displayio_layout_cartesian_simpletest.py +++ b/examples/displayio_layout_cartesian_simpletest.py @@ -42,9 +42,6 @@ posx = 0 posy = 0 -while True: - my_plane.update_pointer(posx, posy) - display.show(my_group) +for i in range(0, 90, 2): + my_plane.update_pointer(i, i) time.sleep(0.5) - posx = posx + 2 - posy = posy + 2 From 636b449344df34e425b854f7d61434d3194a5d46 Mon Sep 17 00:00:00 2001 From: jposada202020 Date: Sun, 28 Mar 2021 12:16:33 -0400 Subject: [PATCH 31/36] =?UTF-8?q?#=20UPDATE:=20for=20loop=20inside=20while?= =?UTF-8?q?=20=20=20=20=20[=E2=88=9A]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/displayio_layout_cartesian_simpletest.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/examples/displayio_layout_cartesian_simpletest.py b/examples/displayio_layout_cartesian_simpletest.py index ee5727f..2f5a881 100644 --- a/examples/displayio_layout_cartesian_simpletest.py +++ b/examples/displayio_layout_cartesian_simpletest.py @@ -42,6 +42,7 @@ posx = 0 posy = 0 -for i in range(0, 90, 2): - my_plane.update_pointer(i, i) - time.sleep(0.5) +while True: + for i in range(0, 90, 2): + my_plane.update_pointer(i, i) + time.sleep(0.5) From e05033d2b9e1bf7cac18fa2817aeef1750524082 Mon Sep 17 00:00:00 2001 From: jposada202020 Date: Sun, 28 Mar 2021 13:57:05 -0400 Subject: [PATCH 32/36] =?UTF-8?q?#=20UPDATE:=20adding=20nudge=20parameter,?= =?UTF-8?q?=20update=20docs,=20and=20function=20=20=20=20[=E2=88=9A]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../widgets/cartesian.py | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/adafruit_displayio_layout/widgets/cartesian.py b/adafruit_displayio_layout/widgets/cartesian.py index 1a82048..3beb17d 100644 --- a/adafruit_displayio_layout/widgets/cartesian.py +++ b/adafruit_displayio_layout/widgets/cartesian.py @@ -66,6 +66,13 @@ class Cartesian(Widget): :param int pointer_radius: pointer radius in pixels defaults to 1 :param int pointer_color: pointer color. Defaults to white (0xFFFFFF) + :param bool subticks: inclusion of subticks in the plot area. Default to False + + :param int nudge_x: movement in pixels in the x direction to move the origin. + Defaults to 0 + :param int nudge_y: movement in pixels in the y direction to move the origin. + Defaults to 0 + **Quickstart: Importing and using Cartesian** @@ -110,7 +117,10 @@ class Cartesian(Widget): The `cartesian` widget has some options for controlling its position, visible appearance, and scale through a collection of input variables: - - **position**: ``x``, ``y`` or ``anchor_point`` and ``anchored_position`` + - **position**: ``x``, ``y``, ``anchor_point``, ``anchored_position`` and + `nudge_x`, `nudge_y`. Nudge parameters are used to account for the float and int + conversions required to display different ranges and values. Conversion are required + as displays work in integers and not floats - **size**: ``width`` and ``height`` @@ -168,6 +178,8 @@ def __init__( pointer_radius: int = 1, pointer_color: int = 0xFFFFFF, subticks: bool = False, + nudge_x: int = 0, + nudge_y: int = 0, **kwargs, ) -> None: @@ -286,6 +298,9 @@ def __init__( y=0, ) + self._nudge_x = nudge_x + self._nudge_y = nudge_y + self._draw_axes() self._draw_ticks() @@ -476,8 +491,10 @@ def update_line(self, x: int, y: int) -> None: :return: None rtype: None """ - local_x = int((x - self._xrange[0]) * self._factorx) - local_y = int((self._yrange[0] - y) * self._factory) + self.height + 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: From c691045cf60ebf7657c816ae20a39ae666d7170d Mon Sep 17 00:00:00 2001 From: jposada202020 Date: Sun, 28 Mar 2021 14:14:32 -0400 Subject: [PATCH 33/36] =?UTF-8?q?#=20UPDATE:=20correcting=20``nudge=5Fx``,?= =?UTF-8?q?=20``nudge=5Fy``=20=20=20=20[=E2=88=9A]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- adafruit_displayio_layout/widgets/cartesian.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adafruit_displayio_layout/widgets/cartesian.py b/adafruit_displayio_layout/widgets/cartesian.py index 3beb17d..ba16752 100644 --- a/adafruit_displayio_layout/widgets/cartesian.py +++ b/adafruit_displayio_layout/widgets/cartesian.py @@ -118,7 +118,7 @@ class Cartesian(Widget): and scale through a collection of input variables: - **position**: ``x``, ``y``, ``anchor_point``, ``anchored_position`` and - `nudge_x`, `nudge_y`. Nudge parameters are used to account for the float and int + ``nudge_x``, ``nudge_y``. Nudge parameters are used to account for the float and int conversions required to display different ranges and values. Conversion are required as displays work in integers and not floats From a0d98ae6f74ac5af0aef4354435861b2c90d7ecd Mon Sep 17 00:00:00 2001 From: jposada202020 Date: Mon, 29 Mar 2021 22:16:05 -0400 Subject: [PATCH 34/36] =?UTF-8?q?#=20TODO:=20Including=20nudge=20in=20th?= =?UTF-8?q?=20update=20function=20=20=20=20[=E2=88=9A]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- adafruit_displayio_layout/widgets/cartesian.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/adafruit_displayio_layout/widgets/cartesian.py b/adafruit_displayio_layout/widgets/cartesian.py index ba16752..f639c8f 100644 --- a/adafruit_displayio_layout/widgets/cartesian.py +++ b/adafruit_displayio_layout/widgets/cartesian.py @@ -469,8 +469,10 @@ def update_pointer(self, x: int, y: int) -> None: :return: None rtype: None """ - local_x = int((x - self._xrange[0]) * self._factorx) - local_y = int((self._yrange[0] - y) * self._factory) + self.height + 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 local_x >= 0 or local_y <= 100: if self._update_line: From b07162c6999cd8a54d5f4406057577a0460bcfe0 Mon Sep 17 00:00:00 2001 From: Adafruit Adabot Date: Sat, 3 Apr 2021 11:44:52 -0400 Subject: [PATCH 35/36] # Correcting the off bit dimension --- adafruit_displayio_layout/widgets/__init__.py | 4 +--- .../widgets/cartesian.py | 21 +------------------ 2 files changed, 2 insertions(+), 23 deletions(-) diff --git a/adafruit_displayio_layout/widgets/__init__.py b/adafruit_displayio_layout/widgets/__init__.py index a02e091..ed1bae9 100644 --- a/adafruit_displayio_layout/widgets/__init__.py +++ b/adafruit_displayio_layout/widgets/__init__.py @@ -53,9 +53,7 @@ def rectangle_helper( """ if bitmaptool: - bitmaptools.fill_region( - bitmap, x0, y0, x0 + width - 1, y0 + height - 1, color_index - ) + bitmaptools.fill_region(bitmap, x0, y0, x0 + width, y0 + height, color_index) else: rect = vectorio.Rectangle(width, height) vectorio.VectorShape( diff --git a/adafruit_displayio_layout/widgets/cartesian.py b/adafruit_displayio_layout/widgets/cartesian.py index f639c8f..eee948b 100644 --- a/adafruit_displayio_layout/widgets/cartesian.py +++ b/adafruit_displayio_layout/widgets/cartesian.py @@ -26,8 +26,8 @@ import displayio import terminalio -import vectorio from adafruit_display_text import bitmap_label +import vectorio from adafruit_displayio_layout.widgets.widget import Widget from adafruit_displayio_layout.widgets import rectangle_helper @@ -512,22 +512,3 @@ def update_line(self, x: int, y: int) -> None: local_y, 1, ) - - def set_widget_style(self, new_style: str) -> None: - """set_widget_style function - Allows to set the widget style - :param str new_style: style for the widget - :return: None - """ - # import would change after library packaging - # pylint: disable=import-outside-toplevel - try: - from adafruit_styles import get_hex - from adafruit_styles import styles - - colorset = styles.THEME - self._pointer_color = get_hex(colorset[new_style]["TEXT"]) - self._font_color = get_hex(colorset[new_style]["TEXT"]) - self._draw_ticks() - except ImportError: - print("This feature is not yet implemented") From 001b4efb57a4e10c898a1a8bf1403342c32acc92 Mon Sep 17 00:00:00 2001 From: Adafruit Adabot Date: Sun, 4 Apr 2021 21:00:30 -0400 Subject: [PATCH 36/36] Correcting example to remove the reference to the style library --- examples/displayio_layout_cartesian_advanced_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/displayio_layout_cartesian_advanced_test.py b/examples/displayio_layout_cartesian_advanced_test.py index 10bd6a0..a6b6b89 100644 --- a/examples/displayio_layout_cartesian_advanced_test.py +++ b/examples/displayio_layout_cartesian_advanced_test.py @@ -53,7 +53,7 @@ tick_color=0xFFFFFF, subticks=True, ) -car4.set_widget_style("LightGreen6") + my_group.append(car4) car5 = Cartesian(