Related
Here is the problem. We have two points (spheres) in xyz, with this info:
1- x,y,z => The center of the object is currently located at
2- r => The collision radius of the object
3- Vx, Vy, Vz => object is traveling along the vector. If that vector is (0,0,0), the object is stationary.
Note: The radii and positions are in meters and velocities are measured in meters per second.
Question: For each test, output a single line containing the time (in seconds) since the start of the test at which the two objects will first collide. If they never collide, print No collision instead.
I want to know about the formula of calculation this time. Any idea would be appreciated.
Examples:
1-
xyz(1): -7 5 0
v(1): -1 0 3
r(1): 3
xyz(2): 10 7 -6
v(2): -2 0 4
r(2): 6
t: 8.628 // this is the answer
2-
xyz(1): 10 3 -10
v(1): -9 3 -8
r(1): 5
xyz(2): 2 0 0
v(2): 6
r(2): -4 3 -10
t: 0.492 // this is the answer
To simplify problem, let us use Halileo's principle. Consider the first object as base point, so the second objects moves relative to it.
Put the first object position in coordinate origin.
Subtract the first object initial coordinates from the second one coordinates, do the same for velocity components
x2_0 = x2_0 - x1_0 (same for y,z)
Vx2 = Vx2 - Vx1 (same for y,z)
Now we have second center coordinates against time
x = x2_0 + Vx2 * t
y = y2_0 + Vy2 * t
z = z2_0 + Vz2 * t
and squared distance to origin:
dd = x*x + y*y + z*z =
(x2_0 + Vx2 * t)^2 + ... =
x2_0^2 + 2*x2_0*Vx2*t + Vx2^2*t^2 + ...
and we need to calculate when dd becomes equal to squared radius sum (r1+r2)^2
t^2 * (Vx2^2+Vy2^2+Vz2^2) + t*(2*x2_0*Vx2+2*y2_0*Vy2+2*z2_0*Vz2) +
x2_0^2 + y2_0^2 + y2_0^2 - (r1+r2)^2 = 0
Solve this quadratic equation for t, get 0,1 or 2 solutions.
Case of 0 solutions - no collision
Case of 1 solution with positive t - moment of touching
Case of two solutions - get smaller positive t for the moment of collision.
Negative values of t mean collision "in the past", before the start of the test
Quick test in Python (ideone)
from math import sqrt, isclose
def collisiontime(x1,y1,z1,vx1,vy1,vz1,r1, x2,y2,z2,vx2,vy2,vz2,r2):
x2 -= x1
y2 -= y1
z2 -= z1
vx2 -= vx1
vy2 -= vy1
vz2 -= vz1
a = vx2**2 + vy2**2 + vz2**2
b = 2*x2*vx2 + 2*y2*vy2 + 2*z2*vz2
c = x2**2 + y2**2 + z2**2 - (r1+r2)**2
D = b**2-4*a*c
if D < 0:
return None
if isclose(D, 0):
return -b/2/a
return (-b - sqrt(D)) / 2 /a, (-b + sqrt(D)) / 2 /a
print(collisiontime(0, 0, 0, 2, 0, 0, 2, 25, 0, 0, -3, 0, 0, 3)) # 1=> <=2
print(collisiontime(0, 0, 0, 2, 0, 0, 2, 25, 5, 0, 1, 0, 0, 3)) # 1==> 2=> chase with touching
print(collisiontime(-7, 5, 0,-1, 0, 3, 3, 10, 7, -6, -2, 0, 4, 6))
print(collisiontime(10, 3, -10,-9, 3, -8,5, 2, 0, 0, -4, 3, -10, 6))
(4.0, 6.0)
25.0
(8.627718676730986, 14.372281323269014)
(0.4917797757201004, 3.646151258762658)
I transformed a vector which lays on the transformation matrix's eigen space using Object3D.applyMatrix4. I expected it not to move because the eigen value was 1, or at least stay on the eigen span, but it moved to an unexpected place.
I've made an sample project: stackblitz
But below is probably all the code you would need to examine
let pointGeo = new THREE.Geometry()
pointGeo.vertices = [new THREE.Vector3(1,-1,1)]
let pmat = new THREE.PointsMaterial({color: 0x00f0f0, size: 0.3})
let pointObj = new THREE.Points(pointGeo, pmat)
let matrix = new THREE.Matrix4()
matrix.set( 1, 3, 3, 0,
-3, -5, -3, 0,
3, 3, 1, 0,
0, 0, 0, 1)
pointObj.applyMatrix4(matrix)
Specifically I'm transforming a point (1, -1, 1) (where the purple square is) with a matrix. Multiplication by the matrix shouldn't change the value. (double checked by hand calculating) But it moves it to where the blue square is.
Is there other stages where some other transformation is applied? What am I missing here?
I've found that Object3D.applyMatrix4 wasn't the right function for explicitly defining local matrix. I tried setting Object3D.matrix property directly and it worked. I changed code like this:
o.matrix = mat
o.matrixAutoUpdate = false
o.updateMatrixWorld(true)
here is the source for applyMatrix4... are you hand applying your matrix exactly like this:
applyMatrix4 ( m ) {
var x = this.x, y = this.y, z = this.z;
var e = m.elements;
var w = 1 / ( e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] );
this.x = ( e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] ) * w;
this.y = ( e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] ) * w;
this.z = ( e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] ) * w;
return this;
},
```
I'm trying to understand the rotation of the matrices using WebGL.
I got this mat4() matrix and I have to apply these transformations :
m = translate(torsoHeight+1*headHeight, 5, 0.0);
m = mult(m, rotate(theta[head1Id], 1, 0, 0))
m = mult(m, rotate(theta[head2Id], 0, 1, 0));
m = mult(m, translate(0.0, -0.5*headHeight, 0.0));
figure[headId] = createNode( m, head, leftUpperArmId, null);
break;
I did not understand exactly how the mult function works. The first parameter is my matrix.
The theta[] is built in this way :
var theta = [0, 0, 0, 0, 0, 0, 180, 0, 180, 0, 0];
and
var headId = 1;
var head1Id = 1;
var head2Id = 10;
Am I right if I thought that the second parameter is another matrix build with the rotate() function ? In this case how does the rotate function work ?
rotate and translate are functions that create matrices.
rotate looks like it's arguments are (angle, vectorx, vectory, vectorz) to create a matrix rotating points around the given vectory.
mult is the standard mathematical multiplication for 4x4 matrices.
You probably should dig in linear algebra tutorials such as https://open.gl/transformations
OSX 10.8.3, Python, PyOpenGL.
I'm trying to put together a basic terrain-drawing function in PyOpenGL using VBOs. Having a couple of problems I don't know how to resolve, mostly because I don't fully understand the way VBOs work. This is a basic test sandbox I started when I had too much difficulty changing my project over to VBOs, so it's sloppy in places (see: frame counter).
I've hardcoded a basic 3x3 terrain array and corresponding index array, but it seems to be only drawing two of three rows (it does the y=0 row and y=0.5 but not y=2.0). I'm not entirely comfortable with numpy, so that might be the cause.
The contents of the colour array have only erratic bearing on the final colours: assigning numpy.zeros() to the array produces a black screen, assigning numpy.ones() produces green and purple stripes rather than the white surface I'm expecting. Was initially using random colours but that didn't do anything different from ones(). I don't really understand how OpenGL is supposed to determine that this is a color VBO rather than anything else.
The triangle-drawing algorithm will be problematic, when I get to it - I don't know how best to draw multiple rows without using GL_PRIMITIVE_RESTART, which isn't available in GLUT (I'd rather only change to GLFW or similar as a last resort). Right now, I'm not too concerned about it. Drawing in strips like this isn't quite what I want: http:// www.matrix44.net/cms/notes/opengl-3d-graphics/understanding-gl_triangle_strip (sorry, don't have 10 reputation)
How it currently looks, when rotating: http://i.imgur.com/4Db4qYJ.png
Have been using http://www.mbsoftworks.sk/index.php?page=tutorials&series=1&tutorial=8 as my most successful guide.
I'd really appreciate some guidance with this - no single resource I've found on the web has explained it all, and this isn't exactly a complex topic.
from OpenGL.GL import *
from OpenGL.GLUT import *
from OpenGL.GLU import *
from OpenGL.arrays import vbo
from math import sin, cos, tan, radians, sqrt
from numpy import *
from random import random
hWindow = 0
frameno = 0
sr2 = sqrt(0.75)
def InitGL( nWidth, nHeight ):
glClearColor( 0.0, 0.0, 0.0, 0.0 )
glClearDepth( 1.0 )
glDepthFunc( GL_LESS )
glEnable( GL_DEPTH_TEST )
glShadeModel( GL_SMOOTH )
print str(glGetString( GL_VERSION ))
global terrain_vbo, index_vbo, color_vbo
# these two will produce a working (huge) triangle
#terrain_array = array([[ 0,0,0 ], [ 9,0,0 ], [ 0,9,0 ], [ 0,0,9 ]], dtype=float32)
#index_array = array([ 0,1, 0,2, 0,3, 2,3, 2,1],dtype=ubyte)
terrain_array = array([ [[0,0,0], [0,0,1], [0,0,2]],
[[1,0.5,0], [1,0.5,1], [1,0.5,2]],
[[2,2,0], [2,2,1], [2,2,2]] ], dtype=float32)
index_array = array([ 0, 3, 1, 4, 2, 5,
8, 4, 7, 3, 6 ], dtype=ubyte )
color_array = zeros( (9, 3) )
for i in range(9):
color_array[i] += (1.0, 1.0, 1.0)
'''
color_array[0] = [1.0, 0.0, 0.0]
color_array[1] = [0.0, 1.0, 0.0]
color_array[2] = [0.0, 0.0, 1.0]
color_array[3] = [1.0, 1.0, 1.0]
color_array[4] = [1.0, 1.0, 0.0]
'''
#for i in range(len(terrain_array)):
#index_array[i][0] = i
for i in range(len(terrain_array)):
print terrain_array[i]
terrain_vbo = vbo.VBO(terrain_array)
#index_vbo = vbo.VBO( zeros((1,3)), target=GL_ELEMENT_ARRAY_BUFFER )
index_vbo = vbo.VBO(index_array, target=GL_ELEMENT_ARRAY_BUFFER)
color_vbo = vbo.VBO(color_array)
ResizeGLScene( nWidth, nHeight )
def ResizeGLScene( nWidth, nHeight ):
# prevent a divide-by-zero error if the window is too small
if nHeight == 0:
nHeight = 1
# reset the current viewport and recalculate the perspective transformation
# for the projection matrix
glViewport( 0, 0, nWidth, nHeight )
glMatrixMode( GL_PROJECTION )
glLoadIdentity( )
gluPerspective( 45.0, float( nWidth )/float( nHeight ), 0.1, 100.0 )
# return to the modelview matrix mode
glMatrixMode( GL_MODELVIEW )
#
# Draw the scene.
#
def DrawGLScene( ):
# clear the screen and depth buffer
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT )
# reset the matrix stack with the identity matrix
glLoadIdentity( )
global frameno
frameno = frameno + 1
glTranslatef( 0.0, -0.2, -2.0 )
glRotatef( frameno/6, 0.0, sr2, 0.0 )
# draw code
#glTranslatef( 0.0, 0.0, -3.0 )
glScalef( 0.5, 0.5, 0.5 )
glColor3f( 1.0, 1.0, 1.0 )
global index_vbo, terrain_vbo, color_vbo
color_vbo.bind()
glEnableClientState( GL_COLOR_ARRAY )
glColorPointer( 3, GL_FLOAT, 0, color_vbo )
terrain_vbo.bind()
glEnableClientState(GL_VERTEX_ARRAY)
glVertexPointer( 3, GL_FLOAT, 0, None )
index_vbo.bind()
glDrawElements(GL_TRIANGLE_STRIP, 6, GL_UNSIGNED_BYTE,None)
glDisableClientState( GL_COLOR_ARRAY )
glDisableClientState( GL_VERTEX_ARRAY )
index_vbo.unbind()
terrain_vbo.unbind()
color_vbo.unbind()
glutSwapBuffers( )
def KeyPressed( key, x, y ):
key = ord(key)
if key == 27:
glutDestroyWindow( hWindow )
sys.exit( )
def main( ):
global hWindow
# initialise GLUT and a few other things
glutInit( "" )
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH )
glutInitWindowSize( 640, 480 )
glutInitWindowPosition( 0, 0 )
# create our window
hWindow = glutCreateWindow( "VBO testing" )
# setup the display function callback
glutDisplayFunc( DrawGLScene )
# go full-screen if we want to
glutFullScreen( )
# setup the idle function callback -- if we idle, we just want to keep
# drawing the screen
glutIdleFunc( DrawGLScene )
# setup the window resize callback -- this is only needed if we arent going
# full-screen
glutReshapeFunc( ResizeGLScene )
# setup the keyboard function callback to handle key presses
glutKeyboardFunc( KeyPressed )
# call our init function
InitGL( 640, 480 )
# enter the window's main loop to set things rolling
glutMainLoop( )
print "Hit ESC key to quit."
main( )
I want to write a ruby program that steps over space in an arbitrary number of dimensions.
In 3 dimensions what I'm doing looks like this:
x_range = (-1..1)
y_range = (-1..1)
z_range = (-1..1)
step_size = 0.01
x_range.step(step_size) do |x|
y_range.step(step_size) do |y|
z_range.step(step_size) do |z|
# do something with the point x,y,z
end
end
end
I want to do the same for n dimensions
This is the first thing that comes to mind for me:
def enumerate(nDimens, bottom, top, step_size)
bottom = (bottom / step_size).to_i
top = (top / step_size).to_i
range = (bottom..top).to_a.map{ |x| x * step_size }
return range.repeated_permutation(nDimens)
end
stepper = enumerate(4, -1, 1, 0.1)
loop do
puts "#{stepper.next()}"
end
This produces:
[-1.0, -1.0, -1.0, -1.0]
[-1.0, -1.0, -1.0, -0.9]
[-1.0, -1.0, -1.0, -0.8]
# Lots more...
[1.0, 1.0, 1.0, 0.8]
[1.0, 1.0, 1.0, 0.9]
[1.0, 1.0, 1.0, 1.0]
This assumes all dimensions have the same range, but it'd be easy to adjust if for some reason that doesn't hold.
Recursion could solve this kind of problem easily and perfectly. Code below fits any number of dimensions, and also various length of ranges.
def traversal(ranges, step_size, conjunction = [], &blk)
ranges[0].step(step_size) do |x|
conjunction.push(x)
if ranges.size > 1
traversal(ranges[1..-1], step_size, conjunction, &blk)
else
blk.call(conjunction) if block_given?
conjunction.pop
end
end
conjunction.pop
end
Run: (dimension = 4, length = 3, 3, 4, 2)
x = (1..3)
y = (4..6)
z = (7..10)
w = (100..101)
test_data = [x, y, z, w]
step_size = 1
traversal(test_data, step_size) do |x|
puts "Point: #{x.join('-')}"
end
Output: (72 points in total, which is 3 * 3 * 4 * 2)
Point: 1-4-7-100
Point: 1-4-7-101
Point: 1-4-8-100
Point: 1-4-8-101
Point: 1-4-9-100
Point: 1-4-9-101
Point: 1-4-10-100
Point: 1-4-10-101
Point: 1-5-7-100
Point: 1-5-7-101
Point: 1-5-8-100
Point: 1-5-8-101
Point: 1-5-9-100
Point: 1-5-9-101
Point: 1-5-10-100
Point: 1-5-10-101
Point: 1-6-7-100
Point: 1-6-7-101
Point: 1-6-8-100
Point: 1-6-8-101
Point: 1-6-9-100
Point: 1-6-9-101
Point: 1-6-10-100
Point: 1-6-10-101
Point: 2-4-7-100
Point: 2-4-7-101
Point: 2-4-8-100
Point: 2-4-8-101
Point: 2-4-9-100
Point: 2-4-9-101
Point: 2-4-10-100
Point: 2-4-10-101
Point: 2-5-7-100
Point: 2-5-7-101
Point: 2-5-8-100
Point: 2-5-8-101
Point: 2-5-9-100
Point: 2-5-9-101
Point: 2-5-10-100
Point: 2-5-10-101
Point: 2-6-7-100
Point: 2-6-7-101
Point: 2-6-8-100
Point: 2-6-8-101
Point: 2-6-9-100
Point: 2-6-9-101
Point: 2-6-10-100
Point: 2-6-10-101
Point: 3-4-7-100
Point: 3-4-7-101
Point: 3-4-8-100
Point: 3-4-8-101
Point: 3-4-9-100
Point: 3-4-9-101
Point: 3-4-10-100
Point: 3-4-10-101
Point: 3-5-7-100
Point: 3-5-7-101
Point: 3-5-8-100
Point: 3-5-8-101
Point: 3-5-9-100
Point: 3-5-9-101
Point: 3-5-10-100
Point: 3-5-10-101
Point: 3-6-7-100
Point: 3-6-7-101
Point: 3-6-8-100
Point: 3-6-8-101
Point: 3-6-9-100
Point: 3-6-9-101
Point: 3-6-10-100
Point: 3-6-10-101
If ranges are not too big you can do something like this:
n = 5 # 5 dimentions
x = (-1..1).to_a
x.product(*[x]*(n-1)).each {|i| p i}
Result:
[-1, -1, -1, -1, -1]
[-1, -1, -1, -1, 0]
[-1, -1, -1, -1, 1]
[-1, -1, -1, 0, -1]
[-1, -1, -1, 0, 0]
[-1, -1, -1, 0, 1]
[-1, -1, -1, 1, -1]
[-1, -1, -1, 1, 0]
[-1, -1, -1, 1, 1]
[-1, -1, 0, -1, -1]
[-1, -1, 0, -1, 0]
# skipped
This is what you could do... here is an example iterator.
#next(l[dim] array of lower ranges ,h[dim] = upper ranges, step[dim], dim = dimensions -1, curr[dim] = current state in dim dimensions )
def nextx(l ,h, step, dim, curr)
x = dim
update= false
while (update==false)
if curr[x] == h[x]
if x > 0
x = x-1
else
exit
end
else
curr[x]= curr[x]+step[x]
while (x < dim)
x = x+1
curr[x] = l[x]
end
update = true
end
end
return curr
end
l = [0,0,0]
h = [3,3,3]
step = [1,1,1]
currx = [0,0,2]
i = 0
while i < 70
currx = nextx(l, h, step, 2, currx)
puts currx.inspect
i=i+1
end
This is typically encountered in algorithms that explore a search space. The do loops are creating a product space from the one dimensional ranges.
First pack as many ranges are needed into an array e.g.
search_space_1Ds = [x_range.step(step_size).to_a, y_range.step(step_size).to_a, z_range.step(step_size).to_a]
then the following will work with an arbitrary number of dimensions.
search_space = search_spaces_1Ds.shift.product(*search_space_1Ds)
search_space.map do |vec|
# calculate something with vec
end
This implementation is not only concise, it makes it very clear what your algorithm is doing; enumerating through a search space that is created as the product space of the one dimensional search spaces.