[cells-cvs] CVS cells-gtk3/ph-maths
phildebrandt
phildebrandt at common-lisp.net
Sun Apr 13 10:59:25 UTC 2008
Update of /project/cells/cvsroot/cells-gtk3/ph-maths
In directory clnet:/tmp/cvs-serv5005/ph-maths
Added Files:
ph-maths.asd ph-maths.lisp
Log Message:
cells-gtk3 initial.
--- /project/cells/cvsroot/cells-gtk3/ph-maths/ph-maths.asd 2008/04/13 10:59:24 NONE
+++ /project/cells/cvsroot/cells-gtk3/ph-maths/ph-maths.asd 2008/04/13 10:59:24 1.1
(asdf:defsystem :ph-maths
:name "ph-maths"
:components
((:file "ph-maths")))
--- /project/cells/cvsroot/cells-gtk3/ph-maths/ph-maths.lisp 2008/04/13 10:59:24 NONE
+++ /project/cells/cvsroot/cells-gtk3/ph-maths/ph-maths.lisp 2008/04/13 10:59:24 1.1
;;;
;;; Linear algebra 2d
(defpackage :ph-maths-2d
(:use :cl)
(:nicknames :2d)
(:export :v
:x
:y
:v+
:v-
:v*
:min-abs
:max-abs
:v-polar
:r
:phi
:polar-coords
:polar-radius
:polar-angle
:cartesian-coords
:abs-angle
:deg->rad
:rad->deg
:v0
:vp
:p
:<>
:intersect-line-circle
:distance-point-line
:point-in-box-p
:to-decimal
:to-rgb
:to-rgb-vector
:~=))
(in-package :ph-maths-2d)
(declaim (optimize (speed 1) (debug 3) (space 0)))
(defun denil (lst)
(loop for val in lst if val collect val))
;;; represent 2d vector as cons
(declaim (inline v x y))
(defun v (x y)
(cons x y))
(defun x (v)
(car v))
(defun y (v)
(cdr v))
;;; basic linear algebra
(declaim (inline v-reduce v+ v- v*))
(defun v-reduce (fn vectors)
(declare (function fn))
(reduce #'(lambda (v1 v2) (v (funcall fn (x v1) (x v2)) (funcall fn (y v1) (y v2)))) (denil vectors)))
(defun v+ (&rest vectors)
(v-reduce #'+ vectors))
(defun v- (&rest vectors)
(v-reduce #'- vectors))
(defun v* (lambda vector)
(v (* (x vector) lambda) (* (y vector) lambda)))
;;; min/max
(declaim (inline abs-reduce min-abs max-abs))
(defun abs-reduce (fn vals)
(reduce fn (denil vals) :key #'abs))
(defun min-abs (&rest vals)
(abs-reduce #'min vals))
(defun max-abs (&rest vals)
(abs-reduce #'max vals))
; polar coordinates
(declaim (inline v-polar phi r polar-radius polar-angle polar-coords))
(defun v-polar (phi r)
(cons phi r))
(defun phi (v)
(car v))
(defun r (v)
(cdr v))
(defun polar-radius (v)
"return radius of cartesian vector v"
(sqrt (+ (* (x v) (x v)) (* (y v) (y v)))))
(defun polar-angle (v)
"return angle of cartesian vector v"
(if (zerop (x v))
(if (>= (y v) 0)
#.(* pi -0.5)
#.(* pi 0.5))
(atan (- (y v)) (x v))))
(defun polar-coords (v)
"return a polar representation of cartesian vector v"
(v-polar (polar-angle v) (polar-radius v)))
; cartesian coords
(declaim (inline cartesian-coords))
(defun cartesian-coords (v-polar)
"returns a cartesian representation of polar vector v-polar"
(v (* (r v-polar) (cos (phi v-polar)))
(* -1 (r v-polar) (sin (phi v-polar)))))
; degrees
(declaim (inline deg->rad rad->deg abs-angle))
(defun deg->rad (degs)
(/ (* degs pi) 180.0))
(defun rad->deg (rads)
(* (/ rads pi) 180.0))
(defun abs-angle (phi)
"returns a positive angle 0 <= phi <= 2pi"
(cond
((or (= phi #.(* 2 pi)) (= phi #.(* -2 pi))) phi)
(t (mod phi #.(* 2 pi)))))
; albegra -- 2d
(declaim (inline v0 vp <> p))
(defun v0 (v)
"returns a vector with the same direction as v and unit length"
(let ((r (polar-radius v)))
(if (plusp r) (v* (/ 1 r) v) (v 0 0))))
(defun vp (v)
"returns a unit vector perpendicular to v"
(let ((u (v0 v)))
(v (- (y u)) (x u))))
(defun <> (v1 v2)
"returns the scalar product <v1, v2>"
(+ (* (x v1) (x v2)) (* (y v1) (y v2))))
(defun p (v1 v2)
"returns the projection of v1 onto v2. Second return value is the length of the projection."
(let* ((v2_0 (v0 v2))
(len (<> v2_0 v1)))
(values (v* len v2_0) len)))
(declaim (inline distance-point-line intersect-line-circle point-in-box-p))
(defun distance-point-line (point p1 p2)
"returns the shortest distance from point to the line p1,p2."
(abs (second (multiple-value-list (p (v- p1 point) (vp (v- p2 p1)))))))
(defun intersect-line-circle (p1 p2 r)
"returns the intersection of a line through p1 and p2 and a circle around p2 with radius r"
(v+ p2 (v* r (v0 (v- p1 p2)))))
(defun point-in-box-p (p p1 p2 &key (tol 0))
"returns true if p is inside the box given by p1,p2"
(and (< (- (min (x p1) (x p2)) tol) (x p) (+ (max (x p1) (x p2)) tol))
(< (- (min (y p1) (y p2)) tol) (y p) (+ (max (y p1) (y p2)) tol))))
;; base conversion
(defun to-decimal (val &key (base 16))
"converts val (a value in base base as a string) to an integer"
(loop for p from 0 to (1- (length val))
for x downfrom (1- (length val))
summing (* (let ((c (char-code (char val p))))
(cond ((< 47 c 58) (- c 48))
((< 64 c 91) (- c 55))
((< 96 c 123) (- c 87))
(t (warn "Illegal character in hex argument to to-decimal") 0)))
(expt base x))))
(defun to-rgb (html-color)
"parses an html color code like #A204B2 to '(.8 .01 .7 4)"
(loop for val from 0 to 2
for pos = (1+ (* val 2))
collecting (/ (to-decimal (subseq html-color pos (+ pos 2))) 256)))
(defun to-rgb-vector (html-color)
"parses an html color code like #A204B2 to #(.8 .01 .7 4)"
(coerce (loop for val from 0 to 2
for pos = (1+ (* val 2))
collecting (/ (to-decimal (subseq html-color pos (+ pos 2))) 256))
'vector))
; fuzzy comparison
(defun ~= (&rest params)
(if (cdr params)
(let ((max (apply #'max params))
(min (apply #'min params)))
(> .05 (abs (/ (- max min) (max (abs max) (abs min) 1d-8)))))
t))
More information about the Cells-cvs
mailing list