java 三次样条插值 画光滑曲线 例子

主要是做数值拟合,根据sin函数采点,取得数据后在java中插值并在swing中画出曲线,下面为截图  不光滑和光滑曲线前后对比:

  

代码:

执行类:

 package com.yang.logic;

 import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List; import com.yang.logic.Drawlineforspline.Mypanel; public class Testspline { // 根据X排序
class SortByX implements Comparator {
public int compare(Object obj1, Object obj2) {
PointStruct point1 = (PointStruct) obj1;
PointStruct point2 = (PointStruct) obj2;
if (point1.dx > point2.dx)
return 1;
else
return 0;
}
}
//转化成数组
public static ArrayList<Double> getArrayfList(List<PointStruct> l, String type) {
ArrayList<Double> tmplist = new ArrayList<Double>();
for (PointStruct p : l) {
if (type == "ix") {
tmplist.add((double) p.ix);
} else if (type == "iy") {
tmplist.add((double) p.iy);
} else if (type == "dx") {
tmplist.add(p.dx);
} else if (type == "dy") {
tmplist.add(p.dy);
}
}
return tmplist;
} public static void main(String[] args) { //将来做插值的点列表
List <PointStruct> pl=new ArrayList<PointStruct>(); //【1】 模拟 sin函数值 做初始化特定点(插值点或样条), 曲线将来就穿过下面几点
// 0.1 1 2 3 4
// 0.099833417 0.841470985 0.909297427 0.141120008 0.61802 pl.add(new PointStruct(0.1,0.099833417));
pl.add(new PointStruct(1,0.841470985));
pl.add(new PointStruct(2,0.909297427));
pl.add(new PointStruct(3,0.141120008));
pl.add(new PointStruct(4,0.61802)); //【2】 添加 需要的未知点(新插值点), 为了使曲线光滑 采用小的步长 填充在已知点之间
List <PointStruct> target=new ArrayList<PointStruct>();
double step=0.1;
for(int k=0;k<pl.size();k++){ if((k+1)<pl.size()){
double tmpd=0;
while(tmpd<pl.get(k+1).dx){
tmpd=tmpd+step;
target.add(new PointStruct(tmpd,0.0));
}
}
} //把点集合转化成为 x,y 各自的坐标点 Double[]集合
ArrayList tmp_x = getArrayfList(pl,"dx");
ArrayList tmp_y = getArrayfList(pl,"dy");
Double[] xspline=new Double[tmp_x.size()];
Double[] yspline=new Double[tmp_x.size()];
for(int e=0;e<tmp_x.size();e++){
xspline[e]=(Double) tmp_x.get(e);
yspline[e]=(Double) tmp_y.get(e);
} //【3】根据 插值点初始化插值对象,并用spline样条函数进行计算(做三次样条插值运算)
Interpolation ip = new Interpolation(xspline, yspline);
for(int j=0;j<target.size();j++){
target.get(j).dy=ip.spline(target.get(j).dx);
} //把新生成的样条添加到点集合中 做以后画图用
pl.addAll(target); //根据x点的大小进行点集合的排序
Testspline t2=new Testspline();
Collections.sort(pl, t2.new SortByX()); //因为结果太小,所有必要放大一定度数,同时 Java画图最像是整数,所有把双精度转成整形
int intScale=100;
for(PointStruct p:pl){
p.ix=(int) (p.dx*intScale);
p.iy=(int) (p.dy*intScale);
} //查看中间结果 即画图所用到的所有点
int times=0;
for(PointStruct p:pl){
System.out.println(" order: :"+times++ +" p.ix:"+p.ix+" p.iy:"+p.iy);
} //【4】 调用画图类 画图
Drawlineforspline dlfs=new Drawlineforspline(pl);
Mypanel myp=dlfs.new Mypanel();
dlfs.add(myp); }
}

依赖类:

PointStruct

 package com.yang.logic;

 public class PointStruct {

     double dx;
double dy; int ix;
int iy; public PointStruct(double dx, double dy) {
this.dx = dx;
this.dy = dy;
} public PointStruct(int ix, int iy) {
this.ix = ix;
this.iy = iy;
} public PointStruct(double dx, double dy,boolean round) {
this.ix = RoundF(dx);
this.iy = RoundF(dy);
} public int RoundF(double a){
return (int) Math.round(a);
}
}

