我正在自定义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 列表,这构成了算法的主要输入。
该算法进行如下。
active_y
。这是非 Activity 列表上第一个子视图的y坐标。 active_y
行上具有原点的子视图移动到工作列表中,并按x升序排序。这是 Activity 列表。 left
和right
)。一旦看到无法与right
相交的left
子视图,就可以推进left
索引。 active_y
下方。一旦完成,您应该将其从 Activity 列表中删除。 当非 Activity 列表上的所有子视图都已被使用并且 Activity 列表的最终运行完成时,该算法完成。
该算法大大减少了您需要执行的冲突检测次数,大约为O(n log n),但它也可以简化冲突检测本身。
由于 Activity 列表是从左到右排序的,因此您在执行例行程序时始终知道检测哪个在左边,哪个在右边。因此,例如,在比较示例中的箭头形状时,您仅需要检查右侧形状的两个最左侧顶点是否在左侧形状内。您可能会发现
CGPathContainsPoint
有用。如果要处理的不同形状的数量增加,则可能需要考虑将碰撞检测推入扫描线算法本身。这有点棘手,但是从根本上讲,列表将代替包含子视图指针的列表,而将包含构成形状的线段(不包括水平线段)。