[SOLVED]2D polygon collision detection cant index table vertices

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
kuzika
Prole
Posts: 16
Joined: Tue Apr 21, 2020 3:58 pm

[SOLVED]2D polygon collision detection cant index table vertices

Post by kuzika »

I'm getting this simple error but I have no idea why lua is not indexing the table...

Code: Select all

Error

main.lua:104: attempt to index local 'vn' (a nil value)


Traceback

main.lua:104: in function 'polyPoint'
main.lua:41: in function 'update'
[C]: in function 'xpcall'
This is the table with the vertices for a polygon shape. Its in funciton load

Code: Select all

--love.load()
v = {}
v[1] = {x = 200,y = 100}
v[2] = {x = 400,y = 130}
v[3] = {x = 350,y = 300}
v[4] = {x = 250,y = 300}
--test is a string that outputs "collision" if the collision is true
test = ""
I am using push.lua so I set the mouse.x and mouse.y to game values with push:toGame(x,y)
I'm also aware that this can return nil so I make an if statement to stop it from checking nil

Code: Select all

--love.update()
local x = love.mouse.getX()
local y = love.mouse.getY()
mouse.x,mouse.y = push:toGame(x,y)
  if not(mouse.x == nil) and not(mouse.y == nil) then
    if polyPoint(v,mouse.x,mouse.y) then
      test = "collision"
    else
      test = ""
    end
  else
    test = ""
  end
The polygon draws perfect so I doubt my table has problems in syntax.

Code: Select all

 --love.draw()
    love.graphics.polygon("fill",v[1].x,v[1].y,v[2].x,v[2].y,v[3].x,v[3].y,v[4].x,v[4].y)
    love.graphics.print(""..test,0,0)
This is where the error points to, the line with << local vn = vertices[next] >> I would think you can drop a table in a variable like this.

Code: Select all

function polyPoint(vertices,px,py)
local collision = false
local next = 1
  for current = 1, #vertices do
    next = current + 1
    if (next == #vertices) then
      next = 1
    end
    local vc = vertices[current]
    local vn = vertices[next]
    if(((vc.y >= py) or (vc.y < py and vn.y >= py)) and
    (px < (vn.x - vc.x)*(py - vc.y)/(vn.y - vc.y)+vc.x)) then
        collision = not(collision)
    end
  end
  return collision
end
The original post is here about 2d point and polygon collision detection using "Jordan Curve Theorem" math.
http://www.jeffreythompson.org/collisio ... point.php

If you don't want to go to the site here is the original code. Its in C++. I converted it into Lua or at least tried to.

Code: Select all

float px = 0;    // point position
float py = 0;

// array of PVectors, one for each vertex in the polygon
PVector[] vertices = new PVector[4];


void setup() {
  size(600,400);
  noCursor();

  strokeWeight(5);  // make the point easier to see

  // set position of the vertices
  // here we draw a distorted trapezoid, but
  // you could make much more complex shapes
  // or even randomize the points!
  vertices[0] = new PVector(200,100);
  vertices[1] = new PVector(400,130);
  vertices[2] = new PVector(350,300);
  vertices[3] = new PVector(250,300);
}


void draw() {
  background(255);

  // update point to mouse coordinates
  px = mouseX;
  py = mouseY;

  // check for collision
  // if hit, change fill color
  boolean hit = polyPoint(vertices, px,py);
  if (hit) fill(255,150,0);
  else fill(0,150,255);

  // draw the polygon using beginShape()
  noStroke();
  beginShape();
  for (PVector v : vertices) {
    vertex(v.x, v.y);
  }
  endShape();

  // draw the point
  stroke(0, 150);
  point(px,py);
}


// POLYGON/POINT
boolean polyPoint(PVector[] vertices, float px, float py) {
  boolean collision = false;

  // go through each of the vertices, plus
  // the next vertex in the list
  int next = 0;
  for (int current=0; current<vertices.length; current++) {

    // get next vertex in list
    // if we've hit the end, wrap around to 0
    next = current+1;
    if (next == vertices.length) next = 0;

    // get the PVectors at our current position
    // this makes our if statement a little cleaner
    PVector vc = vertices[current];    // c for "current"
    PVector vn = vertices[next];       // n for "next"

    // compare position, flip 'collision' variable
    // back and forth
    if (((vc.y >= py && vn.y < py) || (vc.y < py && vn.y >= py)) &&
         (px < (vn.x-vc.x)*(py-vc.y) / (vn.y-vc.y)+vc.x)) {
            collision = !collision;
    }
  }
  return collision;
}
Last edited by kuzika on Wed May 20, 2020 7:44 pm, edited 1 time in total.
"kuzika" literally means "to burry"
User avatar
siberian
Prole
Posts: 23
Joined: Sat Apr 06, 2019 1:42 pm

Re: 2D polygon collision detection cant index table vertices

Post by siberian »

Try to replace

Code: Select all

if (next == #vertices) then

with this

Code: Select all

if (next > #vertices) then
or you can set next index like this

Code: Select all

next = (current < #vertices) and current + 1 or 1 
User avatar
kuzika
Prole
Posts: 16
Joined: Tue Apr 21, 2020 3:58 pm

Re: 2D polygon collision detection cant index table vertices

Post by kuzika »

Thanks, it now works perfect. I also cleaned up the if statement so its exactly the same as the original one in C++. Below is the clean code of the polyPoint now working with LOVE2D.

Code: Select all

function polyPoint(vertices,px,py)
local collision = false
local next = 1
  for current = 1, #vertices do
    next = current + 1
    if (next > #vertices) then
      next = 1
    end
    local vc = vertices[current]
    local vn = vertices[next]
    if (((vc.y >= py and vn.y < py) or (vc.y < py and vn.y >= py)) and
    (px < (vn.x-vc.x)*(py-vc.y) / (vn.y-vc.y)+vc.x)) then
        collision = not(collision)
    end
  end
  return collision
  
Here is a .love (version 11.3). I hope this helps out others.
polypoint.love
(591 Bytes) Downloaded 486 times
I also posted this in the wiki here.
https://love2d.org/wiki/polypoint
"kuzika" literally means "to burry"
Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot], Google [Bot] and 13 guests