Not getting straight line with simple algorithm

Hey there,

I have been having troubles with a simple algorithm to convert degrees to radians.

This is the code which I am using.

//caculate position on the where the line ends (in relation to the rotation)
  dim r, x, y as integer
  r = me.width /2
  x = r + (Cos(Rotation.Value * (pi / 180)) * r)
  y = r + (Sin(Rotation.Value * (pi / 180)) * r)
  
  g.DrawLine((me.width / 2), (me.height / 2), x, y)

I have a class called ‘Angle’ which stores the desired rotation value and I have a property called Rotation of type Angle. When the line is drawn, it is not drawn perfectly straight.

The angle of the line seems to be almost there but there is something not quite right about it that is not making it always perfectly straight. I have feeling it has something to do with the width being an odd number of something like that.

Does anybody have any ideas on how I could fix this issue and maybe make it more acurate. And btw I almost forgot to mention that ‘pi’ is a constant with the value of ‘3.14159265358979323846264338327950’. It is only a small drawing area so maybe that long pi value is unnecessarily accurate. Any idea if I should use a shorter Pi value?

Thanks

ts not the value of pi.

in fact you can ditch the match entirely and just use drawling to get the same results… its just point to point drawing.

at certain angles, antialiasing kicks in.
the line is surrounded by fuzzy grey pixels, but is definitely straight.

i tested curve shape with this too, with the same results.

you might draw to a canvas with antialias turned off, then copy that to the screen perhaps?

Remove the r from the part going into Sin, Cos. You just need to scale the angle from degrees to radians, radius is not part of that. Oh, and the results of Sin, Cos are scaled by radius, so there you want to multiply.

x = r * (Cos(Rotation.Value * (pi / 180))) y = r * (Sin(Rotation.Value * (pi / 180)))

And when you draw you should also offset the xy.

dim halfW, halfH As double halfW = me.Width / 2 halfH = me.Height / 2 g.DrawLine(halfW, halfH, halfW + x, halfH + y)

Now looking back I see r, x, y are integers. It might be more accurate to use doubles. Hmm, let me rewrite this…

dim r, x, y, hw, hh, a As double hw = me.Width * 0.5 hh = me.Height * 0.5 r = hw a = Rotation.Value * pi / 180 x = r * Cos(a) y = r * Sin(a) g.DrawLine(hw, hh, hw + x, hh + y)

You might need to change that last bit to “hh - y” for standard math angles. I mean increasing counterclockwise.

[quote=139636:@Will Shank]Remove the r from the part going into Sin, Cos. You just need to scale the angle from degrees to radians, radius is not part of that. Oh, and the results of Sin, Cos are scaled by radius, so there you want to multiply.

x = r * (Cos(Rotation.Value * (pi / 180))) y = r * (Sin(Rotation.Value * (pi / 180)))

And when you draw you should also offset the xy.

dim halfW, halfH As double halfW = me.Width / 2 halfH = me.Height / 2 g.DrawLine(halfW, halfH, halfW + x, halfH + y)

Now looking back I see r, x, y are integers. It might be more accurate to use doubles. Hmm, let me rewrite this…

dim r, x, y, hw, hh, a As double hw = me.Width * 0.5 hh = me.Height * 0.5 r = hw a = Rotation.Value * pi / 180 x = r * Cos(a) y = r * Sin(a) g.DrawLine(hw, hh, hw + x, hh + y)

You might need to change that last bit to “hh - y” for standard math angles. I mean increasing counterclockwise.[/quote]
273 degrees goes directly up but not 280? I tried turning off AntiAlias.
Thanks

[quote=139635:@Jeff Tullin]ts not the value of pi.

in fact you can ditch the match entirely and just use drawling to get the same results… its just point to point drawing.

at certain angles, antialiasing kicks in.
the line is surrounded by fuzzy grey pixels, but is definitely straight.

i tested curve shape with this too, with the same results.

