Detecting collisions between rotated UIViews

前端 未结 1 1636
闹比i
闹比i 2021-01-06 17:21

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

    self.rectView.transform = CGAffineTransformRotate(self.rectView.tr         


        
相关标签:
1条回答
  • 2021-01-06 17:51

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

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

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

    but after rotating by 45 degree, the frame changed to

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

    screenshot of running app showing frame of blue view with black border

    Because the frame always return the smallest enclosing rectangle of that view.

    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.

    In .m file

    @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;
    }
    

    Hope this helps.

    0 讨论(0)
提交回复
热议问题