【问题标题】:Preventing polygons from overlapping防止多边形重叠
【发布时间】:2015-07-31 05:56:55
【问题描述】:

我正在为 Pixelsense 创建一个 WPF 应用程序,其中有七个多边形。我可以使用触摸来移动它们。目前它们相互重叠,如下图 1 所示。

我希望一个形状(形状 A)不与另一个形状(形状 B)重叠,而是应该在靠近时卡入到位(形状 A 和形状 B 最终并排或彼此上下)如下所示。

我在 StackOverflow 上搜索过类似的问题,但是,我只能找到一些与检查点或鼠标单击是否在形状内相关的链接。不适用于重叠的完整形状或关于如何将它们固定到位。

有人对我如何做到这一点有任何想法吗?任何帮助将不胜感激。

【问题讨论】:

  • Stack Overflow 不是论坛/BBS,所以他们的简码在这里不起作用。尝试学习如何使用 SO 的 markdown 语法。
  • 非常感谢您修复它。我尝试使用 SO 的语法添加图像,但它说我需要有 10 的声誉才能发布图像。
  • 我也许可以提供一个您可以检测重叠的代码。会有帮助吗?

标签: c# wpf polygon pixelsense


【解决方案1】:

如果我们假设您使用多边形,这里有一些检测重叠的解决方案;

public static bool PointCollectionsOverlap_Slow(PointCollection area1, PointCollection area2)
{
    PathGeometry pathGeometry1 = GetPathGeometry(area1);
    PathGeometry pathGeometry2 = GetPathGeometry(area2);
    bool result = pathGeometry1.FillContainsWithDetail(pathGeometry2) != IntersectionDetail.Empty;
    return result;
}

public static PathGeometry GetPathGeometry(PointCollection polygonCorners)
{
    List<PathSegment> pathSegments = new List<PathSegment> { new PolyLineSegment(polygonCorners, true) };
    PathGeometry pathGeometry = new PathGeometry();
    pathGeometry.Figures.Add(new PathFigure(polygonCorners[0], pathSegments, true));
    return pathGeometry;
}

还有一个更快的;

public static bool PointCollectionsOverlap_Fast(PointCollection area1, PointCollection area2)
{
    for (int i = 0; i < area1.Count; i++)
    {
        for (int j = 0; j < area2.Count; j++)
        {
            if (lineSegmentsIntersect(area1[i], area1[(i + 1) % area1.Count], area2[j], area2[(j + 1) % area2.Count]))
            {
                return true;
            }
        }
    }

    if (PointCollectionContainsPoint(area1, area2[0]) ||
        PointCollectionContainsPoint(area2, area1[0]))
    {
        return true;
    }

    return false;
}

public static bool PointCollectionContainsPoint(PointCollection area, Point point)
{
    Point start = new Point(-100, -100);
    int intersections = 0;

    for (int i = 0; i < area.Count; i++)
    {
        if (lineSegmentsIntersect(area[i], area[(i + 1) % area.Count], start, point))
        {
            intersections++;
        }
    }

    return (intersections % 2) == 1;
}

private static double determinant(Vector vector1, Vector vector2)
{
    return vector1.X * vector2.Y - vector1.Y * vector2.X;
}

private static bool lineSegmentsIntersect(Point _segment1_Start, Point _segment1_End, Point _segment2_Start, Point _segment2_End)
{
    double det = determinant(_segment1_End - _segment1_Start, _segment2_Start - _segment2_End);
    double t = determinant(_segment2_Start - _segment1_Start, _segment2_Start - _segment2_End) / det;
    double u = determinant(_segment1_End - _segment1_Start, _segment2_Start - _segment1_Start) / det;
    return (t >= 0) && (u >= 0) && (t <= 1) && (u <= 1);
}

【讨论】:

  • 谢谢你。我正在尝试使用您提供的第一段代码(因为它似乎更容易理解),我只是想知道您是否可以提供一些关于理解它的进一步帮助。我有一个各种形状的对象列表,所以我想知道我应该将什么作为区域 1 和 2 传递给 PointCollectionsOverlap_Slow() 方法?我是否应该首先检测碰撞发生的位置,然后获取这两个对象的位置?
  • 因此,如果您有形状列表,则还应该有每个多边形/形状的点列表。作为参数,您应该以“PointCollection collection = polygon1.Points;”的形式传递这些点列表
  • 所以它会检测是否存在交叉路口
  • 好的,我会试试的。谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-18
  • 2012-04-22
  • 1970-01-01
  • 1970-01-01
  • 2023-04-04
  • 1970-01-01
相关资源
最近更新 更多