Skip to content

Instantly share code, notes, and snippets.

@kardasis
Created January 21, 2024 16:46
Show Gist options
  • Save kardasis/ebf227a6a62103eef6dd4d81ec10f084 to your computer and use it in GitHub Desktop.
Save kardasis/ebf227a6a62103eef6dd4d81ec10f084 to your computer and use it in GitHub Desktop.
Modeling Charges on the surface of a sphere
import { Vector } from 'p5'
type Vertex = {
position: Vector
velocity: Vector
neighbors: Vertex[]
charge: number
}
type Edge = [Vertex, Vertex]
export default class ChargeBall {
vertices: Vertex[]
edges: Edge[]
constructor (vertexCount: number) {
this.vertices = []
this.edges = []
for (var i = 0; i < vertexCount; i++) {
const position = new Vector(
2 * Math.random() - 1,
2 * Math.random() - 1,
2 * Math.random() - 1
).normalize()
this.vertices.push({
position,
velocity: new Vector(0, 0, 0),
neighbors: [],
charge: 2 * Math.random() - 1
})
}
this.edges = []
for (let i = 0; i < this.vertices.length; i++) {
for (let j = i + 1; j < this.vertices.length; j++) {
this.addEdge(this.vertices[i], this.vertices[j])
}
}
}
update (mode: string, dampening: number) {
this.vertices.forEach(vertex => {
let acc = new Vector(0, 0)
vertex.neighbors.forEach(n => {
const dist = Vector.sub(n.position, vertex.position).mag()
const direction = Vector.sub(vertex.position, n.position).normalize()
let chargeStrength
switch (mode) {
case 'attract':
chargeStrength = 1
break
case 'repel':
chargeStrength = -1
break
default:
chargeStrength = n.charge * vertex.charge
break
}
n.charge * vertex.charge
const dAcc = direction.mult(chargeStrength / (dist * dist))
acc.add(dAcc)
})
acc.mult(-0.00001)
vertex.velocity.add(acc)
vertex.velocity.sub(project(vertex.velocity, vertex.position)) // project velocity onto plane normal to position
vertex.position.add(vertex.velocity)
vertex.velocity.mult(dampening)
vertex.position.normalize()
})
}
addEdge (a: Vertex, b: Vertex) {
b.neighbors.push(a)
a.neighbors.push(b)
this.edges.push([a, b])
}
}
// project p onto v
function project (p: Vector, v: Vector) {
const vNorm = Vector.normalize(v)
return vNorm.mult(vNorm.dot(p))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment