  C RUBY-ON-RAILS MYSQL ASP.NET DEVELOPMENT RUBY .NET LINUX SQL-SERVER REGEX WINDOWS ALGORITHM ECLIPSE VISUAL-STUDIO STRING SVN PERFORMANCE APACHE-FLEX UNIT-TESTING SECURITY LINQ UNIX MATH EMAIL OOP LANGUAGE-AGNOSTIC VB6 MSBUILD # Good acceleration structure for ray sphere tests with spheres that move  » development » Good acceleration structure for ray sphere tests with spheres that move

By : Jiří Dzurko
Date : October 26 2020, 11:52 AM
this one helps. 100x100=10k, an optimized brute force does not seem incoherent, especially that ray/sphere intersection test involve only add/multiply. You can always precompute all normalized ray vector before the main loop.
If you make the assumption that you live in a bounded universe and the spatial density of spheres and rays is relatively uniform, you could use a fixed spatial grid (fixed oct-tree) --something like a 16x16x16 cells grid, or more--, and: code : ## Determining if a sphere is enclosed completely by other spheres placed around it

By : Raghu Sankaran
Date : March 29 2020, 07:55 AM
This might help you Cool question. Here's an algorithm that should do the trick:
Notation: Let's call our moveable sphere S. Write diam(X) for the diameter of a sphere X Write dist(X,Y) for the distance from X to Y; this is the same as the distance from the center of X to the center of Y minus the sum of the radii. The algorithm: For any two unmoveable spheres A and B, check whether S can pass directly between the centers of A and B (i.e. is diam(S) <= dist(A,B)?). If so, for each other sphere C, check whether S could simultaneously touch all three spheres A, B, and C, if there were no other spheres present. If S could simultaneously touch all 3, draw a triangle between the centers of A, B, and C. This can be checked in several ways. One fairly easy way: the possible positions of the center of S while touching both A and B form a circle. You want to know whether this circle has a point on it which is less than diam(S) + diam(C) away from the center of C. This is easy geometry. The problem now reduces to the question: do the triangles separate the initial position of the center of S from infinity? You can answer this one connected component at a time. In fact, you can even answer this one "edge-connected" component at a time, where a component is edge-connected if any two non-vertex points can be linked by a path that doesn't pass through any vertices. You can calculate these components through a simple graph search. For a given edge-connected component, you need to decide whether the component separates the center of S from infinity. There are a few ways you might do this: Calculate the 2-homology of the component, choose effective generators, and for each, ask whether your point and infinity are on the same side of the cycle or not, which can be checked using the orientation class. Or, just start painting the component: Start with a triangle that you can reach from S, and paint every face that can be reached from there. This is slightly subtle, but the algorithm is just "start anywhere, queue up the edges, cross each edge onto the face forming the smallest angle with that edge, and stop when there are no edges left." Keep in mind that the opposite side of the same triangle might be the face forming the smallest angle. Do the same from infinity. Did you cross any painted triangles? If yes, your sphere can escape. If no, it can't. Why it works ## Calculating individual spheres position to create a sphere made of spheres

By : Kirti Vaghela
Date : March 29 2020, 07:55 AM
I wish did fix the issue. I would definitely say that this is a perfect use case of a physics engine. Making this simulation without a physics engine sounds like a real hassle, so "including an entire physics engine" doesn't seam like such a big cost to me. Most of the JavaScript physics engines that i've found are leight weight anyway. It will however demand some extra CPU power for the physics calculations!
I sat down and tried to create something similar to what you describe with the physics engine CANNON.js. It was quite easy to get a basic simulation working, but to get the parameters just right took is what seems a bit tricky, and will need more adjusting.
code :
``````function pullOrigin(body){
body.force.set(
-body.position.x,
-body.position.y,
-body.position.z
);
}
``````
``````let scene = new THREE.Scene();
let world = new CANNON.World();
world.solver.iterations = 5;

let camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );

let renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );

function Proton(){

return {
// Cannon
body: new CANNON.Body({
mass: 1, // kg
position: randomPosition(6),
}),
// THREE
mesh: new THREE.Mesh(
new THREE.SphereGeometry( radius, 32, 32 ),
new THREE.MeshPhongMaterial( { color: 0xdd5555, specular: 0x999999, shininess: 13} )
)
}
}

function Neutron(){

return {
// Cannon
body: new CANNON.Body({
mass: 1, // kg
position: randomPosition(6),
}),
// THREE
mesh: new THREE.Mesh(
new THREE.SphereGeometry( radius, 32, 32 ),
new THREE.MeshPhongMaterial( { color: 0x55dddd, specular: 0x999999, shininess: 13} )
)
}
}

function Electron(){

return {
// Cannon
body: new CANNON.Body({
mass: 0.5, // kg
position: randomPosition(10),
}),
// THREE
mesh: new THREE.Mesh(
new THREE.SphereGeometry( radius, 32, 32 ),
new THREE.MeshPhongMaterial( { color: 0xdddd55, specular: 0x999999, shininess: 13} )
)
}
}

