Page 1 of 1
Arcs and angles
Posted: Mon Aug 13, 2012 6:05 pm
by meoiswa
I'm trying to create an arc using mouse position.
The idea is that the arc begins where you start pressing the mouse button, and ends where the mouse is currently at
However I'm having some troubles because the angle is normalized or something,
Click then start dragging the mouse:
Suddendly this happens:
As you may see, the finish angle changes from a positive to a negative value
Code: Select all
function love.load()
cx = love.graphics.getWidth()/2
cy = love.graphics.getHeight()/2
begin = 0
finish = 0
end
function love.update(dt)
mx = love.mouse.getX()
my = love.mouse.getY()
dx = mx-cx
dy = my-cy
angle = math.atan2(dy,dx)
if love.mouse.isDown("l") then
finish = angle
end
end
function love.draw()
love.graphics.arc("line",cx,cy,100,begin,finish)
love.graphics.print("begin: "..begin.. " finish: "..finish,30,30)
end
function love.mousepressed( x, y, button )
mx = love.mouse.getX()
my = love.mouse.getY()
dx = mx-cx
dy = my-cy
angle = math.atan2(dy,dx)
begin = angle
end
function love.mousereleased( x, y, button )
begin = 0
finish = 0
end
Re: Arcs and angles
Posted: Mon Aug 13, 2012 6:20 pm
by dreadkillz
Hello, math.atan2 returns the smallest angle. So if your arc is 270 degrees, it will return -90. What happens is that when you arc crosses the horizontal, it switches angle from negative to positive and vice versa; this will switch the orientation of the arc. You'll need to add some sort of check to determine which way your mouse is spinning.
Re: Arcs and angles
Posted: Mon Aug 13, 2012 6:22 pm
by Xgoff
meoiswa wrote:I'm trying to create an arc using mouse position.
The idea is that the arc begins where you start pressing the mouse button, and ends where the mouse is currently at
However I'm having some troubles because the angle is normalized or something,
Click then start dragging the mouse:
<image>
Suddendly this happens:
<image>
As you may see, the finish angle changes from a positive to a negative value
Code: Select all
function love.load()
cx = love.graphics.getWidth()/2
cy = love.graphics.getHeight()/2
begin = 0
finish = 0
end
function love.update(dt)
mx = love.mouse.getX()
my = love.mouse.getY()
dx = mx-cx
dy = my-cy
angle = math.atan2(dy,dx)
if love.mouse.isDown("l") then
finish = angle
end
end
function love.draw()
love.graphics.arc("line",cx,cy,100,begin,finish)
love.graphics.print("begin: "..begin.. " finish: "..finish,30,30)
end
function love.mousepressed( x, y, button )
mx = love.mouse.getX()
my = love.mouse.getY()
dx = mx-cx
dy = my-cy
angle = math.atan2(dy,dx)
begin = angle
end
function love.mousereleased( x, y, button )
begin = 0
finish = 0
end
iirc love uses the absolute value of the difference between the two angles to determine which of the two arcs it should draw
dunno, i just found love.graphics.arc to be frustrating. maybe i was just being stupid but i had to fuck around with the values A LOT just to get the corners of a rounded box to work. i ended up just writing my own arc function (i needed the capability to leave off the two straight lines, which love.graphics.arc doesn't have an option for)
Re: Arcs and angles
Posted: Mon Aug 13, 2012 6:51 pm
by meoiswa
Can I get to see that custom arc function? I want to be able to draw this shape and I guess I'll have to create my own function for that:
Re: Arcs and angles
Posted: Mon Aug 13, 2012 8:13 pm
by dreadkillz
Here's an example where you can use the dot and cross product so that the orientation of the arc remains constant while drawing it.
Code: Select all
function love.load()
cx = love.graphics.getWidth()/2
cy = love.graphics.getHeight()/2
begin = 0
finish = 0
end
function love.update(dt)
mx = love.mouse.getX()
my = love.mouse.getY()
if love.mouse.isDown("l") then
x2,y2 = mx-cx,my-cy
dot = x1*x2+y1*y2 -- find delta angle by using dot product
lprod = math.sqrt((x1*x1+y1*y1)*(x2*x2+y2*y2))
angled = math.acos(dot/lprod)
crossK = x1*y2-y1*x2 -- fine direction of angle by cross product
if crossK < 0 then angled = -angled end
finish = finish+angled
x1,y1 = x2,y2
end
end
function love.draw()
love.graphics.arc("line",cx,cy,100,begin,finish)
love.graphics.print("begin: "..begin.. " finish: "..finish,30,30)
end
function love.mousepressed( x, y, button )
x1,y1 = mx-cx,my-cy
begin = math.atan2(y1,x1)
finish = begin
end
function love.mousereleased( x, y, button )
begin = 0
finish = 0
end
Re: Arcs and angles
Posted: Mon Aug 13, 2012 9:43 pm
by meoiswa
Thank you very much, I guessed using dot product I could achieve what I wanted but I kept failing to do it :c
Re: Arcs and angles
Posted: Mon Aug 13, 2012 9:43 pm
by Xgoff
meoiswa wrote:Can I get to see that custom arc function? I want to be able to draw this shape and I guess I'll have to create my own function for that:
this is what i used: positive sweep goes ccw, negative goes cw
Code: Select all
local function arc (mode, x, y, radius, start, sweep, segments, omitlines)
local points = { }
sweep = math.max(-math.pi * 2, math.min(sweep, math.pi * 2))
local o = 0
if mode == "fill" or not omitlines then
o = 2
points[1] = x
points[2] = y
end
segments = (segments or 10) - 1
for i = 0, segments do
local dir = start + (i / segments) * sweep
points[o+i*2+1] = math.cos(dir) * radius + x
points[o+i*2+2] = -math.sin(dir) * radius + y
end
if mode == "fill" then
love.graphics.polygon("fill", points)
elseif mode == "line" then
if not omitlines then
points[#points+1] = x
points[#points+1] = y
end
love.graphics.line(points)
end
end
not extensively tested
EDIT: technically this by itself wouldn't draw the exact shape you want (it could just be used for the outline)
Re: Arcs and angles
Posted: Tue Aug 14, 2012 1:56 am
by Ref
Again Xgoff has outdone me but for what's it worth, heres my approach:
Code: Select all
function arc_seg()
local acx, acy = mask.width/2, mask.height/2 -- arc center
local rado, radi = 1.5 * mask.size, mask.size -- outer & inner radius
local arco, arci = {}, {} -- tables of arc points
local arcs, arce = mask.angle, mask.angle + mask.circle -- start & ending angle
local idx = mask.size / 4 -- steps in arc
local val = 1
for i = arcs, arce,pi / idx do
local xo = rado * math.cos(i) + acx
local yo = rado * math.sin(i) + acy
local xi = radi * math.cos(i) + acx
local yi = radi * math.sin(i) + acy
arco[val] = { xo, yo }
arci[val] = { xi, yi }
val = val + 1
end
for i = 1, #arco - 1 do -- polygon can't handle all the points at once
gr.polygon('fill',
arco[i][1], arco[i][2], arco[i+1][1], arco[i+1][2],
arci[i+1][1], arci[i+1][2], arci[i][1], arci[i][2])
end
end
Added code to my test script 'mask.love'.
<c><v> change the number of segments in arc
<q><w> change radius of arc
Polygon adds a hidden gotch-u because of its limits.
Re: Arcs and angles
Posted: Wed Aug 15, 2012 8:28 pm
by arundel
You can try to get the degrees between the origin and mouse pos ( 0 to 360 deg) along the unit circle with no negative value:
Code: Select all
math.deg(math.atan2(t1.y-t2.y,t1.x-t2.x))+180