检测旋转的UIView之间的冲突 [英] Detecting collisions between rotated UIViews

查看:48
本文介绍了检测旋转的UIView之间的冲突的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个UIView,其中一个使用以下代码每0.01秒旋转一次:

I have two UIViews, one of which is rotated every .01 second using the following code:

    self.rectView.transform = CGAffineTransformRotate(self.rectView.transform, .05);

现在,我想知道另一个名为View的UIView是否与rectView相交。我使用了以下代码:

Now, I want to be able to tell if another UIView, called view, intersects rectView. I used this code:

if(CGRectIntersectsRect(self.rectView.frame, view.frame)) {
    //Intersection
}

但是,这可能是一个问题,您可能知道。这是屏幕截图:

There is a problem with this, however, as you probably know. Here is a screenshot:

在这种情况下,即使很明显它们没有接触,也会检测到碰撞。我环顾四周,但似乎找不到真正的代码来检测此冲突。如何才能做到这一点?在这种情况下用于检测碰撞的工作代码将不胜感激!也许还有比UIView更好的类?

In this case, a collision is detected, even though obviously they are not touching. I have looked around, but I cannot seem to find real code to detect this collision. How can this be done? Working code for detecting the collision in this case would be greatly appreciated! Or maybe would there be a better class to be using other than UIView?

推荐答案

旋转视图时,其边界将不会消失。 t改变但它的框架改变了。

when you rotate a view, its bounds won't change but its frame changes.

所以,对于我的backgroundColor blue,

我设置的初始帧是

So, for my view with backgroundColor blue,
the initial frame i set to was


frame =(30,150,150,35);

范围= {{{0,0},{150,35}};

frame = (30, 150, 150, 35);
bounds={{0, 0}, {150, 35}};

,但旋转45度后,帧变为< br>

but after rotating by 45 degree, the frame changed to


frame =(39.5926 102.093; 130.815 130.815);

bounds = {{0,0}, {150,35}};

frame = (39.5926 102.093; 130.815 130.815);
bounds={{0, 0}, {150, 35}};


因为该框架始终返回最小包围该视图的矩形

所以,在您的情况下,即使看起来ws不相交,它们的框架相交。

So, in your case, even-though it looks both views are not intersecting,their frames intersect.

要解决此问题,可以使用分离轴测试
如果您想学习,请链接此处

To solve it you can use, separating axis test. If you want learn on it, link here

我试图解决它,最后得到了解决方案。
如果您要检查,下面是代码。
复制以下代码,将其粘贴到一个空项目中以进行检查。

I tried to solve it and finally got the solution. If you like to check, below is the code. Copy paste the below code into an empty project to check it out.

在.m文件中

@implementation ViewController{
    UIView *nonRotatedView;
    UIView *rotatedView;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    nonRotatedView =[[UIView alloc] initWithFrame:CGRectMake(120, 80, 150, 40)];
    nonRotatedView.backgroundColor =[UIColor blackColor];
    [self.view addSubview:nonRotatedView];

    rotatedView =[[UIView alloc] initWithFrame:CGRectMake(30, 150, 150, 35)];
    rotatedView.backgroundColor =[UIColor blueColor];
    [self.view addSubview:rotatedView];
    CGAffineTransform t=CGAffineTransformMakeRotation(M_PI_4);
    rotatedView.transform=t;

    CAShapeLayer *layer =[CAShapeLayer layer];
    [layer setFrame:rotatedView.frame];
    [self.view.layer addSublayer:layer];
    [layer setBorderColor:[UIColor blackColor].CGColor];
    [layer setBorderWidth:1];

    CGPoint p=CGPointMake(rotatedView.bounds.size.width/2, rotatedView.bounds.size.height/2);

    p.x = -p.x;p.y=-p.y;
    CGPoint tL =CGPointApplyAffineTransform(p, t);
    tL.x +=rotatedView.center.x;
    tL.y +=rotatedView.center.y;

    p.x = -p.x;
    CGPoint tR =CGPointApplyAffineTransform(p, t);
    tR.x +=rotatedView.center.x;
    tR.y +=rotatedView.center.y;

    p.y=-p.y;
    CGPoint bR =CGPointApplyAffineTransform(p, t);
    bR.x +=rotatedView.center.x;
    bR.y +=rotatedView.center.y;

    p.x = -p.x;
    CGPoint bL =CGPointApplyAffineTransform(p, t);
    bL.x +=rotatedView.center.x;
    bL.y +=rotatedView.center.y;


    //check for edges of nonRotated Rect's edges
    BOOL contains=YES;
    CGFloat value=nonRotatedView.frame.origin.x;
    if(tL.x<value && tR.x<value && bR.x<value && bL.x<value)
        contains=NO;
    value=nonRotatedView.frame.origin.y;
    if(tL.y<value && tR.y<value && bR.y<value && bL.y<value)
        contains=NO;
    value=nonRotatedView.frame.origin.x+nonRotatedView.frame.size.width;
    if(tL.x>value && tR.x>value && bR.x>value && bL.x>value)
        contains=NO;
    value=nonRotatedView.frame.origin.y+nonRotatedView.frame.size.height;
    if(tL.y>value && tR.y>value && bR.y>value && bL.y>value)
        contains=NO;

    if(contains==NO){
        NSLog(@"no intersection 1");
        return;
    }
    //check for roatedView's edges
    CGPoint rotatedVertexArray[]={tL,tR,bR,bL,tL,tR};

    CGPoint nonRotatedVertexArray[4];
    nonRotatedVertexArray[0]=CGPointMake(nonRotatedView.frame.origin.x,nonRotatedView.frame.origin.y);
    nonRotatedVertexArray[1]=CGPointMake(nonRotatedView.frame.origin.x+nonRotatedView.frame.size.width,nonRotatedView.frame.origin.y);
    nonRotatedVertexArray[2]=CGPointMake(nonRotatedView.frame.origin.x+nonRotatedView.frame.size.width,nonRotatedView.frame.origin.y+nonRotatedView.frame.size.height);
    nonRotatedVertexArray[3]=CGPointMake(nonRotatedView.frame.origin.x,nonRotatedView.frame.origin.y+nonRotatedView.frame.size.height);

    NSInteger i,j;
    for (i=0; i<4; i++) {
        CGPoint first=rotatedVertexArray[i];
        CGPoint second=rotatedVertexArray[i+1];
        CGPoint third=rotatedVertexArray[i+2];
        CGPoint mainVector =CGPointMake(second.x-first.x, second.y-first.y);
        CGPoint selfVector =CGPointMake(third.x-first.x, third.y-first.y);
        BOOL sign;
        sign=[self crossProductOf:mainVector withPoint:selfVector];
        for (j=0; j<4; j++) {
            CGPoint otherPoint=nonRotatedVertexArray[j];
            CGPoint otherVector = CGPointMake(otherPoint.x-first.x, otherPoint.y-first.y);
            BOOL checkSign=[self crossProductOf:mainVector withPoint:otherVector];
            if(checkSign==sign)
                break;
            else if (j==3)
                contains=NO;
        }
        if(contains==NO){
            NSLog(@"no intersection 2");
            return;
        }
    }
    NSLog(@"intersection");
}


-(BOOL)crossProductOf:(CGPoint)point1 withPoint:(CGPoint)point2{
    if((point1.x*point2.y-point1.y*point2.x)>=0)
         return YES;
    else
        return NO;
}

希望这会有所帮助。

这篇关于检测旋转的UIView之间的冲突的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