Skip to content

Instantly share code, notes, and snippets.

@JustinSDK
Last active September 8, 2022 03:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JustinSDK/8cfad14db92981726d710d469a2f0e67 to your computer and use it in GitHub Desktop.
Save JustinSDK/8cfad14db92981726d710d469a2f0e67 to your computer and use it in GitHub Desktop.
circle packing
const n_start = 200;
let circles = [];
function setup() {
createCanvas(640, 480);
noFill();
strokeWeight(1.5);
stroke(5);
for (let i = 0; i < n_start; i++) {
circles[i] = new Circle(createVector(width / 2, height / 2), p5.Vector.random2D());
}
}
function draw() {
background(255);
for (let c of circles) {
c.pack(circles);
circle(c.coordinate.x, c.coordinate.y, c.diameter);
}
}
class Circle {
constructor(coordinate, velocity, maxSpeed = 1.5, maxForce = 1.5, maxDiameter = 50) {
this.coordinate = coordinate;
this.velocity = velocity.limit(maxSpeed);
this.maxSpeed = maxSpeed;
this.maxForce = maxForce;
this.maxDiameter = maxDiameter;
this.diameter = 1;
}
applyForce(force) {
this.velocity.add(force);
}
separate(circles) {
let steer = createVector(0, 0); // 初始分離力
// 計算期望速度
for(let c of circles) {
let d = p5.Vector.dist(this.coordinate, c.coordinate);
// 交疊
if(d > 0 && d < this.diameter / 2 + c.diameter / 2 + 2) {
let diff = p5.Vector
.sub(this.coordinate, c.coordinate)
// 跟距離平方成反比,越近影響越大
.div(d * d);
steer.add(diff); // 累加
}
}
// 如果速度不為 0
if(steer.mag() > 0) {
steer.normalize(); // 只需要方向
steer.mult(this.maxSpeed); // 拼命避開(用最大速度)
steer.sub(this.velocity); // 轉向力=期望速度-目前速度
steer.limit(this.maxForce); // 限制力道
}
return steer;
}
updateCoordinate() {
this.coordinate.add(this.velocity);
}
updateDiameter() {
this.diameter =
noise(this.coordinate.x * 0.01, this.coordinate.y * 0.01) * this.maxDiameter + 1;
}
pack(nodes) {
let sep = this.separate(nodes);
// 加總後套用至節點
this.applyForce(sep);
// 更新座標
this.updateCoordinate();
this.updateDiameter();
if(sep.mag() === 0) {
this.velocity.mult(0);
}
}
}
function mouseClicked() {
circles.push(new Circle(createVector(mouseX, mouseY), p5.Vector.random2D()));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment