2013-01-12 57 views
0

我有1000+行正弦波數據隨時間變化,我想用處理語言將其可視化。我的目標是創建一個動畫,從矩形[height/2]的中間開始繪製正弦波。我也只想顯示那一波的1秒鐘。我的意思是1秒後,第一個座標應該消失,等等。處理可視化正弦波

我該如何做到這一點? 感謝

樣本數據:

TIME X Y 
0.1333 0 0 
0.2666 0.1 0.0999983333 
0.3999 0.2 0.1999866669 
0.5332 0.3 0.299955002 
0.6665 0.4 0.3998933419 
0.7998 0.5 0.4997916927 
0.9331 0.6 0.5996400648 
1.0664 0.7 0.6994284734 

回答

1

你實現這一目標的方式是這個項目拆分成任務:

  1. 負載&解析數據
  2. 更新時間和呈現數據

爲了確保第1部分順利地,最好確保你的數據很容易解析。示例數據看起來像表格/電子表格,但它沒有用標準分隔符(例如逗號或製表符)格式化。你可以擺弄的東西,當你分析,但我建議先用乾淨的數據,例如,如果你打算使用space作爲分隔符:

TIME X Y 
0.1333 0.0 0 
0.2666 0.1 0.0999983333 
0.3999 0.2 0.1999866669 
0.5332 0.3 0.299955002 
0.6665 0.4 0.3998933419 
0.7998 0.5 0.4997916927 
0.9331 0.6 0.5996400648 
1.0664 0.7 0.6994284734 

一旦這樣做了,你可以使用loadStrings()加載數據和split()將一行分成3個元素,它們可以從字符串轉換爲浮點數。

一旦你有使用價值,你可以存儲它們。您可以創建三個數組,每個數組都持有來自加載數據的字段(一個用於所有X值,一個用於所有Y值,一個用於所有時間值),或者可以作弊並使用單個數組對象。雖然PVector是用於3D數學/線性代數,但您有2D座標,因此您可以將時間存儲爲第3個「維度」/分量。

第二部分主要圍繞基於時間的更新展開,這就是millis()派上用場的地方。您可以檢查更新之間傳遞的時間量,並且如果它大於某個(延遲)值,那麼是另一次更新(幀/數據行索引)的時間。

您需要擔心的最後一部分是在屏幕上呈現數據。幸運的是,在您的示例數據中,座標被標準化(在0.0和1.0之間),這使得繪圖尺寸(通過使用簡單的乘法)變得很容易。否則,map()函數就派上用場了。

下面就來說明上述的草圖,data.csv是從上面包含格式化的樣本數據的文本文件:

PVector[] frames;//keep track of the frame data(position(x,y) and time(store in PVector's z property)) 
int currentFrame = 0,totalFrames;//keep track of the current frame and total frames from the csv 
int now, delay = 1000;//keep track of time and a delay to update frames 

void setup(){ 
    //handle data 
    String[] rows = loadStrings("data.csv");//load data 
    totalFrames = rows.length-1;//get total number of lines (-1 = sans the header) 
    frames = new PVector[totalFrames];//initialize/allocate frame data array 
    for(int i = 1 ; i <= totalFrames; i++){//start parsing data(from 1, skip header) 
    String[] frame = rows[i].split(" ");//chop each row into 3 strings(time,x,y) 
    frames[i-1] = new PVector(float(frame[1]),float(frame[2]),float(frame[0]));//parse each row(not i-1 to get back to 0 index) and how the PVector's initialized 1,2,0 (x,y,time) 
    } 
    now = millis();//initialize this to keep track of time 
    //render setup, up to you 
    size(400,400);smooth();fill(0);strokeWeight(15); 
} 
void draw(){ 
    //update 
    if(millis() - now >= delay){//if the amount of time between the current millis() and the last time we updated is greater than the delay (i.e. every 'delay' ms) 
    currentFrame++;//update the frame index 
    if(currentFrame >= totalFrames) currentFrame = 0;//reset to 0 if we reached the end 
    now = millis();//finally update our timer/stop-watch variable 
    } 
    PVector frame = frames[currentFrame];//get the data for the current frame 
    //render 
    background(255); 
    point(frame.x * width,frame.y * height);//draw 
    text("frame index: " + currentFrame + " data: " + frame,mouseX,mouseY); 
} 

有需要一些額外的注意事項:

  1. 你在1秒後移動到下一個座標。從我在示例數據中可以看到每秒有8次更新,因此1000/8可能會更好。這取決於你如何處理時間。
  2. 我假設你的全套包含正弦波運動的數據。我已映射到完整座標,但在draw()循環的渲染部分中,您可以根據自己的喜好(例如,包括高度/ 2偏移量等)進行映射。另外,如果您不熟悉正弦波,請查看這些處理資源:Daniel Shiffman's SineWave sample,Ira Greenberg's trig tutorial