【LVGL笔记】-- 贝塞尔曲线绘制

这篇具有很好参考价值的文章主要介绍了【LVGL笔记】-- 贝塞尔曲线绘制。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

什么是贝塞尔曲线

贝塞尔曲线(Bézier Curve,也被称为贝塞尔多项式(Bézier Polynomial),是由一系列控制点(Control Point)所定义的一条平滑曲线。Pierre Bézier于1960年开始利用该曲线设计雷诺的车身线条,故命名为贝塞尔曲线。目前,贝塞尔曲线被广泛应用于图形设计、路径优化(无人机、无人驾驶相关)等诸多相关领域中。

贝塞尔具体描述,可以搜索,网上也是一大把,如下链接为推导过程

贝塞尔曲线(Bezier Curve)原理、公式推导及matlab代码实现_beijing_txr的博客-CSDN博客_贝塞尔曲线

lvgl 贝塞尔函数(三阶函数):

lvgl提供了三阶贝塞尔函数(即四个点绘制图形)

/**
 * Calculate a value of a Cubic Bezier function.
 * @param t time in range of [0..LV_BEZIER_VAL_MAX]
 * @param u0 start values in range of [0..LV_BEZIER_VAL_MAX]
 * @param u1 control value 1 values in range of [0..LV_BEZIER_VAL_MAX]
 * @param u2 control value 2 in range of [0..LV_BEZIER_VAL_MAX]
 * @param u3 end values in range of [0..LV_BEZIER_VAL_MAX]
 * @return the value calculated from the given parameters in range of [0..LV_BEZIER_VAL_MAX]
 */

#define LV_BEZIER_VAL_MAX 1024 /**< Max time in Bezier functions (not [0..1] to use integers)*/
#define LV_BEZIER_VAL_SHIFT 10 /**< log2(LV_BEZIER_VAL_MAX): used to normalize up scaled values*/

uint32_t lv_bezier3(uint32_t t, uint32_t u0, uint32_t u1, uint32_t u2, uint32_t u3)
{
    uint32_t t_rem  = LV_BEZIER_VAL_MAX - t;
    uint32_t t_rem2 = (t_rem * t_rem) >> 10;
    uint32_t t_rem3 = (t_rem2 * t_rem) >> 10;
    uint32_t t2     = (t * t) >> 10;
    uint32_t t3     = (t2 * t) >> 10;

    uint32_t v1 = (t_rem3 * u0) >> 10;
    uint32_t v2 = (3 * t_rem2 * t * u1) >> 20;
    uint32_t v3 = (3 * t_rem * t2 * u2) >> 20;
    uint32_t v4 = (t3 * u3) >> 10;

    return v1 + v2 + v3 + v4;
}

注:LV_BEZIER_VAL_MAX 参数值为什么定义是:2^n,这里是为了在嵌入式中可以通过移位,优化算法(毕竟做除法运算量是相当大的),另外很多时候分两次移位,因为uint32_t 做乘法的时候精度丢失。

t:(0~LV_BEZIER_VAL_MAX) 可以理解为横坐标

u0,u1,u2,u3 四个点纵坐标

v1 + v2 + v3 + v4: 算出当前绘制点的纵坐标

三阶绘制效果

lvgl贝塞尔曲线,lvgl,ui

贝塞尔函数(二阶函数):

自己手搓优化的二阶贝塞尔函数
lvgl贝塞尔曲线,lvgl,ui

转成C语言优化过后如下:

#define MAX_TIME   (256)

uint32_t lv_bezier2(uint32_t t, uint32_t u0, uint32_t u1, uint32_t u2)
{
    uint32_t t_rem  = MAX_TIME - t;
    uint32_t t_rem2 = (t_rem * t_rem) >> 8;
    uint32_t t2 = (t * t) >> 8;

    uint32_t v0 = (t_rem2 * u0) >> 8;
    uint32_t v1 = (2 * u1 * t * t_rem) >> 16;
    uint32_t v2 = (t2 * u2) >> 8;

    return (v0 + v1 + v2);
}
二阶绘制效果

lvgl贝塞尔曲线,lvgl,ui

贝塞尔函数(四阶函数):

根据多项式公式,四阶数学函数和C语言代码如下:

P = (1-t)^4P0 + 4(1-t)^3tP1 + 6(1-t)2*t2P2 + 4(1-t)t^3P3 + t^4*P4

uint32_t lv_bezier4(uint32_t t, uint32_t u0, uint32_t u1, uint32_t u2, uint32_t u3, uint32_t u4)
{
    //注意数据溢出问题,提前做好移位偏移

    uint32_t t_rem  = MAX_TIME - t;  //差值

    //n次方计算
    uint32_t t_rem2 = (t_rem * t_rem) >> 8;
    uint32_t t_rem3 = (t_rem2 * t_rem) >> 8;   
    uint32_t t_rem4 = (t_rem3 * t_rem) >> 8;  

    //n次方计算
    uint32_t t2 = (t * t) >> 8;  
    uint32_t t3 = (t2 * t) >> 8; 
    uint32_t t4 = (t2 * t2) >> 8;    

    uint32_t v0 = (t_rem4 * u0) >> 8;
    uint32_t v1 = (4 * t_rem3 * t * u1) >> 16;
    uint32_t v2 = (6 * t2 * t_rem2 * u2) >> 16;
    uint32_t v3 = (4 * t_rem * t3 * u3) >> 16;
    uint32_t v4 = (t4 * u4) >> 8;

    return (v0 + v1 + v2 + v3 + v4);
}
四阶绘制效果

多阶用移位方式优化导致了部分精度丢失,所以线段毛刺严重(运算能力强的控制单元可以考虑适用浮点运算)

lvgl贝塞尔曲线,lvgl,ui

绘制代码如下
/**************************************************START OF FILE*****************************************************/






/*------------------------------------------------------------------------------------------------------------------
Includes
*/
#include "lvgl.h"
#include "xGUI_Common.h"
#include "xGUI_ImgLoad.h"
#include "xGUI_Page_Eq.h"

/*------------------------------------------------------------------------------------------------------------------
Macros
*/
#define CHART_POINTS_NUM 256
#define MAX_TIME      (256)
#define USE_BEZIER_4  (1)   //四阶还是二阶

typedef struct
{
    bool is_style_init;

    //style list
    lv_style_t style_btn_main;

    lv_style_t style_src_main;
    lv_style_t style_src_main_focused;  
    lv_style_t style_src_main_enited;       
    lv_style_t style_src_indicator;

    lv_style_t style_combox_main;

    lv_obj_t *pWidgetBtnClose;
    lv_obj_t *pWidgetBtnSave;
    lv_obj_t *pWidgetCombox[3];
    lv_obj_t *pWidgetChart[2];

    lv_obj_t *pWidgetSubChart;
    lv_obj_t *pWidgetBtnChart[3];

    lv_chart_series_t *ser1[2];

    lv_obj_t *pWidgetArc[6];
    uint16_t arcPara[6];
}ui_eq_page_manage_t;

/*------------------------------------------------------------------------------------------------------------------
Variables
*/
extern lv_obj_t *pMainWidget;
ui_eq_page_manage_t ui_eq_page_manage = 
{
    .arcPara[0] = 127,
    .arcPara[1] = 127,
    .arcPara[2] = 127,
    .arcPara[3] = 127,
    .arcPara[4] = 127,
    .arcPara[5] = 127,
};


/*------------------------------------------------------------------------------------------------------------------
Functions
*/
static void eq_style_init(void);
static void refer_chart_cubic_bezier(void);

static void btn_event_callback(lv_event_t * e)
{
    lv_obj_t *obj = lv_event_get_target(e);    
    lv_event_code_t event = lv_event_get_code(e);

    if (event == LV_EVENT_CLICKED)
    {
		if(obj == ui_eq_page_manage.pWidgetBtnClose)
		{
			DisplayPara.MenuID = UI_PAGE_CHAIN;
		}
		else if(obj == ui_eq_page_manage.pWidgetBtnSave)
		{
			
		}        
    }
}

static void arc_event_callback(lv_event_t * e)
{
	lv_obj_t *obj = lv_event_get_target(e);
	lv_event_code_t event = lv_event_get_code(e);
    uint16_t* puser_data = (uint16_t*)lv_event_get_user_data(e);
    char buf[6];

    int16_t subData;

	if (event == LV_EVENT_VALUE_CHANGED)
	{
		*puser_data = lv_arc_get_value(obj);

        lv_obj_t *label = lv_obj_get_child(obj, NULL);

        lv_snprintf(buf, sizeof(buf), "%d", *puser_data);
        lv_label_set_text(label ,buf);
	}

    refer_chart_cubic_bezier();   
}

/*
********************************************************************************************************************
@ Brief  : 贝塞尔二阶函数

@ Param  : None

@ Return : None

@ Author : lyc

@  Date  : 2023 - 02 - 17
********************************************************************************************************************
*/
uint32_t lv_bezier2(uint32_t t, uint32_t u0, uint32_t u1, uint32_t u2)
{
    uint32_t t_rem  = MAX_TIME - t;
    uint32_t t_rem2 = (t_rem * t_rem) >> 8;
    uint32_t t2 = (t * t) >> 8;

    uint32_t v0 = (t_rem2 * u0) >> 8;
    uint32_t v1 = (2 * u1 * t * t_rem) >> 16;
    uint32_t v2 = (t2 * u2) >> 8;

    return (v0 + v1 + v2);
}

uint32_t lv_bezier4(uint32_t t, uint32_t u0, uint32_t u1, uint32_t u2, uint32_t u3, uint32_t u4)
{
    //注意数据溢出问题,提前做好移位偏移

    uint32_t t_rem  = MAX_TIME - t;  //差值

    //n次方计算
    uint32_t t_rem2 = (t_rem * t_rem) >> 8;
    uint32_t t_rem3 = (t_rem2 * t_rem) >> 8;   
    uint32_t t_rem4 = (t_rem3 * t_rem) >> 8;  

    //n次方计算
    uint32_t t2 = (t * t) >> 8;  
    uint32_t t3 = (t2 * t) >> 8; 
    uint32_t t4 = (t2 * t2) >> 8;    

    uint32_t v0 = (t_rem4 * u0) >> 8;
    uint32_t v1 = (4 * t_rem3 * t * u1) >> 16;
    uint32_t v2 = (6 * t2 * t_rem2 * u2) >> 16;
    uint32_t v3 = (4 * t_rem * t3 * u3) >> 16;
    uint32_t v4 = (t4 * u4) >> 8;

    return (v0 + v1 + v2 + v3 + v4);
}

/*
********************************************************************************************************************
@ Brief  : 界面显示初始化

@ Param  : None

@ Return : None

@ Author : lyc

@  Date  : 2023 - 01 - 29
********************************************************************************************************************
*/
void gui_eq_init(void)
{
    int i;
    lv_obj_t *label;
    char buf[30];

    eq_style_init();

    ui_eq_page_manage.pWidgetBtnClose = lv_label_create(pMainWidget);
    lv_obj_align(ui_eq_page_manage.pWidgetBtnClose, LV_ALIGN_DEFAULT, 740, 10);
    lv_obj_set_style_text_font(ui_eq_page_manage.pWidgetBtnClose, &icon_font_32, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_text_color(ui_eq_page_manage.pWidgetBtnClose, lv_color_white(), LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_label_set_text(ui_eq_page_manage.pWidgetBtnClose, LV_SYMBOL_CLOSE);
    lv_obj_add_flag(ui_eq_page_manage.pWidgetBtnClose, LV_OBJ_FLAG_CLICKABLE);
    lv_obj_add_event_cb(ui_eq_page_manage.pWidgetBtnClose, btn_event_callback, LV_EVENT_CLICKED, NULL);        
    
    label = lv_label_create(pMainWidget);
    lv_obj_align(label, LV_ALIGN_DEFAULT, 50, 5);
    lv_obj_set_style_text_color(label, lv_palette_main(LV_PALETTE_PURPLE), LV_PART_MAIN | LV_STATE_DEFAULT);  //
    lv_obj_set_style_text_font(label, &bold_font_20, LV_PART_MAIN);
    lv_label_set_text(label , "AI EQ MASTER");

    ui_eq_page_manage.pWidgetCombox[0] = lv_dropdown_create(pMainWidget);
    lv_obj_set_size(ui_eq_page_manage.pWidgetCombox[0], 200, 40);
    lv_obj_align(ui_eq_page_manage.pWidgetCombox[0], LV_ALIGN_DEFAULT, 50, 35);
    lv_obj_add_style(ui_eq_page_manage.pWidgetCombox[0],&ui_eq_page_manage.style_combox_main,LV_PART_MAIN);
	lv_dropdown_clear_options(ui_eq_page_manage.pWidgetCombox[0]);
    for (i = 0; i < 10; i++)
    {
    	lv_snprintf(buf,sizeof(buf), "Type: Destortion%02d", i);
		lv_dropdown_add_option(ui_eq_page_manage.pWidgetCombox[0], buf, i);
    }
    lv_dropdown_set_symbol(ui_eq_page_manage.pWidgetCombox[0], LV_SYMBOL_DOWN);

    ui_eq_page_manage.pWidgetCombox[1] = lv_dropdown_create(pMainWidget);
    lv_obj_set_size(ui_eq_page_manage.pWidgetCombox[1], 250, 40);
    lv_obj_align(ui_eq_page_manage.pWidgetCombox[1], LV_ALIGN_DEFAULT, 270, 35);
    lv_obj_add_style(ui_eq_page_manage.pWidgetCombox[1],&ui_eq_page_manage.style_combox_main,LV_PART_MAIN);
	lv_dropdown_clear_options(ui_eq_page_manage.pWidgetCombox[1]);
    for (i = 0; i < 10; i++)
    {
    	lv_snprintf(buf,sizeof(buf), "80`s Rock Phythm %02d", i);
		lv_dropdown_add_option(ui_eq_page_manage.pWidgetCombox[1], buf, i);
    }
    lv_dropdown_set_symbol(ui_eq_page_manage.pWidgetCombox[1], LV_SYMBOL_DOWN);
	
    ui_eq_page_manage.pWidgetCombox[2] = lv_dropdown_create(pMainWidget);
    lv_obj_set_size(ui_eq_page_manage.pWidgetCombox[2], 100, 40);
    lv_obj_align(ui_eq_page_manage.pWidgetCombox[2], LV_ALIGN_DEFAULT, 620, 35);
    lv_obj_add_style(ui_eq_page_manage.pWidgetCombox[2],&ui_eq_page_manage.style_combox_main,LV_PART_MAIN);
	lv_dropdown_clear_options(ui_eq_page_manage.pWidgetCombox[2]);
    for (i = 0; i < 10; i++)
    {
    lv_snprintf(buf,sizeof(buf), "Slot%02d", i);
        lv_dropdown_add_option(ui_eq_page_manage.pWidgetCombox[2], buf, i);
    }
    lv_dropdown_set_symbol(ui_eq_page_manage.pWidgetCombox[2], LV_SYMBOL_DOWN);

    ui_eq_page_manage.pWidgetBtnSave = lv_label_create(pMainWidget);
    lv_obj_align(ui_eq_page_manage.pWidgetBtnSave, LV_ALIGN_DEFAULT, 560, 40);
    lv_obj_set_style_text_font(ui_eq_page_manage.pWidgetBtnSave, &icon_font_32, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_text_color(ui_eq_page_manage.pWidgetBtnSave, lv_color_white(), LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_label_set_text(ui_eq_page_manage.pWidgetBtnSave, LV_SYMBOL_SAVE);
    lv_obj_add_flag(ui_eq_page_manage.pWidgetBtnSave, LV_OBJ_FLAG_CLICKABLE);
    lv_obj_add_event_cb(ui_eq_page_manage.pWidgetBtnSave, btn_event_callback, LV_EVENT_CLICKED, NULL);    

#if USE_BEZIER_4
    ui_eq_page_manage.pWidgetChart[0] = lv_chart_create(pMainWidget);
    lv_obj_align(ui_eq_page_manage.pWidgetChart[0],LV_ALIGN_DEFAULT,50,90);
    lv_obj_set_size(ui_eq_page_manage.pWidgetChart[0], 700, 260);
    lv_obj_set_style_line_color(ui_eq_page_manage.pWidgetChart[0], lv_palette_main(LV_PALETTE_GREY), LV_PART_MAIN);
    lv_obj_set_style_line_opa(ui_eq_page_manage.pWidgetChart[0], LV_OPA_80, LV_PART_MAIN);
    lv_obj_set_style_pad_all(ui_eq_page_manage.pWidgetChart[0], 0, LV_PART_MAIN);
    lv_obj_set_style_size(ui_eq_page_manage.pWidgetChart[0], 0, LV_PART_INDICATOR);
    lv_obj_set_style_bg_color(ui_eq_page_manage.pWidgetChart[0],lv_color_black(),LV_PART_MAIN);  
    lv_obj_set_style_border_width(ui_eq_page_manage.pWidgetChart[0], 0, LV_PART_MAIN);
    lv_chart_set_type(ui_eq_page_manage.pWidgetChart[0], LV_CHART_TYPE_SCATTER);
    lv_chart_set_div_line_count(ui_eq_page_manage.pWidgetChart[0], 11, 7);
    ui_eq_page_manage.ser1[0] = lv_chart_add_series(ui_eq_page_manage.pWidgetChart[0], lv_palette_main(LV_PALETTE_AMBER), LV_CHART_AXIS_PRIMARY_Y);
    lv_chart_set_range(ui_eq_page_manage.pWidgetChart[0], LV_CHART_AXIS_PRIMARY_Y, 0, CHART_POINTS_NUM);
    lv_chart_set_range(ui_eq_page_manage.pWidgetChart[0], LV_CHART_AXIS_PRIMARY_X, 0, CHART_POINTS_NUM);
    lv_chart_set_point_count(ui_eq_page_manage.pWidgetChart[0], CHART_POINTS_NUM);
#else
    for(i=0;i<2;i++)
    {
        ui_eq_page_manage.pWidgetChart[i] = lv_chart_create(pMainWidget);
        lv_obj_align(ui_eq_page_manage.pWidgetChart[i],LV_ALIGN_DEFAULT,50+350*i,90);
        lv_obj_set_size(ui_eq_page_manage.pWidgetChart[i], 350, 260);
        lv_obj_set_style_line_color(ui_eq_page_manage.pWidgetChart[i], lv_palette_main(LV_PALETTE_GREY), LV_PART_MAIN);
        lv_obj_set_style_line_opa(ui_eq_page_manage.pWidgetChart[i], LV_OPA_80, LV_PART_MAIN);
        lv_obj_set_style_pad_all(ui_eq_page_manage.pWidgetChart[i], 0, LV_PART_MAIN);
        lv_obj_set_style_size(ui_eq_page_manage.pWidgetChart[i], 0, LV_PART_INDICATOR);
        lv_obj_set_style_bg_color(ui_eq_page_manage.pWidgetChart[i],lv_color_black(),LV_PART_MAIN);  
        lv_obj_set_style_border_width(ui_eq_page_manage.pWidgetChart[i], 0, LV_PART_MAIN);
        lv_chart_set_type(ui_eq_page_manage.pWidgetChart[i], LV_CHART_TYPE_SCATTER);
        lv_chart_set_div_line_count(ui_eq_page_manage.pWidgetChart[i], 11, 7);
        ui_eq_page_manage.ser1[i] = lv_chart_add_series(ui_eq_page_manage.pWidgetChart[i], lv_palette_main(LV_PALETTE_AMBER), LV_CHART_AXIS_PRIMARY_Y);
        lv_chart_set_range(ui_eq_page_manage.pWidgetChart[i], LV_CHART_AXIS_PRIMARY_Y, 0, CHART_POINTS_NUM);
        lv_chart_set_range(ui_eq_page_manage.pWidgetChart[i], LV_CHART_AXIS_PRIMARY_X, 0, CHART_POINTS_NUM);
        lv_chart_set_point_count(ui_eq_page_manage.pWidgetChart[i], CHART_POINTS_NUM);
    }
#endif    
    ui_eq_page_manage.pWidgetSubChart = lv_obj_create(pMainWidget);
    lv_obj_set_size(ui_eq_page_manage.pWidgetSubChart, 280, 60);
    lv_obj_align(ui_eq_page_manage.pWidgetSubChart,LV_ALIGN_TOP_MID,0,270);
    lv_obj_set_style_border_opa(ui_eq_page_manage.pWidgetSubChart,LV_OPA_TRANSP,LV_PART_MAIN);
    lv_obj_set_style_bg_color(ui_eq_page_manage.pWidgetSubChart,lv_palette_main(LV_PALETTE_GREY),LV_PART_MAIN);
    lv_obj_set_style_bg_opa(ui_eq_page_manage.pWidgetSubChart,LV_OPA_40,LV_PART_MAIN);
    lv_obj_set_style_pad_gap(ui_eq_page_manage.pWidgetSubChart,0,LV_PART_MAIN);
    lv_obj_clear_flag(ui_eq_page_manage.pWidgetSubChart, LV_OBJ_FLAG_SCROLLABLE);

    ui_eq_page_manage.pWidgetBtnChart[0] = lv_btn_create(ui_eq_page_manage.pWidgetSubChart);
    lv_obj_set_size(ui_eq_page_manage.pWidgetBtnChart[0], 40, 40);
    lv_obj_align(ui_eq_page_manage.pWidgetBtnChart[0], LV_ALIGN_CENTER, -90, 0);
    lv_obj_add_style(ui_eq_page_manage.pWidgetBtnChart[0],&ui_eq_page_manage.style_btn_main,LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_add_event_cb(ui_eq_page_manage.pWidgetBtnChart[0], btn_event_callback, LV_EVENT_CLICKED, NULL); 
    label = lv_label_create(ui_eq_page_manage.pWidgetBtnChart[0]);
    lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
    lv_obj_set_style_text_font(label, &icon_font_32, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_label_set_text(label, "\uF111");

    ui_eq_page_manage.pWidgetBtnChart[1] = lv_btn_create(ui_eq_page_manage.pWidgetSubChart);
    lv_obj_set_size(ui_eq_page_manage.pWidgetBtnChart[1], 40, 40);
    lv_obj_align(ui_eq_page_manage.pWidgetBtnChart[1], LV_ALIGN_CENTER, 0, 0);
    lv_obj_add_style(ui_eq_page_manage.pWidgetBtnChart[1],&ui_eq_page_manage.style_btn_main,LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_add_event_cb(ui_eq_page_manage.pWidgetBtnChart[1], btn_event_callback, LV_EVENT_CLICKED, NULL); 
    label = lv_label_create(ui_eq_page_manage.pWidgetBtnChart[1]);
    lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
    lv_obj_set_style_text_font(label, &icon_font_32, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_label_set_text(label, "\uF011");

    ui_eq_page_manage.pWidgetBtnChart[2] = lv_btn_create(ui_eq_page_manage.pWidgetSubChart);
    lv_obj_set_size(ui_eq_page_manage.pWidgetBtnChart[2], 40, 40);
    lv_obj_align(ui_eq_page_manage.pWidgetBtnChart[2], LV_ALIGN_CENTER, 90, 0);
    lv_obj_add_style(ui_eq_page_manage.pWidgetBtnChart[2],&ui_eq_page_manage.style_btn_main,LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_add_event_cb(ui_eq_page_manage.pWidgetBtnChart[2], btn_event_callback, LV_EVENT_CLICKED, NULL); 
    label = lv_label_create(ui_eq_page_manage.pWidgetBtnChart[2]);
    lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
    lv_obj_set_style_text_font(label, &icon_font_32, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_label_set_text(label, "\uF014");

    for(i=0;i<6;i++)
    {
        ui_eq_page_manage.pWidgetArc[i] = lv_arc_create(pMainWidget);
        lv_obj_set_size(ui_eq_page_manage.pWidgetArc[i], 80, 80);
        lv_obj_align(ui_eq_page_manage.pWidgetArc[i],LV_ALIGN_TOP_MID, -300 + 120*i, 370);
        lv_arc_set_bg_angles(ui_eq_page_manage.pWidgetArc[i],135,45);
        lv_arc_set_range(ui_eq_page_manage.pWidgetArc[i], 0, MAX_TIME);
        lv_arc_set_value(ui_eq_page_manage.pWidgetArc[i], ui_eq_page_manage.arcPara[i]);
        lv_obj_add_style(ui_eq_page_manage.pWidgetArc[i],&ui_eq_page_manage.style_src_main,LV_PART_MAIN);
        lv_obj_add_style(ui_eq_page_manage.pWidgetArc[i],&ui_eq_page_manage.style_src_indicator,LV_PART_INDICATOR);
        lv_obj_add_style(ui_eq_page_manage.pWidgetArc[i],&ui_eq_page_manage.style_src_main_focused,LV_PART_MAIN | LV_STATE_FOCUSED);  
        lv_obj_add_style(ui_eq_page_manage.pWidgetArc[i],&ui_eq_page_manage.style_src_main_enited,LV_PART_MAIN | LV_STATE_EDITED);      
        lv_obj_remove_style(ui_eq_page_manage.pWidgetArc[i], NULL, LV_PART_KNOB);
        lv_group_add_obj(pGroupEncoder,ui_eq_page_manage.pWidgetArc[i]);

        label = lv_label_create(ui_eq_page_manage.pWidgetArc[i]);
        lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
        lv_obj_set_style_text_color(label, lv_color_white(), LV_PART_MAIN | LV_STATE_DEFAULT);
        lv_snprintf(buf, sizeof(buf), "%d", ui_eq_page_manage.arcPara[i]);
        lv_label_set_text(label ,buf);
        lv_obj_add_event_cb(ui_eq_page_manage.pWidgetArc[i],arc_event_callback,LV_EVENT_VALUE_CHANGED,&ui_eq_page_manage.arcPara[i]);
    }
    lv_group_focus_obj(ui_eq_page_manage.pWidgetArc[0]); 

    lv_obj_set_style_arc_color(ui_eq_page_manage.pWidgetArc[0],lv_palette_lighten(LV_PALETTE_GREEN,1),LV_PART_INDICATOR | LV_STATE_DEFAULT);
    lv_obj_set_style_arc_color(ui_eq_page_manage.pWidgetArc[1],lv_palette_lighten(LV_PALETTE_PINK,1),LV_PART_INDICATOR | LV_STATE_DEFAULT);
    lv_obj_set_style_arc_color(ui_eq_page_manage.pWidgetArc[2],lv_palette_lighten(LV_PALETTE_RED,1),LV_PART_INDICATOR | LV_STATE_DEFAULT);
    lv_obj_set_style_arc_color(ui_eq_page_manage.pWidgetArc[3],lv_palette_lighten(LV_PALETTE_BLUE,1),LV_PART_INDICATOR | LV_STATE_DEFAULT);
    lv_obj_set_style_arc_color(ui_eq_page_manage.pWidgetArc[4],lv_palette_lighten(LV_PALETTE_BLUE,3),LV_PART_INDICATOR | LV_STATE_DEFAULT);
    lv_obj_set_style_arc_color(ui_eq_page_manage.pWidgetArc[5],lv_palette_lighten(LV_PALETTE_PURPLE,1),LV_PART_INDICATOR | LV_STATE_DEFAULT);

    refer_chart_cubic_bezier();
}

/*
********************************************************************************************************************
@ Brief  : 

@ Param  : None

@ Return : None

@  Date  : 2023 - 02 - 02
********************************************************************************************************************
*/
void xGUI_Page_Eq(const DisplayPara_TypeDef *pDisPlay)
{
   
    if(pDisPlay->MenuID != TempDisplayPara.MenuID )
	{
		if(pMainWidget != NULL)lv_obj_clean(pMainWidget);
        gui_eq_init();
		TempDisplayPara.MenuID = pDisPlay->MenuID;
	}    
}


/*
********************************************************************************************************************
@ Brief  : 风格类型初始化:当前界面所有控件的风格整理

@ Param  : None

@ Return : None

@ Author : lyc

@  Date  : 2023 - 01 - 29
********************************************************************************************************************
*/
static void eq_style_init(void)
{
    if(ui_eq_page_manage.is_style_init == false)
    {
        lv_style_init(&ui_eq_page_manage.style_btn_main);
        lv_style_set_radius(&ui_eq_page_manage.style_btn_main,4);
        lv_style_set_bg_color(&ui_eq_page_manage.style_btn_main,lv_palette_main(LV_PALETTE_GREY));
        lv_style_set_bg_opa(&ui_eq_page_manage.style_btn_main,LV_OPA_30);
        lv_style_set_shadow_opa(&ui_eq_page_manage.style_btn_main,LV_OPA_TRANSP);

        lv_style_init(&ui_eq_page_manage.style_src_main);
        lv_style_set_arc_color(&ui_eq_page_manage.style_src_main,lv_palette_darken(LV_PALETTE_GREY,3));
        lv_style_set_arc_width(&ui_eq_page_manage.style_src_main,8);

        lv_style_init(&ui_eq_page_manage.style_src_indicator);
        lv_style_set_arc_color(&ui_eq_page_manage.style_src_indicator,lv_palette_lighten(LV_PALETTE_ORANGE,1));
        lv_style_set_arc_width(&ui_eq_page_manage.style_src_indicator,8);

        lv_style_init(&ui_eq_page_manage.style_src_main_focused);
        lv_style_set_bg_opa(&ui_eq_page_manage.style_src_main_focused,LV_OPA_TRANSP);  
        lv_style_set_border_opa(&ui_eq_page_manage.style_src_main_focused,LV_OPA_COVER);
        lv_style_set_shadow_width(&ui_eq_page_manage.style_src_main_focused,10);
        lv_style_set_shadow_color(&ui_eq_page_manage.style_src_main_focused,lv_palette_lighten(LV_PALETTE_BLUE,2));
        lv_style_set_arc_color(&ui_eq_page_manage.style_src_main_focused,lv_palette_lighten(LV_PALETTE_GREY,1));

        lv_style_init(&ui_eq_page_manage.style_src_main_enited);
        lv_style_set_bg_opa(&ui_eq_page_manage.style_src_main_enited,LV_OPA_TRANSP);  
        lv_style_set_border_opa(&ui_eq_page_manage.style_src_main_enited,LV_OPA_COVER);
        lv_style_set_shadow_width(&ui_eq_page_manage.style_src_main_enited,10);
        lv_style_set_shadow_color(&ui_eq_page_manage.style_src_main_enited,lv_palette_lighten(LV_PALETTE_PINK,2)); 
        lv_style_set_arc_color(&ui_eq_page_manage.style_src_main_enited,lv_palette_lighten(LV_PALETTE_GREY,3));

        lv_style_init(&ui_eq_page_manage.style_combox_main);
        lv_style_set_radius(&ui_eq_page_manage.style_combox_main,9);
        lv_style_set_border_color(&ui_eq_page_manage.style_combox_main,lv_palette_main(LV_PALETTE_PURPLE));
        lv_style_set_border_width(&ui_eq_page_manage.style_combox_main,2);
        lv_style_set_bg_color(&ui_eq_page_manage.style_combox_main,lv_color_black());
        lv_style_set_text_color(&ui_eq_page_manage.style_combox_main, lv_color_white());
        
        ui_eq_page_manage.is_style_init = true;
    }
}

static void refer_chart_cubic_bezier(void)
{
    int i;
    int32_t step;
#if USE_BEZIER_4
    for(i = 0; i <= CHART_POINTS_NUM; i ++)
    {
        step = lv_bezier4(i, ui_eq_page_manage.arcPara[0], ui_eq_page_manage.arcPara[1], ui_eq_page_manage.arcPara[2],ui_eq_page_manage.arcPara[3], ui_eq_page_manage.arcPara[4]);
        lv_chart_set_value_by_id2(ui_eq_page_manage.pWidgetChart[0], ui_eq_page_manage.ser1[0], i, i, step);
    }

    lv_chart_refresh(ui_eq_page_manage.pWidgetChart[0]);
#else
    for(i = 0; i <= CHART_POINTS_NUM; i ++)
    {
        step = lv_bezier2(i, ui_eq_page_manage.arcPara[0], ui_eq_page_manage.arcPara[1], ui_eq_page_manage.arcPara[2]);
        lv_chart_set_value_by_id2(ui_eq_page_manage.pWidgetChart[0], ui_eq_page_manage.ser1[0], i, i, step);
        step = lv_bezier2(i, ui_eq_page_manage.arcPara[2], ui_eq_page_manage.arcPara[3], ui_eq_page_manage.arcPara[4]);
        lv_chart_set_value_by_id2(ui_eq_page_manage.pWidgetChart[1], ui_eq_page_manage.ser1[1], i, i, step);
    }

    lv_chart_refresh(ui_eq_page_manage.pWidgetChart[0]);
	lv_chart_refresh(ui_eq_page_manage.pWidgetChart[1]);
#endif    
}
/****************************************************END OF FILE*****************************************************/


理解贝塞尔曲线后,可以根据需要搭建多阶算法(阶数越多,曲线拟合更贴切,但算法量越大,对算力较弱的芯片不推荐)文章来源地址https://www.toymoban.com/news/detail-786544.html

到了这里,关于【LVGL笔记】-- 贝塞尔曲线绘制的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 彻底搞懂贝塞尔曲线的原理

    贝塞尔曲线介绍 我们在前面讲了绘制自定义曲线,而实际开发过程还会遇到更复杂的图形绘制,比如下面的这些图形: 这时候就需要用到贝塞尔曲线了。下面是百科关于贝塞尔曲线的介绍。 贝塞尔曲线就是这样的一条曲线,它是依据四个位置任意的点坐标绘制出的一条光滑

    2024年02月20日
    浏览(43)
  • unity 曲线可视化图表制作(lineRenderer + 贝塞尔曲线)

    需求要实现一个动态变化的曲线 思路: 分为两部分:画线和平滑曲线 首先解决画线问题: 1.lineRenderer 2.texture的setpixel 肯定选已经做好的轮子1啦 平滑曲线思路: 1.抛物线 2.贝塞尔曲线 抛物线做连续的曲线太抽象了 肯定选贝塞尔曲线 先了解一下贝塞尔曲线 一次贝塞尔 对应

    2023年04月08日
    浏览(51)
  • Unity中的数学基础——贝塞尔曲线

    一:前言  一条贝塞尔曲线是由一组定义的控制点P0到 Pn,n=1为线性,n=2为二次......第一个和最后一个控制点称为起点和终点,中间的控制点一般不会位于曲线上  获取两个点之间的点就是通过线性插值( Mathf.Lerp),0 = t = 1 二:贝塞尔曲线公式 ——线性公式:给定点P0、P

    2024年02月11日
    浏览(39)
  • 【Unity】运行时创建曲线(贝塞尔的运用)

    1. 实现的目标 在运行状态下创建一条可以使用贝塞尔方法实时编辑的网格曲线。 2. 原理介绍 2.1 曲线的创建 unity建立网格曲线可以参考Unity程序化网格体的实现方法。主要分为顶点,三角面,UV和法线。笔者有类似的文章unity 线绳管道纯代码创建方法_,详细的讲解了网格线的

    2024年02月04日
    浏览(42)
  • 贝塞尔曲线的python实现(简单易理解)

    贝塞尔曲线在计算机图形学中被大量使用,通常可以产生平滑的曲线。比如ps中的钢笔工具,就是利用的这种原理。由于用计算机画图大部分时间是操作鼠标来掌握线条的路径,与手绘的感觉和效果有很大的差别。即使是一位精明的画师能轻松绘出各种图形,拿到鼠标想随心

    2024年02月16日
    浏览(44)
  • Godot插值、贝塞尔曲线和Astar寻路

    线性插值是采用一次多项式上进行的插值计算,任意给定两个值A和B,那么在A和B之间的任意值可以定义为: P(t) = A * (1 - t) + B * t,0 = t = 1。 数学中用于线性拟合,游戏应用可以做出跟随效果(宠物跟随、npc跟随) 贝塞尔是插值的应用之一。贝塞尔曲线是为工业设计,是图形

    2024年04月14日
    浏览(42)
  • Unity ——使用贝塞尔曲线对三维管状物体进行弯曲

    参考链接:【Unity】弹性鱼竿简单实现-通过贝塞尔曲线修改Mesh - 简书 参考论文:吴晓亮, 黄襄念. Unity 中使用贝塞尔曲线对三维物体进行弯曲[J]. 现代计算机, 2016 (5): 57-59. unity项目下载:https://download.csdn.net/download/weixin_43042683/87690343 效果图 随着虚拟现实的发展,在游戏引擎中

    2024年02月11日
    浏览(63)
  • Bezier Curve 贝塞尔曲线 - 在Unity中实现路径编辑

    贝塞尔曲线( Bezier Curve ),又称贝兹曲线或贝济埃曲线,是计算机图形学中相当重要的参数曲线,在我们常用的软件如 Photo Shop 中就有贝塞尔曲线工具,本文简单介绍贝塞尔曲线在Unity中的实现与应用。 给顶点P 0 、P 1 ,只是一条两点之间的直线,公式如下: B(t) = P 0 + (P

    2024年01月23日
    浏览(42)
  • 曲线生成 | 图解贝塞尔曲线生成原理(附ROS C++/Python/Matlab仿真)

    🔥附C++/Python/Matlab全套代码🔥课程设计、毕业设计、创新竞赛必备!详细介绍全局规划(图搜索、采样法、智能算法等);局部规划(DWA、APF等);曲线优化(贝塞尔曲线、B样条曲线等)。 🚀详情:图解自动驾驶中的运动规划(Motion Planning),附几十种规划算法 贝塞尔曲线是一种数学

    2024年01月16日
    浏览(72)
  • 贝塞尔曲线(Bezier Curve)原理、公式推导及matlab代码实现

    目录 参考链接 定义 直观理解  公式推导 一次贝塞尔曲线(线性公式) 二次贝塞尔曲线(二次方公式)  三次贝塞尔曲线(三次方公式) n次贝塞尔曲线(一般参数公式) 代码实现 贝塞尔曲线(Bezier Curve)原理及公式推导_bezier曲线-CSDN博客 贝塞尔曲线(Bezier Curve)原理、公

    2024年01月20日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包