Arcs and angles

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
meoiswa
Prole
Posts: 48
Joined: Wed Mar 14, 2012 8:13 pm
Location: Venezuela

Arcs and angles

Post 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:
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
Write the ö of Löve with Alt+numPad(148) or Alt+numPad(153)
User avatar
dreadkillz
Party member
Posts: 223
Joined: Sun Mar 04, 2012 2:04 pm
Location: USA

Re: Arcs and angles

Post 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.
User avatar
Xgoff
Party member
Posts: 211
Joined: Fri Nov 19, 2010 4:20 am

Re: Arcs and angles

Post 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)
meoiswa
Prole
Posts: 48
Joined: Wed Mar 14, 2012 8:13 pm
Location: Venezuela

Re: Arcs and angles

Post 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:
Image
Write the ö of Löve with Alt+numPad(148) or Alt+numPad(153)
User avatar
dreadkillz
Party member
Posts: 223
Joined: Sun Mar 04, 2012 2:04 pm
Location: USA

Re: Arcs and angles

Post 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
meoiswa
Prole
Posts: 48
Joined: Wed Mar 14, 2012 8:13 pm
Location: Venezuela

Re: Arcs and angles

Post 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
Write the ö of Löve with Alt+numPad(148) or Alt+numPad(153)
User avatar
Xgoff
Party member
Posts: 211
Joined: Fri Nov 19, 2010 4:20 am

Re: Arcs and angles

Post 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:
Image
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)
Last edited by Xgoff on Tue Aug 14, 2012 2:37 am, edited 1 time in total.
User avatar
Ref
Party member
Posts: 702
Joined: Wed May 02, 2012 11:05 pm

Re: Arcs and angles

Post 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.
Attachments
mask_with_arc.love
Just a demo of arc mask
(58.51 KiB) Downloaded 158 times
arundel
Prole
Posts: 31
Joined: Tue Sep 21, 2010 8:49 pm
Location: The Netherlands

Re: Arcs and angles

Post 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
Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot] and 1 guest