【问题标题】:Create a polygon around a polyline like a buffer围绕折线创建一个多边形,如缓冲区
【发布时间】:2012-01-03 19:24:51
【问题描述】:

我环顾四周,找到了一个如何获取折线并在其周围创建缓冲区的示例,因此我最终得到了一个多边形。

到目前为止,我发现我需要 Minkowskis Sums 来执行此操作,但我无法专注于原始算法并将其转换为代码。

我更喜欢 C# 中的示例或算法的演练。

【问题讨论】:

  • 你需要凸多边形还是只需要多边形?
  • 我不需要凸多边形。
  • 可以使用GDI+吗?如果是,那么 GraphicPath.Widen+(OutLine) + GetPathData
  • 2D Geometry 类也可能起作用,例如使用 GetWidenedPathGeometry msdn.microsoft.com/en-us/library/ms615692.aspx获取 PathGeometry

标签: c# geometry polygon polyline


【解决方案1】:

您是否尝试过使用 Codeplex 的“Dot Spatial”库?

http://dotspatial.codeplex.com/

它在内部使用 Geos 和 Proj4,它已经包含您需要的所有功能(世界上大多数 GIS 服务器和产品都建立在这两个代码库之上!)

如果做不到这一点,您可以使用 SQlite:

http://sqlite.phxsoftware.com/

和 Spatialite:

http://www.gaia-gis.it/spatialite/

然后在 C# 中使用 ADO.NET 代码,您可以使用简单的 GIS SQL 查询来执行您的处理 EG:

SELECT AsText(ST_Buffer(polyline,0.25),4326)

WHich 会返回一个类似的字符串:

MULTIPOLYGON((x y, x y, x y, x y......))

然后你就可以解析了。

当您需要的一切都唾手可得时,无需重新发明轮子。

【讨论】:

  • 只有一个问题,'Dot Spatial' 的开源许可证与我正在开发的软件不兼容。
  • 您需要什么样的许可证?
【解决方案2】:

您可以使用Clipper 库中的 OffsetPolygons() 函数,但首先您需要将折线转换为多边形。通过将折线的反向副本附加到折线来执行此操作。但由于不允许重复顶点,反向复制必须排除第一个和最后一个顶点:v1,v2,...,vn, v(n-1),...,v2。

【讨论】:

  • 看起来 Clipper 只将 int 值作为坐标,但我的坐标是 double 值,例如。 (56.30174)。还是我错过了什么?
  • 关于 int 值,请参阅此处文档中的常见问题解答:angusj.com/delphi/clipper/documentation/Docs/Overview/FAQ.htm
  • 你知道delta是否被2除吗?因为我的多边形和我的 delta 一样宽,而不是宽度的两倍。
  • 如果折线按照上面的建议转换为多边形,那么 delta 将是多边形在原始折线两侧的扩展量。因此,新转换和扩展的折线的“宽度”将是 delta 的两倍。
【解决方案3】:

这里有一个示例方法,可以根据此链接对 .NET Framework 中已有的 2D 对象执行此类操作

http://www.charlespetzold.com/blog/2008/04/Rounded-Graphics-in-WPF.html

  // ...
  StreamGeometry geom = new StreamGeometry();

  DrawLines(geom);

  Pen p = new Pen(Brushes.Black, 10);
  p.LineJoin = PenLineJoin.Round;
  p.EndLineCap = PenLineCap.Round;
  p.StartLineCap = PenLineCap.Round;


  PathGeometry pathGeomWide = geom.GetWidenedPathGeometry(p);
  PathGeometry pathGeom = pathGeomWide.GetOutlinedPathGeometry();

  Path myPath = new Path();
  myPath.Stroke = Brushes.Black;
  myPath.Data = pathGeom;
  myCanvas.Children.Add(myPath);
  // ...

private static void DrawLines(StreamGeometry geom)
{
  using (var context = geom.Open())
  {
    context.BeginFigure(new Point(20, 20), false, true);
    context.LineTo(new Point(100, 20), true, true);
    context.LineTo(new Point(100, 100), true, true);
    context.LineTo(new Point(200, 100), true, true);
  }
}

【讨论】:

    猜你喜欢
    • 2011-08-12
    • 1970-01-01
    • 1970-01-01
    • 2012-07-26
    • 1970-01-01
    • 2013-10-22
    • 2020-02-04
    • 2012-09-27
    相关资源
    最近更新 更多