Skip to content

Commit

Permalink
working rotating line + moving ball
Browse files Browse the repository at this point in the history
  • Loading branch information
simianarmy committed Feb 12, 2012
1 parent 66051cd commit 4d3426f
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 27 deletions.
20 changes: 15 additions & 5 deletions source/js/mylibs/Canvas.js.coffee
Expand Up @@ -16,19 +16,28 @@ Canvas = (() ->
@ctxt = canvasEl.getContext(@mode) @ctxt = canvasEl.getContext(@mode)
@width = canvasEl.width @width = canvasEl.width
@height = canvasEl.height @height = canvasEl.height
@worldView = true # Default origin top left


context = () -> @ctxt context = () -> @ctxt


# Set the origin of the canvas # Set the origin of the canvas
# @param {String} id (topleft | bottomleft) # @param {String} id (topleft | bottomleft)
setOrigin = (id) -> setOrigin = (id) ->
if id == 'topleft' if @worldView && (id == 'bottomleft')
# translate world for origin at bottom left # translate world for origin at bottom left
@ctxt.translate(0, @height)
@ctxt.scale(1, -1) @ctxt.scale(1, -1)
@ctxt.translate(0, -@height) @worldView = false
else else if !@worldView
# bottom left is default # 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 # Draw a circle on the canvas
# @param {Circle} c a Circle object # @param {Circle} c a Circle object
drawCircle = (c) -> drawCircle = (c) ->
Expand Down Expand Up @@ -88,7 +97,7 @@ Canvas = (() ->
# Perform actions in a canvas context # Perform actions in a canvas context
inContext = (fn) -> inContext = (fn) ->
@ctxt.save() @ctxt.save()
fn() fn(@ctxt) # pass context back to callback as argument
@ctxt.restore() @ctxt.restore()


# return the constructor # return the constructor
Expand All @@ -100,6 +109,7 @@ Canvas = (() ->
drawLine: drawLine drawLine: drawLine
drawEllipse: drawEllipse drawEllipse: drawEllipse
inContext: inContext inContext: inContext
inWorldView: inWorldView
context: context context: context
rotate: rotate rotate: rotate
translate: translate translate: translate
Expand Down
41 changes: 29 additions & 12 deletions source/js/mylibs/collisions.js.coffee
Expand Up @@ -103,7 +103,7 @@ collisions = (->
[t, collisionNormal] [t, collisionNormal]


# Detect collision between rotating line and circle # 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} theta0 angle of starting position of line from the vertical
# @param {Number} omega angular velocity of rotating line # @param {Number} omega angular velocity of rotating line
# @param {Number} l line length # @param {Number} l line length
Expand All @@ -117,6 +117,7 @@ collisions = (->
angularCollisionLineCircle = (theta0, omega, l, r, d, alpha) -> angularCollisionLineCircle = (theta0, omega, l, r, d, alpha) ->
return collisison.NONE if d > l + r return collisison.NONE if d > l + r
return collisions.EMBEDDED if d < r return collisions.EMBEDDED if d < r
# k = 1 for clockwise motion, -1 otherwise
k = 1 k = 1
# move into a calculation within the range of [0,2pi] # move into a calculation within the range of [0,2pi]
alpha -= theta0 alpha -= theta0
Expand All @@ -131,7 +132,8 @@ collisions = (->
while alpha > pi2 while alpha > pi2
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 return collisions.NONE if alpha > omega


# now perform the appropriate collision check # now perform the appropriate collision check
Expand All @@ -141,14 +143,15 @@ collisions = (->
(alpha - k * Math.acos((l*l + d*d - r*r) / (2*l*d))) / omega (alpha - k * Math.acos((l*l + d*d - r*r) / (2*l*d))) / omega


# Detect collision between rotating line and moving or stationary circle. # Detect collision between rotating line and moving or stationary circle.
# This method is quite different than angularCollisionLineCircle() - # This method is quite different than angularCollisionLineCircle() which only
# it is from the MPFP CDROM collision simulation Director code. # deals with stationary circles.
# NB: No support for cases where the rotating line is offset from its rotating point. # 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 {Line} line shape
# @param {Circle} circle shape # @param {Circle} circle shape
# @param {Number} ts current timestep # @param {Number} ts current timestep
# @return {Object} # @return {Object}
# t: time to collision (0 if collision detected) # t: 0 if collision detected, collisions.NONE if not
# moment1: no idea # moment1: no idea
# moment2: no idea # moment2: no idea
angularCollisionLineCircle2 = (line, circle, ts) -> angularCollisionLineCircle2 = (line, circle, ts) ->
Expand All @@ -169,12 +172,26 @@ collisions = (->
n1 = n1.x(-1) n1 = n1.x(-1)
n2 = n2.x(-2) n2 = n2.x(-2)
startDist = -startDist startDist = -startDist

# check if circle crosses the line noColl = {t: collisions.NONE}
r = circle.radius r = circle.radius
if ((startDist - r) * (n2.dot(endPos) - r) < 0)
# check if intersection overlaps the line # debug shit
if ((startPos.subtract(n1.x(r)).mag() <= line.length) || 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)) (endPos.subtract(n2.x(r)).mag() <= line.length))
return {t: 0, return {t: 0,
normal: n1.x(-1), normal: n1.x(-1),
Expand All @@ -184,7 +201,7 @@ collisions = (->


# otherwise, check for intersection with line endpoints # otherwise, check for intersection with line endpoints
# TODO: # TODO:
{t: collisions.NONE} noColl


isImpendingCollision = (ts) -> isImpendingCollision = (ts) ->
0 < ts <= 1 0 < ts <= 1
Expand Down
2 changes: 1 addition & 1 deletion source/js/mylibs/vec.js.coffee
Expand Up @@ -21,7 +21,7 @@ Vector.isClockwise = (v, p) ->
# @param {String} unit d|r degrees or radians # @param {String} unit d|r degrees or radians
# @return a 3D vector pointing at ang clockwise from the positive x-axis # @return a 3D vector pointing at ang clockwise from the positive x-axis
Vector.directionVector = (angle, unit='r') -> 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]) $V([Math.cos(angle), Math.sin(angle), 0])


# Instance functions # Instance functions
Expand Down
21 changes: 13 additions & 8 deletions source/js/rot_collisions.js.coffee
Expand Up @@ -12,7 +12,7 @@


$(document).ready -> $(document).ready ->
canvas = new Canvas($("#maincanvas").get(0)) canvas = new Canvas($("#maincanvas").get(0))
#canvas.setOrigin('topleft') canvas.setOrigin('bottomleft')
elapsed = lastTime = startingAngle = startingTheta = 0 elapsed = lastTime = startingAngle = startingTheta = 0


angle = 0 angle = 0
Expand All @@ -31,12 +31,16 @@ $(document).ready ->
$('#info').html('') $('#info').html('')


drawText = (text) -> drawText = (text) ->
canvas.inContext -> canvas.inContext((ctxt) ->
ctxt = canvas.context() # 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.fillStyle = 'black'
ctxt.font = '12px Arial sans-serif' ctxt.font = '12px Arial sans-serif'
ctxt.textBaseline = 'top' ctxt.textBaseline = 'top'
ctxt.fillText(text, canvas.width/2, 10) ctxt.fillText(text, canvas.width/2, 20)
)


drawScene = () -> drawScene = () ->
canvas.clear() canvas.clear()
Expand All @@ -48,7 +52,7 @@ $(document).ready ->
when 'Line' when 'Line'
canvas.inContext -> canvas.inContext ->
canvas.translate obj.pos.e(1), obj.pos.e(2) 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.translate(-obj.pos.e(1), -obj.pos.e(2))
canvas.drawLine(obj) canvas.drawLine(obj)


Expand All @@ -57,8 +61,9 @@ $(document).ready ->
canvas.drawCircle obj canvas.drawCircle obj


setupScene = -> setupScene = ->
startingAngle = $("input[name=sAngle]").val() || 20 startingAngle = $("input[name=sAngle]").val() || 0
angularVel = $("input[name=angVel]").val() || 15 angularVel = $("input[name=angVel]").val() || 0
$('#sangle').html("#{startingAngle} deg.")
startingTheta = 90 - startingAngle startingTheta = 90 - startingAngle


# draw rotating line # draw rotating line
Expand All @@ -74,7 +79,7 @@ $(document).ready ->
color: 'blue' color: 'blue'
}) })
if ballMoving = $("input[name=movingBall]:checked").val() == "1" 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 # these two variable can be computed dynamically if the ball is moving
ballDistance = ball.pos.subtract(line.pos).mag() ballDistance = ball.pos.subtract(line.pos).mag()
Expand Down
3 changes: 2 additions & 1 deletion source/rotation_cols.html.erb
Expand Up @@ -8,7 +8,8 @@
<div id="main" role="main"> <div id="main" role="main">
<ul id="controls"> <ul id="controls">
<li> <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>
<li> <li>
Angular velocity: <input name="angVel" size="3" value="15"/> degrees/second Angular velocity: <input name="angVel" size="3" value="15"/> degrees/second
Expand Down

0 comments on commit 4d3426f

Please sign in to comment.