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

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

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

  

 

 

代码:

执行类:

  1 package com.yang.logic;
  2 
  3 import java.util.ArrayList;
  4 import java.util.Collections;
  5 import java.util.Comparator;
  6 import java.util.List;
  7 
  8 import com.yang.logic.Drawlineforspline.Mypanel;
  9 
 10 public class Testspline {
 11     
 12     // 根据X排序
 13     class SortByX implements Comparator {
 14         public int compare(Object obj1, Object obj2) {
 15             PointStruct point1 = (PointStruct) obj1;
 16             PointStruct point2 = (PointStruct) obj2;
 17             if (point1.dx > point2.dx)
 18                 return 1;
 19             else
 20                 return 0;
 21         }
 22     } 
 23     //转化成数组
 24     public static ArrayList<Double> getArrayfList(List<PointStruct> l, String type) {
 25         ArrayList<Double> tmplist = new ArrayList<Double>();
 26         for (PointStruct p : l) {
 27             if (type == "ix") {
 28                 tmplist.add((double) p.ix);
 29             } else if (type == "iy") {
 30                 tmplist.add((double) p.iy);
 31             } else if (type == "dx") {
 32                 tmplist.add(p.dx);
 33             } else if (type == "dy") {
 34                 tmplist.add(p.dy);
 35             }
 36         }
 37         return tmplist;
 38     }
 39     
 40     public static void main(String[] args) {
 41         
 42         //将来做插值的点列表
 43         List <PointStruct> pl=new  ArrayList<PointStruct>();
 44         
 45         //【1】 模拟 sin函数值  做初始化特定点(插值点或样条),  曲线将来就穿过下面几点    
 46         //        0.1    1    2    3    4
 47         //        0.099833417    0.841470985    0.909297427    0.141120008    0.61802
 48         
 49         pl.add(new PointStruct(0.1,0.099833417));
 50         pl.add(new PointStruct(1,0.841470985));
 51         pl.add(new PointStruct(2,0.909297427));
 52         pl.add(new PointStruct(3,0.141120008));
 53         pl.add(new PointStruct(4,0.61802));
 54      
 55         //【2】 添加 需要的未知点(新插值点), 为了使曲线光滑  采用小的步长 填充在已知点之间
 56         List <PointStruct> target=new  ArrayList<PointStruct>();        
 57         double step=0.1;        
 58         for(int k=0;k<pl.size();k++){
 59             
 60             if((k+1)<pl.size()){
 61                 double tmpd=0;
 62                 while(tmpd<pl.get(k+1).dx){
 63                     tmpd=tmpd+step;
 64                     target.add(new PointStruct(tmpd,0.0));
 65                 }
 66             }
 67         }
 68         
 69         //把点集合转化成为 x,y 各自的坐标点 Double[]集合 
 70         ArrayList tmp_x = getArrayfList(pl,"dx");
 71         ArrayList tmp_y = getArrayfList(pl,"dy");
 72         Double[] xspline=new Double[tmp_x.size()];
 73         Double[] yspline=new Double[tmp_x.size()];        
 74         for(int e=0;e<tmp_x.size();e++){
 75             xspline[e]=(Double) tmp_x.get(e);
 76             yspline[e]=(Double) tmp_y.get(e);
 77         } 
 78         
 79         //【3】根据 插值点初始化插值对象,并用spline样条函数进行计算(做三次样条插值运算)
 80         Interpolation ip = new Interpolation(xspline, yspline);
 81         for(int j=0;j<target.size();j++){
 82             target.get(j).dy=ip.spline(target.get(j).dx);        
 83         }
 84         
 85         //把新生成的样条添加到点集合中  做以后画图用 
 86         pl.addAll(target);
 87         
 88         //根据x点的大小进行点集合的排序
 89         Testspline t2=new Testspline();
 90         Collections.sort(pl, t2.new SortByX());
 91         
 92         //因为结果太小,所有必要放大一定度数,同时 Java画图最像是整数,所有把双精度转成整形
 93         int intScale=100; 
 94         for(PointStruct p:pl){
 95              p.ix=(int) (p.dx*intScale);
 96              p.iy=(int) (p.dy*intScale);
 97         }
 98         
 99         //查看中间结果 即画图所用到的所有点
100         int times=0;
101         for(PointStruct p:pl){
102             System.out.println(" order: :"+times++ +"  p.ix:"+p.ix+"    p.iy:"+p.iy);
103         }
104         
105         //【4】 调用画图类 画图
106         Drawlineforspline dlfs=new Drawlineforspline(pl); 
107         Mypanel myp=dlfs.new Mypanel();
108         dlfs.add(myp); 
109 
110     }
111 }