Interpolation

 package com.yang.logic;

 import java.util.Arrays;

 public class Interpolation {

     private int n;
private Double[] xs;
private Double[] ys; private boolean sp_initialized;
private double[] sp_y2s; public Interpolation(Double[] _xs, Double[] _ys) { this.n = _xs.length;
this.xs = Arrays.copyOf(_xs, _xs.length);
this.ys = Arrays.copyOf(_ys, _ys.length); this.sp_initialized = false;
} public double spline(double x)
{
if (!this.sp_initialized) {
// Assume Natural Spline Interpolation
double p, qn, sig, un;
double[] us; us = new double[n-1];
sp_y2s = new double[n];
us[0] = sp_y2s[0] = 0.0; for (int i=1; i<=n-2; i++) {
sig = (xs[i] - xs[i-1]) / (xs[i+1] - xs[i-1]);
p = sig * sp_y2s[i-1] + 2.0;
sp_y2s[i] = (sig - 1.0) / p;
us[i] = (ys[i+1] - ys[i]) / (xs[i+1] - xs[i]) - (ys[i] - ys[i-1]) / (xs[i] - xs[i-1]);
us[i] = (6.0 * us[i] / (xs[i+1] - xs[i-1]) - sig * us[i-1]) / p;
}
qn = un = 0.0; sp_y2s[n-1] = (un - qn * us[n-2]) / (qn * sp_y2s[n-2] + 1.0);
for (int k=n-2; k>=0; k--) {
sp_y2s[k] = sp_y2s[k] * sp_y2s[k+1] + us[k];
} this.sp_initialized = true;
} int klo, khi, k;
double h, b, a; klo = 0;
khi = n-1;
while (khi-klo > 1) {
k = (khi+klo) >> 1;
if (xs[k] > x)
khi = k;
else
klo = k;
}
h = xs[khi] - xs[klo];
if (h == 0.0) {
throw new ArithmeticException();
}
a = (xs[khi] - x) / h;
b = (x - xs[klo]) / h;
return a*ys[klo] + b*ys[khi] + ((a*a*a-a)*sp_y2s[klo]+(b*b*b-b)*sp_y2s[khi])*(h*h)/6.0;
} }

Drawlineforspline

 package com.yang.logic;

 import java.awt.Color;
import java.awt.Graphics;
import java.util.List; import javax.swing.JFrame;
import javax.swing.JPanel; public class Drawlineforspline extends JFrame{ private static final long serialVersionUID = 1L;
List <PointStruct>plist; public Drawlineforspline(){
init();
}
public Drawlineforspline(List<PointStruct> plist){
init();
this.plist=plist;
} private void init(){
this.setTitle("drawline");
this.setBounds(200, 200, 500, 400);
this.setBackground(Color.white);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
this.setVisible(true);
} public class Mypanel extends JPanel{
public void paint(Graphics g){
g.setColor(Color.red);
//System.out.println(plist.size());
for(int i=0;i<plist.size()-1;i++){
g.drawLine(plist.get(i).ix, plist.get(i).iy, plist.get(i+1).ix, plist.get(i+1).iy);
}
}
}
}

代码下载 地址

转载请注明 http://www.cnblogs.com/rojas/p/4595509.html

最新文章

  1. struts2学习笔记--拦截器(Interceptor)和登录权限验证Demo
  2. docker centos7 rabbitmq3.6.5
  3. Web Service 的工作原理
  4. sql 树 递归
  5. 有两个地方,用到了javabean对象和属性字符串值之间的转换
  6. 拒绝了对对象 &#39;**&#39; (数据库 &#39;db&#39;,架构 &#39;dbo&#39;)的 SELECT 权限
  7. 《Usermod:user lee is currently logged in 家目录不能改变解决方法》
  8. 在Ubuntu6.06 在搭建SVN服务器及在windows建立svn+ssh客户端 (续)
  9. 打破C++ Const 的规则
  10. 电子科大POJ &quot;敲错键盘&quot;
  11. [译]Stairway to Integration Services Level 5 - 增量删除数据
  12. windows下取linux系统里面的文件
  13. PHP接口和抽象类的区别
  14. iOS 发布流程 分类: ios相关 app相关 2015-05-22 14:50 186人阅读 评论(0) 收藏
  15. PHp连接数据库实现增删改查
  16. Babel运行原理
  17. Java、Apache Tomcat下载与安装及环境变量配置
  18. tf.nn.in_top_k原理探究
  19. 【Python】多线程-线程池使用
  20. 【转】JS windows.open()详解

热门文章

  1. TI C66x DSP 四种内存保护问题 -之- 外设訪问corePac内部资源时的内存保护问题
  2. QThread 爬坑之旅(三种办法解决QObject: Cannot create children for a parent that is in a different thread)
  3. 22. Angular 中用 a 标签 href 路由时在浏览器中显示异常 &quot;%2F&quot; 路由失败问题
  4. Function的一些结论与eval函数.
  5. vue --- cli build 后的项目,图片路径出错
  6. 104.virtual虚函数多态与异构数据结构
  7. 由安装两块网卡的linux系统中引起网络不通想到的
  8. 【转】一篇关于32位Linux内核使用大内存的文章——Hugemem Kernel Explained  &nb
  9. 二进制部署mysql5.6
  10. 几种类型的db,以及最新的db排名,看一下