[Solved] Coordinate System shearing

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
User avatar
zorfmorf
Prole
Posts: 35
Joined: Sat Mar 10, 2012 12:31 pm

[Solved] Coordinate System shearing

Post by zorfmorf »

I seem to be stuck on a simple conversion problem where I can't reverse coordinate system shearing. In the below example I want to draw the circle exactly where the mouse click occured.

Code: Select all

circle = { x=0, y=0}
angle = -0.3

function love.draw()
    love.graphics.shear(angle, angle)
    love.graphics.circle("fill", circle.x, circle.y, 5, 20)
end

function love.mousepressed(x, y, button)
    if button == "l" then
        circle.x = x - math.sin(angle) * y -- + ?
        circle.y = y - math.sin(angle) * x -- + ?
    end
end
However, I can only get it to work when shearing exclusively in x or y direction, not both. I know it's really simple but I just seem to be too daft today.
Last edited by zorfmorf on Mon May 19, 2014 3:18 pm, edited 1 time in total.
User avatar
zorfmorf
Prole
Posts: 35
Joined: Sat Mar 10, 2012 12:31 pm

Re: Coordinate System shearing

Post by zorfmorf »

Another way to phrase my question based on the article at the bottom of http://www.mathamazement.com/Lessons/Pr ... rices.html:

If x coordinate shearing can be described like this:

Image
Image

and y coordinate shearing like this:

Image
Image

Why doesn't this work then:

Image
Image
User avatar
bartbes
Sex machine
Posts: 4946
Joined: Fri Aug 29, 2008 10:35 am
Location: The Netherlands
Contact:

Re: Coordinate System shearing

Post by bartbes »

Because if you first do x shearing you get:
\(x' = x + ky\)
\(y' = y\)

And then y shearing:
\(x'' = x'\)
\(y'' = kx' + y'\)

So it ends up being:
\(x'' = x' = x + ky\)
\(y'' = kx' + y' = k(x + ky) + y = kx + kky + y\)

And that \(kky\) term is the difference between applying both and your solution.
User avatar
zorfmorf
Prole
Posts: 35
Joined: Sat Mar 10, 2012 12:31 pm

Re: Coordinate System shearing

Post by zorfmorf »

First, let me thank you for taking the time to help me!

However I think my post was unclear. I'm not shearing first into x and then into y direction, I'm shearing into both directions at the same time. I found the source of my conversion problem, though:

If I use shear before drawing something like this:

Code: Select all

love.graphics.shear(angle, angle)
love.graphics.circle('fill', x, y, 2, 20)
The drawing position can be calculated like this

Code: Select all

local nx = x + math.sin(angle) * y
local ny = y + math.sin(angle) * x
love.graphics.circle('fill', nx, ny, 2, 20)
(The first circle get's it's body sheared as well so the two version are not exactly identical. As I'm only interested in the draw position that's fine).

Now if I want to re-convert a position on the screen to "world coordinates", it can be (in theory) easily done like this:

Code: Select all

y = ny - math.sin(angle) * x
x = nx - math.sin(angle) * y
The problem is: If I don't know x and y beforehand (that's why I want to calculate them), I can't calculate them because I'd need their values first.

Shortened example: How would I need to change the mousepressed method so that the circle is always drawn exactly where I click?:

Code: Select all

circle = { x=0, y=0}
angle = -0.3

function love.draw()
    love.graphics.shear(angle, angle)
    love.graphics.circle("fill", circle.x, circle.y, 2, 20)
end

function love.mousepressed(nx, ny, button)
    if button == "l" then
        circle.y = ny - math.sin(angle) * -- ??
        circle.x = nx - math.sin(angle) * -- ??
    end
end
User avatar
zorfmorf
Prole
Posts: 35
Joined: Sat Mar 10, 2012 12:31 pm

Re: Coordinate System shearing

Post by zorfmorf »

After sitting down with a pen and some paper I managed to figure out what I was doing wrong. When shearing for a value k into x and y direction at the same time, screen coordinates (xs,ys) for a point (x,y) are calculated like this:

Code: Select all

xs = x + y * k
ys = y + x * k
The reverse (what I was looking for) can be calculated like this:

Code: Select all

x = (xs - ys * k) / (1 - k * k)
y = (ys - xs * k) / (1 - k * k)
Honestly, I don't know what my problem was with this. I got confused and was trying to solve this using angles and triangles the whole time. Sometimes it's good to just call it a day and try again later. Below is the working example for anyone interested.

Code: Select all

circle = { x=0, y=0}
k = math.random() * math.pi

function love.draw()
    love.graphics.shear(k, k)
    love.graphics.circle("fill", circle.x, circle.y, 2, 20)
end

function love.mousepressed(nx, ny, button)
    if button == "l" then
        circle.y = (ny - nx * k) / (1 - k * k)
        circle.x = (nx - ny * k) / (1 - k * k)
    end
end
Post Reply

Who is online

Users browsing this forum: No registered users and 92 guests