1. 程式人生 > >Canvas利用圓繪製正餘弦函式疊加影象

Canvas利用圓繪製正餘弦函式疊加影象

前言

昨天看傅立葉變換的資料,看到這篇文章:如果看了此文你還不懂傅立葉變換,就過來掐死我吧
講得很清晰,中間一幅圖的美麗深深吸引了我。。。
正弦函式疊加影象
於是萌生了利用Canvas把它畫下來的想法。可是正餘弦函式的基礎早已經忘得差不多了,
所以先畫個大概,慢慢更新當作畢設前練手吧。現在的樣子:
現在的粗糙樣子

部落格新手。。如果各位看官覺得條理比較亂請指教一下

準備工作

畫圓相關

先自定義了一個Circle類,方便新增任意多個圓

public class Circle {
    //主顏色
    private int color;
    //半徑
    private
int radius; //圓心 private Point mCenterPoint; //圓上動點當前位置 private Point mMovePoint; //當前動點移動角度 private int mCurrentDegree; //動點角度增量 private int mIncreaseDegree; //getter和setter省略 }

畫圓之前要先弄清楚一個概念,弧度和角度,引用維基定義:

弧度:單位弧度定義為圓弧長度等於半徑時的圓心角。
角度:一週角分為360等份,每份定義為1度(1°)

圖片均引自:

這篇部落格
弧度示意圖
弧度示意圖

大圓的相關引數

    private List<Circle> circles = new ArrayList<>();

    //第一個大圓的相關引數
    private int mMainColor = 0xFF009688;
    private int mCircleStartDegree = 0;
    private int mCircleIncreaseDegree = 4;
    private Point mCircleCenter = new Point(dp2px(50),dp2px(20));
    private int
mLargeRadius = dp2px(30);

畫影象相關

    //圓當前指向影象的點
    private Point mOriginWavePoint = new Point(dp2px(150),dp2px(100));
    //影象上的點的集合,用連結串列方便增刪
    private int mWaveMaxLength = 180;
    private List<Point> mWavePoints = new LinkedList<>();

繪製

畫圓

新增第一個大圓:

private void init() {
        Circle circle = new Circle(mMainColor);
        circle.setmIncreaseDegree(mCircleIncreaseDegree);
        circle.setmCurrentDegree(mCircleStartDegree);
        circle.setRadius(mLargeRadius);
        circle.setmCenterPoint(mCircleCenter);

        circles.add(circle);
    }

新增圓:

    public void addCircle(Circle circle){
        int mMinRadius = 2;
        if (circles.size() > 0){
            mMinRadius = circles.get(circles.size() - 1).getRadius();
            if (mMinRadius <= 1) return;
        }
        circle.setRadius(circles.get(circles.size() - 1).getRadius()/3);
        circle.setmIncreaseDegree(circles.get(circles.size() - 1).getmIncreaseDegree() * 3);
        circles.add(circle);
    }

畫圓:

    private void drawCircle(Canvas canvas) {
        canvas.save();
        initPaint();
        for (int i = 0; i < circles.size(); i++) {
            Circle circle = circles.get(i);
            //依次設定大圓動點為小圓圓心
            if (i == 0) {
                circle.setmCenterPoint(new Point(dp2px(50),dp2px(100)));
            }else {
                circle.setmCenterPoint(circles.get(i - 1).getmMovePoint());
            }
            initCirclePaint();
            //根據圓的顏色設定畫筆
            mPaint.setColor(circle.getColor());
            canvas.drawCircle(circle.getmCenterPoint().x,circle.getmCenterPoint().y,
                    circle.getRadius(),mPaint);
            //根據動點旋轉角度求座標
            int movePointX = (int) (circle.getmCenterPoint().x + circle.getRadius() * Math.cos(Math.toRadians(circle.getmCurrentDegree())));
            int movePointY = (int) (circle.getmCenterPoint().y + circle.getRadius() * Math.sin(Math.toRadians(circle.getmCurrentDegree())));
            circle.setmMovePoint(new Point(movePointX,movePointY));
            //重設當前旋轉角度
            int currentDegree = (circle.getmCurrentDegree() - circle.getmIncreaseDegree()) % 360;
            circle.setmCurrentDegree(currentDegree);
            //繪製圓心到動點連線
            canvas.drawLine(circle.getmCenterPoint().x,circle.getmCenterPoint().y,
                    movePointX,movePointY,mPaint);
        }
        canvas.restore();
    }

畫函式影象

    private void drawWave(Canvas canvas) {
        //最外圈圓的動點座標
        Point movePoint = circles.get(circles.size() - 1).getmMovePoint();
        //設定影象最左側一點的縱座標
        mOriginWavePoint.y = movePoint.y;
        //影象最長為180個畫素
        if (mWavePoints.size() >= 180){
            mWavePoints.remove(0);
        }
        mWavePoints.add(new Point(mOriginWavePoint));
        //畫一個點
        initPointPaint();
        canvas.drawPoint(mOriginWavePoint.x, mOriginWavePoint.y,mPaint);
        canvas.drawLine(movePoint.x,movePoint.y, mOriginWavePoint.x, mOriginWavePoint.y,mPaint);

        Path path = new Path();
        path.moveTo(mWavePoints.get(0).x,mWavePoints.get(0).y);
        for (int i = mWavePoints.size() - 1 ; i > 0; i --){
            path.lineTo(mWavePoints.get(i).x + mWavePoints.size() - i,mWavePoints.get(i).y);
        }
        canvas.drawPath(path,mPaint);
    }

附上原始碼:原始碼