vrld / HC

General purpose collision detection library for the use with LÖVE.
http://hc.readthedocs.org/
404 stars 48 forks source link

Ensure triangulated vertices are not collinear. #46

Closed TannerRogalsky closed 6 years ago

TannerRogalsky commented 7 years ago

I was running into an issue where, rarely, Polygon:triangulate() would find triangles that were comprised of collinear points. Then, when it went to great new sub-Polygons, it would throw an error about the collinear points.

This additional check avoids adding triangles to the list of triangles if they will have no area.

I have included this test case to further illustrate the case I ran into.

local g = love.graphics

function love.load()
  Polygon = require('HC.polygon')

  points = {
    2, 2,
    3, 2,
    3, 3,
    1, 3,
    1, 2,
    0, 2,
    0, 1,
    2, 1
  }

  for index,point in ipairs(points) do
    points[index] = point * 100
  end

  polygon = Polygon(unpack(points))
  triangles = polygon:triangulate()
end

function love.draw()
  g.translate(100, 0)
  for i,triangle in ipairs(triangles) do
    local x1, y1, x2, y2, x3, y3 = triangle:unpack()
    local x, y = (x1 + x2 + x3) / 3, (y1 + y2 + y3) / 3

    g.setColor(255, 255, 255)
    g.polygon('line', x1, y1, x2, y2, x3, y3)
    g.setColor(255, 0, 0)
    g.circle('fill', x, y, 5)
    g.print(i, x, y)
  end
end
martin-braun commented 6 years ago

Damn, I wished I found this earlier, because I had the same issue and opened an issue ticket #55 lol. I fixed it myself, too: https://github.com/MartyMaro/HC/commit/bde26eca15ffb340d622abd9c399cc59c86201d5

My question to your fix is, why checking for the collinears in the same statement like isEar? If you run into collinear matches it would increase the skipped counter. Is this really right? Because the assert below might be executed too early:

            skipped = skipped + 1
            assert(skipped <= n_vert, "Cannot triangulate polygon")
TannerRogalsky commented 6 years ago

@MartyMaro Maybe! That makes sense!

vrld commented 6 years ago

Merged bde26eca15ffb340d622abd9c399cc59c86201d5 instead