曲线参数化的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. Oracle 表连接

    Oracle 表之间的连接分为三种: 1. 内连接(自然连接) 2. 外连接 (1)左外连接 (左边的表不加限制)      (2)右外连接(右边的表不加限制)      (3)全外连接(左右两表都不 ...

  2. CSS样式应用

    CSS样式应用的方法: (1)行内样式,将css样式直接放到标签当中,一般都是放入标签的style属性中,它是最方便的一种样式,也是最不方便修改的样式.如下: (2)内嵌式,通过将css写在网页源文件 ...

  3. (48) odoo的button用法

    button 应用的比较多,这里来汇总一下 按钮<button>,支持的属性     icon  可用的icon在 addons/web/static/src/img/icons     ...

  4. [转]IE8兼容Object.keys

    转自:http://blog.sina.com.cn/s/blog_6d63cf160102vbsg.html 只需要加入 var DONT_ENUM = "propertyIsEnumer ...

  5. JAVA类与对象

    Employee类: public class EmployeeTest { public static void main(String[] args) { // fill the staff ar ...

  6. C++ void*的使用

    void*类型可以存储任何类型的指针,使用的时候强制转化成对应类型的指针便可. #include <iostream> #include <vector> using name ...

  7. Windows Store App 网络通信 HttpWebRequest

    如果希望更好地控制HTTP请求,可以使用System.Net类库中的HttpWebRequest类,该类对HTTP协议进行了完整的封装,并且提供了很多对HTTP协议中的 Header.Content和 ...

  8. JQUERY MOBILE 中文API站 和 官方论坛

    中文API站:http://www.jqmapi.com/api1.2/preview/quickstartquide.html 官方论坛:http://bbs.phonegapcn.com/foru ...

  9. QT 做软件盘

    最近搞了一个组织细胞脱水机项目,当然,对于国内的项目都是仿来仿去的,我们也不例外,开启被仿机器后,第一个看到的界面就是用户登录界面,需要输入中文,作为一个程序员,我的第一反应就是我需要采用什么用的框架 ...

  10. mongodb 使用场景和不使用场景

    1.mongodb介绍 MongoDB (名称来自"humongous") 是一个可扩展的高性能,开源,模式自由,面向文档的数据库.它使用C++编写.MongoDB特点: a.面向 ...