Commits

Karsten Schmidt committed 3f461ca

initial check in of initial barebones toxiclibs in vanilla clojure

Comments (0)

Files changed (14)

.DS_Store

Binary file added.
+pom.xml
+*jar
+/lib/
+/classes/
+.lein-failures
+.lein-deps-sum
+syntax: glob
+
+pom.xml
+*.jar
+lib
+classes
+autodoc
+docs
+.lein-failures
+.lein-deps-sum
+# toxiclibs.clj
+
+FIXME: write description
+
+## Usage
+
+FIXME: write
+
+## License
+
+Copyright (C) 2011 FIXME
+
+Distributed under the Eclipse Public License, the same as Clojure.
+(defproject toxiclibs.clj "0.1.0-SNAPSHOT"
+  :description "Clojure port of toxiclibs.org"
+  :dependencies [[org.clojure/clojure "1.2.1"]]
+  :dev-dependencies [[lein-marginalia "0.6.1"]]
+  :autodoc {:name "toxiclibs.clj" :page-title "toxiclibs docs" :copyright "(c) 2011 Karsten Schmidt"}
+  :main toxi.core)

src/toxi/core.clj

+(ns toxi.core)
+
+(defn relate
+  [f pred a b] (if (pred (f a) (f b)) a b))
+
+(defn swizzle
+  ([v key] (swizzle v key 0))
+  ([v key z]
+  (case key
+    :x (:x v)
+    :y (:y v)
+    :z (:z v z)
+    :xy {:x (:x v) :y (:y v)}
+    :yx {:x (:y v) :y (:x v)}
+    :xz {:x (:x v) :y (:z v z)}
+    :zx {:x (:z v z) :y (:x v)}
+    :yz {:x (:y v) :y (:z v z)}
+    :zy {:x (:z v z) :y (:y v)}
+    :xyz {:x (:x v) :y (:y v) :z (:z v z)}
+    :xzy {:x (:x v) :y (:z v z) :z (:y v)}
+    :yxz {:x (:y v) :y (:x v) :z (:z v z)}
+    :yzx {:x (:y v) :y (:z v z) :z (:x v)}
+    :zxy {:x (:z v z) :y (:x v) :z (:y v)}
+    :zyx {:x (:z v z) :y (:y v) :z (:x v)}
+    )))

src/toxi/geom/aabb.clj

+(ns toxi.geom.aabb
+ (:require
+   [toxi.geom.vec3d :as v3d]))
+
+(defn AABB
+  ([] (AABB (v3d/vec3d) (v3d/Vec3d 0.5 0.5 0.5)))
+  ([origin extent] {:origin origin :extent extent})
+  ([x y z ex ey ez] (AABB (v3d/vec3d x y z) (v3d/Vec3d ex ey ez))))
+
+(defn min
+  [aabb]
+  (v3d/sub (:origin aabb) (:extent aabb)))
+
+(defn max
+  [aabb]
+  (v3d/add (:origin aabb) (:extent aabb)))
+
+(defn contains-point?
+  [aabb p]
+  (let [min (min aabb) max (max aabb)
+        x1 (:x min) y1 (:y min) z1 (:z min)
+        x2 (:x max) y2 (:y max) z2 (:z max)
+        x (:x p) y (:y p) z (:z p)]
+    (and (>= x x1) (>= y y1) (>= z z1) (<= x x2) (<= y y2) (<= z z2))))

src/toxi/geom/line2d.clj

+(ns toxi.geom.line2d
+ (:require
+   [toxi.geom.vec2d :as v2d]
+   [toxi.geom.rect :as rect]))
+
+(defn line2d
+  ([a b] {:a a :b b})
+  ([^Double x1 ^Double y1 ^Double x2 ^Double y2] (line2d (v2d/vec2d x1 y1) (v2d/vec2d x2 y2))))
+
+(defn split
+  ([line len] (split (:a line) (:b line) len [] true))
+  ([a b len] (split a b len [] true))
+  ([a b len addfirst?] (split a b len [] addfirst?))
+  ([a b len coll addfirst?]
+    (let [coll2 (if addfirst? (conj coll a) coll)
+          dist (v2d/distance-to a b)
+          step (v2d/limit (v2d/sub b a) len)]
+      (if (> dist len)
+        (loop [pos (v2d/add a step)
+               acc coll2
+               d dist]
+          (if (< d len)
+            (conj acc b)
+            (recur (v2d/add pos step) (conj acc pos) (- d len))))
+        (conj coll2 b)))))
+
+(defn classify-point
+  [line p]
+  (let [a (:a line)
+        normal (v2d/perpendicular (v2d/sub (:b line) a))
+        d (v2d/dot (v2d/sub p a) normal)]
+    (Math/signum (float d))))
+
+(defn point-on-line
+  [line t]
+  (v2d/interpolate (:a line) (:b line) t))
+
+(defn intersect-line
+  [l1 l2]
+  (let [ax1 (:x (:a l1)) ay1 (:y (:a l1)) bx1 (:x (:b l1)) by1 (:y (:b l1))
+        ax2 (:x (:a l2)) ay2 (:y (:a l2)) bx2 (:x (:b l2)) by2 (:y (:b l2))
+        denom (- (* (- by2 ay2) (- bx1 ax1)) (* (- bx2 ax2) (- by1 ay1)))
+        na (- (* (- bx2 ax2) (- ay1 ay2)) (* (- by2 ay2) (- ax1 ax2)))
+        nb (- (* (- bx1 ax1) (- ay1 ay2)) (* (- by1 ay1) (- ax1 ax2)))]
+    (if-not (= 0.0 denom)
+      (let [ua (/ na denom) ub (/ nb denom) ipos (point-on-line l1 ua)]
+        (if (and (>= ua 0.0) (<= ua 1.0) (>= ub 0.0) (<= ub 1.0))
+          {:type :intersect :pos ipos :ua ua :ub ub}
+          {:type :no-intersect :pos ipos :ua ua :ub ub}))
+      (if (and (= 0.0 na) (= 0.0 nb))
+        {:type :coincident}
+        {:type :parallel}))))
+
+(defn closest-point-to
+  [line p]
+  (let [a (:a line)
+        b (:b line)
+        v (v2d/sub b a)
+        t (/ (v2d/dot (v2d/sub p a) v) (v2d/mag-squared v))]
+    (cond
+      (< t 0.0) a
+      (> t 1.0) b
+      :else (v2d/interpolate a b t))))
+
+(defn bounds
+  [line] (rect/rect
+           (v2d/min (:a line) (:b line))
+           (v2d/max (:a line) (:b line))))
+

src/toxi/geom/polygon2d.clj

