Hello all, I'm trying to approximate a sine wave using bezier curves (for rendering speed over drawing many straight lines).

I'm trying to follow the non-C# code specified down the page at:
http://commons.wikimedia.org/wiki/File:Harmonic_partials_on_strings.svg

``````// Produces a sine path as flat point array {PT, PT[3], PT[3], ...}
private static List<PointF> SineWavePath(float x, float y, float width, float amp, float num_half_waves)
{
const float PI = 3.1415926535897f;
const float XD = 0.261799388f;
const float SQRT2 = 1.41421356f;
const float Y1 = (2 * SQRT2) / 7 - 1 / 7;
const float Y2 = (4 * SQRT2) / 7 - 2 / 7;
const float Y3 = SQRT2 / 2;
const float Y4 = (3 * SQRT2) / 7 + 2 / 7;

float xmul = width / (num_half_waves * PI);
float xd = XD * xmul;
List<PointF> path = new List<PointF>();

// Add the first point

// Loop all the points
for(int i = 1; i <= num_half_waves; i++)
{
// Add all of the points
path.Add(new PointF(x + xd, y + amp * Y1));
path.Add(new PointF(x + 2 * xd, y + amp * Y2));
path.Add(new PointF(x + 3 * xd, y + amp * Y3));
path.Add(new PointF(x + 4 * xd, y + amp * Y4));
path.Add(new PointF(x + 5 * xd, y + amp));
path.Add(new PointF(x + 6 * xd, y + amp));
path.Add(new PointF(x + 7 * xd, y + amp));
path.Add(new PointF(x + 8 * xd, y + amp * Y4));
path.Add(new PointF(x + 9 * xd, y + amp * Y3));
path.Add(new PointF(x + 10 * xd, y + amp * Y2));
path.Add(new PointF(x + 11 * xd, y + amp * Y1));
path.Add(new PointF(x + 12 * xd, y));

x += (width / num_half_waves);

// flip over vertically every half wave
amp = amp * -1;
}

// Returnt he path
return path;
}``````

And then rendering simply using

``````private void Form1_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
Rectangle r = this.ClientRectangle;

// Create the wave
List<PointF> path = SineWavePath(r.Left, yCenter, r.Width, mAmplitude, (float)Math.Ceiling(r.Width / mWavelength));

// Render
g.DrawBeziers(mPen, path.ToArray());

// Demonstrate where the control points are
Font font = new Font(FontFamily.GenericSansSerif, 12);
for(int i = 0; i < path.Count; i++)
{
g.DrawLine(Pens.Red, path[i], new PointF(path[i].X + 3, path[i].Y + 3));
g.DrawLine(Pens.Red, path[i], new PointF(path[i].X - 3, path[i].Y + 3));
if(i >= 1) g.DrawString((((i - 1) % 12) + 1).ToString(), font, Brushes.Black, path[i]);
}
font.Dispose();
}``````

However, this produces a jagged waveform that comes close, but does not approximate a sine wave.

Anybody see where my flaw is?

2
Contributors
2
Replies
4
Views
8 Years
Discussion Span
Last Post by jda

Just a thought

``````const float Y1 = (2 * SQRT2) / 7 - 1 / 7;
const float Y2 = (4 * SQRT2) / 7 - 2 / 7;
const float Y3 = SQRT2 / 2;
const float Y4 = (3 * SQRT2) / 7 + 2 / 7;``````

7 is not 7.0f
2 is not 2.0f
etc.

Duh. Of course, works like a charm. Thanks, I figured I was missing something simple.

``````const float Y1 = (2 * SQRT2) / 7.0f - 1.0f / 7.0f;
const float Y2 = (4 * SQRT2) / 7.0f - 2.0f / 7.0f;
const float Y3 = SQRT2 / 2.0f;
const float Y4 = (3 * SQRT2) / 7.0f + 2.0f / 7.0f;``````
This question has already been answered. Start a new discussion instead.
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.