2021-09-13 11:11:10 +01:00
# include "../../lv_examples.h"
2023-07-05 13:05:19 +02:00
//TODO Should be a chart feature
2023-07-10 05:27:32 +08:00
# if LV_USE_CHART && LV_DRAW_SW_COMPLEX && LV_BUILD_EXAMPLES && 0
2021-09-13 11:11:10 +01:00
/* A struct is used to keep track of the series list because later we need to draw to the series in the reverse order to which they were initialised. */
2022-02-13 13:59:17 -05:00
typedef struct {
lv_obj_t * obj ;
lv_chart_series_t * series_list [ 3 ] ;
2021-09-13 11:11:10 +01:00
} stacked_area_chart_t ;
static stacked_area_chart_t stacked_area_chart ;
/**
* Callback which draws the blocks of colour under the lines
* */
2022-02-13 13:59:17 -05:00
static void draw_event_cb ( lv_event_t * e )
2021-09-13 11:11:10 +01:00
{
2022-02-13 13:59:17 -05:00
lv_obj_t * obj = lv_event_get_target ( e ) ;
2021-09-13 11:11:10 +01:00
/*Add the faded area before the lines are drawn*/
2022-02-13 13:59:17 -05:00
lv_obj_draw_part_dsc_t * dsc = lv_event_get_draw_part_dsc ( e ) ;
if ( dsc - > part = = LV_PART_ITEMS ) {
if ( ! dsc - > p1 | | ! dsc - > p2 )
2021-09-13 11:11:10 +01:00
return ;
/*Add a line mask that keeps the area below the line*/
lv_draw_mask_line_param_t line_mask_param ;
2022-02-13 13:59:17 -05:00
lv_draw_mask_line_points_init ( & line_mask_param , dsc - > p1 - > x , dsc - > p1 - > y , dsc - > p2 - > x , dsc - > p2 - > y ,
LV_DRAW_MASK_LINE_SIDE_BOTTOM ) ;
2021-09-13 11:11:10 +01:00
int16_t line_mask_id = lv_draw_mask_add ( & line_mask_param , NULL ) ;
/*Draw a rectangle that will be affected by the mask*/
lv_draw_rect_dsc_t draw_rect_dsc ;
lv_draw_rect_dsc_init ( & draw_rect_dsc ) ;
draw_rect_dsc . bg_opa = LV_OPA_COVER ;
draw_rect_dsc . bg_color = dsc - > line_dsc - > color ;
lv_area_t a ;
a . x1 = dsc - > p1 - > x ;
a . x2 = dsc - > p2 - > x ;
a . y1 = LV_MIN ( dsc - > p1 - > y , dsc - > p2 - > y ) ;
2022-02-13 13:59:17 -05:00
a . y2 = obj - > coords . y2 -
13 ; /* -13 cuts off where the rectangle draws over the chart margin. Without this an area of 0 doesn't look like 0 */
2023-07-05 13:05:19 +02:00
lv_draw_rect ( dsc - > layer , & draw_rect_dsc , & a ) ;
2021-09-13 11:11:10 +01:00
/*Remove the mask*/
lv_draw_mask_free_param ( & line_mask_param ) ;
lv_draw_mask_remove_id ( line_mask_id ) ;
}
}
/**
* Helper function to round a fixed point number
* */
static int32_t round_fixed_point ( int32_t n , int8_t shift )
{
/* Create a bitmask to isolates the decimal part of the fixed point number */
int32_t mask = 1 ;
2022-02-13 13:59:17 -05:00
for ( int32_t bit_pos = 0 ; bit_pos < shift ; bit_pos + + ) {
2021-09-13 11:11:10 +01:00
mask = ( mask < < 1 ) + 1 ;
}
int32_t decimal_part = n & mask ;
/* Get 0.5 as fixed point */
int32_t rounding_boundary = 1 < < ( shift - 1 ) ;
/* Return either the integer part of n or the integer part + 1 */
return ( decimal_part < rounding_boundary ) ? ( n & ~ mask ) : ( ( n > > shift ) + 1 ) < < shift ;
}
/**
* Stacked area chart
*/
void lv_example_chart_8 ( void )
{
/*Create a stacked_area_chart.obj*/
2023-10-12 20:37:27 +02:00
stacked_area_chart . obj = lv_chart_create ( lv_screen_active ( ) ) ;
2021-09-13 11:11:10 +01:00
lv_obj_set_size ( stacked_area_chart . obj , 200 , 150 ) ;
lv_obj_center ( stacked_area_chart . obj ) ;
lv_chart_set_type ( stacked_area_chart . obj , LV_CHART_TYPE_LINE ) ;
lv_chart_set_div_line_count ( stacked_area_chart . obj , 5 , 7 ) ;
2023-02-20 20:50:58 +01:00
lv_obj_add_event ( stacked_area_chart . obj , draw_event_cb , LV_EVENT_DRAW_PART_BEGIN , NULL ) ;
2021-09-13 11:11:10 +01:00
/* Set range to 0 to 100 for percentages. Draw ticks */
2022-02-13 13:59:17 -05:00
lv_chart_set_range ( stacked_area_chart . obj , LV_CHART_AXIS_PRIMARY_Y , 0 , 100 ) ;
2021-09-13 11:11:10 +01:00
lv_chart_set_axis_tick ( stacked_area_chart . obj , LV_CHART_AXIS_PRIMARY_Y , 3 , 0 , 5 , 1 , true , 30 ) ;
/*Set point size to 0 so the lines are smooth */
2022-07-19 15:46:51 +02:00
lv_obj_set_style_size ( stacked_area_chart . obj , 0 , 0 , LV_PART_INDICATOR ) ;
2021-09-13 11:11:10 +01:00
/*Add some data series*/
2022-02-13 13:59:17 -05:00
stacked_area_chart . series_list [ 0 ] = lv_chart_add_series ( stacked_area_chart . obj , lv_palette_main ( LV_PALETTE_RED ) ,
LV_CHART_AXIS_PRIMARY_Y ) ;
stacked_area_chart . series_list [ 1 ] = lv_chart_add_series ( stacked_area_chart . obj , lv_palette_main ( LV_PALETTE_BLUE ) ,
LV_CHART_AXIS_PRIMARY_Y ) ;
stacked_area_chart . series_list [ 2 ] = lv_chart_add_series ( stacked_area_chart . obj , lv_palette_main ( LV_PALETTE_GREEN ) ,
LV_CHART_AXIS_PRIMARY_Y ) ;
for ( int point = 0 ; point < 10 ; point + + ) {
2021-09-13 11:11:10 +01:00
/* Make some random data */
uint32_t vals [ 3 ] = { lv_rand ( 10 , 20 ) , lv_rand ( 20 , 30 ) , lv_rand ( 20 , 30 ) } ;
int8_t fixed_point_shift = 5 ;
uint32_t total = vals [ 0 ] + vals [ 1 ] + vals [ 2 ] ;
uint32_t draw_heights [ 3 ] ;
uint32_t int_sum = 0 ;
uint32_t decimal_sum = 0 ;
/* Fixed point cascade rounding ensures percentages add to 100 */
2022-02-13 13:59:17 -05:00
for ( int32_t series_index = 0 ; series_index < 3 ; series_index + + ) {
2021-09-13 11:11:10 +01:00
decimal_sum + = ( ( ( vals [ series_index ] * 100 ) < < fixed_point_shift ) / total ) ;
int_sum + = ( vals [ series_index ] * 100 ) / total ;
int32_t modifier = ( round_fixed_point ( decimal_sum , fixed_point_shift ) > > fixed_point_shift ) - int_sum ;
/* The draw heights are equal to the percentage of the total each value is + the cumulative sum of the previous percentages.
The accumulation is how the values get " stacked " */
draw_heights [ series_index ] = int_sum + modifier ;
/* Draw to the series in the reverse order to which they were initialised.
Without this the higher values will draw on top of the lower ones .
2022-01-17 14:10:23 +01:00
This is because the Z - height of a series matches the order it was initialised */
2022-02-13 13:59:17 -05:00
lv_chart_set_next_value ( stacked_area_chart . obj , stacked_area_chart . series_list [ 3 - series_index - 1 ] ,
draw_heights [ series_index ] ) ;
2021-09-13 11:11:10 +01:00
}
}
lv_chart_refresh ( stacked_area_chart . obj ) ;
}
2021-10-25 12:44:44 -04:00
# endif