From da6e772be72d1bba23f96a0813455acf6ea1596a Mon Sep 17 00:00:00 2001 From: Matthias Richter Date: Mon, 7 Feb 2011 00:08:02 +0100 Subject: [PATCH] add ray intersection --- polygon.lua | 33 +++++++++++++++++++++++++++++++++ shapes.lua | 19 +++++++++++++++++-- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/polygon.lua b/polygon.lua index 39bec54..9c4c447 100644 --- a/polygon.lua +++ b/polygon.lua @@ -352,6 +352,39 @@ function Polygon:contains(x,y) return in_polygon end +function Polygon:intersectsRay(x,y, dx,dy) + local p = vector(x,y) + local v = vector(dx,dy):normalize_inplace() + local n = v:perpendicular() + + local vertices = self.vertices + for i = 1, #vertices do + local q1, q2 = vertices[i], vertices[ (i % #vertices) + 1 ] + local w = q2 - q1 + local det = v:cross(w) + + if det ~= 0 then + -- there is an intersection point. check if it lies on both + -- the ray and the segment. + local r = q2 - p + local l = r:cross(w) + local m = v:cross(r) + if l >= 0 and m >= 0 and m <= det then return true end + else + -- lines parralel or incident. get distance of line to + -- anchor point. if they are incident, check if an endpoint + -- lies on the ray + local dist = (q1 - p) * n + if dist == 0 then + if n:cross(q1) > 0 or n:cross(q2) > 0 then + return true + end + end + end + end + return false +end + -- module() as shortcut to module.Polygon() do diff --git a/shapes.lua b/shapes.lua index 66d320a..312c449 100644 --- a/shapes.lua +++ b/shapes.lua @@ -216,6 +216,23 @@ function CircleShape:contains(x,y) return (x - self._center):len2() < self._radius * self._radius end + +function ConcavePolygonShape:intersectsRay(x,y, dx,dy) + return self._polygon:intersectsRay(x,y, dx,dy) +end + +function ConvexPolygonShape:intersectsRay(x,y, dx,dy) + return self._polygon:intersectsRay(x,y, dx,dy) +end + +-- circle intersection if distance of ray/center is smaller +-- than radius +function CircleShape:intersectsRay(x,y, dx,dy) + local n = vector(-dy,dx):normalize_inplace() -- normal vector + local d = vector(x,y) - self._center + return d * vector(dx,dy) >= 0 and (d * n) < self._radius +end + -- -- auxiliary -- @@ -311,5 +328,3 @@ function CircleShape:draw(mode, segments) love.graphics.circle(mode, self._center.x, self._center.y, self._radius, segments) end - -