Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

figured out angular velocity and rotating line + stationary circle co…

…llisions
  • Loading branch information...
commit a421701df80ee34f5f75a9fbbb71cbe79a6cab68 1 parent 58d6d45
@simianarmy authored
View
7 source/js/bitmap.js.coffee
@@ -1,3 +1,6 @@
+# @module bitmapDemo
+
+#= require ./mylibs/Math
#= require ./mylibs/Polygon
#= require ./mylibs/collisions
@@ -75,7 +78,7 @@ bitmapDemo = (bitmap) ->
lastRot += 45
context.save()
context.translate(imgX, imgY)
- context.rotate degreesToRadians(lastRot)
+ context.rotate Math.degreesToRadians(lastRot)
context.drawImage(img, 0, 0)
context.restore()
@@ -85,7 +88,7 @@ bitmapDemo = (bitmap) ->
context.save()
context.translate(imgX, imgY)
context.scale 0.5, 0.5
- context.rotate degreesToRadians(lastRot)
+ context.rotate Math.degreesToRadians(lastRot)
context.drawImage(img, 0, 0)
context.restore()
View
7 source/js/mylibs/Canvas.js.coffee
@@ -17,6 +17,8 @@ Canvas = (() ->
@width = canvasEl.width
@height = canvasEl.height
+ context = () -> @ctxt
+
# Set the origin of the canvas
# @param {String} id (topleft | bottomleft)
setOrigin = (id) ->
@@ -24,7 +26,9 @@ Canvas = (() ->
# translate world for origin at bottom left
@ctxt.scale(1, -1)
@ctxt.translate(0, -@height)
-
+ else
+ # bottom left is default
+
# Draw a circle on the canvas
# @param {Circle} c a Circle object
drawCircle = (c) ->
@@ -96,6 +100,7 @@ Canvas = (() ->
drawLine: drawLine
drawEllipse: drawEllipse
inContext: inContext
+ context: context
rotate: rotate
translate: translate
clear: clear
View
28 source/js/mylibs/Math.js.coffee
@@ -0,0 +1,28 @@
+# @module Math
+#
+# Extensions to the built-in Math module
+
+#= require ./vec
+
+# angularVelocity
+#
+# Angular velocity of a particle in 2 dimensions
+# @param {Vector} v velocity vector of the particle
+# @param {Vector} r position vector of the particle (from origin or rotation)
+# @param {Float} theta angle of rotation (in radians)
+# @return {Float} the angular velocity
+Math.angularVelocity = (v, r, theta) ->
+ (v.mag() * Math.sin(theta)) / r.mag()
+
+# Returns a random float between min and max
+# Using Math.round() will give you a non-uniform distribution!
+Math.getRandom = (min, max) ->
+ (Math.random() * (max - min + 1)) + min
+
+# Returns a random integer between min and max
+# Using Math.round() will give you a non-uniform distribution!
+Math.getRandomInt = (min, max) ->
+ Math.floor(Math.random() * (max - min + 1)) + min
+
+Math.degreesToRadians = (degrees) ->
+ degrees * Math.PI / 180
View
5 source/js/mylibs/PoolTable.coffee
@@ -1,5 +1,6 @@
-# PoolTable.coffee
+# @module PoolTable
+#= require ./Math
#= require ./vec
#= require ./collisions
#= require ./Line
@@ -319,7 +320,7 @@ PoolTable = (ctxt, opts) ->
context.save()
context.translate balls[0].pos.e(1), balls[0].pos.e(2)
- context.rotate degreesToRadians(cueRotDegrees)
+ context.rotate Math.degreesToRadians(cueRotDegrees)
context.translate ogCuePos.e(1), ogCuePos.e(2)
context.drawImage(cueImg, 0, 0, cueImg.width, cueImg.height)
context.restore()
View
19 source/js/mylibs/Shape.js.coffee
@@ -9,9 +9,14 @@ class Shape
@mass = @efficiency = 1.0
@collisionNormal = null # vector
@[x] = val for x, val of opts
+ # initial speed, angular speed, etc
@velocity ?= Vector.Zero(3)
@displacement ?= Vector.Zero(3)
@direction ?= Vector.Zero(3)
+ @speed ?= 0
+ @rotation ?= 0
+ @angSpeed ?= 0
+ @rotDirection ?= 1
move: (vec) ->
@pos = @pos.add(vec)
@@ -20,6 +25,20 @@ class Shape
y: -> @pos.e(2)
z: -> @pos.e(3)
+ angularDirection: -> @rotDirection
+
+ # calculate shape's angular velocity
+ # @return {Number} pseudovector omega with sign dependent
+ # on direction of rotation around axis (clockwiseNormal)
+ angularVelocity: ->
+ @angularDirection() * @angSpeed
+
+ # set the shape's angular velocity
+ # @param {Number} v degrees/second
+ setAngularVelocity: (v) ->
+ @rotDirection = if v > 0 then 1 else -1
+ @angSpeed = Math.abs(v) # * 180 / Math.PI
+
# prototype properties
toString: ->
kvs = for key, val of @ when val? and typeof(val) != 'function'
View
11 source/js/mylibs/circles_scene.js.coffee
@@ -1,8 +1,9 @@
# @module scene
# Module for moving circles in a box
-#= require 'libs/raphael-min'
+#= require libs/raphael-min
#= require ./vec
+#= require ./Math
#= require ./collisions
#= require ./Line
#= require ./Circle
@@ -63,15 +64,15 @@ scene = (opts) ->
# Return a random circle color
randomCircleColor = ->
- CIRCLE_COLORS[getRandomInt(1, CIRCLE_COLORS.length)-1]
+ CIRCLE_COLORS[Math.getRandomInt(1, CIRCLE_COLORS.length)-1]
# Return a y-value for a circle
circleY = ->
- if freeY then getRandom(-MAX_VELOCITY_Y, MAX_VELOCITY_Y) else 0
+ if freeY then Math.getRandom(-MAX_VELOCITY_Y, MAX_VELOCITY_Y) else 0
# Create and return a new (free) circle
createFreeCircle = (x, y, i) ->
- velx = getRandom(-MAX_VELOCITY_X, MAX_VELOCITY_X)
+ velx = Math.getRandom(-MAX_VELOCITY_X, MAX_VELOCITY_X)
new Circle(x, y, 0, {
radius: CIRCLE_RADIUS
velocity: Vector.create([velx, circleY(), 0])
@@ -91,7 +92,7 @@ scene = (opts) ->
if diff > 0
# Add balls
for i in [1..diff]
- circles.push createFreeCircle(getRandom(0, bw), bh/2, i)
+ circles.push createFreeCircle(Math.getRandom(0, bw), bh/2, i)
else
# remove balls
circles.pop() for i in [1..(circles.length-nballs)]
View
42 source/js/mylibs/collisions.js.coffee
@@ -2,7 +2,8 @@
#= require ../libs/sylvester
-collisions = ->
+collisions = {}
+collisions = (->
# constants
collisions.NONE = -1
collisions.EMBEDDED = -2
@@ -106,6 +107,39 @@ collisions = ->
t = intersectionTime(c.pos.add(r), c.displacement, wall.pos, wall.vec)
[t, collisionNormal]
+ # Check for collision between rotating line and circle
+ # Anglular values should 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
+ # @param {Number} r ball radius
+ # @param {Number} d distance of line origin to ball center
+ # @param {Number} alpha angle of vertical and line to ball center
+ angularCollisionLineCircle = (theta0, omega, l, r, d, alpha) ->
+ return collisison.NONE if d > l + r
+ return collisions.EMBEDDED if d < r
+ k = 1
+ # move into a calculation within the range of [0,2pi]
+ alpha -= theta0
+ if omega < 0
+ omega = -omega
+ alpha = -alpha
+ k = -1
+
+ pi2 = Math.PI * 2
+ while alpha < 0
+ alpha += pi2
+ while alpha > pi2
+ alpha -= pi2
+
+ # check if there is a possible collision
+ # return collisions.NONE if alpha > omega
+ # now perform the appropriate collision check
+ if d*d <= (l*l + r*r)
+ (alpha - k * Math.asin(r / d)) / omega
+ else
+ (alpha - k * Math.acos((l*l + d*d - r*r) / (2*l*d))) / omega
+
isImpendingCollision = (ts) ->
0 < ts <= 1
@@ -321,8 +355,10 @@ collisions = ->
isImpendingCollision,
resolveCollision,
resolveInelasticCollisionFixed,
+ angularCollisionLineCircle,
pointInTriangle,
pointInPolygon}
-
+)()
+
root = exports ? window
-root.collisions = collisions()
+root.collisions = collisions
View
3  source/js/mylibs/vec.js.coffee
@@ -9,7 +9,7 @@
# isClockwise
#
-# Determines if object at p with velocity v is moving clockwise about the origin
+# Determines if object starts at p with velocity v is moving clockwise about the origin
# @returns {Boolean}
Vector.isClockwise = (v, p) ->
n = p.clockwiseNormal()
@@ -93,4 +93,3 @@ Vector::clockwiseNormal = ->
Vector::moment = (p) ->
@clockwiseNormal().dot(p)
-
View
18 source/js/plugins.js
@@ -31,21 +31,3 @@ window.requestAnimFrame = (function() {
window.setTimeout(callback, 1000/60);
};
})();
-
-// Returns a random float between min and max
-// Using Math.round() will give you a non-uniform distribution!
-function getRandom(min, max)
-{
- return (Math.random() * (max - min + 1)) + min;
-}
-
-// Returns a random integer between min and max
-// Using Math.round() will give you a non-uniform distribution!
-function getRandomInt(min, max)
-{
- return Math.floor(Math.random() * (max - min + 1)) + min;
-}
-
-function degreesToRadians(degrees) {
- return degrees * Math.PI / 180
-}
View
80 source/js/rot_collisions.js.coffee
@@ -4,31 +4,54 @@
#= require ./plugins
#= require mylibs/vec
+#= require mylibs/Math
#= require mylibs/Line
#= require mylibs/Circle
#= require mylibs/Canvas
+#= require mylibs/collisions
$(document).ready ->
canvas = new Canvas($("#maincanvas").get(0))
- canvas.setOrigin('topleft')
- elapsed = lastTime = 0
+ #canvas.setOrigin('topleft')
+ elapsed = lastTime = lastAngle = 0
+ startingAngle = 20
+ startingTheta = 90 - startingAngle
angle = 0
- angleInc = .3
+ angularVel = 15 # degrees / second
lineLength = 200
line = null
ball = null
objects = []
paused = true
-
- drawScene = (objects, dt) ->
+ angVel = tanVel = ballDistance = ballAngle = collisionIn = 0
+
+ drawInfo = (text) ->
+ $('#info').append(text + '<br/>')
+
+ drawText = (text) ->
+ canvas.inContext ->
+ ctxt = canvas.context()
+ ctxt.fillStyle = 'black'
+ ctxt.font = '12px Arial sans-serif'
+ ctxt.textBaseline = 'top'
+ ctxt.fillText(text, canvas.width/2, 10)
+
+ drawScene = () ->
canvas.clear()
+ if collisionIn >= 0
+ drawText "Collision in #{collisionIn}"
+ else if collisionIn == collisions.EMBEDDED
+ drawText "EMBEDDED"
+ else
+ drawText "No collision"
+
for obj in objects
switch obj.name
when 'Line'
canvas.inContext ->
canvas.translate obj.pos.e(1), obj.pos.e(2)
- canvas.rotate(degreesToRadians(angle))
+ canvas.rotate(Math.degreesToRadians(-obj.rotation))
canvas.translate(-obj.pos.e(1), -obj.pos.e(2))
canvas.drawLine(obj)
@@ -38,26 +61,51 @@ $(document).ready ->
setupScene = ->
# draw rotating line
- angle = 90
+ angle = lastAngle = startingAngle
line = new Line(canvas.width/2, canvas.height/2, lineLength, 0, {
- color: 'black'
+ color: 'black',
+ rotation: startingAngle
})
# draw stationary circle
- ball = new Circle(canvas.width/2+lineLength/2, canvas.height/2+40, 0, {
- radius: lineLength/8
+ ball = new Circle(canvas.width/2+lineLength/1.2, canvas.height/2, 0, {
+ radius: lineLength/8,
color: 'blue'
})
+ # these two variable can be computed dynamically if the ball is moving
+ ballDistance = ball.pos.subtract(line.pos).mag()
+ ballAngle = Math.degreesToRadians 90
+ line.setAngularVelocity(angularVel)
+ angVel = Math.degreesToRadians(line.angularVelocity())
objects = [line, ball]
+ drawInfo("Theta0: #{startingTheta}")
+ drawInfo("Line length: #{lineLength}")
+ drawInfo("rotation axis: #{line.pos.inspect()}")
+ drawInfo("ball pos: #{ball.pos.inspect()}")
+ drawInfo("ball radius: #{ball.radius}")
+ drawInfo("ball angle: #{ballAngle}")
+ drawInfo("axis-ball distance: #{ballDistance}")
+ drawInfo("ang vel: #{angVel}")
+
+ updateObjects = (t) ->
+ # update the line's rotation
+ rot = line.rotation - line.angularVelocity() * (t / 1000)
+ if Math.abs(rot) >= 360
+ rot = 0
+ line.rotation = rot
+
+ checkCollisions = (t) ->
+ collisionIn = collisions.angularCollisionLineCircle(Math.degreesToRadians(90-line.rotation),
+ angVel, lineLength, ball.radius, ballDistance, ballAngle)
+
# animate all objects
update = ->
# Pass latest timestep to the collision detection function
timeNow = new Date().getTime()
if lastTime != 0
elapsed = timeNow - lastTime
- angle -= angleInc
- if Math.abs(angle) >= 360
- angle = 0
+ updateObjects(elapsed)
+ checkCollisions()
lastTime = timeNow
@@ -66,12 +114,16 @@ $(document).ready ->
requestAnimFrame(tick)
unless paused
update()
- drawScene(objects, elapsed)
+
+ drawScene(objects, elapsed)
# event handlers
$('canvas').click ->
+ checkCollisions elapsed
paused = !paused
setupScene()
+ checkCollisions()
+ drawScene(objects, 0)
tick()
View
4 source/rotation_cols.html.erb
@@ -12,8 +12,8 @@
</ul>
Click on canvas to play or pause
<canvas id="maincanvas" width="800" height="600"></canvas>
- <p>
- </p>
+ <div id="info">
+ </div>
</div>
<footer>
Source:
Please sign in to comment.
Something went wrong with that request. Please try again.