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

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

相关文章

一份LLM资源清单围观技术大佬的日常;手把手教你在美国搭建「百万卡」AI数据中心;为啥大模型做不好简单的数学计算? | ShowMeAI日报

👀日报&周刊合集 | 🎡ShowMeAI官网 | 🧡 点赞关注评论拜托啦! 1. 为啥大模型做不好简单的数学计算?从大模型高考数学成绩不及格说起 司南评测体系 OpenCompass 选取 7 个大模型 (6 个开源模型+ GPT-4o),组织参与了 2024 年高考「新课标I卷」的语文、数学、英语考试,然后由经验丰富的判卷老师评判得分。 结果如上图所

代码随想录算法训练营:12/60

非科班学习算法day12 | LeetCode150:逆波兰表达式 ,Leetcode239: 滑动窗口最大值  目录 介绍 一、基础概念补充: 1.c++字符串转为数字 1. std::stoi, std::stol, std::stoll, std::stoul, std::stoull(最常用) 2. std::stringstream 3. std::atoi, std

回调的简单理解

之前一直不太明白回调的用法,现在简单的理解下 就按这张slidingmenu来说,主界面为Activity界面,而旁边的菜单为fragment界面。1.现在通过主界面的slidingmenu按钮来点开旁边的菜单功能并且选中”区县“选项(到这里就可以理解为A类调用B类里面的c方法)。2.通过触发“区县”的选项使得主界面跳转到“区县”相关的新闻列表界面中(到这里就可以理解为B类调用A类中的d方法

人工智能机器学习算法总结神经网络算法(前向及反向传播)

1.定义,意义和优缺点 定义: 神经网络算法是一种模仿人类大脑神经元之间连接方式的机器学习算法。通过多层神经元的组合和激活函数的非线性转换,神经网络能够学习数据的特征和模式,实现对复杂数据的建模和预测。(我们可以借助人类的神经元模型来更好的帮助我们理解该算法的本质,不过这里需要说明的是,虽然名字是神经网络,并且结构等等也是借鉴了神经网络,但其原型以及算法本质上还和生物层面的神经网络运行原理存在

自制的浏览器主页,可以是最简单的桌面应用,可以把它当成备忘录桌面应用

自制的浏览器主页,可以是最简单的桌面应用,可以把它当成备忘录桌面应用。如果你看不懂,请留言。 完整代码: <!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><ti

python实现最简单循环神经网络(RNNs)

Recurrent Neural Networks(RNNs) 的模型: 上图中红色部分是输入向量。文本、单词、数据都是输入,在网络里都以向量的形式进行表示。 绿色部分是隐藏向量。是加工处理过程。 蓝色部分是输出向量。 python代码表示如下: rnn = RNN()y = rnn.step(x) # x为输入向量,y为输出向量 RNNs神经网络由神经元组成, python

大林 PID 算法

Dahlin PID算法是一种用于控制和调节系统的比例积分延迟算法。以下是一个简单的C语言实现示例: #include <stdio.h>// DALIN PID 结构体定义typedef struct {float SetPoint; // 设定点float Proportion; // 比例float Integral; // 积分float Derivative; // 微分flo

宝塔面板部署青龙面板教程【简单易上手】

首先,你得有一台部署了宝塔面板的服务器(自己用本地电脑也可以)。 宝塔面板部署自行百度一下,很简单,这里就不走流程了,官网版本就可以,无需开心版。 首先,打开宝塔面板的软件商店,找到下图这个软件(Docker管理器)安装,青龙面板还是安装在docker里,这里依赖宝塔面板安装和管理docker。 安装完成后,进入SSH终端管理,输入代码安装青龙面板。ssh可以直接宝塔里操作,也可以安装ssh连接

LeetCode 算法:二叉树的中序遍历 c++

原题链接🔗:二叉树的中序遍历 难度:简单⭐️ 题目 给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。 示例 1: 输入:root = [1,null,2,3] 输出:[1,3,2] 示例 2: 输入:root = [] 输出:[] 示例 3: 输入:root = [1] 输出:[1] 提示: 树中节点数目在范围 [0, 100] 内 -100 <= Node.

【Java算法】滑动窗口 下

​ ​    🔥个人主页: 中草药 🔥专栏:【算法工作坊】算法实战揭秘 🦌一.水果成篮 题目链接:904.水果成篮 ​ 算法原理 算法原理是使用“滑动窗口”(Sliding Window)策略,结合哈希表(Map)来高效地统计窗口内不同水果的种类数量。以下是详细分析: 初始化:创建一个空的哈希表 map 用来存储每种水果的数量,初始化左右指针 left