acid-drop

- Hacking the planet from a LilyGo T-Deck using custom firmware
git clone git://git.acid.vegas/acid-drop.git
Log | Files | Refs | Archive | README | LICENSE

lv_example_chart_8.py (4692B)

      1 import display_driver
      2 import lvgl as lv
      3 
      4 # A class is used to keep track of the series list because later we
      5 #  need to draw to the series in the reverse order to which they were initialised.
      6 class StackedAreaChart:
      7     def __init__(self):
      8         self.obj = None
      9         self.series_list = [None, None, None]
     10 
     11 stacked_area_chart = StackedAreaChart()
     12 
     13 #
     14 # Callback which draws the blocks of colour under the lines
     15 #
     16 def draw_event_cb(e):
     17 
     18     obj = e.get_target()
     19     cont_a = lv.area_t()
     20     obj.get_coords(cont_a)
     21 
     22     #Add the faded area before the lines are drawn
     23     dsc = e.get_draw_part_dsc()
     24     if dsc.part == lv.PART.ITEMS:
     25         if not dsc.p1 or not dsc.p2:
     26             return
     27 
     28         # Add a line mask that keeps the area below the line
     29         line_mask_param = lv.draw_mask_line_param_t()
     30         line_mask_param.points_init(dsc.p1.x, dsc.p1.y, dsc.p2.x, dsc.p2.y, lv.DRAW_MASK_LINE_SIDE.BOTTOM)
     31         line_mask_id = lv.draw_mask_add(line_mask_param, None)
     32 
     33         #Draw a rectangle that will be affected by the mask
     34         draw_rect_dsc = lv.draw_rect_dsc_t()
     35         draw_rect_dsc.init()
     36         draw_rect_dsc.bg_opa = lv.OPA.COVER
     37         draw_rect_dsc.bg_color = dsc.line_dsc.color
     38 
     39         a = lv.area_t()
     40         a.x1 = dsc.p1.x
     41         a.x2 = dsc.p2.x
     42         a.y1 = min(dsc.p1.y, dsc.p2.y)
     43         a.y2 = cont_a.y2 - 13 # -13 cuts off where the rectangle draws over the chart margin. Without this an area of 0 doesn't look like 0
     44         dsc.draw_ctx.rect(draw_rect_dsc, a)
     45 
     46         # Remove the mask
     47         lv.draw_mask_free_param(line_mask_param)
     48         lv.draw_mask_remove_id(line_mask_id)
     49 
     50 
     51 #
     52 # Helper function to round a fixed point number
     53 #
     54 def round_fixed_point(n, shift):
     55     # Create a bitmask to isolates the decimal part of the fixed point number
     56     mask = 1
     57     for bit_pos in range(shift):
     58         mask = (mask << 1) + 1
     59 
     60     decimal_part = n & mask
     61 
     62     # Get 0.5 as fixed point
     63     rounding_boundary = 1 << (shift - 1)
     64 
     65     # Return either the integer part of n or the integer part + 1
     66     if decimal_part < rounding_boundary:
     67         return (n & ~mask)
     68     return ((n >> shift) + 1) << shift
     69 
     70 
     71 #
     72 # Stacked area chart
     73 #
     74 def lv_example_chart_8():
     75 
     76     #Create a stacked_area_chart.obj
     77     stacked_area_chart.obj = lv.chart(lv.scr_act())
     78     stacked_area_chart.obj.set_size(200, 150)
     79     stacked_area_chart.obj.center()
     80     stacked_area_chart.obj.set_type( lv.chart.TYPE.LINE)
     81     stacked_area_chart.obj.set_div_line_count(5, 7)
     82     stacked_area_chart.obj.add_event_cb( draw_event_cb, lv.EVENT.DRAW_PART_BEGIN, None)
     83 
     84     # Set range to 0 to 100 for percentages. Draw ticks
     85     stacked_area_chart.obj.set_range(lv.chart.AXIS.PRIMARY_Y,0,100)
     86     stacked_area_chart.obj.set_axis_tick(lv.chart.AXIS.PRIMARY_Y, 3, 0, 5, 1, True, 30)
     87 
     88     #Set point size to 0 so the lines are smooth
     89     stacked_area_chart.obj.set_style_size(0, lv.PART.INDICATOR)
     90 
     91     # Add some data series
     92     stacked_area_chart.series_list[0] = stacked_area_chart.obj.add_series(lv.palette_main(lv.PALETTE.RED), lv.chart.AXIS.PRIMARY_Y)
     93     stacked_area_chart.series_list[1] = stacked_area_chart.obj.add_series(lv.palette_main(lv.PALETTE.BLUE), lv.chart.AXIS.PRIMARY_Y)
     94     stacked_area_chart.series_list[2] = stacked_area_chart.obj.add_series(lv.palette_main(lv.PALETTE.GREEN), lv.chart.AXIS.PRIMARY_Y)
     95 
     96     for point in range(10):
     97         # Make some random data
     98         vals = [lv.rand(10, 20), lv.rand(20, 30), lv.rand(20, 30)]
     99 
    100         fixed_point_shift = 5
    101         total = vals[0] + vals[1] + vals[2]
    102         draw_heights = [0, 0, 0]
    103         int_sum = 0
    104         decimal_sum = 0
    105 
    106         # Fixed point cascade rounding ensures percentages add to 100
    107         for series_index in range(3):
    108             decimal_sum += int(((vals[series_index] * 100) << fixed_point_shift) // total)
    109             int_sum += int((vals[series_index] * 100) / total)
    110 
    111             modifier = (round_fixed_point(decimal_sum, fixed_point_shift) >> fixed_point_shift) - int_sum
    112 
    113             #  The draw heights are equal to the percentage of the total each value is + the cumulative sum of the previous percentages.
    114             #   The accumulation is how the values get "stacked"
    115             draw_heights[series_index] = int(int_sum + modifier)
    116 
    117             #  Draw to the series in the reverse order to which they were initialised.
    118             #   Without this the higher values will draw on top of the lower ones.
    119             #   This is because the Z-height of a series matches the order it was initialised
    120             stacked_area_chart.obj.set_next_value( stacked_area_chart.series_list[3 - series_index - 1], draw_heights[series_index])
    121 
    122     stacked_area_chart.obj.refresh()
    123 
    124 lv_example_chart_8()