Add space in chart in circular mode

Hello Dear friends.
I am working with charts in circular mode. I am looking for adding some space between the recent data and the oldest data. Now it does stick them together. What should I do to achieve this?

By which I mean to hide 3 to 5 old data and hide them away.

I was thinking about adding such feature but haven’t done yet. You can do it by manually pre-deleting some points.

Just get the the array of the values with lv_chart_get_y_array(chart, ser1), set a point’s value and also set the next 3 or 5 values to LV_CHART_POINT_NONE to add a gap.

So how can one get which place is the current pointing place (index) of the chart for the next value? It would get the array, but it is also important to know which place is, so one can change the value by hand.

So after some thinking, I think you meant that to not use the lv_chart_set_next_value and use the lv_chart_set_ext_y_array?

I’ve added an example, see here: https://github.com/lvgl/lvgl/pull/2565

Thank you,
It’s helpful but it seems it needs more effort.

It’s helpful but it seems it needs more effort.

Is the “more effort” related to “gap”? If so, please let us know. Others may have the same questions.

@kisvegabor I’ve faced some issues and trying to find the source. It may have happend on my side, so when I got assured of the source of the problem, I would notify here.
The problem I have encountered is that in some cases it tries to tie the current point to some points on the grid lines.

Dear @kisvegabor
I know this is an old issue but I have found the symptom, I don’t know if it is due to the origin or if it relies on the way I used the widget. Speaking about “line type chart” in circular mode, following the code in https://github.com/lvgl/lvgl/blob/master/examples/widgets/chart/lv_example_chart_9.c,
if the space between points is considerable, for example about 10 points, the “very old” point of the chart which will be updated by the next update command, tries to stick the newest data inserted into the graph. In this case, the graph ignores that the previous data in the chart is None, but would stick to the data that is not None.

Sorry, I don’t really what the problem is :sweat_smile:

Can you send a code snippet to show the issue?

@kisvegabor I know it is an old topic, but I have encountered this issue another time and now I can explain it more clear. Now I am using version 8.4.0 and I think the problem is the way the chart widget handles the start point to redraw the chart.
Consider that the chart has 512 data points. Chart have written 512 data in advance and it is in the redraw stage. Suppose in the redraw stage the last data have been written at index 200 and now you want to add another data. So in the redraw of the chart, data at index 201 is the newest one and consider you want to have non-drawing items of 8 points. In this case, the point at index 209 is the oldest data available in the series from the last redraw.
Now the problem arises. For example, if the newest data at index 201, would be 150, and the oldest data which is at index 209, would be 100, the widget library tries to stick to the last available data rather than LV_CHART_POINT_NONE. This way there would be a line drawn between level 150 to 100 in index 209. Now what I would expect is that it should have stuck to data at point 208 which is LV_CHART_POINT_NONE rather than considering data at 201 which is 150. I think the function draw_series_line for this concept may need reconsideration.

I haven’t tested V9.1 but I think since the majority of the code concept is the same, this issue can be present in that version.

@kisvegabor
I have tested these two functions in the core and suggest looking at these reimplementations if you will.

void lv_chart_set_next_value(lv_obj_t * obj, lv_chart_series_t * ser,
 lv_coord_t value,uint8_t space_len)
{
    LV_ASSERT_OBJ(obj, MY_CLASS);
    LV_ASSERT_NULL(ser);

    lv_chart_t * chart  = (lv_chart_t *)obj;
    ser->y_points[ser->start_point] = value;
    for (uint8_t i = 1; i < space_len; i++)
    {
        if(ser->start_point+i >= chart->point_cnt)
        	ser->y_points[ser->start_point + i - chart->point_cnt] = LV_CHART_POINT_NONE;
        else
        	ser->y_points[ser->start_point + i] = LV_CHART_POINT_NONE;
    }
    invalidate_point(obj, ser->start_point);
    ser->start_point = (ser->start_point + 1) % chart->point_cnt;
    invalidate_point(obj, ser->start_point);
}

and in function draw_series_line(...) here is my suggestion

if(crowded_mode) {
    if(ser->y_points[p_prev] != LV_CHART_POINT_NONE && ser->y_points[p_act] != LV_CHART_POINT_NONE) {
        /*Draw only one vertical line between the min and max y-values on the same x-value*/
        y_max = LV_MAX(y_max, p2.y);
        y_min = LV_MIN(y_min, p2.y);
        if(p1.x != p2.x) {
            lv_coord_t y_cur = p2.y;
            p2.x--;         /*It's already on the next x value*/
            p1.x = p2.x;
            p1.y = y_min;
            p2.y = y_max;
            if(p1.y == p2.y) p2.y++;    /*If they are the same no line will be drawn*/
            lv_draw_line(draw_ctx, &line_dsc_default, &p1, &p2);
            p2.x++;         /*Compensate the previous x--*/
            y_min = y_cur;  /*Start the line of the next x from the current last y*/
            y_max = y_cur;
        }
    }
    else if(ser->y_points[p_prev] == LV_CHART_POINT_NONE && ser->y_points[p_act] != LV_CHART_POINT_NONE)
    {
    	y_min = p2.y;
    	y_max = p2.y;
    }
}

the else if part resolved my issue finally.

Hi,

I see the problem. For 512 data on the chart what is the width of the chart widget?

I dont fully understand what you say, but if you mean in centimeter, i use at070tn92 lcd which is a 7 inch lcd. Each pixel width is 0.1926mm. Which makes it to be 512x0.1926 = 98.61mm.

I mean in pixels, but it seems it’s 512 pixels for 512 points.

Could you send a Pull request with the proposed fix? It would be easier to review it on GitHub :slight_smile: