我有这个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层深度。
如何在这里创建递归,这将转到整个可能性树?
感谢。
答案 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
要跑步 - 抱歉打字错误!
达明