平面波動方程實現線條波動效果

前兩天看到一個水波的動畫圖,形如下面這樣子,突然波動方程在記憶深處就復活了。發現這個方程可以很好玩,雖然只是二維的,但還是分享給大家。


waveWater.gif

* 波動方程的推導

已知波源A的振動方程:y=Acos(ωt+φA?)。假設波沿x軸正方向傳播速率記為u,沿x軸負方向傳播速率記為V。以O點為坐標原點,A點的坐標為Xa,以水平向右為x軸的正方向建立坐標系。
當波沿x軸正方向傳播的時候,如下圖所示,在x軸正方向上任取一點P,與o點相距Xp。當得波向右傳播時,P點的振動落后于A點,落后的相位為ω (Xp-Xa)/u。可得P點在任意時刻t的位移:y=Acos[ωt-ω (Xp-Xa)/u+φa]= Acos[ωt- ω Xp/u+(φa+ ω Xa/u)]。可參考:如何求解平面簡諧波的波動方程

沿x軸方向傳播的平面簡諧波

得到的這個方程叫平面簡諧波動方程,形如:

y=Acos[ωt- ω Xp/u+(φa+ ω Xa/u)]

它能描述任意時刻任意點在Y軸方向上的位移y。加上一個微分的思想,取一個X+dx值,然后計算出對應的y值,將這些n個y值連成一條線就是任意時刻的波形圖。當t在流逝的時候這個波形圖不斷的在重畫,就形成了一個波動圖了!在代碼前先分析一下這個方程:y=Acos[ωt- ω Xp/u+(φa+ ω Xa/u)]

* 方程的物理意義

  • y是y坐標的位置,也就是我們要計算點的y值
  • A是振幅,就這個波振動幅度的大小
  • ω是頻率,可以理解為是振動的快慢,ω = 2 / T(T是周期)
  • t就是時間了,時間是均勻(絕對時空觀)往前走的
  • u描述的是波的傳播速率,波速=波長/周期
  • φa描述的波源的初相位,在圖上看就是這個點是在x軸(φa=0)上開始振動,還是在x軸上多少或下多少(cosφa)的地方開始振動。

只是為了實現這種效果,我們就利用最簡單的簡諧波了。此時:

  • 波的初相為φa = 0
  • 波源就在Xa處,即Xa = 0

此時波動方程就變成了:

* 最簡方程

y=Acos(ωt- ω Xp/u)

是不是簡單了好多!這樣再設兩個變量,一個是周期T和波長K,根據 “波速=波長/周期(u = K / T)” 和 ω = 2π / T。波動方程就可以推導成這個:

y = Acos2π(t/T - Xp/K)

這樣代碼的樣子就出來了,忍不住開始代碼了吧!

*代碼實現

利用Quartz2D就可以簡單實現,用一個UIView來實現,命名為WaveView(所有代碼都在WaveView.m文件里面)。
設置波的基本屬性:

    @interface WaveView ()
{
    CGFloat screenWidth;
    
    float A;    // 振幅
    float t;    // 時間變量
    
    float T;    // 周期
    float K;    // 波長
}
@end

在init方法里面初始化波的基本屬性值:

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        
        // 設置波的基本屬性()
        A = 6;
        t = 0;
        T = 1.0;
        K = 80;
        
        [self setBackgroundColor:[UIColor clearColor]];
        
        // 設置刷新圖像的頻率,0.3秒人眼就很難分辨出來了
        [NSTimer scheduledTimerWithTimeInterval:0.03 target:self selector:@selector(animateWave) userInfo:nil repeats:YES];
    }
    return self;
}

啟動動畫:

-(void)animateWave
{
    // 這里是時間機器,如果和刷新圖像的時間間隔一樣,那么就是正常時間的速度
    // 如果大于刷新時間間隔,那么時間就走的很快,是平常的多少倍自己去計算
    // 如果小于刷新時間間隔,那么時間就走的慢
    
    t+=0.05; // 這里比實際時間快
    
    [self setNeedsDisplay];
    

動畫算法的實現:

- (void)drawRect:(CGRect)rect
{
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGMutablePathRef path = CGPathCreateMutable();
    CGContextSetLineWidth(context, 2);
    CGContextSetStrokeColorWithColor(context, [[UIColor blackColor] CGColor]);
    float y=axleXOnScreenHeight;
    CGPathMoveToPoint(path, NULL, 0, y);
    
    // 這是將x軸微分單位為1pt,就是每隔1pt計算一個y值,將所有的y值連起來就是一個波圖
    // 可以將微分單位設置大一點,有不一樣的效果
    // y 值的計算就用推導出來的公式:y = Acos2π(t/T - Xp/K)
    for(float x=0;x <= screenWidth;x+=1){
        y =  A * cos(2*M_PI * (t / T -  x / K)) + axleXOnScreenHeight;
        CGPathAddLineToPoint(path, nil, x, y);
    }
    
    CGContextAddPath(context, path);
    CGContextDrawPath(context, kCGPathStroke);
    CGPathRelease(path);
}

效果如下,波長為80,屏幕寬了375剛好5個波峰的樣子:


waveView.gif

其它好玩的效果(比如波動過程中改變振幅的大小,就可以增加波的節奏感等):


waveViewZheXian.gif
waveViewWater.gif

waveViewUnkown.gif

是不是挺好玩的,可惜沒有接觸過3D引擎,不然整個世界都可以波動起來。
趕緊試試!
源碼位置:https://github.com/stoull/Wave

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,321評論 6 543
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,559評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,442評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,835評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,581評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,922評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,931評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,096評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,639評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,374評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,591評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,104評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,789評論 3 349
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,196評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,524評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,322評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,554評論 2 379

推薦閱讀更多精彩內容