you might draw to a canvas with antialias turned off, then copy that to the screen perhaps?[/quote]
‘ts’? I do not see how directly drawing to the canvas’s graphics object (if that’s what you meant) could make any difference from drawing to a picture and copying that over.
Thanks

Do you mean 283 is directly up? If so then pi is probably in an integer. Directly up (with clockwise winding) is 270 degrees, but because of floating point error there’s a 1 pixel tilt. At least on mac, maybe on windows the plotting will be exactly vertical.

Okay, so I should I write some code that straightens the line if it is at 280 degrees?
Thanks

At 270 degrees. If you see the effect.

Sorry I meant I thought 280 degrees was meant to be straight not 270. Thanks

I tried it at 270. It is slightly off. 271 is perfectly straight however.
Thanks

So is the problem that when you choose 90,180,270 etc you don’t get lines which are horizontal or vertical, or is it the antialias effect that is the problem?

ts was supposed to It’s but edit didn’t work to allow me to fix the spelling.
And I mentioned drawing on a canvas because when I tried turning antialias off for a window’s graphics , it made no difference.
I didn’t have time to amend the test project to try that theory out.

If your PI value is being held in an integer then although you think it is 3.14159… it is actually 3
Try adding msgbox str(pi) in the code to check that

[quote=139672:@Jeff Tullin]So is the problem that when you choose 90,180,270 etc you don’t get lines which are horizontal or vertical, or is it the antialias effect that is the problem?

ts was supposed to It’s but edit didn’t work to allow me to fix the spelling.
And I mentioned drawing on a canvas because when I tried turning antialias off for a window’s graphics , it made no difference.
I didn’t have time to amend the test project to try that theory out.

If your PI value is being held in an integer then although you think it is 3.14159… it is actually 3
Try adding msgbox str(pi) in the code to check that[/quote]
Thanks. Will debug the pi value. All the angles that should be straight are perfectly straight apart from 270 degrees.
Thanks

3.14159 shows up so it is not an integer. I put it in a constant so that should all be handled for me.

Thanks

No idea how effective this workaround is but I have changed the code that sets a to ‘a = If(Rotation.Value = 270, 271, Rotation.Value) * (pi / 180)’.
Thanks

are ANY of the terms you are using anything less than DOUBLE… any INTEGER variables will contribute to answers that are percieved to be incorrect.

Line widths less than a pixel (or a point on Retina) will possible look incorrect

0,90,180 and 270 are the North, South, East and West directions… not 280, not 271

Drawline will round/truncate all arguments to the nearest integer value

[quote=139745:@Dave S]are ANY of the terms you are using anything less than DOUBLE… any INTEGER variables will contribute to answers that are percieved to be incorrect.

Line widths less than a pixel (or a point on Retina) will possible look incorrect

0,90,180 and 270 are the North, South, East and West directions… not 280, not 271

Drawline will round/truncate all arguments to the nearest integer value[/quote]
The linewidth is 2, I tried 3 and it still happened. I looked very closely and it appears that the line’s starting point is slightly off centre.

I am using a double variable to calculate this.

Thanks

[quote=139819:@Oliver Scott-Brown]Drawline will round/truncate all arguments to the nearest integer value
The linewidth is 2, I tried 3 and it still happened. I looked very closely and it appears that the line’s starting point is slightly off centre.

I am using a double variable to calculate this.[/quote]

Just by curiosity, what is the size of the picture ?

34 by 43. thanks

I am wondering if I go up to 360 degrees does that mean I can put the user back to 0 degrees.

Should I use a starting 0 degree rotation or 360? Does it matter?

I am basically asking if 0 degrees is a standard rotation to replace 360 degrees? thanks

0 degrees is ‘the same’ as 360 degrees but for clarity I’d choose 0

Horrible kludge, I know, but…
Maybe the odd effect you see at ‘known angles’ can be avoided by showing the line without calculation.

At 0 degrees, X = me.width / 2 and y is 0
At 90 degrees, y = me.height / 2 and x is me.width
At 180 degrees, x = me.width / 2 and y is me.height
at 270 degrees, y is me.height / 2 and x is 0