2012-07-13 200 views
2

我正在自定义UIView中创建多个自定义UIView's。自定义子视图的创建是可以的。他们是这样的:多个UIView的重叠

enter image description here

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]; 

它添加到超级视图也非常简单:

ITContextFigure *view = [[ITContextFigure alloc] initWithFrame:CGRectMake(location.x, location.y, 135.0f, 50.0f)]; 
    [view setBackgroundColor:[UIColor yellowColor]]; 
    [self addSubview:view]; 

所以我的问题是:

1)Ho我可以检测到一个与另一个重叠吗?

我看到这个解决方案:

if (CGRectContainsRect([myImageView1 frame], [myImageView2 frame])) { 
     NSLog(@"Overlaped, it's working!"); 
} 

但是,如果我有多个UIViews,做对super view一个for和检查每一个单个子视图似乎并没有很好的解决方案给我。

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

enter image description here

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

enter image description here


更新1.0

打算尝试什么已经显示为here,因为没有更优雅的方式。如果我能够实现它,我会在Github上发布代码,如果有人需要的话。

+0

我想你可能想要搜索算法来检测相交多边形(这涉及每对线段和线段相交的蛮力)。 – nhahtdh 2012-07-13 15:12:13

+0

我猜你在2)的情况是边界矩形重叠,但视图的主要内容不? – 2012-07-13 15:12:25

+0

@nhahtdh不总是一个蛮力,你可以做分离轴定理检测任意(凸)多边形上的交点 – 2012-07-13 15:13:16

回答

3

通过巧妙地对数据进行排序(这些称为扫描线或渗透线算法),您可以显着减少您需要执行的碰撞​​检测次数。以下是您如何将这种技术应用于您的情况的大纲。

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

算法进行如下。

  1. 虽然有不活动的子视图,请选择active_y。这是非活动列表中第一个子视图的y坐标。

  2. 将所有具有active_y行上的原点的子视图移动到工作列表,按升序x排序。这是活动列表。

  3. 通过活动列表冲突测试每个子视图与列表中的后续列表。你可以在列表中使用两个索引(我们称之为leftright)。只要您看到right子视图不能与left相交,就可以提前输入left索引。

  4. 在进行碰撞检测时,您还要检查子视图是否现在完全低于active_y。一旦它,你应该从活动列表中删除它。

算法在非活动列表上的所有子视图都已被占用并且最终运行通过活动列表完成时完成。

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

由于活动列表是从左到右排序的,因此您总是知道您在做什么检测例程,哪一个在左边,哪个在右边。因此,例如,在比较示例中的箭头形状时,只需检查右侧形状的两个最左侧顶点是否落在左侧形状内。你可能会发现CGPathContainsPoint有用。

如果您正在处理的不同形状的数量增加,那么您可能需要考虑将碰撞检测推入扫描线算法本身。这有点棘手,但基本上,而不是持有子视图指针的列表,他们将持有构成形状(不包括水平)的线段。

+0

idz是否可以删除多余的黄色部分? – Peres 2012-07-19 08:47:18

+1

是的,不是设置背景颜色,而是用黄色填充路径,然后用棕色填充。将UIView的背景颜色设置为clearColor,并确保视图的opaque属性为NO。检出'CGContextFillPath',你也可能需要'CGContextSetRGBFillColor'(我不记得是否通过'UIColor'设置了填充颜色)。 – idz 2012-07-19 18:01:26