依赖类:

PointStruct

 1 package com.yang.logic;
 2 
 3 public class PointStruct {
 4     
 5     double dx;
 6     double dy;
 7     
 8     int ix;
 9     int iy;
10     
11     public PointStruct(double dx, double dy) {
12         this.dx = dx;
13         this.dy = dy;
14     }
15 
16     public PointStruct(int ix, int iy) {
17         this.ix = ix;
18         this.iy = iy;
19     }
20     
21     public PointStruct(double dx, double dy,boolean round) {
22         this.ix = RoundF(dx);
23         this.iy = RoundF(dy);
24     }
25     
26     public int RoundF(double a){
27         return (int) Math.round(a);
28     }
29 }
View Code

Interpolation

 1 package com.yang.logic;
 2 
 3 import java.util.Arrays;
 4 
 5 public class Interpolation {
 6 
 7     private int n;
 8     private Double[] xs;
 9     private Double[] ys;
10      
11     private boolean sp_initialized;
12     private double[] sp_y2s;
13 
14     public Interpolation(Double[] _xs, Double[] _ys) {
15         
16         this.n = _xs.length;
17         this.xs = Arrays.copyOf(_xs, _xs.length);
18         this.ys = Arrays.copyOf(_ys, _ys.length);
19         
20         this.sp_initialized = false;
21     } 
22     
23     public double spline(double x)
24     {
25         if (!this.sp_initialized) {
26             // Assume Natural Spline Interpolation
27             double p, qn, sig, un;
28             double[] us;
29             
30             us = new double[n-1];
31             sp_y2s = new double[n];
32             us[0] = sp_y2s[0] = 0.0;
33             
34             for (int i=1; i<=n-2; i++) {
35                 sig = (xs[i] - xs[i-1]) / (xs[i+1] - xs[i-1]);
36                 p = sig * sp_y2s[i-1] + 2.0;
37                 sp_y2s[i] = (sig - 1.0) / p;
38                 us[i] = (ys[i+1] - ys[i]) / (xs[i+1] - xs[i]) - (ys[i] - ys[i-1]) / (xs[i] - xs[i-1]);
39                 us[i] = (6.0 * us[i] / (xs[i+1] - xs[i-1]) - sig * us[i-1]) / p;
40             }
41             qn = un = 0.0;
42             
43             sp_y2s[n-1] = (un - qn * us[n-2]) / (qn * sp_y2s[n-2] + 1.0);
44             for (int k=n-2; k>=0; k--) {
45                 sp_y2s[k] = sp_y2s[k] * sp_y2s[k+1] + us[k];
46             }
47 
48             this.sp_initialized = true;
49         }
50         
51         int klo, khi, k;
52         double h, b, a;
53         
54         klo = 0;
55         khi = n-1;
56         while (khi-klo > 1) {
57             k = (khi+klo) >> 1;
58             if (xs[k] > x)
59                 khi = k;
60             else
61                 klo = k;
62         }
63         h = xs[khi] - xs[klo];
64         if (h == 0.0) {
65             throw new ArithmeticException();
66         }
67         a = (xs[khi] - x) / h;
68         b = (x - xs[klo]) / h;
69         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;
70     }
71 
72 }
View Code

Drawlineforspline

 1 package com.yang.logic;
 2 
 3 import java.awt.Color;
 4 import java.awt.Graphics;
 5 import java.util.List;
 6 
 7 import javax.swing.JFrame;
 8 import javax.swing.JPanel;
 9 
10 public class Drawlineforspline extends JFrame{
11     
12     private static final long serialVersionUID = 1L;
13     List <PointStruct>plist;
14      
15     public Drawlineforspline(){
16         init();
17     }
18     public Drawlineforspline(List<PointStruct> plist){
19         init();
20         this.plist=plist;
21     }    
22     
23     private void init(){
24         this.setTitle("drawline");
25         this.setBounds(200, 200, 500, 400);
26         this.setBackground(Color.white);
27         this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
28         this.setLocationRelativeTo(null);
29         this.setVisible(true); 
30     }
31     
32     public class Mypanel extends JPanel{     
33         public void paint(Graphics g){
34             g.setColor(Color.red);
35             //System.out.println(plist.size());
36             for(int i=0;i<plist.size()-1;i++){
37                 g.drawLine(plist.get(i).ix, plist.get(i).iy, plist.get(i+1).ix, plist.get(i+1).iy);
38             }         
39         }
40     }
41 }
View Code

 

代码下载 地址

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

posted on 2015-06-23 15:32  rojas  阅读(5083)  评论(0编辑  收藏  举报