【问题标题】:Partial Convex Hull部分凸包
【发布时间】:2018-12-29 21:01:53
【问题描述】:

我有一个顶点为 P1、P2、P3、.....P11 的多边形。我的顶点坐标数据类型是双精度的。

我在 P1、P7 之间也有一条线。

我想在 P1 和 P7 之间创建一个部分凸包,并在 P7 之后保留我原来的多边形顶点。

所以最终的多边形如下;

到目前为止,我将整个多边形转换为凸包,删除凸包中的顶点并添加包顶点。它适用于小多边形,但当顶点数增加时,这种方式管理起来并不容易。

我试图寻找可用于部分凸包的 c# 算法,但除了一些研究之外我找不到任何东西。

有什么想法吗?

【问题讨论】:

  • 经过中间的那条线到底与问题有什么关系?
  • 只是随机的,不在中间。这就是为什么安德鲁的单调链凸包算法也不适合:(
  • 但是它是从哪里来的,它与问题有什么关系呢?
  • 多边形代表障碍物,线是起点和终点之间的直线延伸,穿过障碍物。
  • 您是否在做部分凸包以确保这些点之间没有障碍物?因为那并不总是有效。另一方面,也有很多情况下,由这两个点之间的顶点定义的部分凸包远远超过了移除障碍物所需的量。也许有关您的最终目标的更多详细信息将有助于我们为您提供更多帮助。

标签: c# convex-hull


【解决方案1】:

我使用 DotSpatial 裁剪了多边形

internal static IGeometry Polygonize(IGeometry geometry)
        {
            var lines = LineStringExtracter.GetLines(geometry);
            var polygonizer = new Polygonizer();
            polygonizer.Add(lines);
            var polys = polygonizer.GetPolygons();
            var polyArray = GeometryFactory.ToGeometryArray(polys);
            return geometry.Factory.CreateGeometryCollection(polyArray);
        }

        internal static IGeometry PolygonizeForClip(IGeometry geometry, IPreparedGeometry clip)
        {
            var lines = LineStringExtracter.GetLines(geometry);
            var clippedLines = new List<IGeometry>();
            foreach (ILineString line in lines)
            {
                if (clip.Contains(line))
                    clippedLines.Add(line);
            }
            var polygonizer = new Polygonizer();
            polygonizer.Add(clippedLines);
            var polys = polygonizer.GetPolygons();
            var polyArray = GeometryFactory.ToGeometryArray(polys);
            return geometry.Factory.CreateGeometryCollection(polyArray);
        }

        internal static IGeometry SplitPolygon(IGeometry polygon, IGeometry line)
        {
            var nodedLinework = polygon.Boundary.Union(line);
            var polygons = Polygonize(nodedLinework);

            // only keep polygons which are inside the input
            var output = new List<IGeometry>();
            for (var i = 0; i < polygons.NumGeometries; i++)
            {
                var candpoly = (IPolygon)polygons.GetGeometryN(i);
                if (polygon.Contains(candpoly.InteriorPoint))
                    output.Add(candpoly);
            }

            return polygon.Factory.BuildGeometry(output);
        }

        internal static IGeometry ClipPolygon(IGeometry polygon, IPolygonal clipPolygonal)
        {
            var clipPolygon = (IGeometry)clipPolygonal;
            var nodedLinework = polygon.Boundary.Union(clipPolygon.Boundary);
            var polygons = Polygonize(nodedLinework);


            // only keep polygons which are inside the input
            var output = new List<IGeometry>();
            for (var i = 0; i < polygons.NumGeometries; i++)
            {
                var candpoly = (IPolygon)polygons.GetGeometryN(i);
                var interiorPoint = candpoly.InteriorPoint;
                if (polygon.Contains(interiorPoint) &&

                    clipPolygon.Contains(interiorPoint))
                    output.Add(candpoly);
            }

            return polygon.Factory.BuildGeometry(output);
        }

然后

var Splitted = SplitPolygon(Polygon, Line);

然后添加部分。

【讨论】:

    【解决方案2】:

    从多边形中删除顶点 P8 到 P11 并将它们存储起来,然后在剩下的部分(P1 到 P7)上运行凸包转换。之后,重新插入顶点 P8 到 P11(在 P7 和 P1 之间)。

    【讨论】:

    • 这就是我现在正在做的,但我需要一个更好的解决方案。我正计划使用具有 1M 顶点的多边形,这不是一个合适的方法。
    • 抱歉,如果我误解了,但听起来你现在正在做的是在整个多边形上运行转换,如果你首先删除你想不理会的顶点,可以优化它。如果情况已经如此,您认为从不同的方法可以获得什么收益?如果您要转换 1M 顶点中的很大一部分,那么我不确定除了找到一个高性能的外壳转换算法之外还能做些什么。如果您希望转换的百分比很低,那么所描述的方法就足够了。是否有更具体的瓶颈让您担心?
    • 实际上整个多边形需要大约 3ms 才能转换为带点空间的凸包。删除和重建需要更长的时间,尤其是对于大多边形。我只是厌倦了删除和重建,所以想也许有一些东西可以让这更容易。我正在研究其他方法,方法是使用点空间将多边形剪裁成碎片,将凸包应用于我需要的碎片并再次合并碎片。看起来它比我的第一种方法要少。
    猜你喜欢
    • 2013-11-12
    • 2012-07-13
    • 1970-01-01
    • 2015-05-24
    • 1970-01-01
    • 2018-07-28
    • 2016-11-19
    • 2013-10-09
    • 2018-11-21
    相关资源
    最近更新 更多