希望有人可以指出为什么这不起作用或我可能出错的地方。我通过c中的for循环产生正弦波。最终目标是生成一个显示此文件的.ppm文件。我正在以1比1的像素比率工作。我的盒子是128H * 256W。正弦波正在显示,但由于以rad为单位产生的答案,结果是一个非常小的两像素高“波”。我认为这是由于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;
}
编辑:这是通过infraview打开时在.ppm文件中生成的内容。另外我在#defining PI 3.141592653589793。这又可能是一个问题。
答案 0 :(得分:1)
我认为y
是int
。
您的sin
值将被截断为整数;大多数情况下为0,但偶尔为-1或+1。
修复很简单:对y
使用浮点,并在想要将其用作数组索引时进行转换。
答案 1 :(得分:0)
y = y * 50
,其中y = H/2
(+或 - 1)为您提供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;
}
答案 2 :(得分:0)
由于y
commented为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;
}