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

SCM Repository

[sml3d] View of /trunk/sml3d/src/sml3d/base/vec2d.sml
ViewVC logotype

View of /trunk/sml3d/src/sml3d/base/vec2d.sml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1260 - (download) (annotate)
Tue Jan 17 14:01:50 2012 UTC (7 years, 8 months ago) by jhr
File size: 2739 byte(s)
  Working on new SML3d core library
(* vec2d.sml
 *
 * COPYRIGHT (c) 2012 The SML3d Project (http://sml3d.cs.uchicago.edu)
 * All rights reserved.
 *
 * Operations on vectors in R^2 (double-precision version).
 *)

structure Vec2d :> VEC2 where type flt = Double.flt
  = struct

    structure Flt = Double

    type flt = Flt.flt

    val epsilon = Flt.epsilon
    val slerpTolerance : flt = 0.999

    type vec2 = flt SML3dTypes.vec2
    type vec3 = flt SML3dTypes.vec3

    open Vec2

  (* lift a 3D vector into homogeneous space *)
    fun vector (x, y) : vec3 = (x, y, 0.0)
    fun point (x, y) : vec3 = (x, y, 1.0)

    val zero : vec2 = (0.0, 0.0)

    val e1 : vec2 = (1.0, 0.0)
    val e2 : vec2 = (0.0, 1.0)

    fun toString (v : vec2) = concat[
	    "<", Flt.toString(#1 v), ",", Flt.toString(#2 v), ">"
	  ]

    fun neg ((x, y) : vec2) = (~x, ~y)

    fun add ((x1, y1) : vec2, (x2, y2)) = (x1+x2, y1+y2)

    fun sub ((x1, y1) : vec2, (x2, y2)) = (x1-x2, y1-y2)

    fun mul ((x1, y1) : vec2, (x2, y2)) = (x1*x2, y1*y2)

    fun scale (s, (x, y) : vec2) = (s*x, s*y)

    fun adds (v1, s, v2) = add(v1, scale(s, v2))

    fun abs (x, y) = (Flt.abs x, Flt.abs y)
    fun min ((x1, y1), (x2, y2)) = (Flt.min(x1, x2), Flt.min(y1, y2))
    fun max ((x1, y1), (x2, y2)) = (Flt.max(x1, x2), Flt.max(y1, y2))

    fun dot ((x1, y1) : vec2, (x2, y2)) = (x1*x2 + y1*y2)

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

  (* spherical interpolation between unit vectors *)
    fun slerp (v1, t, v2) = let
	  val cosAngle = dot(v1, v2)
	  in
	    if (cosAngle < slerpTolerance)
	      then let
		val angle = Flt.acos cosAngle
		val recipSinAngle = 1.0 / Flt.sin angle
		val scale1 = recipSinAngle * Flt.sin((1.0 - t) * angle)
		val scale2 = recipSinAngle * Flt.sin(t * angle)
		in
		  adds (scale(scale1, v1), scale1, v2)
		end
	      else lerp(v1, t, v2)
	  end

    fun lengthSq v = dot(v, v)
    fun length v = Flt.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 / Flt.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 : vec2) = (#2 v, ~(#1 v))
  (* rotate the vector by 90 degrees in the CCW direction *)
    fun perpCCW (v : vec2) = (~(#2 v), #1 v)

  end

root@smlnj-gforge.cs.uchicago.edu
ViewVC Help
Powered by ViewVC 1.0.0