这只是我的复活尝试。在下面阅读更多内容。
我之所以发布此信息,只是为了保留上周在这里新成员发布的一个有趣的问题,后来他自己自愿将其删除;甚至在问题发布后几小时内就收到了几张赞成票和星星。
链接到原始/现已删除的问题:https://stackoverflow.com/questions/54478107/2d-particle-interactions
我不是该领域的专家,目前对此有点兴趣,但是我很聪明,可以将所有代码和链接保存为离线;)
原始问题-重构
问题
我想模拟和可视化受[[image source]控制的粒子相互作用
使用给定的设置:
PPS = 〈r = 5,α= 180°,β= 17°,v = 0.67〉
有效地复制以下观察结果:[image source]
如以下视频所示:
但是创建者没有提供他们所说的源代码:
“请您发布密码?”
“我们将所需的所有内容都放入了《科学报告》 开放获取。没有更多了。我们曾经压缩过 完全运行的模型变成一条推文。那个时候 推文有140个字符。该模型非常简单,而且非常短。”
请参阅此问题开头的伪代码。
问题
重要说明:原始作者的代码工作未在此处复制
如何按照显示的方式进行这项工作?
答案 0 :(得分:0)
PPS系统的JavaScript中已经有一些解决方案/工作代码示例:
https://github.com/nagualdesign/Primordial-Particle-System
旧版/原始版@ Google云端硬盘
https://drive.google.com/file/d/1eX_cczNM4qfDue6j83f8T4gG4ecjSV-p
https://drive.google.com/file/d/1KoJf753p3HXPHwP4N2lW9cWLXgusTP72
我将在此处仅以片段形式发布他的较早的较简单代码版本。 请访问他的GitHub页面以获取最新版本。
// author: user "nagualdesign" @ github
// github repository: https://github.com/nagualdesign/Primordial-Particle-System
// For more information visit: https://www.youtube.com/watch?v=makaJpLvbow
// This video focuses primarily on specific values of alpha, beta, v and r
// It goes on to show the effects of altering the values of alpha and beta
// To replicate the video it is necessary to tune the density of particles
// Density depends on the screen size, as well as particle size and number
// You can also increase/decrease density by zooming in/out and refreshing
// Global variables:
var a=180; // Alpha in degrees
var b=17; // Beta in degrees
var v=0.67; // Speed of particles
var r=5.0; // Radius of neighbourhood
// Convert to radians!
a=(a/180)*Math.PI;
b=(b/180)*Math.PI;
var canvas, context; // HTML canvas
var t=40; // Time interval in milliseconds
var s=5; // Size/scale of particles
var n=1200; // Number of particles
var p=new Array(n); // Particles
function init() {
// Set up canvas:
canvas=document.getElementById("canvas");
canvas.width=window.innerWidth;
canvas.height=window.innerHeight;
context=canvas.getContext("2d");
for (i=0; i<n; i++) { // Randomize position and orientation of particles:
p[i]=new Array(4); // Each particle has 4 variables
p[i][0]=Math.random()*window.innerWidth; // Set random x coordinate
p[i][1]=Math.random()*window.innerHeight; // Set random y coordinate
p[i][2]=Math.random()*2*Math.PI; // Set random orientation
}
}
function draw() {
context.clearRect(0,0,canvas.width,canvas.height); // Clear canvas
for (i=0; i<n; i++) { // For each particle:
// Set fill colour based on number of neighbours:
let fc='#00C200'; // Green
if (p[i][3]>35) fc='#F8E302'; // Yellow
else if (p[i][3]>16) fc='#0064FF'; // Blue
else if (p[i][3]>15) fc='#FF0792'; // Magenta
else if (p[i][3]>12) fc='#A4714B'; // Brown
// Draw particle:
context.beginPath();
context.arc(p[i][0],p[i][1],s,0,2*Math.PI);
context.fillStyle=fc;
context.fill();
}
}
function scope(ang) { // Ensure angles are between 0 and 2*pi radians!
while (ang>(2*Math.PI)) ang=ang-(2*Math.PI);
while (ang<0) ang=ang+(2*Math.PI);
return ang;
}
function loop() {
for (i=0; i<n; i++) { // For each particle:
// Count neighbors within radius r:
let nLeft=0, nRight=0, nTotal=0;
for (j=0; j<n; j++) if (i!=j) { // Compare every other particle:
let sX=p[j][0]-p[i][0]; // X axis separation
let sY=p[j][1]-p[i][1]; // Y axis separation
let sD=Math.sqrt((sX*sX)+(sY*sY)); // Separation distance
if (sD<(r*s*2)) { // Distance is within radius r
nTotal++; // Increase count
let sA=scope(Math.atan2(sY,sX)); // Separation angle
if (scope(sA-p[i][2])<Math.PI) nRight++; // Neighbour on right
else nLeft++; // Neighbour on left
}
}
p[i][3]=nTotal; // Used for colouring particles
// delta_phi = alpha + beta × N × sign(R - L)
let deltaPhi=a+(b*nTotal*Math.sign(nRight-nLeft));
// turn right delta_phi
p[i][2]+=deltaPhi;
p[i][2]=scope(p[i][2]); // Keep angles within scope!
// Move forward v
p[i][0]+=(v*s*2*Math.cos(p[i][2])); // X coordinate
p[i][1]+=(v*s*2*Math.sin(p[i][2])); // Y coordinate
// Wrap screen edges, Pac-Man style!
if (p[i][0]<(s*-1)) p[i][0]=(canvas.width+s);
else if (p[i][0]>(canvas.width+s)) p[i][0]=(s*-1);
if (p[i][1]<(s*-1)) p[i][1]=(canvas.height+s);
else if (p[i][1]>(canvas.height+s)) p[i][1]=(s*-1);
}
draw(); // Update canvas
}
function run() {
init();
run=setInterval(loop,t);
}
<body style="margin:0; background:#000; overflow:hidden;" onLoad="run();">
<canvas id="canvas" onclick="window.clearTimeout(run)"></canvas>
</body>