精华内容
下载资源
问答
  • 通过多点绘制光滑曲线 (as3.0

    千次阅读 2008-07-18 08:09:00
    通过多点绘制光滑曲线 (as3.0) 来源:闪吧个人空间作者:ywxgood 2008-06-24 【大 中小】 问题:有n个随机点,需要用光滑曲线将起连接起来,曲线看上去要有一定的曲度?思路1:从第一个点穿过第二个点到第三个点绘制...

     通过多点绘制光滑曲线 (as3.0)
    来源:闪吧个人空间作者:ywxgood 2008-06-24 【大 中小】

    问题:有n个随机点,需要用光滑曲线将起连接起来,曲线看上去要有一定的曲度?

    思路1:从第一个点穿过第二个点到第三个点绘制曲线,然后再穿过第四个点到第五个点绘制曲线,穿过第六个点到第七个点。。。这样可以看出来,点的个数n比为奇数,才可以画到终点,暂设置n=9。

    var numPoints = n;//n必为奇数,暂设为9
    //创建随机点构成的一个数组
    var points:Array = new Array();
    for(var i=0;i<numPoints;i++){
       points[i] = {};
       points[i].x = Math.random()*stage.width;
       points[i].y = Math.random()*stage.height;
    }
    //设置笔触样式
    lineStyle(1);
    //移动笔到第一个点
    moveTo(points[0].x,points[0].y);
    //循环每一个相邻的后续对画曲线
    for(i=1;i<numPoints;i+=2){
       curveTo(points[i].x,points[i].y,points[i+1].x,points[i+1].y); 

    }
    思路2:在每两个点之间插入一个新的点,位于原两点之间,用所插入的点为每条曲线的起始点和终点,用原来的点作为控制点画曲线,这样没有点的个数必为奇数的限制,且画出来的曲线比第一种方法的曲线更加“好看”。如下图:

     

     

    空心白点为原来的点,黑色实心点为插入的新点(图片来源:http://lovejulia.cn/blog/article.asp?id=107,参考:http://lovejulia.cn/blog/article.asp?id=107http://blog.sina.com.cn/s/blog_3ecb9b1101008z9g.html

    从图上看出,第一个插入的点,与最后一个插入的点没有用到,也就是说没有用来作为任何控点和终点,所以只需要在第二个点和倒数第二个点之间插入新点,算法如下:

    var numPoints = n;
    var points:Array = new Array();
    for(var i=0;i<numPoints;i++){
       points[i] = {};
       points[i].x = Math.random()*stage.width;
       points[i].y = Math.random()*stage.height;
    }
    lineStyle(1);
    moveTo(points[0].x,points[0].y);
    //在第二个点与倒数第二个点间插入新点,并绘制曲线
    for(i=1;i<numPoints-2;i++){
       var xc = (points[i].x+points[i+1].x)/2;
       var yc = (points[i].y+points[i+1].y)/2;
       //i从1开始的,即第一个控点是原来的第二个点,终点(xc,yc)为原第二个点与第三个点间插入的新点,即第一个插入的点。。。循环结束i=numPoints-2,即还剩下两个点没有画线
       curveTo(points[i].x,points[i].y,xc,yc);
    }
    //追加最后一条曲线(倒数第二个点为控点,最后一个点为终点)
    curveTo(points[i].x,points[i].y,points[i+1].x,points[i+1].y); 


    总结:思路1中是经过每个原始点画曲线,但必须要求点的个数为奇数,且最小给定点个数为 三,画出来的曲线可以看出明显的衔接,曲度不够,不是要求的曲线;思路2中的曲线只是经过了第一个点和最后一个点,中间的点是根据原有点来插入的点,也就 是说并没有经过给出的点,而是经过由给出点所得出的新点,这种方法得出的曲线没有点数必为奇数的限制,且曲度也可以达到要求。
    文章来自: 闪客居(www.flashas.net) 详文参考:http://www.flashas.net/html/flashasyy/20080624/3364.html

    展开全文
  • 用JFreeChart绘制光滑曲线(二) 简单实现上个月写了一篇 用JFreeChart绘制光滑曲线(原创)的文章, 其中用到的代码为我所做毕业设计项目的源码,因为牵涉到大量的数据库数据及数据库数据的算,和大量的化学物质物性...

    用JFreeChart绘制光滑曲线 (利用最小二乘法数学原理计算)

    绘制图形:

     

    代码:

    FittingCurve.java

     

    <pre name="code" class="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;
     //设置多项式的次数
     int times = 2;
     
     public FittingCurve(String title) {
      super(title);
      //使用最小二乘法计算拟合多项式中各项前的系数。
    /*
    请注意: 多项式曲线参数计算 与 Chart图表生成 是分开处理的。
    多项式曲线参数计算: 负责计算多项式系数, 返回多项式系数List。
    Chart图表生成: 仅仅负责按照给定的数据绘图。 比如对给定的点进行连线。
                    本实例中,光滑的曲线是用密度很高的点连线绘制出来的。  由于我们计算出了多项式的系数,所以我们让X轴数据按照很小的步长增大,针对每一个X值,使用多项式计算出Y值, 从而得出点众多的(x,y)组。 把这些(x, y)组成的点连线绘制出来,则显示出光滑的曲线。
    XYSeries为JFreeChart绘图数据集, 用于绘制一组有关系的数据。 XYSeries对应于X,Y坐标轴数据集, 添加数据方式为: XYSeries s.add(x,y);
    XYSeriesCollection 为XYSeries的集合, 当需要在一个Chart上绘制多条曲线的时候,需要把多条曲线对应的XYSeries添加到XYSeriesCollection
     添加方法:dataset.addSeries(s1);  
    dataset.addSeries(s2);
    */
      //多项式的次数从高到低,该函数需要的参数:x轴数据<List>,y轴数据<List>,多项式的次数<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轴数据集
      XYDataset xydataset = this.getXYDataset();
      //创建用坐标表示的折线图
      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;
     }
     
    //数据集按照逻辑关系添加到对应的集合
     public XYDataset getXYDataset() {
     //预设数据点数据集
      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));
      }
    // 拟合曲线绘制 数据集 XYSeries s1 = new XYSeries("拟合曲线");
      //获取拟合多项式系数,equation在构造方法中已经实例化
      List<Double> list = this.equation;
      //获取预设的点数据
      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);
         }
      
       //把预设数据集合拟合数据集添加到XYSeriesCollection
         XYSeriesCollection dataset = new XYSeriesCollection();
            dataset.addSeries(s1);
            dataset.addSeries(s2);
      return dataset;
      
     }
     //模拟设置绘图数据(点)
     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;
      
     }
     
    //以下代码为最小二乘法计算多项式系数
    //最小二乘法多项式拟合
     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 放入二维数组,作为矩阵
      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();
      }
      //把矩阵转化为三角矩阵
      matrix = this.matrixConvert(matrix);
      //计算多项式系数,多项式从高到低排列
      result = this.MatrixCalcu(matrix);
      return result;
     }
     //矩阵转换为三角矩阵
     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;
     }
     
     //计算一元多次方程前面的系数, 其排列为 xm xm-1 …… x0(多项式次数从高到低排列)
     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数据的最大最小值
     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;
     }
     
    }
     


    
    


    展开全文
  • "data":[ { "name":"指标a", ... "smooth":true,//当为true时,即为光滑曲线(默认为true);当为false,即为折线。 "data":[116, 129, 135, 86, 73, 85, 73,68,92,130,245,139,115,111] } ] ...
    "data":[
          {
            "name":"指标a",
            "type":"line",
            "stack": "总量",
            "smooth":true,//当为true时,即为光滑的曲线(默认为true);当为false,即为折线。
            "data":[116, 129, 135, 86, 73, 85, 73,68,92,130,245,139,115,111]
          }
        ]
    
    展开全文
  • 在Android中如何绘制光滑曲线(二)

    千次阅读 2014-10-29 22:13:18
    上一篇主要介绍了绘制经过每个点的光滑曲线的原理,本文会重点介绍一下在Android中如何从零开始使用贝塞尔方法编写一个光滑曲线图控件。程序的设计图如下: 一、样式控制类ChartStyle ...

    上一篇主要介绍了绘制经过每个点的光滑曲线的原理,本文会重点介绍一下在Android中如何从零开始使用贝塞尔方法编写一个光滑曲线图控件。程序的设计图如下:

    bessel_chart

    一、样式控制类ChartStyle

    二、基础数据集合ChartData

    2.1、坐标轴标签Label

    2.2、时间序列Series

    2.3、横向标题Title

    2.4、数据结点Point

    三、光滑曲线图BesselChartView

    四、核心类BesselCalculator

    五、核心代码:

    5.1 计算光滑曲线的贝塞尔控制点

    5.2、坐标变换。由于手机屏幕的坐标是朝右下方的,而我们实际显示的时候是朝左上方的,所以需要进行坐标变换,代码:

    5.3、实现拖动

    实现OnGestureListener的OnScroll方法

    在BesselChartView的onDraw方法中调用如下代码来平移画布实现拖动

     

    5.4、实现滑动

    只实现拖动会让人有一种不流畅的感觉,所以还需要实现滑动,考虑到应用要支持api level 8,可以使用Scroller来实现(api level 9以后google推荐使用OverScroller来实现,OverScroller允许滚动超出边界,可以实现回弹效果), OnGestureListener的onFling和onDown方法:

    获取scroller计算的偏移,同时刷新UI,computeScroll()会在View的onDraw方法之前执行

    5.5、实现滚动动画

    六、使用到的绘图相关的api

    6.1 Canvas 画布

    6.2 Paint 画笔

    6.3 Path 路径

    七、源代码地址:https://github.com/TomkeyZhang/BesselChart

    八、在安居客android app中的效果图

    graph

    展开全文