曲线参数化的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 ...
随机推荐
- python3 生成器&迭代器
#Author by Andy#_*_ coding:utf-8 _*_import timefrom collections import Iterable#列表生成式def func(): lis ...
- Web之路笔记之一
简单说一句,现在开始准备面试前端的知识,每天完成相关的任务,记录一些点. 2014秋季学期Web2.0课程习题 <Lab1 - About Me Page> 目标是自己动手写一个粗略的包含 ...
- gulp教程之gulp-less
简介: 使用gulp-less插件将less文件编译成css,当有less文件发生改变自动编译less,并保证less语法错误或出现异常时能正常工作并提示错误信息. 1.安装nodejs/全局安装gu ...
- 开发Blog整理
开发Blog记录 清理收藏夹 太多了,来不及看了. http://blog.sina.com.cn/s/blog_67d95f40010113ec.htmlhttp://segmentfault.co ...
- php简单单例模式
所谓单例模式,适用于使用一个对象可以完成所有的业务逻辑的类(一般不考虑继承的类) //单例模式 function getInstance($class_name){ //创建一个存储各种需要单例的类的 ...
- React Native 学习-01
React Native 学习 (学习版本 0.39) 一.环境配置 二.IDE选择 webstorm 1.webstorm配置 ①.首先是可以选择使用汉化包汉化.eu68 ②.安装插件和外部库. 由 ...
- 设置java web工程中默认访问首页的几种方式
1.demo中最常见的方式是在工程下的web.xml中设置(有时候根据业务可能需要设置action,在action中处理逻辑加载跳转什么的,比较少): <welcome-file-list> ...
- DataTable数据导出CSV文件
public static void SaveAsExcel(DataTable dt1) { //System.Windows.Forms.SaveFileDialog sfd = new Syst ...
- hibernate入门实例
1. 环境配置 1.1 hiberante环境配置 hibernate可实现面向对象的数据存储.hibernate的官网:http://hibernate.org/ 官网上选择hibernate OR ...
- linux学习 命令ll后字段的解释(转)
原文链接:http://jz20080153.blog.sohu.com/161554070.html ls -l 列表信息详解 我们平时用ls -l 命令查看一个目录下的文件和子目录的详悉信息时,会 ...