|
| 1 | +-- Convex hull algorithms implementation |
| 2 | +-- See : http://en.wikipedia.org/wiki/Convex_hull |
| 3 | + |
| 4 | +-- Checks if points p, q, r are oriented counter-clockwise |
| 5 | +local function isCCW(p, q, r) |
| 6 | + local cross = (q.y - p.y) * (r.x - q.x) |
| 7 | + - (q.x - p.x) * (r.y - q.y) |
| 8 | + return cross < 0 |
| 9 | +end |
| 10 | + |
| 11 | +-- Returns the convex hull using Jarvi's Gift wrapping algorithm). |
| 12 | +-- It expects an array of points as input. Each point is defined |
| 13 | +-- as : {x = <value>, y = <value>}. |
| 14 | +-- See : http://en.wikipedia.org/wiki/Gift_wrapping_algorithm |
| 15 | +-- points : an array of points |
| 16 | +-- returns : the convex hull as an array of points |
| 17 | +local function jarvi_convex_hull(points) |
| 18 | + -- We need at least 3 points |
| 19 | + local numPoints = #points |
| 20 | + if numPoints < 3 then return end |
| 21 | + |
| 22 | + -- Find the left-most point |
| 23 | + local leftMostPointIndex = 1 |
| 24 | + for i = 1, numPoints do |
| 25 | + if points[i].x < points[leftMostPointIndex].x then |
| 26 | + leftMostPointIndex = i |
| 27 | + end |
| 28 | + end |
| 29 | + |
| 30 | + local p = leftMostPointIndex |
| 31 | + local hull = {} -- The convex hull to be returned |
| 32 | + |
| 33 | + -- Process CCW from the left-most point to the start point |
| 34 | + repeat |
| 35 | + -- Find the next point q such that (p, i, q) is CCW for all i |
| 36 | + q = points[p + 1] and p + 1 or 1 |
| 37 | + for i = 1, numPoints, 1 do |
| 38 | + if isCCW(points[p], points[i], points[q]) then q = i end |
| 39 | + end |
| 40 | + |
| 41 | + table.insert(hull, points[q]) -- Save q to the hull |
| 42 | + p = q -- p is now q for the next iteration |
| 43 | + until (p == leftMostPointIndex) |
| 44 | + |
| 45 | + return hull |
| 46 | +end |
| 47 | + |
| 48 | +return { |
| 49 | + jarvi = jarvi_convex_hull |
| 50 | +} |
0 commit comments