這篇是爲了下一篇作點鋪墊,也是來複習一些數學基礎
本篇屬於休閒娛樂,不要太較真,小科普一下,不喜勿噴
本文知識點前4點你能夠隨便看看,但第5點很是重要
,本文源碼見捷文規範
git
本文知識點:
1)數學函數的概念
2)直角座標系的下函數圖形
3)極座標下的函數圖象
4)參數方程下的函數圖形
5)正弦函數的詳細分析(爲下一篇文章作鋪墊)github
設A,B爲非空的數集,若是按照某種肯定的對應關係f,
使對於集合A中的任意的任意一個數x,在集合B中都有惟一肯定的數f(x)和它對應,
那麼就稱"f:A→B"爲從集合A到集合B的一個函數,記做:
y=f(x),x∈A
其中,x叫作自變量,x的取值範圍叫作函數的[定義域]
與x的值對應的y值叫作函數值,函數值的集合{f(x)|x∈A}叫作函數的[值域]
複製代碼
設數集D⊂ R,則稱映射f:D→R爲定義在D上的函數,一般簡記爲
y=f(x),x∈ D
其中x稱自變量,y稱因變量,D稱定義域,記做Df,即Df=D.
值域:Rf=f(D)={y|y=f(x),x∈ D}
複製代碼
設X,Y是兩個非集合,若是存在一個法則f,使的對X中的每一個元素x,
按法則f,在Y中有惟一肯定的元素y與之對應,則稱f爲X到Y的映射,記做
f:X→Y
其中y稱爲元素x(在映射f下)的像,並記做f(x),即y=f(x)
而元素x稱爲元素y(在映射f下)的原像
複製代碼
這裏只是模擬函數,而後繪製出可視的圖象
數學中的實數是連續的,這裏在屏幕中將像素做爲基本的單元
繪圖核心:點集成線,單點半徑1px
自變量:x
定義域:Df用集合Set表示
函數關係:函數f(x)
點集用Map表示,x→y編程
網格和座標系我已經封裝,初始View以下:canvas
public class MathView extends View {
private Point mCoo = new Point(500, 700);//座標系
private Picture mCooPicture;//座標系canvas元件
private Picture mGridPicture;//網格canvas元件
private Paint mHelpPint;//輔助畫筆
private Paint mPaint;//主畫筆
private Path mPath;//主路徑
public MathView(Context context) {
this(context, null);
}
public MathView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();//初始化
}
private void init() {
//初始化主畫筆
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.BLUE);
mPaint.setStrokeWidth(2);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeCap(Paint.Cap.ROUND);
//初始化主路徑
mPath = new Path();
//初始化輔助
mHelpPint = HelpDraw.getHelpPint(Color.RED);
mCooPicture = HelpDraw.getCoo(getContext(), mCoo);
mGridPicture = HelpDraw.getGrid(getContext());
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
HelpDraw.draw(canvas, mGridPicture, mCooPicture);
canvas.save();
canvas.translate(mCoo.x, mCoo.y);
canvas.scale(1, -1);//y軸向上
canvas.restore();
}
複製代碼
具體細節這裏不說了,詳見:Android關於Canvas你所知道的和不知道的一切,或源碼bash
private TreeSet<Float> Df = new TreeSet<>();//定義域
private Map<Float, Float> funMap = new HashMap<>();//映射表
private Paint mTextPaint;//文字畫筆
複製代碼
/**
* 初始化定義域
*/
private void initDf() {
for (float i = -200; i <= 300; i++) {
Df.add(i);//初始化定義域
}
}
複製代碼
/**
* 對應法則
* @param x 原像(自變量)
* @return 像(因變量)
*/
private float f(Float x) {
float y = x;
return y;
}
複製代碼
/**
* 遍歷定義域,將原像x和像f(x)加入映射表
*/
private void map() {
Df.forEach(x -> {
funMap.put(x, f(x));
});
//添加全部點
}
複製代碼
/**
* 繪製映射表
* @param canvas 畫筆
* @param map 點集映射表
*/
private void drawMap(Canvas canvas, Map<Float, Float> map) {
map.forEach((k, v) -> {
canvas.drawPoint(k, v, mPaint);
});
}
複製代碼
只需改一點微信
/**
* 對應法則
* @param x 原像(自變量)
* @return 像(因變量)
*/
private float f(Float x) {
float y=Math.abs(x);
return y;
}
複製代碼
/**
* 對應法則
* @param x 原像(自變量)
* @return 像(因變量)
*/
private float f(Float x) {
float y=(x - 100) * (x - 100) / 200 + 100;
return y;
}
複製代碼
/**
* 初始化定義域
*/
private void initDf() {
for (float i = 1; i <= 1000; i++) {
Df.add(i);//初始化定義域
}
}
/**
* 對應法則
*
* @param x 原像(自變量)
* @return 像(因變量)
*/
private float f(Float x) {
float y = (float) (100.f * Math.log10(x));
return y;
}
複製代碼
/**
* 初始化定義域
*/
private void initDf() {
for (float i = -400; i <= 500; i++) {
Df.add(i);//初始化定義域
}
}
/**
* 對應法則
*
* @param x 原像(自變量)
* @return 像(因變量)
*/
private float f(Float x) {
float y= 100*(float) Math.pow(Math.E,x/300f);
return y;
}
複製代碼
/**
* 初始化定義域
*/
private void initDf() {
for (float i =-360; i <= 450; i++) {
Df.add(i);//初始化定義域
}
}
/**
* 對應法則
*
* @param x 原像(自變量)
* @return 像(因變量)
*/
private float f(Float x) {
float y= (float) (100*Math.sin(Math.PI/180*x));
return y;
}
複製代碼
經歷過上面幾個函數的繪製,不難發現,只有更改對應法則,即函數關係式就能夠了ide
1).尋找角度thta和長度p的函數關係
2).使用極座標與直角座標系的轉換關係來繪製點集函數
ρ= 100*(1-cosθ)
/**
* 初始化定義域
*/
private void initDf() {
for (float i = 1; i <= 360; i++) {
Df.add(i);//初始化定義域
}
}
/**
* 繪製映射表
*
* @param canvas 畫筆
* @param map 點集映射表
*/
private void drawMap(Canvas canvas, Map<Float, Float> map) {
map.forEach((thta, p) -> {
Log.e(TAG, "drawMap: "+p+thta);
canvas.drawPoint((float) (p * Math.cos(thta)), (float) (p * Math.sin(thta)), mPaint);
});
}
/**
* 對應法則
*
* @param thta 原像(自變量)
* @return 像(因變量)
*/
private float f(Float thta) {
float p = (float) (100 * (1 - Math.cos(thta)));
return p;
}
/**
* 遍歷定義域,將原像x和像f(x)加入映射表
*/
private void map() {
Df.forEach(x -> {
float thta = (float) (Math.PI / 180 * x);
funMap.put(thta, f(thta));
});
//添加全部點
}
複製代碼
ρ= 100*(1-4*sinθ)
/**
* 對應法則
*
* @param thta 原像(自變量)
* @return 像(因變量)
*/
private float f(Float thta) {
float p = (float) (100 * (1 - Math.sin(4 * thta)));
return p;
}
複製代碼
ρ=(e^(cosθ)- 2cos(4θ) + [sin(θ/12)]^5)*100
/**
* 對應法則
*
* @param thta 原像(自變量)
* @return 像(因變量)
*/
private float f(Float thta) {
float p = (float) (100f*(Math.pow(Math.E,Math.cos(thta)) - 2 * Math.cos(4 * thta) + Math.pow(Math.sin(thta / 12), 5)));;
return p;
}
複製代碼
ρ= a*θ
/**
* 對應法則
*
* @param thta 原像(自變量)
* @return 像(因變量)
*/
private float f(Float thta) {
float p = 30*thta;
return p;
}
複製代碼
/**
* 對應法則
*
* @param thta 原像(自變量)
* @return 像(因變量)
*/
private float f(Float thta) {
float p = 200;
return p;
}
複製代碼
x=a/cosα
,y=btanα
/**
* 初始化定義域
*/
private void initDf() {
for (float i = 0; i <= 360 ; i++) {
Df.add(i);//初始化定義域
}
}
/**
* 繪製映射表
*
* @param canvas 畫筆
* @param map 點集映射表
*/
private void drawMap(Canvas canvas, Map<Float, Float> map) {
map.forEach((k, v) -> {
canvas.drawPoint(k, v, mPaint);
});
}
/**
* 對應法則
*
* @param thta 原像(自變量)
* @return y像(因變量)
*/
private float y(Float thta) {
float y = (float) (100 * Math.tan(thta));
return y;
}
/**
* 對應法則
*
* @param thta 原像(自變量)
* @return x像(因變量)
*/
private float x(Float thta) {
float x = (float) (200 / Math.cos(thta));
return x;
}
/**
* 遍歷定義域,將原像x和像f(x)加入映射表
*/
private void map() {
Df.forEach(x -> {
float thta = (float) (Math.PI / 180 * x);
funMap.put(x(thta), y(thta));
});
//添加全部點
}
複製代碼
x=a*cosα
,y=bsinα
/**
* 對應法則
*
* @param thta 原像(自變量)
* @return y像(因變量)
*/
private float y(Float thta) {
float y = (float) (300 * Math.sin(thta));
return y;
}
/**
* 對應法則
*
* @param thta 原像(自變量)
* @return x像(因變量)
*/
private float x(Float thta) {
float x = (float) (400 * Math.cos(thta));
return x;
}
複製代碼
x=a√(cos2θ )cosθ
,y=a√(cos2θ)sinθ
/**
* 對應法則:y=a√(cos2θ)sinθ
*
* @param thta 原像(自變量)
* @return y像(因變量)
*/
private float y(Float thta) {
float y = (float) (200 * Math.sqrt(Math.cos(2*thta))*Math.sin(thta));
return y;
}
/**
* 對應法則:x=a√(cos2θ )cosθ
*
* @param thta 原像(自變量)
* @return x像(因變量)
*/
private float x(Float thta) {
float x = (float) (200 * Math.sqrt(Math.cos(2*thta))*Math.cos(thta));
return x;
}
複製代碼
你可能已經吐槽了:什麼鬼,怎麼後面都是斷斷續續的點拼成的
等等...先別急,咱們來看看這幅圖能說明什麼?
先看一下定義域: [-360,450],共810個點,每一個點半徑1px,每一個點橫向距離1px
點密集則說明相鄰兩點間的dy很小,相反,稀疏則說明相鄰兩點間的dy很大
也就是密集說明函數變化的幅度小,稀疏說明函數變化的幅度大
當相鄰兩點距離大於圓的直徑(2px)時,視覺上會看出兩個點,即不連續。post
爲了方便描述,這裏定義了幾個概念優化
若是把一條完美的函數曲線看做P,
那全部現實中(紙、屏幕)的函數圖象P'都是對P的取點模擬, 從P上取點的行爲稱爲[取樣], 採樣的個數稱爲[取樣總數], 取樣的相鄰兩點xn,xn+1間的距離稱爲[取樣距離dxn] 當每一個dxn值都相等的時,稱爲[等距採樣] 兩個樣本點pn,pn+1之間的距離稱爲[樣本距離dpn] 複製代碼
在加入點集時過濾掉相鄰兩點間距離大於直徑的點
/**
* 兩點間的距離
* @return
*/
private float dis(float x0, float y0, float x1, float y1) {
return (float) Math.sqrt((x0 - x1) * (x0 - x1) + (y0 - y1) * (y0 - y1));
}
複製代碼
/**
* 遍歷定義域,將原像x和像f(x)加入映射表
*/
private void map() {
Df.forEach(x -> {
float dis = dis(x, f(x), x + 1, f(x + 1));//每相鄰兩點間距離
if (dis < mLineWidth && dis > mLineWidth / 2) {
funMap.put(x, f(x));
}
});
複製代碼
思路也就是在間距處再取樣
/**
* 遍歷定義域,將原像x和像f(x)加入映射表
*/
private void map() {
Df.forEach(x -> {
float dis = dis(x, f(x), x + 1, f(x + 1));//每相鄰兩點間距離
if (dis < mLineWidth && dis > mLineWidth / 2) {
funMap.put(x, f(x));
} else if (dis > mLineWidth) {
float num = dis / mLineWidth;//在切割數
for (float di = 0; di <= num; di += (1.f / num)) {
x += di;
funMap.put(x, f(x));
}
}
});
//添加全部點
}
複製代碼
其中A,ω,φ,k是常數,且ω≠0
振幅:A
角頻率:ω
週期:T=2π/ω
頻率:f=1/T=ω/2π
相位:ωx+φ
初相:φ
平衡線:y=k
波峯:最大值|A|
波谷:最小值-|A|
複製代碼
離開平衡位置的最大距離
下面橫軸的每格表明90°,化爲弧度製表示即:π/2,每四格是360°,即2π
A=300
A=100
決定正弦曲線的波峯與波谷,形象來講就是"高矮"
振幅越大,波峯越高,波谷越低,每一個週期的圖象顯得"高"
複製代碼
單位時間內變化的相角弧度值
ω=2
ω=5
決定正弦曲線的週期,形象來講就是"胖瘦"
角頻率越大,週期越小,每一個週期的圖象顯得"瘦"
ω=2 週期:T = 2π/ω = π 從圖中看,每兩格一週期,即π
頻率:f = 1/T = 1/π
複製代碼
x=0時的相位
φ=π/6
φ=π/2
相位決定了標準正弦函數的左右偏移:正左偏,負右偏,偏移量:φ/ω
複製代碼
決定平衡線的位置
k=100
k=200
平衡值決定標準正弦函數的上下偏移:正上偏,負下偏,偏移量:k
複製代碼
如今對於幾個正弦函數的參數值已經有了一點了解,本篇結束
← | ↑ | → | ↓ |
---|---|---|---|
∪ | ∩ | ⊂ | ⊃ |
∈ | ∝ | ⊆ | ⊇ |
∞ | θ | ρ | φ |
π | α | β | γ |
η | μ | ζ | Ω |
項目源碼 | 日期 | 備註 |
---|---|---|
V0.1-github | 2018-1-2 | Android繪製函數圖象及正弦函數的介紹 |
筆名 | 微信 | 愛好 | |
---|---|---|---|
張風捷特烈 | 1981462002 | zdl1994328 | 語言 |
個人github | 個人簡書 | 個人掘金 | 我的網站 |
1----本文由張風捷特烈原創,轉載請註明
2----歡迎廣大編程愛好者共同交流
3----我的能力有限,若有不正之處歡迎你們批評指證,一定虛心改正
4----看到這裏,我在此感謝你的喜歡與支持