let x = (2 * Math.random() - 1 ) * outerRadius,
y = (2 * Math.random() - 1 ) * outerRadius,
z = (2 * Math.random() - 1 ) * outerRadius
return new CANNON.Vec3(x, y, z);
}

}

// create our Atom
let protons = Array(5).fill(0).map( () => Proton() );
let neutrons = Array(5).fill(0).map( () => Neutron() );
let electrons = Array(15).fill(0).map( () => Electron() );

let light = new THREE.AmbientLight( 0x202020 ); // soft white light

let directionalLight = new THREE.DirectionalLight( 0xffffff, 0.5 );
directionalLight.position.set( -1, 1, 1 );

camera.position.z = 18;

const timeStep = 1/60;

//Small impulse on the electrons to get them moving in the start
electrons.forEach((electron) => {
let centerDir = electron.body.position.vsub(new CANNON.Vec3(0, 0, 0));
centerDir.normalize();
let impulse = centerDir.cross(new CANNON.Vec3(0, 0, 1));
impulse.scale(2, impulse);
electron.body.applyLocalImpulse(impulse, new CANNON.Vec3(0, 0, 0));
});

function render () {
requestAnimationFrame( render );

// all particles pull towards the center
protons.forEach(pullOrigin);
neutrons.forEach(pullOrigin);
electrons.forEach(pullOrigin);

// electrons should also be pushed by protons and neutrons
electrons.forEach( (electron) => {
let pushForce = new CANNON.Vec3(0, 0, 0 );

protons.forEach((proton) => {
let f = electron.body.position.vsub(proton.body.position);
});

neutrons.forEach((neutron) => {
let f = electron.body.position.vsub(neutron.body.position);
});

pushForce.scale(0.07, pushForce);
})

// protons and neutrons slows down (like wind resistance)
neutrons.forEach((neutron) => resistance(neutron, 0.95));
protons.forEach((proton) => resistance(proton, 0.95));

// Electrons have a max velocity
electrons.forEach((electron) => {maxVelocity(electron, 5)});

// Step the physics world
world.step(timeStep);
// Copy coordinates from Cannon.js to Three.js
protons.forEach(updateMeshState);
neutrons.forEach(updateMeshState);
electrons.forEach(updateMeshState);

renderer.render(scene, camera);
};

function updateMeshState(object){
object.mesh.position.copy(object.body.position);
object.mesh.quaternion.copy(object.body.quaternion);
}

function pullOrigin(object){
object.body.force.set(
-object.body.position.x,
-object.body.position.y,
-object.body.position.z
);
}

function maxVelocity(object, vel){
if(object.body.velocity.length() > vel)
object.body.force.set(0, 0, 0);
}

function resistance(object, val) {
if(object.body.velocity.length() > 0)
object.body.velocity.scale(val, object.body.velocity);
}
render();``````
``````<script src="https://cdnjs.cloudflare.com/ajax/libs/cannon.js/0.6.2/cannon.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r75/three.min.js"></script>``````
``````function Atom(nProtons, nNeutrons, nElectrons, pos = new CANNON.Vec3(0, 0, 0)){

//variable to move the atom, which att the particles will pull towards
let position = pos;

// create our Atom
let protons = Array(nProtons).fill(0).map( () => Proton() );
let neutrons = Array(nNeutrons).fill(0).map( () => Neutron() );
let electrons = Array(nElectrons).fill(0).map( () => Electron() );

// Public Functions
//=================
// add to a three.js and CANNON scene/world
protons.forEach((proton) => {
});
neutrons.forEach((neutron) => {
});
electrons.forEach((electron) => {
});
}

function simulate() {

protons.forEach(pullParticle);
neutrons.forEach(pullParticle);

//pull electrons if they are further than 5 away
electrons.forEach((electron) => { pullParticle(electron, 5) });
//push electrons if they are closer than 6 away
electrons.forEach((electron) => { pushParticle(electron, 6) });

// give the particles some friction/wind resistance
//electrons.forEach((electron) => resistance(electron, 0.95));
neutrons.forEach((neutron) => resistance(neutron, 0.95));
protons.forEach((proton) => resistance(proton, 0.95));

}

function electronStartingVelocity(vel) {
electrons.forEach((electron) => {
let centerDir = electron.body.position.vsub(position);
centerDir.normalize();
let impulse = centerDir.cross(new CANNON.Vec3(0, 0, 1));
impulse.scale(vel, impulse);
electron.body.applyLocalImpulse(impulse, new CANNON.Vec3(0, 0, 0));
});
}

// Should be called after CANNON has simulated a frame and before THREE renders.
function updateAtomMeshState(){
protons.forEach(updateMeshState);
neutrons.forEach(updateMeshState);
electrons.forEach(updateMeshState);
}

// Private Functions
// =================

