我正在自定义UIView's中创建多个自定义UIView。可以创建自定义子视图。他们看起来像这样:

draw方法非常简单:

[[UIColor brownColor] set];

CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(ctx,
                      5.0f);
CGContextBeginPath(ctx);
CGContextMoveToPoint(ctx, 0.0f, 0.0f);
CGContextAddLineToPoint(ctx, 100.0f, 0.0);
CGContextAddLineToPoint(ctx, 130.0f, 25.0f);
CGContextAddLineToPoint(ctx, 100.0f, 50.0f);
CGContextAddLineToPoint(ctx, 0.0f, 50.0f);
CGContextClosePath(ctx);
CGContextStrokePath(ctx);
[super drawRect:rect];

将其添加到 super 视图也非常简单:
    ITContextFigure *view = [[ITContextFigure alloc] initWithFrame:CGRectMake(location.x, location.y, 135.0f, 50.0f)];
    [view setBackgroundColor:[UIColor yellowColor]];
    [self addSubview:view];

所以我的问题是:

1)如何检测一个何时与另一个重叠?

我看到了这个解决方案:
if (CGRectContainsRect([myImageView1 frame], [myImageView2 frame])) {
        NSLog(@"Overlaped, it's working!");
}

但是,如果我有多个UIViews,则在for上执行super view并检查每个子视图对我来说似乎不是一个好的解决方案。

2)在这种情况下,可以做什么?

我的主要目标是检测何时发生这种情况:



更新1.0

尝试尝试here显示的内容,因为没有更优雅的方法了。如果我能够实现它,如果有人需要的话,我会将代码发布在Github上。

最佳答案

您可以通过巧妙地对数据进行排序(称为扫描线或渗透线算法)来大幅减少所需的碰撞检测次数。下面概述了如何将这种技术应用于您的情况。

将子视图排序为按y升序排列的数组。如果两个子视图共享相同的y,则将x升序排列。这是您的非 Activity 列表,这构成了算法的主要输入。

该算法进行如下。

  • 存在不 Activity 的子视图时,选择active_y。这是非 Activity 列表上第一个子视图的y坐标。
  • 将所有在active_y行上具有原点的子视图移动到工作列表中,并按x升序排序。这是 Activity 列表。
  • 运行 Activity 列表,对每个子视图与列表中的后续子视图进行碰撞测试。您可以使用列表中的两个索引来完成此操作(我们将其称为leftright)。一旦看到无法与right相交的left子视图,就可以推进left索引。
  • 在进行冲突检测时,您还要检查子视图是否现在完全位于active_y下方。一旦完成,您应该将其从 Activity 列表中删除。

  • 当非 Activity 列表上的所有子视图都已被使用并且 Activity 列表的最终运行完成时,该算法完成。

    该算法大大减少了您需要执行的冲突检测次数,大约为O(n log n),但它也可以简化冲突检测本身。

    由于 Activity 列表是从左到右排序的,因此您在执行例行程序时始终知道检测哪个在左边,哪个在右边。因此,例如,在比较示例中的箭头形状时,您仅需要检查右侧形状的两个最左侧顶点是否在左侧形状内。您可能会发现CGPathContainsPoint有用。

    如果要处理的不同形状的数量增加,则可能需要考虑将碰撞检测推入扫描线算法本身。这有点棘手,但是从根本上讲,列表将代替包含子视图指针的列表,而将包含构成形状的线段(不包括水平线段)。

    10-07 19:49
    查看更多