WPF将点列连接成光滑曲线——贝塞尔曲线
背景
最近在写一个游戏场景编辑器,虽然很水,但是还是遇到了不少问题。连接离散个点列成为光滑曲线就是一个问题。主要是为了通过关键点产生2D的赛道场景。总之马路不可能是直线相连的,当然需要曲线光滑相连。现在我就来解决这个问题。
贝塞尔曲线
贝塞尔曲线,又称贝兹曲线或贝济埃曲线,一般的矢量图形软件通过它来精确画出曲线,贝兹曲线由线段与节点组成,节点是可拖动的支点,线段像可伸缩的皮筋,我们在绘图工具上看到的钢笔工具就是来做这种矢量曲线的。当然在一些比较成熟的位图软件中也有贝塞尔曲线工具,如PhotoShop等。在Flash4中还没有完整的曲线工具,而在Flash5里面已经提供出贝塞尔曲线工具。
这里是百度里面的介绍。直接搬过来了。
问题

如图,这些绿色的点我们希望用光滑的曲线连接它们。
看看WPF给我们提供的函数:


来自MSDN
我们发现point3和point4是我们需要的,这两个点我们直接可以从点列中取得,但是point1和point2如何获取呢?控制点到底是个什么东西。当然我试了很多次失败了很多次~~
巧妙的解决方案
大致思路就是 先算出相邻原始点的中点,在把相邻中点连成的线段平移到对应的原始点,以平移后的中点作为控制点,相邻原始点为起始点画贝塞尔曲线,这样就保证了连接处的光滑。而贝塞尔曲线本身是光滑的,所以就把这些原始点用光滑曲线连起来了。
(http://liyiwen.javaeye.com/blog/705489)

实验结果

看起来连接的还是比较光滑的。
相关代码
Path path;
public void UpdateRoad()
{
MapCanvas.Children.Remove(path);
if (ScenePoint.roadPoint.Count > 0)
{
List<Point> list = new List<Point>();
foreach (ScenePoint sp in ScenePoint.roadPoint)
{
list.Add(new Point((sp.position.X + Shift.X) * Zoom, (sp.position.Y + Shift.Y) * Zoom));
}
PathFigure pf = new PathFigure(); pf.StartPoint = list[0];
List<Point> controls = new List<Point>();
for (int i = 0; i < list.Count; i++)
{
controls.AddRange(Control1(list, i));
}
for (int i = 1; i < list.Count; i++)
{
BezierSegment bs = new BezierSegment(controls[i * 2 - 1], controls[i * 2], list[i], true);
bs.IsSmoothJoin = true; pf.Segments.Add(bs);
}
PathFigureCollection pfc = new PathFigureCollection();
pfc.Add(pf);
PathGeometry pg = new PathGeometry(pfc); path = new Path();
path.Stroke = Brushes.Black;
path.Data = pg;
MapCanvas.Children.Add(path);
}
}
public void UpdateHeightCanvas()
{
HeightCanvas.Children.Clear();
foreach (ScenePoint sp in ScenePoint.listPoint)
{
HeightCanvas.Children.Add(sp.Ellipseh);
}
}
public List<Point> Control1(List<Point> list, int n)
{
List<Point> point = new List<Point>();
point.Add(new Point());
point.Add(new Point());
if (n == 0)
{
point[0] = list[0];
}
else
{
point[0] = Average(list[n - 1], list[n]);
}
if (n == list.Count - 1)
{
point[1] = list[list.Count - 1];
}
else
{
point[1] = Average(list[n], list[n+1]);
}
Point ave = Average(point[0], point[1]);
Point sh = Sub(list[n], ave);
point[0] = Mul(Add(point[0], sh),list[n],0.6);
point[1] = Mul(Add(point[1], sh),list[n],0.6);
//Line line = new Line();
//line.X1 = point[0].X;
//line.Y1 = point[0].Y;
//line.X2 = point[1].X;
//line.Y2 = point[1].Y;
//line.Stroke = Brushes.Red;
//MapCanvas.Children.Add(line);
return point;
}
public Point Average(Point x, Point y)
{
return new Point((x.X+y.X)/2,(x.Y+y.Y)/2);
}
public Point Add(Point x, Point y)
{
return new Point(x.X + y.X, x.Y + y.Y);
}
public Point Sub(Point x, Point y)
{
return new Point(x.X - y.X, x.Y - y.Y);
}
public Point Mul(Point x, Point y,double d)
{
Point temp = Sub(x, y);
temp = new Point(temp.X * d, temp.Y * d);
temp = Add(y, temp);
return temp;
}
WPF将点列连接成光滑曲线——贝塞尔曲线的更多相关文章
- WPF绘制光滑连续贝塞尔曲线
1.需求 WPF本身没有直接把点集合绘制成曲线的函数.可以通过贝塞尔曲线函数来绘制. 贝塞尔曲线类是:BezierSegment,三次贝塞尔曲线,通过两个控制点来控制开始和结束方向. Quadrati ...
- 关于曲线 规划 算法 线性 S曲线 贝塞尔曲线
工控领域经常会涉及速度加减速的算法:线性加减速,S曲线加减速(sin函数,拓展其他三角函数曲线), 贝塞尔曲线,等等. 线性加减速: 设定起始速度V0,目标速度V1,加速时间Ta(s,或加速度) ...
- Unity3d游戏中自定义贝塞尔曲线编辑器[转]
关于贝塞尔曲线曲线我们再前面的文章提到过<Unity 教程之-在Unity3d中使用贝塞尔曲线>,那么本篇文章我们来深入学习下,并自定义实现贝塞尔曲线编辑器,贝塞尔曲线是最基本的曲线,一般 ...
- Unity游戏中使用贝塞尔曲线
孙广东 2015.8.15 比方在3D rpg游戏中.我们想设置弹道,不同的轨迹类型! 目的:这篇文章的主要目的是要给你关于在游戏怎样使用贝塞尔曲线的基本想法. 贝塞尔曲线是最主要的曲线,一般用在 ...
- svg path中的贝塞尔曲线
首先介绍以下什么是贝塞尔曲线 贝塞尔曲线又叫贝茨曲线(Bezier),由两个端点以及若干个控制点组成,只有两个端点在曲线上,控制点不在曲线上,只是控制曲线的走向. 控制点个数为0时,它是一条直线; 控 ...
- iOS - Quartz 2D 贝塞尔曲线
1.贝塞尔曲线 贝塞尔曲线(Bézier curve),又称贝兹曲线或贝济埃曲线,是应用于二维图形应用程序的数学曲线.一般的矢量图形软件通过它来精确画出曲线,贝兹曲线由线段与节点组成,节点是可拖动的支 ...
- 【Unity】贝塞尔曲线关于点、长度、切线计算在 Unity中的C#实现
原文:[Unity]贝塞尔曲线关于点.长度.切线计算在 Unity中的C#实现 写在前面 最近给项目做了个路径编辑,基本思路是满足几个基本需求: [额外说明]其实本篇和这个没关系,可以跳过" ...
- 贝塞尔曲线 WPF MVVM N阶实现 公式详解+源代码下载
源代码下载 效果图: 本程序主要实现: N阶贝塞尔曲线(通用公式) 本程序主要使用技术 MVVM InterAction 事件绑定 动态添加Canvas的Item 第一部分公式: n=有效坐标点数量 ...
- WPF贝塞尔曲线示例
WPF贝塞尔曲线示例 贝塞尔曲线在之前使用SVG的时候其实就已经有接触到了,但应用未深,了解的不是很多,最近在进行图形操作的时候需要用到贝塞尔曲线,所以又重新来了解WPF中贝塞尔曲线的绘制. 一阶贝塞 ...
随机推荐
- 【84.62%】【codeforces 552A】Vanya and Table
time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...
- Android 设置图片透明度
我了解的比较快捷的ImageView设置图片的透明度的方法有: setAlpha(); setImageAlpha(); getDrawable().setAlpha(). 其中setAlpha()已 ...
- BZOJ3073 Journeys - 线段树优化建边
传送门 题意: Seter建造了一个很大的星球,他准备建造N个国家和无数双向道路.N个国家很快建造好了,用1..N编号,但是他发现道路实在太多了,他要一条条建简直是不可能的!于是他以如下方式建造道路: ...
- RoundingMode 几个参数详解
第一版 java.math.RoundingMode 几个参数详解 java.math.RoundingMode里面有几个参数搞得我有点晕,现以个人理解对其一一进行总结: 为了能更好理解,我们可以画一 ...
- erlang浅谈
优点: 1.面向并发,有成熟而且久经考验的框架可供使用,网络部分已经经过了良好封装 2.内存缓存解决方案进程字典,前者的读写速度是50NS-100Ns级别的 3.对二进制数据解析的语法是直观,简单,强 ...
- 一起学Python:协程
一:协程-yield 协程,又称微线程,纤程.英文名Coroutine. 协程是啥 协程是python个中另外一种实现多任务的方式,只不过比线程更小占用更小执行单元(理解为需要的资源). 为啥说它是一 ...
- Linux环境下搭建VPS服务
说明 由于大部分VPN被封,FQ过程中无意间接触到了VPS(Virtual Private Server 虚拟专用服务器,可用于FQ),所以简单记录下VPS服务搭建流程. 此教程基于centos7,本 ...
- Android Studio:Grade 全局参数定义
Grade 全局参数定义 实际开发中设置公共的编译依赖参数等. 方法一: 在项目外层的build.gradle文件中定义,格式如下: 文件名:build.gradle ext { sourceComp ...
- Android-apktool-就从此处开始反编译之旅
前言 一直听说过反编译,感觉很高大上,一直没自己用过,今天因缘巧合之下,终于要开始逐渐认识,了解和学习一下反编译了~先给自己说下加油,鼓励一下下 apktool的下载和安装 apktool 下载地址: ...
- android高仿人人网
经过几个月的努力,终于基本完成了人人API拥有的所有功能,界面采用仿照人人梦想版5.13制作,其中资源文件也采用人人的APK文件资源,完成的功能及知识点如下: 1.通过三种动画仿照出人人引导页的放大切 ...