我刚刚了解到,从另一个粒子的参考系(同一物体)观察时,刚体的任何粒子都只执行圆周运动,无论物体遵循什么混沌路径!所以我尝试模拟同样的情况。
我创建了 100 个紧密相连的粒子以形成一个物体,并让它们遵循任意路径,但现在我不知道如何坚持其中一个粒子的参考系并观察其他粒子。 这就是我所做的(我认为没有用):
var path = [];
var particles = [];
class Particle {
constructor(x_, y_) {
this.x_ = x_;
this.y_ = y_;
this.x = 0;
this.y = 0;
this.pathIndex = 0;
this.draw = () => {
fill(360, 100, 100);
circle(this.x, this.y, 1);
}
this.update = () => {
if (this.pathIndex >= path.length) {
this.pathIndex = 0;
} else {
this.x = (path[this.pathIndex].x + this.x_);
this.y = (path[this.pathIndex].y + this.y_);
this.pathIndex++;
}
this.draw();
}
}
}
function setup() {
createCanvas(400, 400);
colorMode(HSB);
for (let i = 0; i < 10; i++) {
for (let j = 0; j < 10; j++) {
particles.push(new Particle(i * 2, j * 2));
}
}
}
function draw() {
background(50);
fill(0);
noStroke();
for (let i = 0; i < path.length; i++) {
circle(path[i].x, path[i].y, 5);
}
for (let i = 0; i < particles.length; i++) {
particles[i].update();
}
}
function mouseDragged() {
path.push({
x: mouseX,
y: mouseY
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/p5.min.js"></script>
对于真正的刚体,每个粒子都可以有自己的速度,我想我可以使用相对速度概念移动到单个粒子的参考系,然后我可以将其他粒子的速度设置为:
v(1/2) = v1 - v2
通常在可视化移动物体时,我们将物体的速度存储在 v_x、v_y 等变量中(就像位置本身一样)。然后更新函数看起来像这样:
this.update = () => {
this.x += this.v_x;
this.y += this.v_y;
}
如果物体的速度可以通过力改变,那么加速度(a_x,a_y)应该传递给更新方法(或通过其他计算来计算),如下所示:
this.update = (a_x, a_y) => {
this.x += this.v_x;
this.y += this.v_y;
this.v_x += a_x;
this.v_y += a_y;
}
但是,就您的情况而言,如果我正确理解您的问题,则无需将速度存储为变量。因此,您只需要知道整体的
x, y, a
,以及粒子的 x, y
:
const NUM_PARTICLES = 5;
let selectedParticleIdx = 0;
const particle_offsets = [];
let rigidBody;
function setup() {
createCanvas(400, 400);
rigidBody = {
'x': width / 2,
'y': height / 2,
'a': 0,
'width': width / 2,
'height': height / 2,
}
for (let i=0; i < NUM_PARTICLES; i++) {
let x_offset = random(rigidBody.width) - rigidBody.width / 2;
let y_offset = random(rigidBody.height) - rigidBody.height / 2;
particle_offsets.push([x_offset, y_offset]);
}
}
您还可以沿着连接它们的线绘制粒子,以显示身体的刚度:
function drawBody() {
push();
translate(rigidBody.x, rigidBody.y);
rotate(rigidBody.a);
// Draw lines
for (let i = 0; i < NUM_PARTICLES; i++) {
let particleX1 = particle_offsets[i][0];
let particleY1 = particle_offsets[i][1];
for (let j = i + 1; j < NUM_PARTICLES; j++) {
let particleX2 = particle_offsets[j][0];
let particleY2 = particle_offsets[j][1];
line(particleX1, particleY1, particleX2, particleY2);
}
}
// Draw particles
for (let i = 0; i < NUM_PARTICLES; i++) {
let particleX = particle_offsets[i][0];
let particleY = particle_offsets[i][1];
ellipse(particleX, particleY, 10, 10); // Adjust the size as needed
}
pop();
}
现在,为了展示您刚才谈到的物理概念,我建议在像这样的框中显示粒子 POV:
function showParticlePrespective(coef) {
push();
translate(280, 10, 80, 100);
rect(0, 0, 110, 90);
translate(55, 45);
rotate(rigidBody.a);
let mainParticleX = particle_offsets[0][0];
let mainParticleY = particle_offsets[0][1];
// Draw particles
for (let i = 0; i < NUM_PARTICLES; i++) {
let particleX = particle_offsets[i][0];
let particleY = particle_offsets[i][1];
if (i == selectedParticleIdx) {
fill('red');
} else {
fill('white');
}
ellipse((particleX - mainParticleX) / coef, (particleY - mainParticleY) / coef, 2, 2); // Adjust the size as needed
}
pop();
}
最后为了移动粒子,您可以在绘图函数中更改其 x,y,a 值:
function draw() {
background(100); // Set background color
drawBody(0);
rigidBody.x += 0.3;
rigidBody.y += 0.3;
rigidBody.a += 0.04;
showParticlePrespective(3);
}
更好的方法是让主体根据用户输入(键盘)更改其
x, y, a
值。