【问题标题】:Scanline algorithm: how to calculate intersection points扫描线算法:如何计算交点
【发布时间】:2014-06-28 17:49:20
【问题描述】:

我必须从我们的教授那里实现扫描线算法,但我真的不明白如何从扫描线与多边形获取交点。 这是算法:

我已经实现了自己的多边形(使用 paint()contains() 等方法),并且我将多边形的所有边保存在这样的数组中:

int[] pointsX;
int[] pointsY;

我保存了 x 和 y 的最小值和最大值

int ymin, ymax, xmin, xmax;

所以我的第一个想法是我必须创建一个从0,ymin 开始的扫描线,并检查下一个点是否在多边形内。我这样实现了这个方法:

public boolean contains(Point test) {
    boolean result = false;

    java.awt.Polygon polygon = new java.awt.Polygon(pointsX, pointsY, pointsX.length);
    if (polygon.contains(test)) {
        result = true;
    }

    return result;
}

所以当下一个点在多边形内时,我就有了一个交点,依此类推。为此我有这个循环:

ArrayList<Point> intersectionPoints = new ArrayList<>();
wasInside = false;
    for (int yTemp = ymin; yTemp <= ymax; yTemp++) {
        for (int xTemp = xmin; xTemp <= xmax; xTemp++) {
            if (wasInside != this.contains(new Point(xTemp, yTemp))) {
                intersectionPoints.add(new Point(xTemp, yTemp));
                wasInside = !wasInside;
            }
        }
    }

但我从my stackoverflow question 得到提示,这不是正确的解决方案。

有人可以给我一个提示,我可以如何从我的教授那里开始实施算法?我在哪里获得 x1,y1,x2,y2,c 积分?我知道这些是边缘,但我怎么知道我必须采取哪些边缘?

编辑: 好的,现在我将所有边按它们的 y 值排序。我可以用给定的公式 Sx=x1+(x2-x1)/... 计算交点吗? 我的第一次尝试是这样的:

for (int c = ymin; c <= ymax; c++) {
        for (int xTemp = xmin; xTemp <= xmax; xTemp++) {
            for (int currentEdge = 0; currentEdge < edges.size() - 1; currentEdge++) {
                int x1 = edges.get(currentEdge).x;
                int x2 = edges.get(currentEdge + 1).x;
                int y1 = edges.get(currentEdge).y;
                int y2 = edges.get(currentEdge + 1).y;
                if ((y1 <= c && y2 > c) || (y2 <= c && y1 > c)) {
                    intersectionPoints.add(new Point((x1 + (x2 - x1) / (y2 - y1) * (c - y1)),c));
                }
            }
        }
    }

但这似乎是错误的,因为我在intersectionPoints 中得到了很多错误的积分。

【问题讨论】:

  • 扫描线算法通常维护一组“活动边”(即与当前扫描线相交的边)。 “c”只是扫描线的当前 y 位置。并且 (x1,y1) 和 (x2,y2) 点只是一个活动边的端点。你必须根据它们的 y 值对所有边进行排序,然后让 c 从 ymin 走到 ymax,每当你扫描一个角时更新一组活动边。
  • 感谢您的提示。我添加了计算交点的尝试,但其中有错误。我究竟做错了什么?我想我还没有很好地理解这个算法......
  • 您从未设法说出您要计算的内容。 “扫描线”是一类可以计算很多东西的算法。正如@Marco13 所说,扫描线本身是一个数据结构,通常包括它当前相交的边、线段、弧等的列表。边缘等的端点以及交叉点被处理为改变扫描线的“事件”。
  • 对不起,我想用扫描线算法填充多边形。

标签: java scanline


【解决方案1】:

问题是我用int 数字和int 除以另一个int 计算结果不准确。因此,只需使用 double 数字就可以解决它。

这就是我计算交点的方式: edges 是一个包含边缘点的ArrayList&lt;Point&gt;ymin 是最低的 y 值,而 `ymax`` 是最高的。

for (int yTemp = ymin; yTemp <= ymax; yTemp++) {
        ArrayList<Point> intersectionPoints = new ArrayList<>();

        for (int p = 0; p < edges.size() - 1; p++) {
            int x1, x2, y1, y2;
            double deltax, deltay, x;
            x1 = edges.get(p).x;
            y1 = edges.get(p).y;
            x2 = edges.get(p + 1).x;
            y2 = edges.get(p + 1).y;

            deltax = x2 - x1;
            deltay = y2 - y1;

            int roundedX;
            x = x1 + deltax / deltay * (yTemp - y1);
            roundedX = (int) Math.round(x);
            if ((y1 <= yTemp && y2 > yTemp) || (y2 <= yTemp && y1 > yTemp)) {
                intersectionPoints.add(new Point(roundedX, yTemp));
            }
        }
        //for the last interval
        int x1, x2, y1, y2;
        x1 = edges.get(edges.size() - 1).x;
        y1 = edges.get(edges.size() - 1).y;
        x2 = edges.get(0).x;
        y2 = edges.get(0).y;
        if ((y1 <= yTemp && y2 > yTemp) || (y2 <= yTemp && y1 > yTemp)) {
            intersectionPoints.add(new Point(x1 + (x2 - x1) / (y2 - y1) * yTemp - y1, yTemp));
        }
        //you have to sort the intersection points of every scanline from the lowest x value to thr highest
        Collections.sort(intersectionPoints, new SortXPoints());
        pointsOfScanline.add(intersectionPoints);

这将为您提供一个 ArrayList,其中包含每个扫描线的扫描线点的 ArrayList。所以你只需要使用drawLine(x1, y2, x2, y2) 来绘制它们。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-07
    • 1970-01-01
    相关资源
    最近更新 更多