toxiclibs.clj / src / toxi / math / core.clj

(ns toxi.math.core
  (:use
    [toxi.geom.types]
    [toxi.math.types])
  (:import
    [java.util Random]
    [toxi.geom.types Vec4D]
    [toxi.math.types Matrix4x4]))

(def ^:const PI (double Math/PI))
(def ^:const TWO_PI (* 2 PI))
(def ^:const HALF_PI (* 1/2 PI))
(def ^:const THIRD_PI (* 1/3 PI))
(def ^:const QUARTER_PI (* 1/4 PI))
(def ^:const SIXTH_PI (* 1/6 PI))
(def ^:const THREE_HALVES_PI (* 3/2 PI))

(def ^:const SQRT2 (Math/sqrt 2))
(def ^:const SQRT3 (Math/sqrt 3))

(def ^:const LOG2 (Math/log 2))

(def ^:dynamic *rnd* (Random.))

(def ^:dynamic *epsilon* 1e-6)

(defprotocol IMatrix
  (matrix-multiply [m m2])
  (matrix-transpose [m])
  (transform-point [m v])
  (transform-normal [m v])
)

;(defprotocol IMatrix4x4)

(defn matrix4x4
  {:added "0.1"
   :java-id "toxi.geom.Matrix4x4"}
  ([]
    (Matrix4x4.
      1 0 0 0
      0 1 0 0
      0 0 1 0
      0 0 0 1))
  ([mat]
    (Matrix4x4.
      (get mat 0) (get mat 1) (get mat 2) (get mat 3)
      (get mat 4) (get mat 5) (get mat 6) (get mat 7)
      (get mat 8) (get mat 9) (get mat 10) (get mat 11)
      (get mat 12) (get mat 13) (get mat 14) (get mat 15)))
  ([m00 m01 m02 m03 m10 m11 m12 m13 m20 m21 m22 m23 m30 m31 m32 m33]
    (Matrix4x4.
      m00 m01 m02 m03
      m10 m11 m12 m13
      m20 m21 m22 m23
      m30 m31 m32 m33)))

(defn quaternion
  {:added "0.1"
   :java-id "toxi.geom.Quaternion"}
  ([] (Vec4D. 0.0 0.0 0.0 1.0))
  ([^double w xyz] (Vec4D. (:x xyz) (:y xyz) (:z xyz) w))
  ([^double w ^double x ^double y ^double z] (Vec4D. x y z w)))

(defn radians
  {:added "0.1"
   :java-id "toxi.math.MathUtils.radians"}
  ^double [^double x] (/ (* PI x) 180.0))

(defn degrees
  {:added "0.1"
   :java-id "toxi.math.MathUtils.degrees"}
  ^double [^double x] (/ (* 180.0 x) PI))

(defmacro fma
  [a b c]
  `(+ (* ~a ~b) ~c))

(defn lerp
  {:added "0.1"
   :java-id "toxi.math.MathUtils.lerp"}
  ^double [^double a ^double b ^double t] (fma (- b a) t a))

(defn map-interval
  "Maps x from one interval into another. Intervals can be defined as vectors."
  {:added "0.1"
   :java-id "toxi.math.MathUtils.mapInterval"}
  ^double
  ([x [minIn maxIn] [minOut maxOut]]
    (fma (- maxOut minOut) (/ (- x minIn) (- maxIn minIn)) minOut))
  ([x minIn maxIn minOut maxOut]
    (fma (- maxOut minOut) (/ (- x minIn) (- maxIn minIn)) minOut)))

(defn abs
  {:added "0.1"
   :java-id "toxi.math.MathUtils.abs"}
  [x] (if (neg? x) (- x) x))

(defn floor
  {:added "0.1"
   :java-id "toxi.math.MathUtils.floor"}
  ^long
  [^double x]
  (let [y (int x)]
    (if (and (neg? x) (not= x y))
      (dec y)
      y)))

(defmacro in-range?
  "Returns true if x >= min and x < max."
  ([x [min max]]
   `(and (>= ~x ~min) (< ~x ~max)))
  ([x min max]
   `(and (>= ~x ~min) (< ~x ~max))))

(defn round-to
  {:added "0.1"
   :java-id "toxi.math.MathUtils.roundTo"}
  ^double
  [^double x ^double prec] (* (floor (+ (/ x prec) 0.5)) prec))

(defn ceil-power2
  {:added "0.1"
   :java-id "toxi.math.MathUtils.ceilPowerOf2"}
  [x]
  (loop [pow2 1]
    (if (>= pow2 x)
      pow2
      (recur (* pow2 2)))))

(defn floor-power2
  {:added "0.1"
   :java-id "toxi.math.MathUtils.floorPowerOf2"}
  ^long
  [x] (long (Math/pow 2 (long (/ (Math/log x) LOG2)))))

(defn clip
  {:added "0.1"
   :java-id "toxi.math.MathUtils.clip"}
  [x min max]
  (if (< x min) min (if (> x max) max x)))

(defn clip-normalized
  {:added "0.1"
   :java-id "toxi.math.MathUtils.clipNormalized"}
  ^double
  [^double x] (clip x -1.0 1.0))

(defmacro with-rnd
  [rnd & body]
  `(binding [*rnd* ~rnd] (do ~@body)))

(defn random
  {:added "0.1"
   :java-id "toxi.math.MathUtils.random"}
  ^double
  ([] (.nextDouble ^Random *rnd*))
  ([^double upper] (* (.nextDouble ^Random *rnd*) upper))
  ([^double lower upper] (+ (* (.nextDouble ^Random *rnd*) (- upper lower)) lower)))

(defn normalized-random
  {:added "0.1"
   :java-id "toxi.math.MathUtils.normalizedRandom"}
  ^double
  [] (dec (* (.nextDouble *rnd*) 2)))

(defn impulse
  {:added "0.1"
   :java-id "toxi.math.MathUtils.impulse"}
  ^double
  [^double k ^double t]
  (let [h (* k t)]
    (* h (Math/exp (- 1.0 h)))))

(defmacro with-epsilon
  [eps & body]
  `(binding [*epsilon* ~eps] (do ~@body)))

(defn delta=
  "Compares the absolute difference between a and b and returns true
   if less than delta."
  {:added "0.1"
   :java-id :none}
  ([a b] (delta= a b *epsilon*)) 
  ([a b delta] (< (abs (- b a)) delta)))
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.