Permalink
Browse files

working rotating line + moving ball

  • Loading branch information...
1 parent 66051cd commit 4d3426f6ead725e6be50c78f2530cb481d4b4412 @simianarmy committed Feb 12, 2012
@@ -16,19 +16,28 @@ Canvas = (() ->
@ctxt = canvasEl.getContext(@mode)
@width = canvasEl.width
@height = canvasEl.height
+ @worldView = true # Default origin top left
context = () -> @ctxt
# Set the origin of the canvas
# @param {String} id (topleft | bottomleft)
setOrigin = (id) ->
- if id == 'topleft'
+ if @worldView && (id == 'bottomleft')
# translate world for origin at bottom left
+ @ctxt.translate(0, @height)
@ctxt.scale(1, -1)
- @ctxt.translate(0, -@height)
- else
+ @worldView = false
+ else if !@worldView
# bottom left is default
-
+ @ctxt.scale(1, -1)
+ @ctxt.translate(0, -@height)
+ @worldView = true
+
+ # @return true if drawing with world view coordinates (default = true)
+ inWorldView = () ->
+ @worldView
+
# Draw a circle on the canvas
# @param {Circle} c a Circle object
drawCircle = (c) ->
@@ -88,7 +97,7 @@ Canvas = (() ->
# Perform actions in a canvas context
inContext = (fn) ->
@ctxt.save()
- fn()
+ fn(@ctxt) # pass context back to callback as argument
@ctxt.restore()
# return the constructor
@@ -100,6 +109,7 @@ Canvas = (() ->
drawLine: drawLine
drawEllipse: drawEllipse
inContext: inContext
+ inWorldView: inWorldView
context: context
rotate: rotate
translate: translate
@@ -103,7 +103,7 @@ collisions = (->
[t, collisionNormal]
# Detect collision between rotating line and circle
- # Anglular values should be in radians
+ # Anglular values must be in radians
# @param {Number} theta0 angle of starting position of line from the vertical
# @param {Number} omega angular velocity of rotating line
# @param {Number} l line length
@@ -117,6 +117,7 @@ collisions = (->
angularCollisionLineCircle = (theta0, omega, l, r, d, alpha) ->
return collisison.NONE if d > l + r
return collisions.EMBEDDED if d < r
+ # k = 1 for clockwise motion, -1 otherwise
k = 1
# move into a calculation within the range of [0,2pi]
alpha -= theta0
@@ -131,7 +132,8 @@ collisions = (->
while alpha > pi2
alpha -= pi2
- # check if there is a possible collision
+ # check if there is a possible collision.
+ # this means any collision in t > 1 will not be considered.
return collisions.NONE if alpha > omega
# now perform the appropriate collision check
@@ -141,14 +143,15 @@ collisions = (->
(alpha - k * Math.acos((l*l + d*d - r*r) / (2*l*d))) / omega
# Detect collision between rotating line and moving or stationary circle.
- # This method is quite different than angularCollisionLineCircle() -
- # it is from the MPFP CDROM collision simulation Director code.
- # NB: No support for cases where the rotating line is offset from its rotating point.
+ # This method is quite different than angularCollisionLineCircle() which only
+ # deals with stationary circles.
+ # From the MPFP CDROM collision simulation Director code.
+ # TODO: Support for cases where the rotating line is offset from its rotating point.
# @param {Line} line shape
# @param {Circle} circle shape
# @param {Number} ts current timestep
# @return {Object}
- # t: time to collision (0 if collision detected)
+ # t: 0 if collision detected, collisions.NONE if not
# moment1: no idea
# moment2: no idea
angularCollisionLineCircle2 = (line, circle, ts) ->
@@ -169,12 +172,26 @@ collisions = (->
n1 = n1.x(-1)
n2 = n2.x(-2)
startDist = -startDist
-
- # check if circle crosses the line
+
+ noColl = {t: collisions.NONE}
r = circle.radius
- if ((startDist - r) * (n2.dot(endPos) - r) < 0)
- # check if intersection overlaps the line
- if ((startPos.subtract(n1.x(r)).mag() <= line.length) ||
+
+ # debug shit
+ console.log "start: #{startPos.inspect()} end: #{endPos.inspect()}"
+ console.log "line start ang: #{lineStartAng} lineEndAng: #{lineEndAng}"
+ console.log "n1: #{n1.inspect()}"
+ console.log "n2: #{n2.inspect()}"
+ # NOTE:
+ # Equation can't be solved algebraically - an approximation method must be used
+ # Save time by checking whether it's possible for the 2 objects to collide at all
+
+ # 1. Check if circle intersects the complete circle swept out by the line
+ unless (startDist - r) * (n2.dot(endPos) - r) < 0
+ return noColl
+
+ # 2. Check if angle swept out by the circle during the time interval
+ # overlaps with the angle swept out by the line.
+ if ((startPos.subtract(n1.x(r)).mag() <= line.length) ||
(endPos.subtract(n2.x(r)).mag() <= line.length))
return {t: 0,
normal: n1.x(-1),
@@ -184,7 +201,7 @@ collisions = (->
# otherwise, check for intersection with line endpoints
# TODO:
- {t: collisions.NONE}
+ noColl
isImpendingCollision = (ts) ->
0 < ts <= 1
@@ -21,7 +21,7 @@ Vector.isClockwise = (v, p) ->
# @param {String} unit d|r degrees or radians
# @return a 3D vector pointing at ang clockwise from the positive x-axis
Vector.directionVector = (angle, unit='r') ->
- ang *= (Math.PI / 180) if unit == 'd'
+ angle *= (Math.PI / 180) if unit == 'd'
$V([Math.cos(angle), Math.sin(angle), 0])
# Instance functions
@@ -12,7 +12,7 @@
$(document).ready ->
canvas = new Canvas($("#maincanvas").get(0))
- #canvas.setOrigin('topleft')
+ canvas.setOrigin('bottomleft')
elapsed = lastTime = startingAngle = startingTheta = 0
angle = 0
@@ -31,12 +31,16 @@ $(document).ready ->
$('#info').html('')
drawText = (text) ->
- canvas.inContext ->
- ctxt = canvas.context()
+ canvas.inContext((ctxt) ->
+ # when origin is cartesian, we must restore to world view to draw text
+ if !canvas.inWorldView()
+ ctxt.scale(1, -1);
+ ctxt.translate(0, -canvas.height);
ctxt.fillStyle = 'black'
ctxt.font = '12px Arial sans-serif'
ctxt.textBaseline = 'top'
- ctxt.fillText(text, canvas.width/2, 10)
+ ctxt.fillText(text, canvas.width/2, 20)
+ )
drawScene = () ->
canvas.clear()
@@ -48,7 +52,7 @@ $(document).ready ->
when 'Line'
canvas.inContext ->
canvas.translate obj.pos.e(1), obj.pos.e(2)
- canvas.rotate(Math.degreesToRadians(-obj.rotation))
+ canvas.rotate(Math.degreesToRadians(obj.rotation))
canvas.translate(-obj.pos.e(1), -obj.pos.e(2))
canvas.drawLine(obj)
@@ -57,8 +61,9 @@ $(document).ready ->
canvas.drawCircle obj
setupScene = ->
- startingAngle = $("input[name=sAngle]").val() || 20
- angularVel = $("input[name=angVel]").val() || 15
+ startingAngle = $("input[name=sAngle]").val() || 0
+ angularVel = $("input[name=angVel]").val() || 0
+ $('#sangle').html("#{startingAngle} deg.")
startingTheta = 90 - startingAngle
# draw rotating line
@@ -74,7 +79,7 @@ $(document).ready ->
color: 'blue'
})
if ballMoving = $("input[name=movingBall]:checked").val() == "1"
- ball.velocity = $V([-5, -10, 0])
+ ball.velocity = $V([-5, 10, 0])
# these two variable can be computed dynamically if the ball is moving
ballDistance = ball.pos.subtract(line.pos).mag()
@@ -8,7 +8,8 @@
<div id="main" role="main">
<ul id="controls">
<li>
- Starting angle: <input name="sAngle" default="90" size="3" value="90"/> degrees
+ Starting angle: <input type="range" name="sAngle" min="0" max="90" step="1" value="75">
+ <span id="sangle"></span>
</li>
<li>
Angular velocity: <input name="angVel" size="3" value="15"/> degrees/second

0 comments on commit 4d3426f

Please sign in to comment.