C# 围绕多段线创建多边形(如缓冲区)

C# 围绕多段线创建多边形(如缓冲区),c#,geometry,polygon,polyline,C#,Geometry,Polygon,Polyline,我环顾四周,找到了一个示例,说明了如何获取多段线并在其周围创建缓冲区,从而最终得到一个多边形 到目前为止,我发现我需要Minkowski求和来实现这一点,但我无法将头脑转向原始算法并将其转换为代码 我更喜欢C#中的示例或算法的演练 您是否尝试过使用Codeplex中的“点空间”库 它在内部使用Geos和Proj4,其中已经包含了您需要的所有功能(世界上大多数GIS服务器和产品都是基于这两个代码库构建的!) 否则,可以使用SQlite: 和Spatialite: 然后使用C#中的ADO.NE

我环顾四周,找到了一个示例,说明了如何获取多段线并在其周围创建缓冲区,从而最终得到一个多边形

到目前为止,我发现我需要Minkowski求和来实现这一点,但我无法将头脑转向原始算法并将其转换为代码


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

您是否尝试过使用Codeplex中的“点空间”库

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

否则,可以使用SQlite:

和Spatialite:

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

SELECT AsText(ST_Buffer(polyline,0.25),4326)
它将返回一个字符串,类似于:

MULTIPOLYGON((x y, x y, x y, x y......))
然后就可以解析了


无需重新发明轮子,因为您需要的一切都已准备就绪。

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


下面是一个示例方法,基于此链接,可以对.NET Framework中已有的2D对象执行类似操作


您需要凸多边形还是只需要多边形?我不需要凸多边形。是否可以使用GDI+?如果是,则GraphicPath.Wided+(OutLine)+GetPathData二维几何体类也可以工作,例如获取一个PathGeometry,GetWidedPathGeometry只有一个问题,“Dot Spatial”所使用的开放源代码许可证与我正在使用的软件不兼容。您需要什么样的许可证?看起来Clipper只使用int值作为坐标,但我的坐标是双值,例如(56.30174)。或者我遗漏了什么?关于int值,请参阅此处文档中的常见问题:您知道增量是除以2还是?因为“我是多边形”的宽度与“我的三角形”的宽度相同,而不是宽度的两倍。如果多段线按照上述建议转换为多边形,则“多边形”将在原始多段线的两侧展开。因此,新转换和扩展的多段线的“宽度”将是增量的两倍。
  // ...
  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);
  }
}