曲线参数化的Javascript实现(代码篇)
在曲线参数化的Javascript实现(理论篇)中推出了曲线弧长积分的公式,以及用二分法通过弧长s来查找样条曲线上对应的u,再求Q(u)的值。弧长积分函数如下:
,其中
-----公式1
Simpson展开后
-------公式2
这里的f(u)就是上面的弧长s的求值函数,既样条曲线拟合函数Q(u)的积分
这部分具体代码如下:1.计算f(u)的系数ABCDE
CParametric.prototype.SegCoef = function(CSpline, o)
{
p0.x=this.k[0]*CSpline.Spline[o].x+this.k[1]*CSpline.Spline[o+1].x+this.k[2]*CSpline.Spline[o+2].x+this.k[3]*CSpline.Spline[o+3].x;
p1.x=this.k[4]*CSpline.Spline[o].x+this.k[5]*CSpline.Spline[o+1].x+this.k[6]*CSpline.Spline[o+2].x+this.k[7]*CSpline.Spline[o+3].x;
p2.x=this.k[8]*CSpline.Spline[o].x+this.k[9]*CSpline.Spline[o+1].x+this.k[10]*CSpline.Spline[o+2].x+this.k[11]*CSpline.Spline[o+3].x;
p3.x=this.k[12]*CSpline.Spline[o].x+this.k[13]*CSpline.Spline[o+1].x+this.k[14]*CSpline.Spline[o+2].x+this.k[15]*CSpline.Spline[o+3].x; p0.y=this.k[0]*CSpline.Spline[o].y+this.k[1]*CSpline.Spline[o+1].y+this.k[2]*CSpline.Spline[o+2].y+this.k[3]*CSpline.Spline[o+3].y;
p1.y=this.k[4]*CSpline.Spline[o].y+this.k[5]*CSpline.Spline[o+1].y+this.k[6]*CSpline.Spline[o+2].y+this.k[7]*CSpline.Spline[o+3].y;
p2.y=this.k[8]*CSpline.Spline[o].y+this.k[9]*CSpline.Spline[o+1].y+this.k[10]*CSpline.Spline[o+2].y+this.k[11]*CSpline.Spline[o+3].y;
p3.y=this.k[12]*CSpline.Spline[o].y+this.k[13]*CSpline.Spline[o+1].y+this.k[14]*CSpline.Spline[o+2].y+this.k[15]*CSpline.Spline[o+3].y; this.A=9*(p0.x*p0.x+p0.y*p0.y);
this.B=12*(p0.x*p1.x+p0.y*p1.y);
this.C=6*(p0.x*p2.x+p0.y*p2.y)+4*(p1.x*p1.x+p1.y*p1.y);
this.D=4*(p1.x*p2.x+p1.y*p2.y);
this.E=p2.x*p2.x+p2.y*p2.y;
}
这里的k数组是Cardinal样条曲线的Mc矩阵,具体内容可以参考Cardinal样条曲线的Javascript实现(理论篇)。这里的p0,p1,p2,p3就是公式1里的ax,ay,bx,by,cx,cy,dx,dy。从而求得积分函数系数。
2.计算扩展的Simpson方法展开后得到的积分函数
CParametric.prototype.ArcLength = function(ustart, uend){
var h,sum,u;
var i;
h=(uend-ustart)*1.0/ITERATION_COUNT; //扩展的Simposon方法的阶数
sum=0;
u=ustart+h;
for(var i=2; i <= ITERATION_COUNT; i++){
if(!(i&1)){
sum += 4.0*this.ArcIntergrand(u);
}
else{
sum += 2.0*this.ArcIntergrand(u);
}
u += h;
}
return(h*this.ArcIntergrand(ustart)+sum+this.ArcIntergrand(uend)/3.0);
}
这里的ITERATION_COUNT是扩展的Simposon方法的阶数,既公式2中的n,其中的ArcIntergrand(u)就是求fi的值,代码如下:
CParametric.prototype.ArcIntergrand = function(u)
{
var f;
f=this.A*u*u*u*u+this.B*u*u*u+this.C*u*u+this.D*u+this.E;
f=Math.sqrt(f);
return f;
}
3.建立s-u索引表
上面的积分函数只能得到没一个曲线段上一个u对应s的值,而一整条样条曲线由多个小曲线段组成,比如计算第二段曲线上累加的s的值的时候只要把前面那段曲线的总长作为一个基数加上去就可以了。建立了s-u索引表之后就可以用二分法来查找每个给定的s对应的u的值了。因为这个函数是严格单调递增的,所以这个索引表肯定是升序的,就可以用二分法来查找。具体代码如下:
CParametric.prototype.SetLengths = function(spline, npoints){
var no_segments; //u分割的精度
var arcLength;
this.seg_lengths = new Array();
no_segments = npoints-3;
arcLength = 0;
this.seg_lengths[0]=0;
for(var i=0; i<no_segments; i++){
this.SegCoef(spline, i);
arcLength += this.ArcLength(0.,1.); //ArcLength(0,1)就是前面一个曲线段的总长
this.seg_lengths[i+1] = arcLength;
}
this.total_length = arcLength;
for(var i=1; i<no_segments; i++){
this.seg_lengths[i] /= this.total_length; //s归一化
}
}
因为弧长累加的值较大,所以对其进行归一化之后可以得到更标准的弧长值。
4.二分法计算弧长为seg的曲线上的点的位置pt
CParametric.prototype.ArcLengthPoint = function(spline, seg){
var uL=0., uR=1., usearch;
var segment_dist, ssearch;
var segment_no=0;
do{
segment_no++;
}while(this.seg_lengths[segment_no] < seg);
segment_no --;
segment_dist = this.total_length*(s-this.seg_lengths[segment_no]);
this.SegCoef(spline,segment_no);
do{
usearch = (uL+uR)/2;
ssearch = this.ArcLength(uL, usearch);
if(segment_dist < ssearch+SEARCH_TOL){
uR=usearch;
}
else{
uL=usearch;
segment_dist -= ssearch;
}
}while((segment_dist>ssearch+SEARCH_TOL) || (segment_dist<ssearch-SEARCH_TOL));
this.GetPointOnSpline(usearch);
};
就是普通的二分查找法,给定一个弧长seg,在函数曲线上找到对应的u的值,返回的usearch就是在指定精度var SEARCH_TOL=0.5(可以任意指定)的情况下得到的u的值。再通过调用this.GetPointOnSpline(usearch)函数来计算u=usearch时对应的Q(u)的值。
CParametric.prototype.GetPointOnSpline=function(usearch){
this.pt[pointnum]= new CPT();
this.pt[pointnum].x=p0.x*usearch*usearch*usearch+p1.x*usearch*usearch+p2.x*usearch+p3.x;
this.pt[pointnum].y=p0.y*usearch*usearch*usearch+p1.y*usearch*usearch+p2.y*usearch+p3.y;
}
曲线参数化的Javascript实现(代码篇)的更多相关文章
- 曲线参数化的Javascript实现(理论篇)
在关键帧动画的制作过程中,动画师在k物体运动的过程中,一般要确定2个参数: 1)运动轨迹(表示物体运动的路径): 2)速度曲线(表示物体随时间的速度变化). 对于运动轨迹通常选用一定的样条曲线,通过动 ...
- Javascript本质第二篇:执行上下文
在上一篇文章<Javascript本质第一篇:核心概念>中,对Javascript执行上下文做了解释,但是这些都是基于Javascript标准中对执行上下文的定义,也就是说理论上的东西,本 ...
- JavaScript 精髓整理篇之一(对象篇)postby:http://zhutty.cnblogs.com
废话篇头: 由于工作关系,所以写博文的时间有那么点~~,其实是输入法太懒了,都是输入法的错~~ 这一系列的博客将总结所有关于JavaScript语言的精髓,适合0基础到大师级别人物阅读. <Ja ...
- 32、可以拿来用的JavaScript实用功能代码
可以拿来用的JavaScript实用功能代码(可能会有些bug,用时稍微修改下,我用了几个还可以) 转载自 1.原生JavaScript实现字符串长度截取 function cutstr(str, l ...
- JavaScript standard 代码规范的全文
这是 JavaScript standard 代码规范的全文. 掌握本规范的最好方法是安装并在自己的代码中使用它. 细则 使用两个空格进行缩进. eslint: indent function hel ...
- JavaScript性能优化篇js优化
JavaScript性能优化篇js优化 随着Ajax越来越普遍,Ajax引用的规模越来越大,Javascript代码的性能越来越显得重要,我想这就是一个很典型的例子,上面那段代码因为会被频繁使用, ...
- rcGIS API for JavaScript之基础篇(一)
ArcGIS API for JavaScript之基础篇(一)上一篇文章介绍了ArcGIS 10.4的安装指南也包含了所需要资源,需要的同学可以去公众号中查找.最近几天学习了2D地图.3D地图以及图 ...
- TODO:一不顺眼就换字体Go之代码篇
TODO:一不顺眼就换字体Go之代码篇 image包实现了一个基本的2D图像库,该包中包含基本的接口叫做image,这个里面包含color,这个将在image/color中描述:新增字体font,进行 ...
- javascript两行代码按指定格式输出日期时间
javascript两行代码按指定格式输出日期时间,具体看代码: function date2str(x,y) { var z ={y:x.getFullYear(),M:x.getMonth()+1 ...
随机推荐
- Centos6.5下的Hadoop安装
开始进行云计算部分的学习,为了存档,写下现在进行过的步骤 需要用到的主要版本: 虚拟机:Vmware Workstation pro 12.5 Linux系统:CentOS6.4 64bit jdk版 ...
- pc端页面在移动端显示问题
1.pc端页面在移动端显示,默认视口宽度是980px(也就是body宽度是980px),可通过meta标签设置为需要的尺寸,比如页面中元素最大宽度是1220px,则如下所示 <meta name ...
- windows安装postgres源代码
http://blog.csdn.net/adrastos/article/details/9093739 1. 下载PostgreSQL的源代码.解压. 2. 在Windows平台下编译需要跳过一个 ...
- 未能加载文件或程序集“Newtonsoft.Json”或它的某一个依赖项。找到的程序集清单定义与程序集引用不匹配
引用第三方的 fineui 库依然使用旧版本导致.更换 fineui为新版,或找到源码更改引用 为新版,问题解决.
- F2工作流引擎这工作流引擎体系架构(二)
F2工作流体系架构概览图 为了能更好的了解F2工作流引擎的架构体系,花了些时间画了整个架构的体系图.F2工作流引擎遵循参考WFCM规范,目标是实现轻量级的工作流引擎,支持多种数据库及快速应用到任何基于 ...
- 设置apache登陆密码验证
一.编辑虚拟目录配置文件,设置认证方式 Alias /test"/var/www/test"<Directory "/var/www/test">O ...
- dll版本冲突的解决方法
问题描述 当运行站点或者控制台等程序时,如果项目引用的dll版本与其它dll所依赖的dll版本不一致,就会报未能加载程序集的错误.错误信息为: 未能加载文件或程序集"Newtonsoft.J ...
- Sql语句复习
1.两张表A,B 其中A表中字段1,字段2,字段3要迁移到B表中字段4,字段5,字段6,迁移后B表的字段7 全赋值为123: insert into B(字段4,字段5,字段6,字段7) select ...
- oracle异常:ORA-01422: exact fetch returns more than requested
ORA-01422: exact fetch returns more than requested 神奇的错误,困扰了我一个下午. 问题描述:明明只有一行记录,结果是报了多条记录的错误.令我百思不得 ...
- UIImagePickerController和UIAlertController结合使用
在处理个人资料 - 头像的时候,通常有两个选项,一个是调用系统相机,一个是调用系统相册.这里要使用的就是UIImagePickerController方法. 在头像位置的imageView添加一个手势 ...