C#中如何判断直线是否与多边形相交?

发布于 2024-07-26 08:29:11 字数 430 浏览 13 评论 0原文

我有一个与此非常相似的问题:

C#中如何知道直线是否与平面相交?

我正在寻找一种方法(在 C# 中)来判断是否线与任意多边形相交。

我认为 Chris Marasti-Georg 的算法非常有帮助,但缺少最重要的方法,即线与线相交。

有谁知道线相交方法来完成 Chris Marasti-Georg 的代码或有类似的方法吗?

C# 中有内置代码吗?

此方法适用于通过禁区功能增强的 Bing 地图算法。 生成的路径不得穿过禁区(任意多边形)。

I have a question very similar to this:

How to know if a line intersects a plane in C#?

I am searching for a method (in C#) that tells if a line is intersecting an arbitrary polygon.

I think the algorithm by Chris Marasti-Georg was very helpful, but missing the most important method, i.e. line to line intersection.

Does anyone know of a line intersection method to complete Chris Marasti-Georg's code or have anything similar?

Is there a built-in code for this in C#?

This method is for use with the Bing Maps algorithm enhanced with a forbidden area feature. The resulting path must not pass through the forbidden area (the arbitrary polygon).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

静谧幽蓝 2024-08-02 08:29:11

.NET 框架中没有内置用于边缘检测的代码。

下面的代码(移植到 C#)可以满足您的需要(实际算法可以在 Google 群组的 comp.graphics.algorithms 中找到):

public static PointF FindLineIntersection(PointF start1, PointF end1, PointF start2, PointF end2)
{
    float denom = ((end1.X - start1.X) * (end2.Y - start2.Y)) - ((end1.Y - start1.Y) * (end2.X - start2.X));

    //  AB & CD are parallel 
    if (denom == 0)
        return PointF.Empty;

    float numer = ((start1.Y - start2.Y) * (end2.X - start2.X)) - ((start1.X - start2.X) * (end2.Y - start2.Y));

    float r = numer / denom;

    float numer2 = ((start1.Y - start2.Y) * (end1.X - start1.X)) - ((start1.X - start2.X) * (end1.Y - start1.Y));

    float s = numer2 / denom;

    if ((r < 0 || r > 1) || (s < 0 || s > 1))
        return PointF.Empty;

    // Find intersection point
    PointF result = new PointF();
    result.X = start1.X + (r * (end1.X - start1.X));
    result.Y = start1.Y + (r * (end1.Y - start1.Y));

    return result;
 }

There is no builtin code for edge detection built into the .NET framework.

Here's code (ported to C#) that does what you need (the actual algorithm is found at comp.graphics.algorithms on Google groups) :

public static PointF FindLineIntersection(PointF start1, PointF end1, PointF start2, PointF end2)
{
    float denom = ((end1.X - start1.X) * (end2.Y - start2.Y)) - ((end1.Y - start1.Y) * (end2.X - start2.X));

    //  AB & CD are parallel 
    if (denom == 0)
        return PointF.Empty;

    float numer = ((start1.Y - start2.Y) * (end2.X - start2.X)) - ((start1.X - start2.X) * (end2.Y - start2.Y));

    float r = numer / denom;

    float numer2 = ((start1.Y - start2.Y) * (end1.X - start1.X)) - ((start1.X - start2.X) * (end1.Y - start1.Y));

    float s = numer2 / denom;

    if ((r < 0 || r > 1) || (s < 0 || s > 1))
        return PointF.Empty;

    // Find intersection point
    PointF result = new PointF();
    result.X = start1.X + (r * (end1.X - start1.X));
    result.Y = start1.Y + (r * (end1.Y - start1.Y));

    return result;
 }
幸福%小乖 2024-08-02 08:29:11

有点偏离主题,但如果该线是无限,我认为有一个更简单的解决方案:

如果所有点都位于多边形的同一,则该线不会穿过多边形线。

在这两个的帮助下:

我得到了这个小宝石:

  public class PointsAndLines
  {
    public static bool IsOutside(Point lineP1, Point lineP2, IEnumerable<Point> region)
    {
      if (region == null || !region.Any()) return true;
      var side = GetSide(lineP1, lineP2, region.First());
      return
        side == 0
        ? false
        : region.All(x => GetSide(lineP1, lineP2, x) == side);
    }

    public static int GetSide(Point lineP1, Point lineP2, Point queryP)
    {
      return Math.Sign((lineP2.X - lineP1.X) * (queryP.Y - lineP1.Y) - (lineP2.Y - lineP1.Y) * (queryP.X - lineP1.X));
    }
  }

Slightly off topic, but if the line is infinite I think there's a much simpler solution:

The line does not go through the polygon if all the point lie on the same side of the line.

With help from these two:

I got this little gem:

  public class PointsAndLines
  {
    public static bool IsOutside(Point lineP1, Point lineP2, IEnumerable<Point> region)
    {
      if (region == null || !region.Any()) return true;
      var side = GetSide(lineP1, lineP2, region.First());
      return
        side == 0
        ? false
        : region.All(x => GetSide(lineP1, lineP2, x) == side);
    }

    public static int GetSide(Point lineP1, Point lineP2, Point queryP)
    {
      return Math.Sign((lineP2.X - lineP1.X) * (queryP.Y - lineP1.Y) - (lineP2.Y - lineP1.Y) * (queryP.X - lineP1.X));
    }
  }
风吹雨成花 2024-08-02 08:29:11

为了检测 silverlight 地图项目中多边形之间的碰撞,我们使用 Clipper 库:

免费用于商业用途、尺寸小、性能出色且非常易于使用。

Clipper 网页

To detect collisions between polygons in our silverlight map project, we're using clipper library:

Free for commercial use, small size, great performance and very easy to use.

Clipper webpage

完美的未来在梦里 2024-08-02 08:29:11

这篇文章看起来会有所帮助

http://www.codeproject.com/KB/recipes /2dpolyclip.aspx

此代码是一种二维多边形裁剪算法,可精确确定直线与多边形边界相交的位置。 该代码适用于完全任意形状的凹多边形和凸多边形,并且能够处理任何线方向。

This article looks like it will help

http://www.codeproject.com/KB/recipes/2dpolyclip.aspx

This code is a two-dimensional polygon-clipping algorithm that determines precisely where a line intersects with a polygon border. This code works for both concave and convex polygons of completely arbitrary shape and is able to handle any line orientation.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文