曲线参数化的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实现(代码篇)的更多相关文章

  1. 曲线参数化的Javascript实现(理论篇)

    在关键帧动画的制作过程中,动画师在k物体运动的过程中,一般要确定2个参数: 1)运动轨迹(表示物体运动的路径): 2)速度曲线(表示物体随时间的速度变化). 对于运动轨迹通常选用一定的样条曲线,通过动 ...

  2. Javascript本质第二篇:执行上下文

    在上一篇文章<Javascript本质第一篇:核心概念>中,对Javascript执行上下文做了解释,但是这些都是基于Javascript标准中对执行上下文的定义,也就是说理论上的东西,本 ...

  3. JavaScript 精髓整理篇之一(对象篇)postby:http://zhutty.cnblogs.com

    废话篇头: 由于工作关系,所以写博文的时间有那么点~~,其实是输入法太懒了,都是输入法的错~~ 这一系列的博客将总结所有关于JavaScript语言的精髓,适合0基础到大师级别人物阅读. <Ja ...

  4. 32、可以拿来用的JavaScript实用功能代码

    可以拿来用的JavaScript实用功能代码(可能会有些bug,用时稍微修改下,我用了几个还可以) 转载自 1.原生JavaScript实现字符串长度截取 function cutstr(str, l ...

  5. JavaScript standard 代码规范的全文

    这是 JavaScript standard 代码规范的全文. 掌握本规范的最好方法是安装并在自己的代码中使用它. 细则 使用两个空格进行缩进. eslint: indent function hel ...

  6. JavaScript性能优化篇js优化

    JavaScript性能优化篇js优化   随着Ajax越来越普遍,Ajax引用的规模越来越大,Javascript代码的性能越来越显得重要,我想这就是一个很典型的例子,上面那段代码因为会被频繁使用, ...

  7. rcGIS API for JavaScript之基础篇(一)

    ArcGIS API for JavaScript之基础篇(一)上一篇文章介绍了ArcGIS 10.4的安装指南也包含了所需要资源,需要的同学可以去公众号中查找.最近几天学习了2D地图.3D地图以及图 ...

  8. TODO:一不顺眼就换字体Go之代码篇

    TODO:一不顺眼就换字体Go之代码篇 image包实现了一个基本的2D图像库,该包中包含基本的接口叫做image,这个里面包含color,这个将在image/color中描述:新增字体font,进行 ...

  9. javascript两行代码按指定格式输出日期时间

    javascript两行代码按指定格式输出日期时间,具体看代码: function date2str(x,y) { var z ={y:x.getFullYear(),M:x.getMonth()+1 ...

随机推荐

  1. NodeJS中的异步I/O、事件驱动

    nodejs的主要特点是单线程.异步I/O.事件驱动.让我们先大概了解一下这些名词的意思. 单线程 单线程是任务按照顺序执行的,并且每次只执行一个任务,只有前面的任务执行完成以后,后面的任务才执行.在 ...

  2. 推荐两个谷歌的json-view插件(附带下载分享地址)

    1.JSONView 网盘下载地址:http://pan.baidu.com/s/1hrGlaVa 效果图: 2.JSON-handle 网盘下载地址:http://pan.baidu.com/s/1 ...

  3. 关于owinstartupattribute的错误

    关于以上的作物究其原因在与引用的Microsoft.owin等一系列的dll文件,出现这个问题只需在内部删除多余的相关包就可以了,在我的项目中需要三个,如下图,其余的都删除 . 这些相关的dll为什么 ...

  4. visual studio错误解决 [error LNK1104: 无法打开文件“gdi32.lib”]

    哔了狗.我是win7装的vs2013,本着体验一下"新"玩意的心情.(然而2017都快出来了),没想到竟遇到如此粗鄙的问题. 从错误信息上明显可以了解是缺少一个静态库.(当然错误信 ...

  5. CentOS下 MySQL5.7 详细的部署安装流程

    MySQL5.7.14安装过程: 下载5.7版本:wget http://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.14-linux-glibc2 ...

  6. CentOS_7.2安装PHP_5.6

    一.安装依赖包和开发工具: yum install vim vim-enhanced wget zip unzip telnet ntsysv compat* apr* nasm* gcc gcc* ...

  7. 代码成长记录之jquery this使用

    后台管理的一个项目,第一次主动尝试自己动手写交互,果然问题来了,之前想当然觉得自己能写,不动笔,真的是对自己不负责任啊! 效果图是这样的,按我的思维写下来是点击一个‘更改’  多个地方会同时触发下拉 ...

  8. mysql5.6新特性总结

    一. server参数默认值设置的变化http://dev.mysql.com/doc/refman/5.6/en/server-default-changes.html 二. innodb增强1.全 ...

  9. PHP分页类,生成分页html字符串

    <?php namespace Common\Common; /** * 该Page类主要有两个方法:showPageString(), showPageStringAsAJAX() * * s ...

  10. virtual_login

    from selenium import webdriverimport timedriver = webdriver.Chrome()driver.set_window_position(30, 4 ...