-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathutility.scheme
90 lines (77 loc) · 3.25 KB
/
utility.scheme
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
(define (square x)
; The square of x, not to be confused with (sqrt x)
(* x x))
(define (square-norm x y z)
; The square of the norm of the vector (x,y,z)
(+ (square x) (square y) (square z)))
(define (norm x y z)
; The norm (that is, length) of the vector (x,y,z)
(sqrt (square-norm x y z)))
(define (normalize x y z)
; Scale a nonzero vector to a unit vector
(let ([n (norm x y z)])
(list (/ x n) (/ y n) (/ z n))))
(define (orthogonal x y z)
; Given a nonzero vector, return two other vectors so that the three vectors
; are orthogonal to each other
(cond [(and (< (abs x) (abs y)) (< (abs x) (abs z)))
(list (list 0 (- z) y)
(list (+ (square y) (square z)) (- (* x y)) (- (* x z))))]
[(< (abs y) (abs z))
(list (list z 0 (- x))
(list (- (* x y)) (+ (square x) (square z)) (- (* y z))))]
[else
(list (list (- y) x 0)
(list (- (* x z)) (- (* y z)) (+ (square x) (square y))))]))
(define (to-orthogonal x y z boston berlin latitude)
; Convert local coordinates (boston,berlin,latitude) into some local
; orthonormal coordinate system where up is in the direction of the
; nonzero vector (x,y,z)
(let ([orthogonals (orthogonal x y z)])
(map + (map (lambda (coord) (* coord latitude))
(normalize x y z))
(map (lambda (coord) (* coord boston))
(apply normalize (car orthogonals)))
(map (lambda (coord) (* coord berlin))
(apply normalize (cadr orthogonals))))))
(define (uniform-disk-helper)
; Pick a point on the unit disk, with uniform probability, and return
; the squared distance of the point from the origin, followed by the
; two coordinates of the point
(let ([sqr-radius (rand)]
[theta (* (rand) 2 pi)])
(let ([radius (sqrt sqr-radius)])
(list sqr-radius
(* radius (cos theta))
(* radius (sin theta))))))
(define (uniform-disk)
; Pick a point on the unit disk, with uniform probability
(cdr (uniform-disk-helper)))
(define (uniform-latitude min-latitude max-latitude)
; Pick a point on the unit sphere between the two given latitudes,
; with uniform probability
(let ([latitude (+ min-latitude (* (- max-latitude min-latitude) (rand)))]
[from-disk (uniform-disk)])
(let ([radius (sqrt (- 1 (square latitude)))])
(list (* radius (car from-disk))
(* radius (cadr from-disk))
latitude))))
(define (uniform-hemisphere)
; Pick a point on the unit hemisphere, with uniform probability
(uniform-latitude 0 1))
(define (uniform-sphere)
; Pick a point on the unit sphere, with uniform probability
(uniform-latitude -1 1))
(define (cosine-hemisphere)
; Pick a point on the unit sphere, with probability density
; proportional to the latitude
(let ([from-disk (uniform-disk-helper)])
(list (cadr from-disk)
(caddr from-disk)
(sqrt (- 1 (car from-disk))))))
(define (lambert x y z)
; Given a vector that is pointing away from and perpendicular to a surface,
; return a vector that points away from the surface, whose direction is
; distributed in proportion to the cosine of the angle between the input and
; output vectors
(apply to-orthogonal x y z (cosine-hemisphere)))