aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/sims/collision/Linear.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/scala/sims/collision/Linear.scala')
-rw-r--r--src/main/scala/sims/collision/Linear.scala67
1 files changed, 67 insertions, 0 deletions
diff --git a/src/main/scala/sims/collision/Linear.scala b/src/main/scala/sims/collision/Linear.scala
new file mode 100644
index 0000000..3c06515
--- /dev/null
+++ b/src/main/scala/sims/collision/Linear.scala
@@ -0,0 +1,67 @@
+/* _____ _ __ ________ ___ *\
+** / ___/(_) |/ / ___/ |__ \ Simple Mechanics Simulator 2 **
+** \__ \/ / /|_/ /\__ \ __/ / copyright (c) 2011 Jakob Odersky **
+** ___/ / / / / /___/ / / __/ **
+** /____/_/_/ /_//____/ /____/ **
+\* */
+
+package sims.collision
+
+import scala.math._
+import sims.math._
+
+/**A base trait for all linear geometric elements specified by one point and a direction.
+ * @throws IllegalArgumentException if the directional vector is the null vector*/
+trait Linear {
+
+ /**A point contained in this linear element.*/
+ val point: Vector2D
+
+ /**Direction vector.*/
+ val direction: Vector2D
+
+ /**Unit directional vector.*/
+ lazy val direction0 = direction.unit
+
+ /**Right normal vector to <code>direction</code>.*/
+ lazy val rightNormal = direction.rightNormal
+
+ /**Right normal unit vector to <code>direction</code>.*/
+ lazy val rightNormal0 = rightNormal.unit
+
+ /**Left normal vector to <code>direction</code>.*/
+ lazy val leftNormal = direction.leftNormal
+
+ /**Left normal unit vector to <code>direction</code>.*/
+ lazy val leftNormal0 = leftNormal.unit
+
+ ///**Computes the closest point on this linear element to a given point.*/
+ //def closest(point: Vector2D): Vector2D
+
+ ///**Computes the shortest distance form this linear element to a given point.*/
+ //def distance(point: Vector2D) = (closest(point) - point).length
+
+ require(direction != 0, "A linear element's direction cannot be the null vector.")
+}
+
+object Linear {
+
+ /** Clips a segment passing through points `p1` and `p2` to a half plain
+ * given by a point `p` and a normal (pointing into the plain) `normal`. */
+ def clip(p1: Vector2D, p2: Vector2D, p: Vector2D, normal: Vector2D): List[Vector2D] = {
+ val normal0 = normal.unit
+ val direction = p2 - p1
+
+ val d1 = (p1-p) dot normal0
+ val d2 = (p2-p) dot normal0
+
+ if (d1 < 0 && d2 < 0) return Nil
+ if (d1 >= 0 && d2 >= 0) return List(p1, p2)
+
+ val intersection = p1 + direction * abs(d1) / (abs(d1) + abs(d2))
+ val inside = if (d1 > 0) p1 else p2
+
+ List(inside, intersection)
+ }
+
+} \ No newline at end of file