一种简单的贝塞尔插值算法

2024-04-22 01:38

本文主要是介绍一种简单的贝塞尔插值算法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

转载地址:http://www.antigrain.com/research/bezier_interpolation/index.html#PAGE_BEZIER_INTERPOLATION

Interpolation with Bezier Curves
A very simple method of smoothing polygons

Initially, there was a question in comp.graphic.algorithms how to interpolate a polygon with a curve in such a way that the resulting curve would be smooth and hit all its vertices. Gernot Hoffmann suggested to use a well-known  B-Spline interpolation. Here is his original article. B-Spline works good and it behaves like an elastic ruler fixed in the polygon vertices.

 

 

But I had a gut feeling that there must be a simpler method. For example, approximation with cubic Bezier curves. A Bezier curve has two anchor points (begin and end) and two control ones (CP) that determine its shape. More information about Bezier curves can be found using any search engine, for example, on Paul Bourke's excellent site. Our anchor points are given, they are pair of vertices of the polygon. The question was, how to calculate the control points. I ran  Xara X and drew this picture. It was pretty easy and I decided to try to calculate their coordinates. It was obvious that the control points of two adjacent edges plus the vertex between them should form one straight line. Only in this case the two adjacent curves will be connected smoothly. So, the two CP should be the a reflection of each other, but… not quite. Reflection assumes equal distances from the central point. For our case it's not correct. First, I tried to calculate a bisectrix between two edges and then take points on the perpendicular to it. But as shown in the picture, the CP not always lie on the perpendicular to thebisectrix.

 

Finally, I found a very simple method that does not require any complicated math. First, we take the polygon and calculate the middle points Ai of its edges.

 

Here we have line segments Ci that connect two points Aiof the adjacent segments. Then, we should calculate points Bi as shown in this picture.

 

The third step is final. We simply move the line segments Ci in such a way that their points Bicoincide with the respective vertices. That's it, we calculated the control points for our Bezier curve and the result looks good.

 

One little improvement. Since we have a straight line that determines the place of our control points, we can move them as we want, changing the shape of the resulting curve. I used a simple coefficient K that moves the points along the line relatively to the initial distance between vertices and control points. The closer the control points to the vertices are the sharper figure will be obtained.

 

Below is the result of rendering a popular in SVG lion in its original form and with Bezier interpolation with K=1.0

 

 

And the enlarged ones.

 

 

The method works quite well with self-intersecting polygons. The examples below show that the result is pretty interesting.


 

 

 

This method is pure heuristic and empiric. It probably gives a wrong result from the point of view of strict mathematical modeling. But in practice the result is good enough and it requires absolute minimum of calculations. Below is the source code that has been used to generate the lions shown above. It's not optimal and just an illustration. It calculates some variables twice, while in real programs we can store and reuse them in the consecutive steps.

    // Assume we need to calculate the control// points between (x1,y1) and (x2,y2).// Then x0,y0 - the previous vertex,//      x3,y3 - the next one.double xc1 = (x0 + x1) / 2.0;double yc1 = (y0 + y1) / 2.0;double xc2 = (x1 + x2) / 2.0;double yc2 = (y1 + y2) / 2.0;double xc3 = (x2 + x3) / 2.0;double yc3 = (y2 + y3) / 2.0;double len1 = sqrt((x1-x0) * (x1-x0) + (y1-y0) * (y1-y0));double len2 = sqrt((x2-x1) * (x2-x1) + (y2-y1) * (y2-y1));double len3 = sqrt((x3-x2) * (x3-x2) + (y3-y2) * (y3-y2));double k1 = len1 / (len1 + len2);double k2 = len2 / (len2 + len3);double xm1 = xc1 + (xc2 - xc1) * k1;double ym1 = yc1 + (yc2 - yc1) * k1;double xm2 = xc2 + (xc3 - xc2) * k2;double ym2 = yc2 + (yc3 - yc2) * k2;// Resulting control points. Here smooth_value is mentioned// above coefficient K whose value should be in range [0...1].ctrl1_x = xm1 + (xc2 - xm1) * smooth_value + x1 - xm1;ctrl1_y = ym1 + (yc2 - ym1) * smooth_value + y1 - ym1;ctrl2_x = xm2 + (xc2 - xm2) * smooth_value + x2 - xm2;ctrl2_y = ym2 + (yc2 - ym2) * smooth_value + y2 - ym2;



And the source code of an approximation with a cubic Bezier curve.

