logo
down
shadow

Good acceleration structure for ray sphere tests with spheres that move


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 :


Share : facebook icon twitter icon
Determining if a sphere is enclosed completely by other spheres placed around it

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

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.broadphase = new CANNON.NaiveBroadphase();
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(){
	let radius = 1;

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

function Neutron(){
	let radius = 1;

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

function Electron(){
	let radius = 0.2;

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

function randomPosition(outerRadius){
	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);
}

function addToWorld(object){
	world.add(object.body);
	scene.add(object.mesh);
}

// 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() );

protons.forEach(addToWorld);
neutrons.forEach(addToWorld);
electrons.forEach(addToWorld);


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

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

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);
			pushForce.vadd(f, pushForce);
		});

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

		pushForce.scale(0.07, pushForce);
		electron.body.force.vadd(pushForce, electron.body.force);
	})

	// 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
    function addToWorld(world, scene) {
        protons.forEach((proton) => {
            world.add(proton.body);
            scene.add(proton.mesh);
        });
        neutrons.forEach((neutron) => {
            world.add(neutron.body);
            scene.add(neutron.mesh);
        });
        electrons.forEach((electron) => {
            world.add(electron.body);
            scene.add(electron.mesh);
        });
    }

    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)
        particle.body.force.vadd(   // add particle force
            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);

        particle.body.force.vadd(   // add particle force
            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,
        "addToWorld":               addToWorld

    }
}

function Proton(){
    let radius = 1;

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

function Neutron(){
    let radius = 1;

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

function Electron(){
    let radius = 0.2;

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


function randomPosition(innerRadius, outerRadius){

    // 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
    randVec = randVec.scale( Math.random() * (outerRadius - innerRadius) + innerRadius); //from inner to outer
    return randVec;
}
let scene = new THREE.Scene();
let world = new CANNON.World();
world.broadphase = new CANNON.NaiveBroadphase();
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
atom.addToWorld(world, scene);

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

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

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

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

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)

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.
Related Posts Related Posts :
  • Passing Query String Param into Response AWS API Gateway
  • Drive Api V3 - How to name file being uploaded?
  • IBM Watson speech to text WebSocket authorization with IAM API key
  • Why does ABAP cut string to one character?
  • Hide Taskbar button in FMX on Windows
  • Limit on the size of Azure table property that can be indexed by search?
  • How to authenticate to influxdb when using k6
  • How to customize the NSIS installer screens for multiple languages
  • How do I do a Depth First Search Alphabetically?
  • Updating already installed sideloaded uwp application
  • Formula returning previous month in `mmmm` format, only returns January
  • Postman API Tests
  • STRIPS Planner Doesn't Compile
  • WebCrypto AES-CBC outputting 256bit instead of 128bits
  • "File format not recognized" when building Petalinux app
  • Long living service with coroutines
  • Define data at cell centers using VTK format
  • Systemverilog interfaces over hierarchical boundaries
  • AIOHTTP:TypeError: index() takes 0 positional arguments but 1 was given
  • ProxySql Master node not serve the traffic untill slave gets shunned
  • Visual Studio 2019 Preview Remote Debugger
  • Setting composer (airflow) bucket using gcloud CLI
  • Cannot refresh subform from other subform
  • Email alert when field meets certain condition
  • MemSql > workaround for SELECT ... FOR UPDATE
  • Declarative Pipeline - Use of when condition, how to do nested conditions anyOf/allOf/not
  • Stateful microservices default 443 port share issue on the azure service fabric cluster
  • TYPO3 imagemagick makes images oversaturated
  • Typo-tolerant text searching?
  • How do I extract the components of a tuple in DAML?
  • Gimp 2.8.22: Change Color & Keep Transparency
  • I tried with this code, but it won't work with Ionic 3
  • Karate-Cucumber Report - No report file was added
  • Autofac - how to register a type used as a constructor parameter that requires the resolving (constructor) type as a gen
  • Tkinter filedialog is stealing focus and not returning it without "Alt-tab" in Python 3.4.1
  • jmeter dashboard report includes transaction controller children
  • Visual Branching in SourceTree
  • Doctrine2 orderBy in Symfony4 UnitTest
  • Match table-record to main-report dataset in Jaspersoft Studio
  • Drupal 8 custom module getting page not found
  • Is it possible that a container instance isn't really a container?
  • Padding not being understood in the UpSampling2D layer of a sequential layer
  • What is the incentive for a participating node in a "Proof of Stake" consensus model of Blockchain?
  • Radial gradient on a node in cytoscape
  • How to create operators from list in Airflow?
  • Is bitly supported for Native Script?
  • Reading log data records from a BLE device
  • How to add aliases in yii2?
  • XPages - Bootstrap popover
  • Misleading exception message in GatewayMethodInboundMessageMapper with un-annotated parameters
  • Inno Setup Disable Next button using multiple validation expressions (when input value matches one of multiple values)
  • 'reference to setCapability is ambiguous' on Appium Java project for Android Caps
  • Quartz .net - Abort/Stop Current Execution of Job & Pause All the triggers
  • Calculate length of road in a Polygon
  • Can Signal have zero recipients in BPMN?
  • Perl6: .sort() doesn't use overridden cmp
  • Find a directory using wildcard in Inno Setup
  • Getting error trying to formrequest login page via scrapy shell
  • Botframework Dialog migration v3 to v4
  • How to load resources from classpath in itext7?
  • shadow
    Privacy Policy - Terms - Contact Us © bighow.org