Current section
Files
Jump to
Current section
Files
lib/shape/face.ex
defmodule Geom.Shape.Face do
@moduledoc """
The face of a polygon represented by its 3 vertices.
"""
alias Geom.Shape.Face
alias Geom.Shape.Vector
@type t :: %Face{v1: Vector.t, v2: Vector.t, v3: Vector.t}
@derive [Poison.Encoder]
defstruct v1: nil, v2: nil, v3: nil
@doc "Returns true if the vector is one of the face's vertices, false otherwise."
@spec is_own_vertex?(Face.t, Vector.t) :: boolean
def is_own_vertex?(%Face{v1: v1, v2: v2, v3: v3}, v0),
do: v0 == v1 or v0 == v2 or v0 == v3
@doc "Returns true if the vector is inside the face, false otherwise."
@spec contains?(Face.t, Vector.t) :: boolean
def contains?(%Face{v1: v1, v2: v2, v3: v3} = face, v0) do
if is_own_vertex?(face, v0) do
true
else
# Compute vectors
vec1 = Vector.sub(v3, v1)
vec2 = Vector.sub(v2, v1)
vec3 = Vector.sub(v0, v1)
# Compute dot products
dot00 = Vector.dot(vec1, vec1)
dot01 = Vector.dot(vec1, vec2)
dot02 = Vector.dot(vec1, vec3)
dot11 = Vector.dot(vec2, vec2)
dot12 = Vector.dot(vec2, vec3)
# Compute barycentric coordinates
invDenom = 1 / (dot00 * dot11 - dot01 * dot01)
u = (dot11 * dot02 - dot01 * dot12) * invDenom
v = (dot00 * dot12 - dot01 * dot02) * invDenom
# Check if point is in triangle
(u >= 0) && (v >= 0) && (u + v < 1)
end
end
end