class LineSegment @className: "LineSegment" constructor: (@a, @b) -> @slope = (@a.y - @b.y) / (@a.x - @b.x) @y0 = @a.y - (@slope * @a.x) @left = if @a.x < @b.x then @a else @b @right = if @a.x > @b.x then @a else @b @bottom = if @a.y < @b.y then @a else @b @top = if @a.y > @b.y then @a else @b y: (x) -> (@slope * x) + @y0 x: (y) -> (y - @y0) / @slope intersectsLineSegment: (lineSegment) -> if lineSegment.slope is @slope if lineSegment.y0 is @y0 if lineSegment.left.x is @left.x or lineSegment.left.x is @right.x or lineSegment.right.x is @right.x or lineSegment.right.x is @left.x # segments are of the same line with shared start and/or end points return true else [left, right] = if lineSegment.left.x < @left.x then [lineSegment, @] else [@, lineSegment] if left.right.x > right.left.x # segments are of the same line and one is contained within the other return true else if Math.abs(@slope) isnt Infinity and Math.abs(lineSegment.slope) isnt Infinity x = (lineSegment.y0 - @y0) / (@slope - lineSegment.slope) if x >= @left.x and x <= @right.x and x >= lineSegment.left.x and x <= lineSegment.right.x return true else if Math.abs(@slope) isnt Infinity or Math.abs(lineSegment.slope) isnt Infinity [vertical, nonvertical] = if Math.abs(@slope) isnt Infinity then [lineSegment, @] else [@, lineSegment] x = vertical.a.x bottom = vertical.bottom.y top = vertical.top.y y = nonvertical.y(x) left = nonvertical.left.x right = nonvertical.right.x if y >= bottom and y <= top and x >= left and x <= right return true false pointOnLine: (point, segment=true) -> if point.y is @y(point.x) if segment [littleY, bigY] = if @a.y < @b.y then [@a.y, @b.y] else [@b.y, @a.y] if littleY <= point.y and bigY >= point.y return true else return true false distanceSquaredToPoint: (point) -> # http://stackoverflow.com/a/1501725/540620 return @a.distanceSquared point if @a.equals @b res = Math.min point.distanceSquared(@a), point.distanceSquared(@b) lineMagnitudeSquared = @a.distanceSquared @b t = ((point.x - @a.x) * (@b.x - @a.x) + (point.y - @a.y) * (@b.y - @a.y)) / lineMagnitudeSquared return @a.distanceSquared point if t < 0 return @b.distanceSquared point if t > 1 point.distanceSquared x: @a.x + t * (@b.x - @a.x), y: @a.y + t * (@b.y - @a.y) distanceToPoint: (point) -> Math.sqrt @distanceSquaredToPoint point toString: -> "lineSegment(a=#{@a}, b=#{@b}, slope=#{@slope}, y0=#{@y0}, left=#{@left}, right=#{@right}, bottom=#{@bottom}, top=#{@top})" serialize: -> {CN: @constructor.className, a: @a, b: @b} @deserialize: (o, world, classMap) -> new LineSegment o.a, o.b serializeForAether: -> @serialize() @deserializeFromAether: (o) -> @deserialize o module.exports = LineSegment