Banach 分形曲线 Java - 递归
Banach Fractal Curve Java - Recursive
我有以下 Banach 分形问题:
可以使用以下分形规则生成所谓的 Banach 曲线:
- 画一个圆。
- 绘制 9 个小圆,每个圆的半径为原圆的⅓
圆圈。其中一个较小的圆圈应与原始圆圈具有相同的中心。其余的中心
8 个较小的圆应沿原圆的圆周等距分布。
- 对每个较小的圆圈重复步骤 b。
注:以点(x,y)为圆心的半径为r的圆是所有点的集合
(x + r · cos(t), y + r · sin(t)) 其中 0 ≤ t ≤ 2π ,t 以弧度表示。我可以使用 Math.toRadians()
准则:
- 只有递归解决方案,不允许循环
- 没有导入&没有列表(所以没有地图左右)&没有
?
- 我只能使用功能
public static void banachCurve(int n)
和帮助功能 private static void banachCurve(double x, double y, double r, int n)
- 只能使用StdDraw绘制或从中调用其他函数,不允许使用其他Std类
我想每次都添加圆圈,因为每次应该在边缘有 9 个,在中心有 1 个,但是我似乎只能在右边或左边得到圆圈,并且由于某种原因运行时错误。
public static void banachCurve(int n) {
banachCurve (0.5,0.5,1,n);
}
private static void banachCurve(double x, double y, double r, int n) {
if (n == 0) {
return;
}
double d = (r/3);
StdDraw.circle (x,y,d);
// StdDraw.ellipse(x, y, r, r);
banachCurve (x + d, y, d, n - 1); // centre
banachCurve (x + d+ d, y+d, d, n--); // left
banachCurve (x , y + d, d, n--); // right
banachCurve (x+d , y +d+ d, d, n--);
banachCurve (x+d , y +d, d, n--);
}
我的输出:
巴拿赫曲线的阶段:
每次调用 n--
时,都会将 n
传递给该函数,然后在下次调用时将其递减 1。相反,您需要将 n - 1
传递给每个调用,因为调用本身将在其自己的递归调用中进一步递减 n
,最终如您正确的那样停止在 0
。
对于四个基点,使用(x + d, y)
、(x, y + d)
、(x - d, y)
和(x, y - d)
可以正常工作,但是对于四个对角点,您将需要使用毕达哥拉斯方法的平方根 (Math.sqrt
) 或三角函数方法的正弦和余弦 (Math.sin
和 Math.cos
)。使用 (x + d, y + d)
等会将它们放在正方形上。
假设 x
和 y
标记了你的圆心,那么你的函数将变为:
private static void banachCurve(final double x, final double y, final double r, final int n) {
if (n == 0) {
return;
}
final double d = r / 3;
StdDraw.circle (x, y, d);
banachCurve (x, y, d, n - 1); // centre
banachCurve (x, y + d, d, n - 1); // north
banachCurve (x + d, y, d, n - 1); // east
banachCurve (x, y - d, d, n - 1); // south
banachCurve (x - d, y, d, n - 1); // west
// Get the diagonal radius for a point at 45 degrees on the circle
final double diagD = Math.cos(Math.toRadians(45)) * d;
banachCurve (x + diagD, y + diagD, d, n - 1); // north-east
banachCurve (x + diagD, y - diagD, d, n - 1); // south-east
banachCurve (x - diagD, y - diagD, d, n - 1); // south-west
banachCurve (x - diagD, y + diagD, d, n - 1); // north-west
}
这是 banachCurve(0.5, 0.5, 1, 6);
的输出:
如果你要将 Math.cos()
拖到图片中,就像当前接受的答案一样,为什么不全力以赴并使用正弦和余弦绕圆移动:
private static void banachCurve(double x, double y, double r, int n) {
if (n == 0) {
return;
}
double d = r / 3;
StdDraw.circle (x, y, d);
banachCurve (x, y, d, n - 1); // center
for (double angle = 0; angle < 360; angle += 45) {
double theta = Math.toRadians(angle);
double dx = x + d * Math.cos(theta);
double dy = y + d * Math.sin(theta);
banachCurve (dx, dy, d, n - 1);
}
}
banachCurve(0.5, 0.5, 1, 3);
的输出
这种方法可以很容易地测试@tucuxi 的建议,即六个而不是八个周围的圆圈。只需将 for
循环中的增量角度从 45 增加到 60:
虽然我不能说这是对原始设计的改进。尽管有七个环绕的圆圈,但鉴于此代码设计,再次测试起来微不足道,但引人注目:
我有以下 Banach 分形问题: 可以使用以下分形规则生成所谓的 Banach 曲线:
- 画一个圆。
- 绘制 9 个小圆,每个圆的半径为原圆的⅓ 圆圈。其中一个较小的圆圈应与原始圆圈具有相同的中心。其余的中心 8 个较小的圆应沿原圆的圆周等距分布。
- 对每个较小的圆圈重复步骤 b。
注:以点(x,y)为圆心的半径为r的圆是所有点的集合
(x + r · cos(t), y + r · sin(t)) 其中 0 ≤ t ≤ 2π ,t 以弧度表示。我可以使用 Math.toRadians()
准则:
- 只有递归解决方案,不允许循环
- 没有导入&没有列表(所以没有地图左右)&没有
?
- 我只能使用功能
public static void banachCurve(int n)
和帮助功能private static void banachCurve(double x, double y, double r, int n)
- 只能使用StdDraw绘制或从中调用其他函数,不允许使用其他Std类
我想每次都添加圆圈,因为每次应该在边缘有 9 个,在中心有 1 个,但是我似乎只能在右边或左边得到圆圈,并且由于某种原因运行时错误。
public static void banachCurve(int n) {
banachCurve (0.5,0.5,1,n);
}
private static void banachCurve(double x, double y, double r, int n) {
if (n == 0) {
return;
}
double d = (r/3);
StdDraw.circle (x,y,d);
// StdDraw.ellipse(x, y, r, r);
banachCurve (x + d, y, d, n - 1); // centre
banachCurve (x + d+ d, y+d, d, n--); // left
banachCurve (x , y + d, d, n--); // right
banachCurve (x+d , y +d+ d, d, n--);
banachCurve (x+d , y +d, d, n--);
}
我的输出:
每次调用 n--
时,都会将 n
传递给该函数,然后在下次调用时将其递减 1。相反,您需要将 n - 1
传递给每个调用,因为调用本身将在其自己的递归调用中进一步递减 n
,最终如您正确的那样停止在 0
。
对于四个基点,使用(x + d, y)
、(x, y + d)
、(x - d, y)
和(x, y - d)
可以正常工作,但是对于四个对角点,您将需要使用毕达哥拉斯方法的平方根 (Math.sqrt
) 或三角函数方法的正弦和余弦 (Math.sin
和 Math.cos
)。使用 (x + d, y + d)
等会将它们放在正方形上。
假设 x
和 y
标记了你的圆心,那么你的函数将变为:
private static void banachCurve(final double x, final double y, final double r, final int n) {
if (n == 0) {
return;
}
final double d = r / 3;
StdDraw.circle (x, y, d);
banachCurve (x, y, d, n - 1); // centre
banachCurve (x, y + d, d, n - 1); // north
banachCurve (x + d, y, d, n - 1); // east
banachCurve (x, y - d, d, n - 1); // south
banachCurve (x - d, y, d, n - 1); // west
// Get the diagonal radius for a point at 45 degrees on the circle
final double diagD = Math.cos(Math.toRadians(45)) * d;
banachCurve (x + diagD, y + diagD, d, n - 1); // north-east
banachCurve (x + diagD, y - diagD, d, n - 1); // south-east
banachCurve (x - diagD, y - diagD, d, n - 1); // south-west
banachCurve (x - diagD, y + diagD, d, n - 1); // north-west
}
这是 banachCurve(0.5, 0.5, 1, 6);
的输出:
如果你要将 Math.cos()
拖到图片中,就像当前接受的答案一样,为什么不全力以赴并使用正弦和余弦绕圆移动:
private static void banachCurve(double x, double y, double r, int n) {
if (n == 0) {
return;
}
double d = r / 3;
StdDraw.circle (x, y, d);
banachCurve (x, y, d, n - 1); // center
for (double angle = 0; angle < 360; angle += 45) {
double theta = Math.toRadians(angle);
double dx = x + d * Math.cos(theta);
double dy = y + d * Math.sin(theta);
banachCurve (dx, dy, d, n - 1);
}
}
banachCurve(0.5, 0.5, 1, 3);
这种方法可以很容易地测试@tucuxi 的建议,即六个而不是八个周围的圆圈。只需将 for
循环中的增量角度从 45 增加到 60:
虽然我不能说这是对原始设计的改进。尽管有七个环绕的圆圈,但鉴于此代码设计,再次测试起来微不足道,但引人注目: