0

我在 java 中做Koch 分形雪花并将其保存在 svg 文件中。

我正在使用 LineStrip2D 类来记忆分形(它是实现可迭代的 Vec2D 的 ArrayList 的包装器)。

主要功能是这个:

public static LineStrip2D repeatPatternIntoLineStrip2D(
        LineStrip2D pattern,
        LineStrip2D polygon, 
        boolean repeatUp) {

    /*
     * pattern: must be a pattern between Vec(0,0) and Vec(1,0)
     *          (normalized beetween 0-1 and in X axis)
     * */

    float angle, distance;
    Vec2D pivot, a, b, direction, b1;
    LineStrip2D new_polygon = new LineStrip2D();

    new_polygon.add(pattern.vertices.get(0));
    a = polygon.vertices.get(0);

    int count=0;
    for (int i = 1; i < polygon.vertices.size(); i++) {
        b = polygon.vertices.get(i);
        a = polygon.vertices.get(i-1);

        distance = b.distanceTo(a);
        direction = b.sub(a).normalize();
        angle = PApplet.atan2(direction.y, direction.x);
        pivot = a;

        for (int j = 1; j < pattern.vertices.size(); j++) {
            Vec2D _b1 = pattern.vertices.get(j);

            b1 =  _b1.copy() ;

            if(repeatUp)b1.y *= -1;             
            b1.scaleSelf(distance);
            b1 = b1.rotate(angle);
            b1.addSelf(pivot);

            new_polygon.add(b1);
            count++;
        }
        a = b;
    }
    System.out.println(count);
    return new_polygon;
}

我有一个带有初始科赫曲线的模式:

在此处输入图像描述

我打电话给:

pattern = GeometryHelper.repeatPatternIntoLineStrip2D(pattern, pattern, false);

现在的问题:

经过一些迭代(851968)我有一个java.lang.OutOfMemoryError: Java heap space。如何避免此错误并获得巨大的 svg 文件?我想我可以通过不同的步骤来完成这个过程,但我不明白如何以一种聪明的方式实现它。

4

4 回答 4

3

首先也是最简单的就是给 JVM 更多的内存。添加 -Xmx=1g 可能就足够了(并且现在可以在大多数机器上使用)。如果您需要更多,请随意添加,直到超过您机器中的可用容量。

话虽这么说,处理分形总是会有内存使用量的上限。首先,您应该分析您的应用程序以查看所有内存都在哪里使用。一旦你发现了这一点,你就可以考虑重新解决这个问题,以使记忆更加友好。或者,您可以转向在迭代之间进行迭代并将结果保存到磁盘的设计,以节省先前迭代的内存。

于 2012-01-03T20:47:23.110 回答
2

正如其他人所提到的,第一步是尝试看看是否可以通过修改JVM堆大小来实现所需的迭代次数(它是命令行参数 -Xmx=... 其中 ... 是最大值您希望分配的内存大小)。如果您的机器上有足够的 RAM,那么您可以将其设置得相当高(也许有一种方法可以让 JVM 使用磁盘交换空间,所以它可能非常高,但我不知道如何/如果这是可能的)。

如果这还不够,那么您将需要管理和序列化您在迭代(非递归)实现中使用的自己的堆栈。这看起来是您将堆栈作为参数传递给您的函数,并且该函数将从堆栈中读取其参数(将它们留在堆栈上),然后在循环之前将参数写入堆栈(和当你达到你想要的最大深度时,你就开始从堆栈中弹出数据)。迭代实现和堆栈管理是非常重要的,堆栈的序列化/持久性也是如此(随着大小的增加,它需要自我管理以将部分存储到磁盘)。

于 2012-01-03T21:09:08.180 回答
1

我相信问题与封装 ArrayList 的 LineStrip2D 类有关:List 实现是由 Array 后端,其大小线性增长(如此处所述ArrayList: How do do the size increase?)。我相信你的内存用完了,因为 ArrayList 分配了一个具有新大小的全新数组,同时保留了旧数组(http://en.wikipedia.org/wiki/Dynamic_array)。因此,要完成您的绘图,您至少需要 2*MAX_SIZE。您应该增加总堆,但切换到 LinkedList 应该会改善这种情况。

于 2012-10-21T10:53:33.913 回答
0

首先你为什么要使用变量count?您可以将其替换为System.out.println(polygon.vertices.size() * polygon.vertices.size());并删除无用的递增操作count

对于内存不足错误,请尝试增加 VM 的堆大小

于 2012-01-03T20:38:36.387 回答