JFreeChart簡(jiǎn)單實(shí)現(xiàn)光滑曲線繪制
用JFreeChart繪制光滑曲線,利用最小二乘法數(shù)學(xué)原理計(jì)算,供大家參考,具體內(nèi)容如下
繪制圖形:
代碼:
FittingCurve.java
package org.jevy; import java.util.ArrayList; import java.util.List; import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartPanel; import org.jfree.chart.JFreeChart; import org.jfree.chart.axis.ValueAxis; import org.jfree.chart.plot.PlotOrientation; import org.jfree.chart.plot.XYPlot; import org.jfree.chart.renderer.xy.XYItemRenderer; import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; import org.jfree.data.xy.XYDataset; import org.jfree.data.xy.XYSeries; import org.jfree.data.xy.XYSeriesCollection; import org.jfree.ui.ApplicationFrame; import org.jfree.ui.RefineryUtilities; public class FittingCurve extends ApplicationFrame{ List<Double> equation = null; //設(shè)置多項(xiàng)式的次數(shù) int times = 2; public FittingCurve(String title) { super(title); //使用最小二乘法計(jì)算擬合多項(xiàng)式中各項(xiàng)前的系數(shù)。 /* 請(qǐng)注意: 多項(xiàng)式曲線參數(shù)計(jì)算 與 Chart圖表生成 是分開處理的。 多項(xiàng)式曲線參數(shù)計(jì)算: 負(fù)責(zé)計(jì)算多項(xiàng)式系數(shù), 返回多項(xiàng)式系數(shù)List。 Chart圖表生成: 僅僅負(fù)責(zé)按照給定的數(shù)據(jù)繪圖。 比如對(duì)給定的點(diǎn)進(jìn)行連線。 本實(shí)例中,光滑的曲線是用密度很高的點(diǎn)連線繪制出來的。 由于我們計(jì)算出了多項(xiàng)式的系數(shù),所以我們讓X軸數(shù)據(jù)按照很小的步長(zhǎng)增大,針對(duì)每一個(gè)X值,使用多項(xiàng)式計(jì)算出Y值, 從而得出點(diǎn)眾多的(x,y)組。 把這些(x, y)組成的點(diǎn)連線繪制出來,則顯示出光滑的曲線。 XYSeries為JFreeChart繪圖數(shù)據(jù)集, 用于繪制一組有關(guān)系的數(shù)據(jù)。 XYSeries對(duì)應(yīng)于X,Y坐標(biāo)軸數(shù)據(jù)集, 添加數(shù)據(jù)方式為: XYSeries s.add(x,y); XYSeriesCollection 為XYSeries的集合, 當(dāng)需要在一個(gè)Chart上繪制多條曲線的時(shí)候,需要把多條曲線對(duì)應(yīng)的XYSeries添加到XYSeriesCollection 添加方法:dataset.addSeries(s1); dataset.addSeries(s2); */ //多項(xiàng)式的次數(shù)從高到低,該函數(shù)需要的參數(shù):x軸數(shù)據(jù)<List>,y軸數(shù)據(jù)<List>,多項(xiàng)式的次數(shù)<2> this.equation = this.getCurveEquation(this.getData().get(0),this.getData().get(1),this.times); //生成Chart JFreeChart chart = this.getChart(); ChartPanel chartPanel = new ChartPanel(chart); chartPanel.setPreferredSize(new java.awt.Dimension(500, 270)); chartPanel.setMouseZoomable(true, false); setContentPane(chartPanel); } public static void main(String[] args) { // TODO Auto-generated method stub FittingCurve demo = new FittingCurve("XYFittingCurve"); demo.pack(); RefineryUtilities.centerFrameOnScreen(demo); demo.setVisible(true); } //生成chart public JFreeChart getChart(){ //獲取X和Y軸數(shù)據(jù)集 XYDataset xydataset = this.getXYDataset(); //創(chuàng)建用坐標(biāo)表示的折線圖 JFreeChart xyChart = ChartFactory.createXYLineChart( "二次多項(xiàng)式擬合光滑曲線", "X軸", "Y軸", xydataset, PlotOrientation.VERTICAL, true, true, false); //生成坐標(biāo)點(diǎn)點(diǎn)的形狀 XYPlot plot = (XYPlot) xyChart.getPlot(); XYItemRenderer r = plot.getRenderer(); if (r instanceof XYLineAndShapeRenderer) { XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) r; renderer.setBaseShapesVisible(false);//坐標(biāo)點(diǎn)的形狀是否可見 renderer.setBaseShapesFilled(false); } ValueAxis yAxis = plot.getRangeAxis(); yAxis.setLowerMargin(2); return xyChart; } //數(shù)據(jù)集按照邏輯關(guān)系添加到對(duì)應(yīng)的集合 public XYDataset getXYDataset() { //預(yù)設(shè)數(shù)據(jù)點(diǎn)數(shù)據(jù)集 XYSeries s2 = new XYSeries("點(diǎn)點(diǎn)連線"); for(int i=0; i<data.get(0).size(); i++){ s2.add(data.get(0).get(i),data.get(1).get(i)); } // 擬合曲線繪制 數(shù)據(jù)集 XYSeries s1 = new XYSeries("擬合曲線"); //獲取擬合多項(xiàng)式系數(shù),equation在構(gòu)造方法中已經(jīng)實(shí)例化 List<Double> list = this.equation; //獲取預(yù)設(shè)的點(diǎn)數(shù)據(jù) List<List<Double>> data = this.getData(); //get Max and Min of x; List<Double> xList = data.get(0); double max =this.getMax(xList); double min = this.getMin(xList); double step = max - min; double x = min; double step2 = step/800.0; //按照多項(xiàng)式的形式 還原多項(xiàng)式,并利用多項(xiàng)式計(jì)算給定x時(shí)y的值 for(int i=0; i<800; i++){ x = x + step2; int num = list.size()-1; double temp = 0.0; for(int j=0; j<list.size(); j++){ temp = temp + Math.pow(x, (num-j))*list.get(j); } s1.add(x, temp); } //把預(yù)設(shè)數(shù)據(jù)集合擬合數(shù)據(jù)集添加到XYSeriesCollection XYSeriesCollection dataset = new XYSeriesCollection(); dataset.addSeries(s1); dataset.addSeries(s2); return dataset; } //模擬設(shè)置繪圖數(shù)據(jù)(點(diǎn)) public List<List<Double>> getData(){ //x為x軸坐標(biāo) List<Double> x = new ArrayList<Double>(); List<Double> y = new ArrayList<Double>(); for(int i=0; i<10; i++){ x.add(-5.0+i); } y.add(26.0); y.add(17.1); y.add(10.01); y.add(5.0); y.add(2.01); y.add(1.0); y.add(2.0); y.add(5.01); y.add(10.1); y.add(17.001); List<List<Double>> list = new ArrayList<List<Double>>(); list.add(x); list.add(y); return list; } //以下代碼為最小二乘法計(jì)算多項(xiàng)式系數(shù) //最小二乘法多項(xiàng)式擬合 public List<Double> getCurveEquation(List<Double> x, List<Double> y, int m){ if(x.size() != y.size() || x.size() <= m+1){ return new ArrayList<Double>(); } List<Double> result = new ArrayList<Double>(); List<Double> S = new ArrayList<Double>(); List<Double> T = new ArrayList<Double>(); //計(jì)算S0 S1 …… S2m for(int i=0; i<=2*m; i++){ double si = 0.0; for(double xx:x){ si = si + Math.pow(xx, i); } S.add(si); } //計(jì)算T0 T1 …… Tm for(int j=0; j<=m; j++){ double ti = 0.0; for(int k=0; k<y.size(); k++){ ti = ti + y.get(k)*Math.pow(x.get(k), j); } T.add(ti); } //把S和T 放入二維數(shù)組,作為矩陣 double[][] matrix = new double[m+1][m+2]; for(int k=0; k<m+1; k++){ double[] matrixi = matrix[k]; for(int q=0; q<m+1; q++){ matrixi[q] = S.get(k+q); } matrixi[m+1] = T.get(k); } for(int p=0; p<matrix.length; p++){ for(int pp=0; pp<matrix[p].length; pp++){ System.out.print(" matrix["+p+"]["+pp+"]="+matrix[p][pp]); } System.out.println(); } //把矩陣轉(zhuǎn)化為三角矩陣 matrix = this.matrixConvert(matrix); //計(jì)算多項(xiàng)式系數(shù),多項(xiàng)式從高到低排列 result = this.MatrixCalcu(matrix); return result; } //矩陣轉(zhuǎn)換為三角矩陣 public double[][] matrixConvert(double[][] d){ for(int i=0; i<d.length-1; i++){ double[] dd1 = d[i]; double num1 = dd1[i]; for(int j=i; j<d.length-1;j++ ){ double[] dd2 = d[j+1]; double num2 = dd2[i]; for(int k=0; k<dd2.length; k++){ dd2[k] = (dd2[k]*num1 - dd1[k]*num2); } } } for(int ii=0; ii<d.length; ii++){ for(int kk=0; kk<d[ii].length; kk++) System.out.print(d[ii][kk]+" "); System.out.println(); } return d; } //計(jì)算一元多次方程前面的系數(shù), 其排列為 xm xm-1 …… x0(多項(xiàng)式次數(shù)從高到低排列) public List<Double> MatrixCalcu(double[][] d){ int i = d.length -1; int j = d[0].length -1; List<Double> list = new ArrayList<Double>(); double res = d[i][j]/d[i][j-1]; list.add(res); for(int k=i-1; k>=0; k--){ double num = d[k][j]; for(int q=j-1; q>k; q--){ num = num - d[k][q]*list.get(j-1-q); } res = num/d[k][k]; list.add(res); } return list; } //獲取List中Double數(shù)據(jù)的最大最小值 public double getMax(List<Double> data){ double res = data.get(0); for(int i=0; i<data.size()-1; i++){ if(res<data.get(i+1)){ res = data.get(i+1); } } return res; } public double getMin(List<Double> data){ double res = data.get(0); for(int i=0; i<data.size()-1; i++){ if(res>data.get(i+1)){ res = data.get(i+1); } } return res; } }
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Java實(shí)現(xiàn)數(shù)字轉(zhuǎn)成英文的方法
這篇文章主要介紹了Java實(shí)現(xiàn)數(shù)字轉(zhuǎn)成英文的方法,涉及java數(shù)組與字符串的相關(guān)操作技巧,需要的朋友可以參考下2015-05-05SpringBoot項(xiàng)目集成xxljob實(shí)現(xiàn)全紀(jì)錄
XXL-JOB是一個(gè)分布式任務(wù)調(diào)度平臺(tái),本文主要介紹了SpringBoot項(xiàng)目集成xxljob實(shí)現(xiàn)全紀(jì)錄,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11java 中使用匿名類直接new接口詳解及實(shí)例代碼
這篇文章主要介紹了java 中使用匿名類直接new接口詳解及實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下2017-03-03Idea?springboot?springCloud熱加載熱調(diào)試兩種常用方式
這篇文章主要介紹了Idea?springboot?springCloud熱加載熱調(diào)試常用的兩種方式,在項(xiàng)目開發(fā)的過程中,需要修改調(diào)試的時(shí)候偶每次都需要重啟項(xiàng)目浪費(fèi)時(shí)間,下面是我整理的兩種常用的兩種方式,需要的朋友可以參考下2023-04-04Java Socket實(shí)現(xiàn)UDP編程淺析
類 DatagramSocket 何 DatagramPacket(數(shù)據(jù)包/數(shù)據(jù)報(bào)) 實(shí)現(xiàn)了基于 UDP協(xié)議網(wǎng)絡(luò)程序;UDP數(shù)據(jù)報(bào)通過數(shù)據(jù)報(bào)套接字 DatagramSocket 發(fā)送和接收,系統(tǒng)不保證 UDP數(shù)據(jù)報(bào)一定能夠安全送達(dá)目的地,也不確定什么時(shí)候可以抵達(dá)2022-11-11Java 中Json中既有對(duì)象又有數(shù)組的參數(shù)如何轉(zhuǎn)化成對(duì)象(推薦)
Gson庫(kù)是一個(gè)功能強(qiáng)大、易于使用的Java序列化/反序列化庫(kù),它提供了豐富的API來支持Java對(duì)象和JSON之間的轉(zhuǎn)換,這篇文章主要介紹了Java 中Json中既有對(duì)象又有數(shù)組的參數(shù)如何轉(zhuǎn)化成對(duì)象,需要的朋友可以參考下2024-07-07Spring Security角色繼承實(shí)現(xiàn)過程解析
這篇文章主要介紹了Spring Security角色繼承實(shí)現(xiàn)過程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08IDEA中SpringBoot項(xiàng)目的yml多環(huán)境配置方式
這篇文章主要介紹了IDEA中SpringBoot項(xiàng)目的yml多環(huán)境配置,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2023-10-10