normalLine: ->
m = @triangle.midpoint()
n = @triangle.midpoint().add(
@triangle.normal().normalize().multiplyScalar(50))
{a: m, b: n}
visibleBy: (point) ->
@hasPoint(point) or (@distance(point) > 0)
connect: (otherFace, link, otherLink) ->
if not link.reverseOf otherLink
throw new Error "can't connect with non-reverse link"
link.to = otherFace
otherLink.to = @
link.inverse = otherLink
otherLink.inverse = link
assign: (point) ->
if @hasPoint point
true
else
d = @distance point
if d >= 0
@assignedPoints.push point
if d > @furthest.distance
@furthest.distance = d
@furthest.point = point
true
else
false
assignPoints = (faces, points) ->
points.forEach (p) ->
_.any faces, (f) -> f.assign p
checkFace = (f) ->
error = false
setError = (msg) ->
console.log msg
error = true
if f.deleted
return
f.links.forEach (l, j) ->
str = "f.links[#{j}]"
if l.horizon == true
setError "#{str}.horizon == true"
if l.from != f
setError "#{str}.from != f"
if l.inverse.to != f
setError "#{str}.inverse.to != f"
if l.inverse.a != l.b
setError "#{str}.inverse.a != l.b"
if l.inverse.b != l.a
setError "#{str}.inverse.b != l.a"
backLinks = _.pluck l.to.links, 'to'
if not _.contains backLinks, f
setError "no reflexive link", f, backLinks
if error then throw new Error "checkFace failed"
checkHorizon = (horizon) ->
_.every _.map horizon, (h, i) ->
next = horizon[(i + 1) % horizon.length]
if h.b != next.a
console.error "discontinuous horizon", h, next
false
else
true
checkHull = (tracer, hull, points) ->
valid = true
_.each hull, (f) ->
_.each points, (p) ->
if visible face, point
valid = false
tracer.trace "OUTSIDE POINT",
faces: [face]
vertices: [point]
valid