// pull a particale towards the atom position (if it is more than distance away)
function pullParticle(particle, distance = 0){

// if particle is close enough, dont pull more
if(particle.body.position.distanceTo(position) < distance)
return false;

//create vector pointing from particle to atom position
let pullForce = position.vsub(particle.body.position);

// same as: particle.body.force = particle.body.force.vadd(pullForce)
pullForce,              // to pullForce
particle.body.force);   // and put it in particle force
}

// Push a particle from the atom position (if it is less than distance away)
function pushParticle(particle, distance = 0){

// if particle is far enough, dont push more
if(particle.body.position.distanceTo(position) > distance)
return false;

//create vector pointing from particle to atom position
let pushForce = particle.body.position.vsub(position);

pushForce,              // to pushForce
particle.body.force);   // and put it in particle force
}

// give a partile some friction
function resistance(particle, val) {
if(particle.body.velocity.length() > 0)
particle.body.velocity.scale(val, particle.body.velocity);
}

// Call this on a particle if you want to limit its velocity
function limitVelocity(particle, vel){
if(particle.body.velocity.length() > vel)
particle.body.force.set(0, 0, 0);
}

// copy ratation and position from CANNON to THREE
function updateMeshState(particle){
particle.mesh.position.copy(particle.body.position);
particle.mesh.quaternion.copy(particle.body.quaternion);
}

// public API
return {
"simulate":                 simulate,
"electrons":                electrons,
"neutrons":                 neutrons,
"protons":                  protons,
"position":                 position,
"updateAtomMeshState":      updateAtomMeshState,
"electronStartingVelocity": electronStartingVelocity,

}
}

function Proton(){

return {
// Cannon
body: new CANNON.Body({
mass: 1, // kg
position: randomPosition(0, 6), // random pos from radius 0-6
}),
// THREE
mesh: new THREE.Mesh(
new THREE.SphereGeometry( radius, 32, 32 ),
new THREE.MeshPhongMaterial( { color: 0xdd5555, specular: 0x999999, shininess: 13} )
)
}
}

function Neutron(){

return {
// Cannon
body: new CANNON.Body({
mass: 1, // kg
position: randomPosition(0, 6), // random pos from radius 0-6
}),
// THREE
mesh: new THREE.Mesh(
new THREE.SphereGeometry( radius, 32, 32 ),
new THREE.MeshPhongMaterial( { color: 0x55dddd, specular: 0x999999, shininess: 13} )
)
}
}

function Electron(){

return {
// Cannon
body: new CANNON.Body({
mass: 0.5, // kg
position: randomPosition(3, 7), // random pos from radius 3-8
}),
// THREE
mesh: new THREE.Mesh(
new THREE.SphereGeometry( radius, 32, 32 ),
new THREE.MeshPhongMaterial( { color: 0xdddd55, specular: 0x999999, shininess: 13} )
)
}
}

// get random direction
let x = (2 * Math.random() - 1 ),
y = (2 * Math.random() - 1 ),
z = (2 * Math.random() - 1 )

// create vector
let randVec = new CANNON.Vec3(x, y, z);

// normalize
randVec.normalize();
// scale it to the right radius
return randVec;
}
``````
``````let scene = new THREE.Scene();
let world = new CANNON.World();
world.solver.iterations = 5;

let camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );

let renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );

// create a Atom with 3 protons and neutrons, and 5 electrons
// all circulating position (-4, 0, 0)
let atom = Atom(3, 3, 5, new CANNON.Vec3(-4, 0, 0));

// move atom (will not be instant)
//atom.position.x = -2;

// add to THREE scene and CANNON world

let light = new THREE.AmbientLight( 0x202020 ); // soft white light

let directionalLight = new THREE.DirectionalLight( 0xffffff, 0.5 );
directionalLight.position.set( -1, 1, 1 );

camera.position.z = 18;

const timeStep = 1/60;

// give the atoms electrons some starting velocity
atom.electronStartingVelocity(2);

function render () {
requestAnimationFrame( render );

// calculate all the particles positions
atom.simulate();

// Step the physics world
world.step(timeStep);

//update the THREE mesh
atom.updateAtomMeshState();

renderer.render(scene, camera);
};

render();
`````` ## Optimally filling a 3D sphere with smaller spheres

By : skwesiga
Date : March 29 2020, 07:55 AM
I wish did fix the issue. your constraints are a bit vague so hard to say for sure but I would try field approach for this. First see:
Computational complexity and shape nesting Path generation for non-intersecting disc movement on a plane How to implement a constraint solver for 2-D geometry? ## sphere-sphere intersection : getting the distance between spheres from the given radius of the intersecting circle

By : Eklavya Sharma
Date : March 29 2020, 07:55 AM
I hope this helps you . Edit: There is no need to reverse that equation.
Simpler formula (thank you, uncle Pythagoras)
code :
``````distance  = Sqrt(R^2-a^2) + Sqrt(r^2-a^2)
`````` ## How to plot a perfectly round sphere in R (rgl.spheres)

By : 丁明梦
Date : March 29 2020, 07:55 AM
Hope that helps The function below is an imitation of rgl.spheres. ng is number of grids on the sphere. if you increase the ng, you have more round sphere. 