【问题标题】:java.awt.geom.Area object duplicating points?java.awt.geom.Area 对象重复点?
【发布时间】:2016-10-07 23:20:44
【问题描述】:

我使用很多 2D 浮点多边形。我想出了一个用例,我需要从另一个中减去一个,所以我想我会使用 java.awt.geom.Area。我用四个点创建了一个 Area 对象:

100.0, 50.0
150.0, 0.0
151.41421356237308, 2.8284271247461112
99.99999999999973, 54.242640687118936

无论我在创建区域时如何排序这些点,我都会返回以下内容:

SEG_MOVETO, 150.0, 0.0
SEG_LINETO, 100.0, 50.0
SEG_LINETO, 99.99999999999973, 54.24264068711893
SEG_LINETO, 99.99999999999974, 54.24264068711893
SEG_LINETO, 151.41421356237308, 2.8284271247461112
SEG_LINETO, 150.0, 0.0
SEG_CLOSE, 150.0, 0.0

注意几乎相同的双重99.99999999999973, 54.24264068711893坐标。

任何有关如何避免这种情况的线索都将受到欢迎。代码如下:

import java.awt.geom.Area;
import java.awt.geom.Path2D;
import java.awt.geom.PathIterator;

class Main {
    public static final void main( String args[] ) {
        double[] myPoly = {100.0, 50.0, 150.0, 0.0, 151.41421356237308, 2.8284271247461112, 99.99999999999973, 54.242640687118936};
        final Area myArea = makeArea(myPoly);
        System.out.println(areaToString(myArea));
    }

    private static Area makeArea(double coords[]) {
        final Path2D path = new Path2D.Double();
        path.moveTo(coords[0], coords[1]);
        for (int i = 2; i < coords.length; i+=2) {
            path.lineTo(coords[i], coords[i+1]);
        }
        path.closePath();
        return new Area(path);
    }

    private static String areaToString(final Area area) {
        final StringBuffer out = new StringBuffer("Area [\n");
        double []pt = new double[6];
        for (PathIterator pi = area.getPathIterator(null); !pi.isDone(); pi.next()) {
            int type = pi.currentSegment(pt);
            out.append(type).append(", ").append(pt[0]).append(", ").append(pt[1]).append("\n");
        }
        return out.append(']').toString();
    }
}

【问题讨论】:

    标签: java duplicates point area path-2d


    【解决方案1】:

    如果您仔细查看这些值,您会发现 99.99999999999973 和 99.99999999999974 在一个 unit of least precision (ULP) 之内。这是浮点数的常见问题。你不能准确地表示每个数字。

    如果你改变一下,用类似的方法直接打印出Path2D对象,就不会发生重复。

    javadoc of Area 状态

    即使原始轮廓简单明了,一个区域也可能需要更多的路径段来描述相同的几何图形。 Area 类必须在路径上执行的分析可能与人类感知的“简单而明显”的概念不同。

    总而言之,可能发生的情况是该区域优化了 Path 对象,从而引入了您看到的工件。我还没有深入研究 Area 的源代码来了解这种特定的路径分解是如何选择的。

    【讨论】:

    • 看起来该区域 javadoc 的项目符号正是针对这种情况编写的。尽管如此,Area 对象会在一个 ULP 内插入一个点,这似乎很奇怪。无论如何,缺点是如果您对这样的对象执行连续的Area.subtract() 操作,重复项会累积。这就是生活。当我将其从区域转换回多边形时,我只是编写了过滤掉重复数据的代码。感谢您的提示。
    • 使用浮点数时,经常会遇到这些问题。我会冒险猜测 Area 做了一些内部计算,然后由于精度损失,点不再匹配并且路径被分割。您可能希望重新构建一条路径,将彼此之间的某些 ULP 内的点组合起来,以便更好地打印。
    猜你喜欢
    • 1970-01-01
    • 2013-07-04
    • 2019-07-23
    • 1970-01-01
    • 2017-05-01
    • 2011-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多