Struggling with arcs (and trig!)

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
Laimbrane
Prole
Posts: 3
Joined: Fri Apr 17, 2015 7:19 pm

Struggling with arcs (and trig!)

Post by Laimbrane »

I'm creating a simple clock program and trying to make it so that the user can highlight an arc of time to give a visual reference for how much time is remaining until some certain future point.

It works fairly well right now unless you swipe across the vertical axis. The angle changes from 4.7 to -1.57 because the arctan function doesn't know the difference between the ratio of a -y/-x and y/x.

Any suggestions?

Code: Select all

function love.draw()

	drawTime()
	love.graphics.setColor(255,0,0)

	if (startingAngle ~= nil) and (endingAngle ~= nil) then
		love.graphics.arc("fill", originX, originY, love.graphics.getWidth()/4, startingAngle, endingAngle, 500)
	end
	love.graphics.setColor(0,0,0)
	love.graphics.print("startingAngle: " .. (startingAngle or 0), 0, 25)
	love.graphics.print("endingAngle: " .. (endingAngle or 0), 0, 50)

	radius = love.graphics.getWidth()/4
	love.graphics.circle("line",originX,originY,love.graphics.getWidth()/4)

	drawClockFace()
	drawClockHand()
end


function love.update()
	checkTime()

	if love.mouse.isDown("l") then
		angleX = love.mouse.getX() - originX
		angleY = love.mouse.getY() - originY
		endingAngle = math.atan(angleY/angleX)

		if love.mouse.getX() <= originX then
				endingAngle = endingAngle + math.pi
		end

	end



end


function love.mousepressed( x, y, button )
	if button == "r" then
		drawArc = 0
	end
	if button == "l" then
		angleX = love.mouse.getX() - originX
		angleY = love.mouse.getY() - originY
		startingAngle = math.atan(angleY/angleX)

		if love.mouse.getX() <= originX then
			startingAngle = startingAngle + math.pi
		end
	end

end
User avatar
ivan
Party member
Posts: 1915
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: Struggling with arcs (and trig!)

Post by ivan »

You're on the right path there.
One thing I would suggest is that instead of storing the "startingAngle",
just store the initial position where the user pressed with the mouse.
When the user releases the mouse you store that position too.
So now you have 2 points, then the problem becomes:

Code: Select all

x, y = initial
x2, y2 = final
ox, oy = origin

-- first, subtract origin from both points
ax, ay = x - ox, y - oy
bx, by = x2 - ox, y2 - oy

-- find the initial angle
angInitial = math.atan2(ay, ax)

-- find the angle between the two vectors
arc = math.vang(ax, ay, bx, by)

-- find the final angle
angFinal = angInitial + arc
Here is what I use for math.vang:

Code: Select all

--- Returns the angle in radians between two vectors
--- Description:
-- Uses the dot product (D) to find the angle (A) between two vectors (a,b)
-- normalized vectors:
-- D = dot(a,b)
-- cos(A) = D
-- A = acos(D)
-- non-normalized vectors:
-- D = dot(a,b)
-- cos(A) = D/(len(a)*len(b))
-- A = acos(D/(len(a)*len(b)))
--- Non-commutative:
-- vang(a,b) == -vang(b,a)
--- Result:
-- -pi <= A <= pi (depending on the angle between the two vectors)
-- A is zero when one of the vectors is zero
--- Parameters:
-- @param ax, ay first vector
-- @param bx, by second vector
-- @return the angle between the two vectors
function vec.vang(ax, ay, bx, by)
  local a = (ax*ax + ay*ay)*(bx*bx + by*by)
  a = math.sqrt(a)
  if a > 0 then
    a = math.acos((ax*bx + ay*by)/a)
    if ax*by - ay*bx < 0 then
      a = -a
    end
  end
  return a
end
Note that the function I posted can return a negative angle.

PS. welcome to the forums. ;)
Laimbrane
Prole
Posts: 3
Joined: Fri Apr 17, 2015 7:19 pm

Re: Struggling with arcs (and trig!)

Post by Laimbrane »

Whoa, I'm impressed. I'll check this out when I get to work on Monday. Thanks.
Laimbrane
Prole
Posts: 3
Joined: Fri Apr 17, 2015 7:19 pm

Re: Struggling with arcs (and trig!)

Post by Laimbrane »

Thank you - it worked, except for the vec.vang function, where I had to change "a = -a" to "a = 2*math.pi-a"

Other than that, beautiful.
User avatar
ivan
Party member
Posts: 1915
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: Struggling with arcs (and trig!)

Post by ivan »

Laimbrane wrote:Thank you - it worked, except for the vec.vang function, where I had to change "a = -a" to "a = 2*math.pi-a"
I'm pretty sure the version I posted is correct.

If you want your result to be always positive just remove:

Code: Select all

    -- if you imagine that the two vectors are the hands of a clock,
    -- check if the second hand is 'before' the first
    if ax*by - ay*bx < 0 then -- dot product of the vectors a and b (where b is rotated 90 degrees)
      a = -a -- negate result since acos always returns a positive value
    end
Keep in mind that in trigonometry the Y axis points UP, the X axis points RIGHT.
And that angles increase as you turn counter-clockwise.
Here is a visual description:

Code: Select all

  b
  ^
  |
  |
  o--->a

a = {1,0}, b = {0,1}, vang(a,b) = math.pi/2
Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot] and 7 guests