如何在多边形的顶点上进行迭代,并将两个顶点进行比较?

huangapple go评论81阅读模式
英文:

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

问题

以下是您要求的翻译内容:

我有一个XML文件,其中包含定义多边形边缘的xy坐标(顶点)列表。我读取这个文件并将顶点保存在一个ArrayList中。现在我想遍历完成的ArrayList,并将两个顶点进行比较,以决定连接这两个顶点的边是简单多边形的北、西、南还是东边。

这是我用来测试由两个点组成的边是北、西、东还是南边的代码。

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

public EdgeType orthoEdgeTypeCCW(double x0, double y0, double x1, double y1)
{
    if(x0 == x1) // 垂直
    {           
        return (y0 < y1) ? EdgeType.RIGHT : 
               (y0 > y1) ? EdgeType.LEFT : 
                           EdgeType.EMPTY;
    }
    else if(y0 == y1) // 水平
    {
        return (x0 < x1) ? EdgeType.BOTTOM : 
               (x0 > x1) ? EdgeType.TOP : 
                           EdgeType.EMPTY;
    }
    else
    {
        throw new IllegalArgumentException("边不正交");
    }
}

我有两个问题没有找到解决方案:

首先,我想测试顶点是否按顺时针或逆时针排序。相应地,我将不得不更改边缘类型的代码。

其次,我不知道如何遍历顶点的ArrayList,以便在每一步中比较两个顶点。例如,在第一步中v1与v2,第二步中v2与v3,第三步中v3与v4,依此类推... 我可以通过索引来访问ArrayList中的顶点吗?

英文:

I have an XML - list of xy-coordinates (vertices) that define the edge of a polygon. I read this file and save the vertices in an 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.

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 &lt; y1) ? EdgeType.RIGHT : 
           (y0 &gt; y1) ? EdgeType.LEFT : 
                       EdgeType.EMPTY;
}
else if(y0 == y1) // horizontal
{
    return (x0 &lt; x1) ? EdgeType.BOTTOM : 
           (x0 &gt; x1) ? EdgeType.TOP : 
                       EdgeType.EMPTY;
}
else
{
    throw new IllegalArgumentException(&quot;Edge not orthogonal&quot;);
}
}

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.
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?

答案1

得分: 1

关于您的第一个问题,有多种方法可以找到多边形的方向。请参考这里的Stack Overflow讨论。

至于比较多边形中的点,您可以像下面这样做:

List<Point2D.Float> points = new ArrayList<>(); //您的初始点集
for (int i = 0; i < points.size(); i++) {
    Point2D.Float current = points.get(i);
    Point2D.Float next = points.get((i + 1) % points.size());
    //在这里进行两个点的比较
}

这将比较每个点与其后一个点,包括将最后一个点与第一个点进行比较以“闭合循环”。如果不需要这样做,您可以做一个小改变,一旦达到最后一个点,就停止:

List<Point2D.Float> points = new ArrayList<>(); //您的初始点集
for (int i = 0; i < points.size() - 1; i++) {
    Point2D.Float current = points.get(i);
    Point2D.Float next = points.get((i + 1));
}
英文:

Regarding your first question, there are a number of ways to find the orientation of a polygon. See the discussion on SO here.

As for comparing the points in a polygon, you can do something like the below:

List&lt;Point2D.Float&gt; points = new ArrayList&lt;&gt;(); //your initial set of points
for (int i = 0; i &lt; 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&lt;Point2D.Float&gt; points = new ArrayList&lt;&gt;(); //your initial set of points
for (int i = 0; i &lt; points.size() - 1; i++) {
    Point2D.Float current = points.get(i);
    Point2D.Float next = points.get((i + 1));
}

答案2

得分: 1

对于一个没有自交的简单正交多边形,你可以通过找到左下角的点,并判断下一个点的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;
}

一旦你有了方向,就可以通过迭代边来确定它们的类型。

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

使用以下方法:

public EdgeType orthoEdgeTypeCCW(Point2D p1, Point2D p2)
{
    if(p1.getX() == p2.getX()) // 垂直
    {			
        return (p1.getY() < p2.getY()) ? EdgeType.RIGHT : 
               (p1.getY() > p2.getY()) ? EdgeType.LEFT : 
                                         EdgeType.EMPTY;
    }
    else if(p1.getY() == p2.getY()) // 水平
    {
        return (p1.getX() < p2.getX()) ? EdgeType.BOTTOM : 
               (p1.getX() > p2.getX()) ? EdgeType.TOP : 
                                         EdgeType.EMPTY;
    }
    else
    {
        throw new IllegalArgumentException("边不正交");
    }
}

显然,对于CW多边形,类型是相反的。

英文:

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).

enum Orientation {CW, CCW}

public Orientation orientation(List&lt;Point2D&gt; points)
{
	int minIdx = 0;
	for(int i=1; i&lt;points.size(); i++)
		if(pointOrder(points.get(i), points.get(minIdx)) &lt;= 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() &lt; p2.getY()) return -1;
	else if(p1.getY() &gt; p2.getY()) return 1;
	else if(p1.getX() &lt; p2.getX()) return -1;
	else if(p1.getX() &gt; 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&lt;points.size(); j=i++)
{
	EdgeType edgeType = orthoEdgeTypeCCW(points.get(j), points.get(i));
	System.out.format(&quot;%s -&gt; %s : %s%n&quot;, points.get(j), points.get(i), edgeType);
}

With

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

Obviously the type for CW polygons is reversed.

huangapple
  • 本文由 发表于 2020年5月5日 20:52:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/61613618.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定