Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

intersect: Fix cpml.intersect.segment_segment bug, fixes #90 #91

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 24 additions & 31 deletions modules/intersect.lua
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,25 @@ local min = math.min
local max = math.max
local intersect = {}

-- Checks if a point belongs to the segment
-- p is a vec3
-- seg[1] is a vec3
-- seg[2] is a vec3
-- Returns a boolean
function intersect.point_segment(p, seg)
local min, max = vec3.component_sort(seg[1], seg[2])
if min.x <= p.x and
min.y <= p.y and
min.z <= p.z and
p.x <= max.x and
p.y <= max.y and
p.z <= max.z
then
return true
end
return false
end

-- https://blogs.msdn.microsoft.com/rezanour/2011/08/07/barycentric-coordinates-and-point-in-triangle-tests/
-- point is a vec3
-- triangle[1] is a vec3
Expand Down Expand Up @@ -305,39 +324,13 @@ end
-- e is a number
function intersect.segment_segment(a, b, e)
local c, d = intersect.line_line(a, b, e)

if c and ((
a[1].x <= c[1].x and
a[1].y <= c[1].y and
a[1].z <= c[1].z and
c[1].x <= a[2].x and
c[1].y <= a[2].y and
c[1].z <= a[2].z
) or (
a[1].x >= c[1].x and
a[1].y >= c[1].y and
a[1].z >= c[1].z and
c[1].x >= a[2].x and
c[1].y >= a[2].y and
c[1].z >= a[2].z
)) and ((
b[1].x <= c[2].x and
b[1].y <= c[2].y and
b[1].z <= c[2].z and
c[2].x <= b[2].x and
c[2].y <= b[2].y and
c[2].z <= b[2].z
) or (
b[1].x >= c[2].x and
b[1].y >= c[2].y and
b[1].z >= c[2].z and
c[2].x >= b[2].x and
c[2].y >= b[2].y and
c[2].z >= b[2].z
)) then
if c and
intersect.point_segment(c[1], a) and
intersect.point_segment(c[2], a) and
intersect.point_segment(c[1], b) and
intersect.point_segment(c[2], b) then
return c, d
end

-- segments do not intersect
return false
end
Expand Down
8 changes: 8 additions & 0 deletions modules/vec3.lua
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,14 @@ function vec3.component_max(a, b)
return new(math.max(a.x, b.x), math.max(a.y, b.y), math.max(a.z, b.z))
end

--- Return the component-wise minimum and maximum of two vectors.
-- @tparam vec3 a Left hand operand
-- @tparam vec3 b Right hand operand
-- @treturn vec3, vec3 sorted vectors
function vec3.component_sort(a, b)
return vec3.component_min(a, b), vec3.component_max(a, b)
end

-- Negate x axis only of vector.
-- @tparam vec3 a Vector to x-flip.
-- @treturn vec3 x-flipped vector
Expand Down