+(ns toxi.geom.polygon2d
+ (:require
+   [toxi.geom.vec2d :as v2d]
+   [toxi.geom.line2d :as l2d]))
+
+(defn edges
+  [poly]
+  (reduce
+    (fn[acc v]
+      (if (vector? acc)
+        (conj acc (l2d/line2d (:b (last acc)) v))
+        [(l2d/line2d acc v)]))
+    (conj poly (first poly))))
+
+(defn contains-point?
+  [poly p]
+  (let [{:keys [x y]} p]
+    (reduce
+      (fn[state v]
+        (let [i (:i state) j (nth poly (:j state))
+              xi (:x v) yi (:y v)
+              xj (:x j) yj (:y j)]
+          (if (and
+                (or (and (< yi y) (>= yj y)) (and (< yj y) (>= yi y)))
+                (< (+ xi (* (/ (- y yi) (- yj yi)) (- xj xi))) x))
+            (assoc state :odd (not (:odd state)) :i (inc i) :j i)
+            (assoc state :i (inc i) :j i))))
+      {:odd false :i 0 :j (dec (count poly))}
+      poly)))
+
+(defn bounds
+  [poly]
+  (let [b (reduce
+            (fn[state v]
+              (let [{:keys [x y]} v]
+                (assoc state
+                  :min (v2d/vec2d (min (:x (:min state)) x) (min (:y (:min state)) y))
+                  :max (v2d/vec2d (max (:x (:max state)) x) (max (:y (:max state)) y)))))
+            {:min (v2d/vec2d (Double/MAX_VALUE) (Double/MAX_VALUE))
+             :max (v2d/vec2d (Double/MIN_VALUE) (Double/MIN_VALUE))}
+            poly)]
+    (rect/rect (:min b) (:max b))))
+
+(defn area
+  [poly]
+  (let [num (count poly)
+        res (reduce
+              (fn[state v]
+                (let [w (nth poly (mod (inc (:i state)) num))
+                      cross (v2d/cross v w)]
+                  (assoc state
+                    :a (+ (:a state) (v2d/cross v w))
+                    :i (inc (:i state)))))
+              {:a 0 :i 0}
+              poly)]
+    (* 1/2 (:a res))))
+
+(defn centroid
+  [poly]
+  (let [num (count poly)
+        res (reduce
+              (fn[state v]
+                (let [w (nth poly (mod (inc (:i state)) num))
+                      cross (v2d/cross v w)]
+                  (assoc state
+                    :i (inc (:i state))
+                    :v (v2d/add (:v state) (v2d/scale-n (v2d/add v w) cross)))))
+              {:v (v2d/vec2d) :i 0}
+              poly)]
+    (v2d/scale-n (:v res) (/ 1.0 (* 6 (area p))))))

src/toxi/geom/rect.clj

+(ns toxi.geom.rect
+ (:require
+   [toxi.geom.vec2d :as v2d]
+   [toxi.geom.line2d :as l2d]))
+
+(defn rect
+  ([] {:x 0 :y 0 :width 0 :height 0})
+  ([min max]
+    (let [dim (v2d/sub max min)]
+      {:x (:x min) :y (:y min) :width (:x dim) :height (:y dim)}))
+  ([^Double x ^Double y ^Double w ^Double h] {:x x :y y :width w :height h}))
+
+(defn to-polygon2d
+  [rect]
+  (let [x1 (:x rect) y1 (:y rect)
+        x2 (+ (:x rect) (:width rect)) y2 (+ (:y rect) (:height rect))]
+    [(v2d/vec2d x1 y1)
+     (v2d/vec2d x2 y1)
+     (v2d/vec2d x2 y2)
+     (v2d/vec2d x1 y2)]))
+
+(defn centroid
+  [rect]
+  (v2d/add rect (v2d/scale-n (v2d/vec2d (:width rect) (:height rect)) 1/2)))

src/toxi/geom/vec2d.clj

