Home My Page Projects Code Snippets Project Openings 3D graphics for Standard ML
 Summary Activity SCM

# SCM Repository

[sml3d] View of /src/common/vec2f.sml
 [sml3d] / src / common / vec2f.sml

# View of /src/common/vec2f.sml

Fri May 9 22:54:04 2008 UTC (11 years, 5 months ago) by jhr
File size: 4022 byte(s)
```  Added 2D vector modules
```
```(* vec2f.sml
*
* COPYRIGHT (c) 2008 John Reppy (http://cs.uchicago.edu/~jhr)
*
* Operations on vectors in R^2 (float version).
*)

structure Vec2f : sig

type float = Float.float

type vec2f = {x : float, y : float}

val unpack : vec2f -> (float * float)
val pack   : (float * float) -> vec2f
val toList : vec2f -> float list

(* functional update *)
val setX : vec2f * float -> vec2f
val setY : vec2f * float -> vec2f

val nth : vec2f * int -> float

val zero : vec2f

(* standard basis vectors *)
val e1 : vec2f
val e2 : vec2f

val toString : vec2f -> string

val neg : vec2f -> vec2f
val add : (vec2f * vec2f) -> vec2f
val sub : (vec2f * vec2f) -> vec2f
val mul : (vec2f * vec2f) -> vec2f

val scale : (float * vec2f) -> vec2f

(* adds (u, s, v) = u + s*v *)
val adds : (vec2f * float * vec2f) -> vec2f

(* lerp (u, t, v) = (1-t)*u + t*v; we assume that 0 <= t <= 1 *)
val lerp : (vec2f * float * vec2f) -> vec2f

val dot : (vec2f * vec2f) -> float
val normalize : vec2f -> vec2f
val length : vec2f -> float
val lengthSq : vec2f -> float		(* length squared *)
val lengthAndDir : vec2f -> (float * vec2f)	(* length and normal vector *)
val distanceSq : (vec2f * vec2f) -> float	(* distance squared *)
val distance : (vec2f * vec2f) -> float	(* distance between two points *)
val clipLength : (vec2f * float) -> vec2f

(* return the parallel and perpendicular components of a vector v relative to a
* unit basis vector.
*)
val parallelComponent : {basis : vec2f, v : vec2f} -> vec2f
val perpendicularComponent : {basis : vec2f, v : vec2f} -> vec2f

(* rotate the vector by 90 degrees in the CW direction *)
val perpCW : vec2f -> vec2f
(* rotate the vector by 90 degrees in the CCW direction *)
val perpCCW : vec2f -> vec2f

(* iterators *)
val map : (float -> 'a) -> vec2f -> {x : 'a, y : 'a}
val app : (float -> unit) -> vec2f -> unit

(* rays *)
type rayf = {orig : vec2f, dir : vec2f}

val rayToPoint : (rayf * float) -> vec2f

end = struct

type float = Float.float

val epsilon : float = 1.0e~5

type vec2f = float SML3dTypes.vec2

open Vec2

val zero : vec2f = {x=0.0, y = 0.0}

val e1 : vec2f = {x = 1.0, y = 0.0}
val e2 : vec2f = {x = 0.0, y = 1.0}

fun toString ({x, y} : vec2f) = concat[
"<", Float.toString x, ",", Float.toString y, ">"
]

fun neg ({x, y} : vec2f) = {x = ~x, y = ~y}

fun add ({x=x1, y=y1} : vec2f, {x=x2, y=y2}) = {x=x1+x2, y=y1+y2}

fun sub ({x=x1, y=y1} : vec2f, {x=x2, y=y2}) = {x=x1-x2, y=y1-y2}

fun mul ({x=x1, y=y1} : vec2f, {x=x2, y=y2}) = {x=x1*x2, y=y1*y2}

fun scale (s, {x, y} : vec2f) = {x = s*x, y = s*y}

fun lerp (v1, t, v2) = add(scale(1.0-t, v1), scale(t, v2))

fun dot ({x=x1, y=y1} : vec2f, {x=x2, y=y2}) = (x1*x2 + y1*y2)

fun lengthSq v = dot(v, v)
fun length v = Float.sqrt(lengthSq v)

fun distanceSq (u, v) = lengthSq (sub (u, v))
fun distance (u, v) = length (sub (u, v))

fun lengthAndDir v = let
val l = length v
in
if (l < epsilon)
then (l, v)
else (l, scale(1.0 / l, v))
end

fun normalize v = #2(lengthAndDir v)

fun clipLength (v, maxLen) = let
val lenSq = lengthSq v
in
if (lenSq < maxLen*maxLen)
then v
else scale(maxLen / Float.sqrt lenSq, v)
end

fun parallelComponent {basis, v} = scale(dot(basis, v), basis)

fun perpendicularComponent {basis, v} = sub(v, parallelComponent {basis=basis, v=v})

(* rotate the vector by 90 degrees in the CW direction *)
fun perpCW (v : vec2f) = {x = #y v, y = ~(#x v)}
(* rotate the vector by 90 degrees in the CCW direction *)
fun perpCCW (v : vec2f) = {x = ~(#y v), y = #x v}

(* rays *)
type rayf = {orig : vec2f, dir : vec2f}

fun rayToPoint ({orig, dir}, s) = adds(orig, s, dir)

end
```