// Number of intermediate points between two source ones,
// Actually, this value should be calculated in some way,
// Obviously, depending on the real length of the curve.
// But I don't know any elegant and fast solution for this
// problem.
#define NUM_STEPS 20void curve4(Polygon* p,double x1, double y1,   //Anchor1double x2, double y2,   //Control1double x3, double y3,   //Control2double x4, double y4)   //Anchor2
{double dx1 = x2 - x1;double dy1 = y2 - y1;double dx2 = x3 - x2;double dy2 = y3 - y2;double dx3 = x4 - x3;double dy3 = y4 - y3;double subdiv_step  = 1.0 / (NUM_STEPS + 1);double subdiv_step2 = subdiv_step*subdiv_step;double subdiv_step3 = subdiv_step*subdiv_step*subdiv_step;double pre1 = 3.0 * subdiv_step;double pre2 = 3.0 * subdiv_step2;double pre4 = 6.0 * subdiv_step2;double pre5 = 6.0 * subdiv_step3;double tmp1x = x1 - x2 * 2.0 + x3;double tmp1y = y1 - y2 * 2.0 + y3;double tmp2x = (x2 - x3)*3.0 - x1 + x4;double tmp2y = (y2 - y3)*3.0 - y1 + y4;double fx = x1;double fy = y1;double dfx = (x2 - x1)*pre1 + tmp1x*pre2 + tmp2x*subdiv_step3;double dfy = (y2 - y1)*pre1 + tmp1y*pre2 + tmp2y*subdiv_step3;double ddfx = tmp1x*pre4 + tmp2x*pre5;double ddfy = tmp1y*pre4 + tmp2y*pre5;double dddfx = tmp2x*pre5;double dddfy = tmp2y*pre5;int step = NUM_STEPS;// Suppose, we have some abstract object Polygon which// has method AddVertex(x, y), similar to LineTo in// many graphical APIs.// Note, that the loop has only operation add!while(step--){fx   += dfx;fy   += dfy;dfx  += ddfx;dfy  += ddfy;ddfx += dddfx;ddfy += dddfy;p->AddVertex(fx, fy);}p->AddVertex(x4, y4); // Last step must go exactly to x4, y4
}

You can download a working application for Windows that renders the lion, rotates and scales it, and generates random polygons. Interpolation with Bezier curves  (bezier_interpolation.zip). Press left mouse button and drag to rotate and scale the image around the center point. Press right mouse button and drag left-right to change the coefficient of smoothing (K). Value K=1 is about 100 pixels from the left border of the window. Each left double-click generates a random polygon. You can also rotate and scale it, and change K.

 
Copyright © 2002-2006 Maxim Shemanarev
Web Design and Programming Maxim Shemanarev

这篇关于一种简单的贝塞尔插值算法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/924541

相关文章

Java中的雪花算法Snowflake解析与实践技巧

《Java中的雪花算法Snowflake解析与实践技巧》本文解析了雪花算法的原理、Java实现及生产实践,涵盖ID结构、位运算技巧、时钟回拨处理、WorkerId分配等关键点,并探讨了百度UidGen... 目录一、雪花算法核心原理1.1 算法起源1.2 ID结构详解1.3 核心特性二、Java实现解析2.

基于Python实现一个简单的题库与在线考试系统

《基于Python实现一个简单的题库与在线考试系统》在当今信息化教育时代,在线学习与考试系统已成为教育技术领域的重要组成部分,本文就来介绍一下如何使用Python和PyQt5框架开发一个名为白泽题库系... 目录概述功能特点界面展示系统架构设计类结构图Excel题库填写格式模板题库题目填写格式表核心数据结构

C/C++ chrono简单使用场景示例详解

《C/C++chrono简单使用场景示例详解》:本文主要介绍C/C++chrono简单使用场景示例详解,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友... 目录chrono使用场景举例1 输出格式化字符串chrono使用场景China编程举例1 输出格式化字符串示

windows和Linux安装Jmeter与简单使用方式

《windows和Linux安装Jmeter与简单使用方式》:本文主要介绍windows和Linux安装Jmeter与简单使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录Windows和linux安装Jmeter与简单使用一、下载安装包二、JDK安装1.windows设

使用雪花算法产生id导致前端精度缺失问题解决方案

《使用雪花算法产生id导致前端精度缺失问题解决方案》雪花算法由Twitter提出,设计目的是生成唯一的、递增的ID,下面:本文主要介绍使用雪花算法产生id导致前端精度缺失问题的解决方案,文中通过代... 目录一、问题根源二、解决方案1. 全局配置Jackson序列化规则2. 实体类必须使用Long封装类3.

Springboot实现推荐系统的协同过滤算法

《Springboot实现推荐系统的协同过滤算法》协同过滤算法是一种在推荐系统中广泛使用的算法,用于预测用户对物品(如商品、电影、音乐等)的偏好,从而实现个性化推荐,下面给大家介绍Springboot... 目录前言基本原理 算法分类 计算方法应用场景 代码实现 前言协同过滤算法(Collaborativ

openCV中KNN算法的实现

《openCV中KNN算法的实现》KNN算法是一种简单且常用的分类算法,本文主要介绍了openCV中KNN算法的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录KNN算法流程使用OpenCV实现KNNOpenCV 是一个开源的跨平台计算机视觉库,它提供了各

springboot+dubbo实现时间轮算法

《springboot+dubbo实现时间轮算法》时间轮是一种高效利用线程资源进行批量化调度的算法,本文主要介绍了springboot+dubbo实现时间轮算法,文中通过示例代码介绍的非常详细,对大家... 目录前言一、参数说明二、具体实现1、HashedwheelTimer2、createWheel3、n

使用Python开发一个简单的本地图片服务器

《使用Python开发一个简单的本地图片服务器》本文介绍了如何结合wxPython构建的图形用户界面GUI和Python内建的Web服务器功能,在本地网络中搭建一个私人的,即开即用的网页相册,文中的示... 目录项目目标核心技术栈代码深度解析完整代码工作流程主要功能与优势潜在改进与思考运行结果总结你是否曾经

Mysql表的简单操作(基本技能)

《Mysql表的简单操作(基本技能)》在数据库中,表的操作主要包括表的创建、查看、修改、删除等,了解如何操作这些表是数据库管理和开发的基本技能,本文给大家介绍Mysql表的简单操作,感兴趣的朋友一起看... 目录3.1 创建表 3.2 查看表结构3.3 修改表3.4 实践案例:修改表在数据库中,表的操作主要