+(ns toxi.geom.vec2d
+ (:require [toxi.math :as math]
+           [toxi.core :as core]))
+
+(defn vec2d
+  ([] {:x 0 :y 0})
+  ([^Double x ^Double y] {:x (double x) :y (double y)}))
+
+(defn add
+  [a b] (assoc a :x (+ (:x a) (:x b)) :y (+ (:y a) (:y b))))
+
+(defn sub
+  [a b] (assoc a :x (- (:x a) (:x b)) :y (- (:y a) (:y b))))
+
+(defn scale
+  [a b] (assoc a :x (* (:x a) (:x b)) :y (* (:y a) (:y b))))
+
+(defn scale-n
+  [v ^Double n] (assoc v :x (* (:x v) n) :y (* (:y v) n)))
+
+(defn perpendicular
+  [v] (assoc v :x (* -1 (:y v)) :y (:x v)))
+
+(defn mag-squared
+  [v] (let [x (:x v) y (:y v)] (+ (* x x) (* y y))))
+
+(defn mag
+  [v] (Math/sqrt (mag-squared v)))
+
+(defn distance-to
+  [a b] (mag (sub a b)))
+
+(defn distance-to-squared
+  [a b] (mag-squared (sub a b)))
+
+(defn normalize
+  [v] (let [m (mag v)] (if (> m 0.0) (assoc v :x (/ (:x v) m) :y (/ (:y v) m)) v)))
+
+(defn normalize-to
+  [v len] (let [m (/ (mag v) len)] (if (> m 0.0) (assoc v :x (/ (:x v) m) :y (/ (:y v) m)) v)))
+
+(defn limit
+  [v len] (if (> (mag-squared v) (* len len)) (normalize-to v len) v))
+
+(defn dot
+  [a b] (+ (* (:x a) (:x b)) (* (:y a) (:y b))))
+
+(defn cross
+  [a b] (- (* (:x a) (:y b)) (* (:y a) (:x b))))
+
+(defn heading
+  [v] (Math/atan2 (:y v) (:x v)))
+
+(defn angle-between
+  [a b] (Math/acos (dot a b)))
+
+(defn angle-between-norm
+  [a b] (Math/acos (dot (normalize a) (normalize b))))
+
+(defn interpolate
+  ([a b ^Double t] (interpolate math/lerp a b t))
+  ([f a b ^Double t] (assoc a :x (f (:x a) (:x b) t) :y (f (:y a) (:y b) t))))
+
+(defn min
+  [a b] (core/relate mag-squared < a b))
+
+(defn max
+  [a b] (core/relate mag-squared > a b))
+
+(defn reflect
+  [v r]
+  (let [rv (scale-n r (* 2 (dot v r)))] (sub rv v)))
+
+(defn to-polar
+  [v] (assoc v :x (mag v) :y (heading v)))
+
+(defn to-cartesian
+  [v] (assoc v :x (* (:x v) (Math/cos (:y v))) :y (* (:x v) (Math/sin (:y v)))))

src/toxi/geom/vec3d.clj

+(ns toxi.geom.vec3d
+ (:require [toxi.math :as math]
+           [toxi.core :as core]))
+
+(defn vec3d
+  ([] {:x 0 :y 0 :z 0})
+  ([^Double x ^Double y ^Double z] {:x (double x) :y (double y) :z (double z)}))
+
+(defn add
+  [a b] (assoc a :x (+ (:x a) (:x b)) :y (+ (:y a) (:y b)) :z (+ (:z a) (:z b))))
+
+(defn sub
+  [a b] (assoc a :x (- (:x a) (:x b)) :y (- (:y a) (:y b)) :z (- (:z a) (:z b))))
+
+(defn scale
+  [a b] (assoc a :x (* (:x a) (:x b)) :y (* (:y a) (:y b)) :z (* (:z a) (:z b))))
+
+(defn scale-n
+  [a ^Double n] (assoc a :x (* (:x a) n) :y (* (:y a) n) :z (* (:z a) n)))

src/toxi/math.clj

+(ns toxi.math)
+
+(def EPS 1e-07)
+
+(def ^Double PI Math/PI)
+(def ^Double TWO_PI (* 2 Math/PI))
+(def ^Double HALF_PI (* 2 Math/PI))
+(def ^Double THIRD_PI (* 1/3 Math/PI))
+(def ^Double QUARTER_PI (* 1/4 Math/PI))
+
+(def ^Double SQRT2 (Math/sqrt 2))
+(def ^Double SQRT3 (Math/sqrt 3))
+
+(defn radians
+  [x] (/ (* PI x) 180))
+
+(defn degrees
+  [x] (/ (* 180 x) PI))
+
+(defn lerp [a b t] (+ a (* (- b a) t)))
+
+(defn map-interval
+  "Maps x from one interval into another. Intervals can be defined as vectors."
+  ([x in out] (map-interval x (in 0) (in 1) (out 0) (out 1)))
+  ([x minIn maxIn minOut maxOut] (lerp minOut maxOut (/ (- x minIn) (- maxIn minIn)))))

test/toxi/test/geom.clj

+(ns toxi.test.geom
+  (:use [toxi.geom])
+  (:use [clojure.test]))
+
+(deftest replace-me ;; FIXME: write
+  (is false "No tests have been written."))