简体   繁体   English

如何迭代多边形的顶点并将两个顶点相互比较?

[英]How can I iterate over the vertices of a polygon and compare two vertices with each other?

I have an XML - list of xy-coordinates (vertices) that define the edge of a polygon.我有一个 XML - 定义多边形边缘的 xy 坐标(顶点)列表。 I read this file and save the vertices in an ArrayList.我阅读了这个文件并将顶点保存在 ArrayList 中。 Now I would like to iterate over the finished ArrayList and compare two vertices with each other to decide whether the edge connecting both vertices is a north, west, south, or east edge of the simple polygon.现在我想遍历完成的 ArrayList 并相互比较两个顶点,以确定连接两个顶点的边是简单多边形的北边、西边、南边还是东边。

This is the code I can use to test whether the edge that makes up two points is a north, west, east, or south edge.这是我可以用来测试组成两点的边是北边、西边、东边还是南边的代码。

enum EdgeType {TOP, BOTTOM, LEFT, RIGHT, EMPTY}

public EdgeType orthoEdgeTypeCCW(double x0, double y0, double x1, double y1)
{
if(x0 == x1) // vertical
{           
    return (y0 < y1) ? EdgeType.RIGHT : 
           (y0 > y1) ? EdgeType.LEFT : 
                       EdgeType.EMPTY;
}
else if(y0 == y1) // horizontal
{
    return (x0 < x1) ? EdgeType.BOTTOM : 
           (x0 > x1) ? EdgeType.TOP : 
                       EdgeType.EMPTY;
}
else
{
    throw new IllegalArgumentException("Edge not orthogonal");
}
}

I have two concerns for which I don't find a solution:我有两个问题没有找到解决方案:

First I would like to test whether the vertices are sorted clockwise or counterclockwise.首先,我想测试顶点是顺时针还是逆时针排序。 Accordingly, I would have to change the code for the edge types.因此,我将不得不更改边缘类型的代码。

Second I don't know how I can iterate over the ArrayList of vertices in order to compare two of the vertices at each step.其次,我不知道如何迭代顶点的 ArrayList 以便在每个步骤中比较两个顶点。 For example in the first step v1 with v2, in the second v2 with v3, in the third v3 with v4 and so on.. Can I perhaps address the vertices in the ArrayList with their indices?例如,在第一步 v1 和 v2 中,在第二个 v2 和 v3 中,在第三个 v3 和 v4 中等等。我可以用它们的索引来处理 ArrayList 中的顶点吗?

Regarding your first question, there are a number of ways to find the orientation of a polygon.关于您的第一个问题,有多种方法可以找到多边形的方向。 See the discussion on SO here.请参阅此处关于 SO 的讨论。

As for comparing the points in a polygon, you can do something like the below:至于比较多边形中的点,您可以执行以下操作:

List<Point2D.Float> points = new ArrayList<>(); //your initial set of points
for (int i = 0; i < points.size(); i++) {
    Point2D.Float current = points.get(i);
    Point2D.Float next = points.get((i + 1) % points.size());
    //do your comparison between the two points here
}

This will compare each point with the next, including comparing the last point with the first to 'close the loop'.这会将每个点与下一个点进行比较,包括将最后一个点与第一个点进行比较以“关闭循环”。 If this isn't needed, you can do a small change to stop as soon as the last point is reached:如果不需要,您可以做一个小的更改以在到达最后一点后立即停止:

List<Point2D.Float> points = new ArrayList<>(); //your initial set of points
for (int i = 0; i < points.size() - 1; i++) {
    Point2D.Float current = points.get(i);
    Point2D.Float next = points.get((i + 1));
}

For a simple orthogonal polygon with no self-intersections you can determine its orientation (CW|CCW) by finding the lower left corner point and determining if the y value of the next point is equal to (CCW) or greater (CW).对于没有自相交的简单正交多边形,您可以通过找到左下角点并确定下一个点的 y 值是否等于 (CCW) 或更大 (CW) 来确定其方向 (CW|CCW)。

enum Orientation {CW, CCW}

public Orientation orientation(List<Point2D> points)
{
    int minIdx = 0;
    for(int i=1; i<points.size(); i++)
        if(pointOrder(points.get(i), points.get(minIdx)) <= 0) minIdx = i;

    int nextIdx = (minIdx+1) % points.size();       
    if(points.get(nextIdx).getY() == points.get(minIdx).getY()) 
        return Orientation.CCW;
    else
        return Orientation.CW;
}

public int pointOrder(Point2D p1, Point2D p2)
{
    if(p1.getY() < p2.getY()) return -1;
    else if(p1.getY() > p2.getY()) return 1;
    else if(p1.getX() < p2.getX()) return -1;
    else if(p1.getX() > p2.getX()) return 1;
    else return 0;
}

Once you have the orientation you can iterate through the edges to determine their type.一旦你有了方向,你就可以遍历边缘来确定它们的类型。

for(int i=0, j=points.size()-1; i<points.size(); j=i++)
{
    EdgeType edgeType = orthoEdgeTypeCCW(points.get(j), points.get(i));
    System.out.format("%s -> %s : %s%n", points.get(j), points.get(i), edgeType);
}

With

public EdgeType orthoEdgeTypeCCW(Point2D p1, Point2D p2)
{
    if(p1.getX() == p2.getX()) // vertical
    {           
        return (p1.getY() < p2.getY()) ? EdgeType.RIGHT : 
               (p1.getY() > p2.getY()) ? EdgeType.LEFT : 
                                         EdgeType.EMPTY;
    }
    else if(p1.getY() == p2.getY()) // horizontal
    {
        return (p1.getX() < p2.getX()) ? EdgeType.BOTTOM : 
               (p1.getX() > p2.getX()) ? EdgeType.TOP : 
                                         EdgeType.EMPTY;
    }
    else
    {
        throw new IllegalArgumentException("Edge not orthogonal");
    }
}

Obviously the type for CW polygons is reversed.显然,CW 多边形的类型是相反的。

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

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