[英]Issues trying to scale up sine wave in c
希望有人可以指出為什么這行不通或我可能在哪里出錯。 Im通過c中的for循環產生正弦波。 最終目的是生成一個顯示此內容的.ppm文件。 我正在以1到1的像素比例工作。 我的盒子是128H * 256W。 正弦波正在顯示,但是由於以弧度為單位產生的答案,結果是非常小的兩個像素高的“波”。 我認為這是由於rad值介於1和-1之間。 這是我的代碼。 我只是嘗試以更大的次數計時以增加y值的大小,希望它能正確繪制,但這很少或更糟,導致應用程序停止運行。 任何想法都非常歡迎。
for (x = 0; x < H; x++)
{
y =(int) H/2+ sin(x*(2*PI));
y = y * 50;
image[y][x][1] = 0;
image[y][x][2] = 255;
image[y][x][3] = 0;
}
編輯:這是通過紅外線查看在.ppm文件中生成的內容。 還在im#定義PI 3.141592653589793。 再有可能這是一個問題領域。
我認為y
是一個int
。
您的sin
值將被截斷為整數; 大多數情況下為0,但偶爾為-1或+1。
修復很簡單:對y
使用浮點數,並在想要將其用作數組索引時進行強制轉換。
y = y * 50
,其中y = H/2
(+或-1)為您提供y約為25*H
,這是超出范圍的。
這是一個更接近的近似值:
y = (int) ( H/2 + H/2 * sin(x*2*PI) )
給出了極端值H/2 - H/2 = 0
和H/2 + H/2 = H
,這太高了。 因此,我們不是按H/2
而是按(H-1)/2
縮放:
y = (int) ( H/2 + (H-1)/2 * sin(x*2*PI) )
這使我們在y范圍0
到H-1
。
為了對正弦波的周期有更多的控制,讓我們這樣寫:
sin( x/W * 2*PI )
在這里,我們將x
除以W
以使x/W
本身的范圍為0到1。然后按2*PI
進行縮放,以產生0到2π的范圍。 這將在整個寬度上繪制一個正弦波周期。 如果我們引入頻率因子f
:
sin( f * x/W * 2*PI )
我們現在可以說要繪制多少個周期,甚至是分數。 對於f=1
,它將繪制一個周期, f=2
將繪制兩個周期,而f=1
將繪制半個周期。
這是一個小JS演示,顯示了f
三個值: 0.5
是紅色, 1
是綠色, 2
是白色:
var c = document.getElementById('c'), W = c.width, H = c.height, ctx = c.getContext('2d'), image = ctx.getImageData(0,0,W,H); for ( var i = 0; i < image.data.length; i +=4) { image.data[i+0]=0; image.data[i+1]=0; image.data[i+2]=0; image.data[i+3]=255; } function render(image,colidx,f) { for ( var x = 0; x < W; x++ ) { var y = H/2 - Math.round( H/2 * Math.sin(f*x/W*Math.PI*2) ); if ( y >=0 && y < H ) { if ( colidx & 1 ) image.data[ 4*( W*y + x ) + 0] = 255; if ( colidx & 2 ) image.data[ 4*( W*y + x ) + 1] = 255; if ( colidx & 4 ) image.data[ 4*( W*y + x ) + 2] = 255; } } } render(image,1,0.5); render(image,2,1); render(image,7,2); ctx.putImageData(image, 0,0);
canvas{ border: 1px solid red;}
<canvas id='c' width='256' height='128'></canvas>
然后,代碼變為:
float f = 1;
for (x = 0; x < W; x++)
{
y = (int) ( (H-1)/2 + (H-1)/2 * sin(f * x/W * 2*PI) );
image[y][x][0] = 0;
image[y][x][1] = 255;
image[y][x][2] = 0;
}
由於y
被注釋為一個int
且H
似乎是一個int
常量,因此請先執行double
計算,然后再轉換為int
。
使用round
可以避免將double
強制轉換為int
截斷效果。
y = (int) round(50*(sin(x*(2*PI)) + H/2.0));
原始代碼也將H/2
縮放了50。我認為代碼可能只想縮放sin()
而不是偏移量。
#define XOffset 0
#define YOffset (H/2.0)
#define XScale (2*PI)
#define YScale 50
y = (int) round(YScale*sin(x*XScale + XOffset) + YOffset);
防御性編程技巧:由於已計算y
,因此在將其用作索引之前,請確保其在有效的索引范圍內。
// Assuming image` is a fixed sized array
#define Y_MAX (sizeof image/sizeof image[0] - 1)
if (y >= 0 && y <= Y_MAX) {
image[y][x][1] = 0;
image[y][x][2] = 255;
image[y][x][3] = 0;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.