簡體   English   中英

嘗試在C中按比例放大正弦波的問題

[英]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。 再有可能這是一個問題領域。

第一正弦波.ppm

我認為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 = 0H/2 + H/2 = H ,這太高了。 因此,我們不是按H/2而是按(H-1)/2縮放:

y = (int) ( H/2 + (H-1)/2 * sin(x*2*PI) )

這使我們在y范圍0H-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注釋為一個intH似乎是一個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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM