简体   繁体   English

java.awt.geom.Area对象重复点?

[英]java.awt.geom.Area object duplicating points?

I work with a lot of 2D floating point polygons. 我使用许多2D浮点多边形。 I came up with a use case where I need to subtract one from another, so I thought I'd use java.awt.geom.Area. 我想出了一个用例,其中我需要一个减去另一个,所以我认为我会使用java.awt.geom.Area。 I create an Area object with four points: 我创建一个具有四个点的Area对象:

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

And independent of how I order those points when creating the Area, I get back the following: 并且与创建区域时如何排序这些点无关,我得到以下信息:

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

Note the almost identical dual 99.99999999999973, 54.24264068711893 coordinates. 注意几乎相同的双99.99999999999973, 54.24264068711893坐标。

Any clues in how to avoid that would be most welcome. 任何避免这种情况的线索都将受到欢迎。 Here's the code: 这是代码:

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();
    }
}

If you take a close look at those values, you will find that 99.99999999999973 and 99.99999999999974 are within one unit of least precision (ULP) of each other. 如果仔细查看这些值,您会发现99.99999999999973和99.99999999999974在彼此的最低精度(ULP)单位内。 This is a common problem with floating-point numbers. 这是浮点数的常见问题。 You can not represent every number exactly. 您不能完全代表每个数字。

If you change things up and directly print out the Path2D object with a similar method, none of the duplicating happens. 如果您进行更改并使用类似的方法直接打印出Path2D对象,则不会发生任何重复。

The javadoc of Area states 区域状态的Javadoc

An Area may take more path segments to describe the same geometry even when the original outline is simple and obvious. 即使原始轮廓简单明了,一个区域也可能需要更多路径段来描述相同的几何图形。 The analysis that the Area class must perform on the path may not reflect the same concepts of "simple and obvious" as a human being perceives. Area类必须在路径上执行的分析可能无法反映出人类所感知的“简单而明显”的概念。

So all in all, what likely happens is that area optimizes the Path object, and thus introduces the artifacts you see. 因此,总而言之,该区域可能会优化Path对象,从而引入您看到的工件。 I have not dug into the source code of Area to find out how exactly this particular decomposition of the path is chosen. 我还没有深入研究Area的源代码,以了解如何选择这种路径的特定分解。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM