iPhone - 矩形的交集

时间:2012-02-10 00:02:28

标签: iphone ios

我有这个NSMutableArray,它是在屏幕上移动的对象的集合。当一个物体与另一个物体相交时,我需要构造一个这个物体相交的数组。如果这个对象本身与另一个对象相交,那么这个对象必须包含在该数组中,依此类推,直到我知道所有与对象相交的对象与另一个相交,依此类推。

示例:我正在移动object1并且我与object2相交,但是object2与相交4的object3相交,相交5,依此类推。

我想在一个数组中收集所有这些对象。

我做的是:

NSMutableArray *intersectingObjects = [NSMutableArray array];

for (Obj *oneObj in allObjects) {
  if (oneObj != movingObject) {
      if (CGRectIntersectsRect(movingObject.frame, oneObj)) {
         [intersectingObjects addObject:oneObj];
      }
   }
}

// at this point I got an array of all objects intersecting with the
// moving object, then I created a similar block to
// test all these intersecting objects against all objects again,
// then I discovered the objects that were intersecting with the first block

问题是这只给了我2层深度。

如何在这里创建递归,这将转到整个可能性树?

感谢。

4 个答案:

答案 0 :(得分:3)

因为1次计算将是O(n ^ 2)的量级,我建议为每个包含它当前正在交叉的对象的对象维护一个NSMutableArray。然后,每个新计算的顺序变为O(n),只需将树中的项目合并即可。

但是,如果你仍然想要追求O(n ^ 2)方法,这是一个例子。我假设Obj是UIView的子类?

- (void) addViewsWhichIntersectView:(Obj*)movingObject toArray:(NSMutableArray*) intersectingObjects
{
    for (Obj *oneObj in allObjects) 
    {
        if (movingObject != oneObj && //assuming you only care about address comparison, override isEqual and use that method otherwise
            ![intersectingObjects containsObject:oneObj) &&
            CGRectIntersectsRect(movingObject.frame, oneObj.frame)
        {
            [intersectingObjects addObject:oneObj];
            [self addViewsWhichIntersectView: oneObj toArray:intersectingObjects];
        }
    }
}

然后对于驱动程序,只需初始化一个可变数组并传入对原始对象的引用。

答案 1 :(得分:2)

[self intersectingObjects:allObjects withObject:movingObject];

- (NSMutableArray*) intersectingObjects:(NSArray*)objects withObject:(id)obj{

   NSMutableArray * objectsToCheck = [NSMutableArray arrayWithArray:objects];
   [objectsToCheck removeObject:obj];

   NSMutableArray * intersectingWith = [NSMutableArray array];

   for (id oneStepObj in objectsToCheck) {

         if (CGRectIntersectsRect(obj.frame, oneStepObj)) {

            //This object intersected with the provided object
            [intersectingWith addObject:oneStepObj];

            //Also add all the objects that intersect with oneStepObj, take care of duplicates
            for(id nStepObj in [self intersectingObjects:objectsToCheck withObject:oneStepObj]){
                if(![intersectingWith containsObject:nStepObj]){
                   [intersectingWith addObject:nStepObj];
                }
            }
         }
      }
   }

   return intersectingWith;
}

答案 2 :(得分:1)

这是N ^ 2方法(适用于小N):

*intersectingObjects = [NSMutableArray array];

for (Obj *oneObj in allObjects) {
    for (Obj* twoObj in allObjects) {
        if ( oneObj != twoObj ) {
            if (CGRectIntersectsRect(movingObject.frame, oneObj)) {
                [intersectingObjects addObject:oneObj];
            }
        }
    }
}

为了更快,你必须做某种索引。除非您拥有按位置索引的对象的数据结构,否则此处的递归不一定更好。但是维护该索引需要工作(通常在更新位置时)。

答案 3 :(得分:1)

我写了一个非常好的应用程序,它被称为QColor - 如果你想看到它,请给我一个促销代码请求。

根据我的经验,iPhone使用效率低下的算法停止更新。这就是我所确定的(伪代码 - 对不起,完整的消息来源还有很多其他内容)。

有一点需要注意,此算法会保留多个重叠的矩形,因此当您更新屏幕时,需要在最长矩形的交叉点上显示SubviewToFront:

NSArray intersections;  // each Intersection is an array of rectangles with a calculated rect - contact me if you want code that can do this (it's not glorious).

- (void) addRect: newRect {
    intersections addObject: newRect;
    for (Intersection *intersection in intersections) {
        if (intersection intersects newRect) {
            create new intersection of intersection + newRect
            // note, do NOT modify the intersection - add a NEW one. Important point.
        }
    }
}

- (void) removeRect: aRect {
    remove every intersection that contains aRect - careful, don't use fast enumeration while editing the data structure.
}

- (void) moveRect: aRect {
    for (Intersection *intersection in intersections) {
        if (intersection contains aRect) {
            recompute the intersection with the moved aRect. If ANY rectangle no longer intersects, delete the entire intersection (compare count before and after recalculation)
        } else { 
            if (intersection intersects newRect) {
                create new intersection of intersection + newRect
            }
        }
    }
}

这不像递归算法那么漂亮,但重要的是保持交叉点总数较低。现在我首先尝试用n!算法当然让它窒息。上面的n ^ 2,我不确定它是否足够。据我了解我的算法,每次通过是n阶,尽管一些重叠(但不完全)的最坏情况例子可能是n! (这是数据,而不是算法)。

如果您想要显示矩形,我的应用页面上有一些屏幕截图:http://itunes.apple.com/ph/app/qcolor/id490077718?mt=8

要跑步 - 抱歉打字错误!

达明