JFreeChart簡單實現(xiàn)光滑曲線繪制
更新時間:2018年06月19日 13:07:07 作者:jvl_jevy
這篇文章主要為大家詳細介紹了JFreeChart簡單實現(xiàn)光滑曲線的繪制,具有一定的參考價值,感興趣的小伙伴們可以參考一下
用JFreeChart繪制光滑曲線,利用最小二乘法數(shù)學原理計算,供大家參考,具體內(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è)置多項式的次數(shù)
int times = 2;
public FittingCurve(String title) {
super(title);
//使用最小二乘法計算擬合多項式中各項前的系數(shù)。
/*
請注意: 多項式曲線參數(shù)計算 與 Chart圖表生成 是分開處理的。
多項式曲線參數(shù)計算: 負責計算多項式系數(shù), 返回多項式系數(shù)List。
Chart圖表生成: 僅僅負責按照給定的數(shù)據(jù)繪圖。 比如對給定的點進行連線。
本實例中,光滑的曲線是用密度很高的點連線繪制出來的。 由于我們計算出了多項式的系數(shù),所以我們讓X軸數(shù)據(jù)按照很小的步長增大,針對每一個X值,使用多項式計算出Y值, 從而得出點眾多的(x,y)組。 把這些(x, y)組成的點連線繪制出來,則顯示出光滑的曲線。
XYSeries為JFreeChart繪圖數(shù)據(jù)集, 用于繪制一組有關(guān)系的數(shù)據(jù)。 XYSeries對應(yīng)于X,Y坐標軸數(shù)據(jù)集, 添加數(shù)據(jù)方式為: XYSeries s.add(x,y);
XYSeriesCollection 為XYSeries的集合, 當需要在一個Chart上繪制多條曲線的時候,需要把多條曲線對應(yīng)的XYSeries添加到XYSeriesCollection
添加方法:dataset.addSeries(s1);
dataset.addSeries(s2);
*/
//多項式的次數(shù)從高到低,該函數(shù)需要的參數(shù):x軸數(shù)據(jù)<List>,y軸數(shù)據(jù)<List>,多項式的次數(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)建用坐標表示的折線圖
JFreeChart xyChart = ChartFactory.createXYLineChart(
"二次多項式擬合光滑曲線", "X軸", "Y軸", xydataset, PlotOrientation.VERTICAL, true, true, false);
//生成坐標點點的形狀
XYPlot plot = (XYPlot) xyChart.getPlot();
XYItemRenderer r = plot.getRenderer();
if (r instanceof XYLineAndShapeRenderer) {
XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) r;
renderer.setBaseShapesVisible(false);//坐標點的形狀是否可見
renderer.setBaseShapesFilled(false);
}
ValueAxis yAxis = plot.getRangeAxis();
yAxis.setLowerMargin(2);
return xyChart;
}
//數(shù)據(jù)集按照邏輯關(guān)系添加到對應(yīng)的集合
public XYDataset getXYDataset() {
//預(yù)設(shè)數(shù)據(jù)點數(shù)據(jù)集
XYSeries s2 = new XYSeries("點點連線");
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("擬合曲線");
//獲取擬合多項式系數(shù),equation在構(gòu)造方法中已經(jīng)實例化
List<Double> list = this.equation;
//獲取預(yù)設(shè)的點數(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;
//按照多項式的形式 還原多項式,并利用多項式計算給定x時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ù)(點)
public List<List<Double>> getData(){
//x為x軸坐標
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;
}
//以下代碼為最小二乘法計算多項式系數(shù)
//最小二乘法多項式擬合
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>();
//計算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);
}
//計算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);
//計算多項式系數(shù),多項式從高到低排列
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;
}
//計算一元多次方程前面的系數(shù), 其排列為 xm xm-1 …… x0(多項式次數(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;
}
}
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Java并發(fā)編程之詳解ConcurrentHashMap類
在之前的文章中已經(jīng)為大家介紹了java并發(fā)編程的工具:BlockingQueue接口、ArrayBlockingQueue、DelayQueue、LinkedBlockingQueue、PriorityBlockingQueue、SynchronousQueue、BlockingDeque接口,本文為系列文章第八篇.需要的朋友可以參考下2021-06-06
java實現(xiàn)把兩個有序數(shù)組合并到一個數(shù)組的實例
今天小編就為大家分享一篇java實現(xiàn)把兩個有序數(shù)組合并到一個數(shù)組的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-05-05
java中申請不定長度數(shù)組ArrayList的方法
今天小編就為大家分享一篇java中申請不定長度數(shù)組ArrayList的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-07-07

