diff options
Diffstat (limited to 'src/main/scala/sims/collision/Ray.scala')
-rw-r--r-- | src/main/scala/sims/collision/Ray.scala | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/src/main/scala/sims/collision/Ray.scala b/src/main/scala/sims/collision/Ray.scala new file mode 100644 index 0000000..80a63fb --- /dev/null +++ b/src/main/scala/sims/collision/Ray.scala @@ -0,0 +1,62 @@ +/* _____ _ __ ________ ___ *\ +** / ___/(_) |/ / ___/ |__ \ Simple Mechanics Simulator 2 ** +** \__ \/ / /|_/ /\__ \ __/ / copyright (c) 2011 Jakob Odersky ** +** ___/ / / / / /___/ / / __/ ** +** /____/_/_/ /_//____/ /____/ ** +\* */ + +package sims.collision + +import scala.math._ +import sims.math._ + +/**A ray. + * @param point starting point of this ray + * @param direction this ray's directional vector + * @throws IllegalArgumentException if the directional vector is the null vector*/ +case class Ray(point: Vector2D, direction: Vector2D) + extends Linear + with Intersectable[Segment] { + + /*def closest(point: Vector2D) = { + var t = ((point - this.point) dot (direction)) / (direction dot direction) + if (t < 0) t = 0 + this.point + direction * t + }*/ + + def intersection(segment: Segment): Option[Vector2D] = { + + val n = segment.leftNormal + + // Handle case when two segments parallel + if ((n dot direction) == 0) None + else { + val t = (n dot (segment.point1 - point)) / (n dot direction) + val i = point + direction * t + if (0 <= t && (i - segment.point1).length <= segment.length) Some(i) + else None + } + /* + // Returns 2 times the signed triangle area. The result is positive if + // abc is ccw, negative if abc is cw, zero if abc is degenerate. + def signed2DTriArea(a: Vector2D, b: Vector2D, c: Vector2D) = { + (a.x - c.x) * (b.y - c.y) - (a.y - c.y) * (b.x - c.x); + } + + if (signed2DTriArea(point, point + direction, segment.point1) * signed2DTriArea(point, point + direction, segment.point2) < 0) { + val ab = segment.point2 - segment.point1 + val ac = segment.point2 - point + val t = (ac.x * ab.y - ac.y * ab.x) / (direction.y * ab.x - direction.x - ab.y) + if (t >= 0) Some(point + direction * t) else None + } else None*/ + } + + /**Checks if this ray contains the point <code>p</code>.*/ + def contains(p: Vector2D) = { + val v = p - point + p == point || + v ~ direction && + signum(direction.x) == signum(v.x) && + signum(direction.y) == signum(v.y) + } +} |