gpt4 book ai didi

java - 圆与圆的碰撞

转载 作者:太空宇宙 更新时间:2023-11-04 08:12:03 25 4
gpt4 key购买 nike

我正在尝试编写一个Java程序来支持离格扩散有限聚合模拟。模拟移动粒子的基本代码已就位,直到所述粒子撞击静态中心粒子。此时,我尝试确保移动粒子恰好接触(相切)静态粒子。然而,由于未知的原因,它有时会失败(8 个粒子中的前 2 个相交,其他 6 个都很好)。

这是代码:

    boolean killed, collide;
double xp, yp, dx, dy, theta, xpp, ypp, length;

int xc = 200;
int yc = 200;
int killRadius = 200;
int releaseRadius = 150;
int partRadius = 14;
int partDiam = 2 * partRadius;

drawCircle(xc, yc, killRadius); // kill
drawCircle(xc, yc, releaseRadius); // release
drawCircle(xc, yc, partRadius); // center particle

//while (true) {
killed = false;
collide = false;

theta = Math.random() * Math.PI * 2;
xp = xc + releaseRadius * Math.cos(theta);
yp = yc + releaseRadius * Math.sin(theta);

while (true) {

theta = Math.random() * Math.PI * 2;
length = partDiam;

xpp = xp;
ypp = yp;

xp = xp + length * Math.cos(theta);
yp = yp + length * Math.sin(theta);

//drawCircle((int) xp, (int) yp, partRadius);

// Should it be killed ? (maybe could use a box to fasten
// computations...
// Would switching the test for kill w test for collision
// improve perf ?
dx = xp - xc;
dy = yp - yc;
if ((dx * dx) + (dy * dy) > killRadius * killRadius) {
killed = true;
break;
}

// Does it collide with center? replace by any particle...
dx = xp - xc;
dy = yp - yc;
if ((dx * dx) + (dy * dy) < (partDiam) * (partDiam)) {
collide = true;
break;
}
}
// Probably something is wrong here...
if (collide) {
// no absolute value because particles move at most by diameter
double depthPenetration = partDiam
- Math.sqrt((dx * dx) + (dy * dy));
dx = xpp - xp;
dy = ypp - yp;
// shorten distance travelled by penetration length to ensure
// that
// particle is tangeant
length = Math.sqrt((dx * dx) + (dy * dy)) - depthPenetration;
xp = xpp + length * Math.cos(theta);
yp = ypp + length * Math.sin(theta);
drawCircle((int) xp, (int) yp, partRadius);
}
//}

当然,在询问之前我检查了很多引用资料,但找不到代码有任何问题...我们将不胜感激。

最佳答案

我对你的代码进行了一些简单的重构,只是为了了解它的作用,发生了什么。

首先让我提一件事:这是意大利面条怪物的复兴,不是吗?你喜欢全局变量吗?长而强大的让我们现在就在这里做这件事?

如果你尽可能晚地引入变量,代码的读者就不需要向上搜索这个变量之前是什么——如果某些东西被覆盖,例如,如果有一个不好的重用。

如果你的变量没有改变:将它们定为最终的。这简化了对它们的推理。 final int KillRadius = 200; 表示获取类型信息以及值,希望在第一次使用之前不久,并且它永远不会改变。仅在源代码中进行配置。可能不是一个太复杂的候选人。与 double dx 相比 - 未初始化,因为它是在循环内初始化的,

static void foo () {

final int xc = 200;
final int yc = 200;
final int killRadius = 200;
final int releaseRadius = 150;
final int partRadius = 14;

drawCircle (xc, yc, killRadius); // kill
drawCircle (xc, yc, releaseRadius); // release
drawCircle (xc, yc, partRadius); // center particle

//while (true) {
boolean killed = false;
boolean collide = false;

double theta = Math.random() * Math.PI * 2;
double xp = xc + releaseRadius * Math.cos (theta);
double yp = yc + releaseRadius * Math.sin (theta);
double dx, dy, xpp, ypp;

while (true) {

theta = Math.random () * Math.PI * 2;
final int partDiam = 2 * partRadius;
final double length = partDiam;

xpp = xp;
ypp = yp;

xp += length * Math.cos (theta);
yp += length * Math.sin (theta);

dx = xp - xc;
dy = yp - yc;
if ((dx * dx) + (dy * dy) > killRadius * killRadius) {
killed = true;
break;
}

// Why again assign dx = xp -xc? Did any of these values change meanwhile?
// I don't think so.
// dx = xp - xc;
// dy = yp - yc;
if ((dx * dx) + (dy * dy) < (partDiam) * (partDiam)) {
collide = true;
break;
}
}
if (collide) {
// no absolute value because particles move at most by diameter
double depthPenetration = partDiam - Math.sqrt((dx * dx) + (dy * dy));
dx = xpp - xp;
dy = ypp - yp;
// shorten distance travelled by penetration length to ensure
// that
// particle is tangeant
final double length = Math.sqrt((dx * dx) + (dy * dy)) - depthPenetration;
xp = xpp + length * Math.cos (theta);
yp = ypp + length * Math.sin (theta);
drawCircle ((int) xp, (int) yp, partRadius);
}

如果你这样构造你的代码,你不仅会看到像 xc 这样的某个值是 200 并且从未改变 - 在 while 循环的头部,你会看到 theta 没有在循环内声明,因此要么稍后在循环外使用它,要么在循环内按顺序修改它。执行 x += 4;你不能在循环传递中初始化 x 。

在最后,你有两个相似的 block :

    dx = xp - xc;
dy = yp - yc;
if ((dx * dx) + (dy * dy) (OP) a OP b) {
c = true;
break;
}

但是 xp、xc 和 dx 同时不会改变 - y 等价物也不会改变。这是一个错误,还是为什么要再次分配它们?

然后,您可以通过这种方式摆脱无尽的 while:由于两个条件都会终止 while,因此将条件放入 while - 测试中,并且仅当第一个 block 未输入时才调用第二个 block (不重复赋值) - 这样做的关键字是 else:

    while (!killed && !collide) {

// ...

dx = xp - xc;
dy = yp - yc;
if ((dx * dx) + (dy * dy) > killRadius * killRadius) {
killed = true;
}
else if ((dx * dx) + (dy * dy) < (partDiam) * (partDiam)) {
collide = true;
}
}

它对查找错误有什么帮助?没那么多。如果两个圆圈放错了,其余的都很好,那么截图就可以了,而值会导致坏圆圈,而值则可以。

关于java - 圆与圆的碰撞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11022156/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com