【问题标题】:Sorting voronoi cell vertices to compute polygon对 voronoi 单元顶点进行排序以计算多边形
【发布时间】:2015-10-04 11:06:05
【问题描述】:

我目前正在尝试从 Polygon-Voronoi-Intersection 获取剪切的单元格。

这是我目前得到的:

我有一个多边形并计算其中的一些点来计算 voronoi 图,下图中的红线是 voronoi 边缘。 然后我使用算法从每个单元格中获取角点,现在我需要在正确的方向(顺时针方向)获取角点以生成单元格多边形。

找到一个单元格的角

一开始我是用这个方法的:

private List<Vector> sortClockwise(List<Vector> points)
    {
        points = points.OrderBy(x => Math.Atan2(x.X, x.Y)).ToList();
        return points;
    }

但在某些特殊的凹多边形中,这不起作用,并且正确的顺序会混淆。

是否有人建议或暗示如何以最简单的方式完成此操作?考虑到多边形点的顺序已经正确,并且 voronoi 角混合在一起,需要对多边形点进行排序。

我的想法:

  • 在单元格角中查找第一个多边形点
  • 沿着多边形方向,看看 voronoi 顶点是否在该线上。
  • 如果是:获取找到的 voronoi 边缘的端点并寻找共享的 voronoi 边缘。
  • 如果找到共享边,总是取最右边的一条
  • 直到你达到拳头为止

这是我能做到的唯一方法吗?

编辑 - 更新

好的,我现在有一些一半的答案。

正如我所说,我拥有属于 voronoi 单元之一的所有顶点,但顺序仍然混乱,所以我想我可以像这样从质心按角度对它们进行排序:

private List<Vector> sortClockwiseBySentroid(List<Vector> points, Vector center)
    {
        points = points.OrderBy(x => Math.Atan2(x.X - center.X, x.Y - center.Y)).ToList();
        return points;
    }

但这并不总是有效。以下是它工作时和不工作时的例子。问题是在凹边上,从质心到拐角的角度有时小于我真正需要的角度。有关如何解决此问题的任何建议?

在这里工作

这里不工作...

【问题讨论】:

  • IMO,按角度排序几乎总是错误的方式。此外,由于您的多边形是凹面的,因此 voronoi 单元格和多边形的交集可能会导致多个多边形。您当前的算法没有考虑到这一点。最佳方法是使用众多多边形剪辑库中的一种,并跳过重新发明轮子。
  • 你能推荐我吗?我真的想把它分成多个多边形,但这个例子只显示了一个单元格的步骤

标签: c# .net polygon computational-geometry voronoi


【解决方案1】:

这就是在我的 Voronoi 一代中按顺时针顺序对一个单元格的顶点列表进行排序的方法。假设您知道需要对该代码进行排序的顶点应该可以完成这项工作。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;


public class ConvexHull
{
private List<Vector2> vertices;

public ConvexHull()
{
    vertices = new List<Vector2>();
}

public ConvexHull(Vector2[] vertices)
{
    this.vertices = new List<Vector2>(vertices);
}

public void AddVertices(Vector2[] vertices)
{
    this.vertices.AddRange(new List<Vector2>(vertices));
}

public Vector2[] Generate()
{
    if (vertices.Count > 1)
    {
        int k = 0;
        Vector2[] hull = new Vector2[2 * vertices.Count];

        // Make the list distinct and sorted
        vertices = vertices.Distinct().OrderBy(v => v.x).ToList();
        //vertices.Sort();
        //Array.Sort(vertices);

        // Build lower hull
        for (int i = 0; i < vertices.Count; ++i)
        {
            while (k >= 2 && Cross(hull[k - 2], hull[k - 1], vertices[i]) <= 0)
                k--;
            hull[k++] = vertices[i];
        }

        // Build upper hull
        for (int i = vertices.Count - 2, t = k + 1; i >= 0; i--)
        {
            while (k >= t && Cross(hull[k - 2], hull[k - 1], vertices[i]) <= 0)
                k--;
            hull[k++] = vertices[i];
        }
        if (k > 1)
        {
            hull = hull.Take(k - 1).ToArray();
        }
        return hull;
    }
    if (vertices.Count <= 1)
    {
        return vertices.ToArray();
    }

    return null;
}

private float Cross(Vector2 p1, Vector2 p2, Vector2 p3)
{
    return (p2.x - p1.x) * (p3.y - p1.y) - (p2.y - p1.y) * (p3.x - p1.x);
}
}

【讨论】:

  • 每当 k return hull.Take( vertices.count ).ToArray() 吗?
猜你喜欢
  • 2011-11-14
  • 2015-04-07
  • 2014-05-23
  • 1970-01-01
  • 2011-10-30
  • 2011-07-28
  • 2012-12-17
  • 2015-03-26
  • 1970-01-01
相关资源
最近更新 更多