【问题标题】:How to discover if 2 CGPath roteted rects intersect?如何发现 2 CGPath 旋转的矩形是否相交?
【发布时间】:2013-09-29 05:14:57
【问题描述】:

在加载视图控制器时,我正在构建 2 个矩形,使用 CGPath。可以使用PanGestureRecognizer 移动矩形。问题是我怎么知道 2 rects 何时相遇?为了不让它们相交?

MainViewController.m

- (void)viewDidLoad
{
    [super viewDidLoad];

    for (int i=0; i< 2; i++) {
        //create rects of CGPath
        CGRectCustomView* randomColorRect = 
                                [[CGRectCustomView alloc]initWithFrame: 
                                CGRectMake(<random place on screen>)];
        //random angle
        randomColorRect.transform = 
                                CGAffineTransformMakeRotation
                                (DegreesToRadians([Shared randomIntBetween:0 and:360]));

        [self.view addSubview:randomColorRect];

    }

}

- (BOOL)areRectsCollide {

      ???How to find this???

}

CGRectCustomView.m:

- (void)drawRect:(CGRect)rect
{
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetLineWidth(context, 8.0); 
    CGContextStrokePath(context); // do actual stroking
    CGContextSetRGBFillColor(context, <green color>, 1); 
    CGContextFillRect(context, CGRectMake(self.frame.origin.x, self.frame.origin.y, self.frame.size.width, self.frame.size.height)); 
    path = CGContextCopyPath(context);
}

在Apple指南here中,有一个函数可以判断路径是否包含点

- (BOOL)containsPoint:(CGPoint)point onPath:(UIBezierPath *)path inFillArea:(BOOL)inFil,

但我有一个无限多点的矩形。所以我该怎么做?打破我的头......

【问题讨论】:

  • 一个矩形有“无限的点数”?这些一定是非常奇怪的矩形......
  • @bummzack 任何线/区域都由无数个点组成。至少在我对几何的理解中。但我可能错了:)
  • 噢!你当然是对的。
  • Apple 没有提供任何方法来检查旋转的矩形交点。这个answer 应该可以帮助您实现旋转矩形。碰撞检测。
  • @bummzack,我的天才朋友刚刚说 rect 仅在数学中具有无限点数,在计算机中没有。矩形仅限于屏幕上的像素。实际上,我什至不必检查矩形中的所有点,只需检查其周边即可。在 CGPath 上搜索像素。感觉退出了。

标签: ios objective-c cgpath


【解决方案1】:

找到了! 我使用了here 描述的算法。 只有一件事:我在屏幕上移动矩形。所以为了让他们在第一次碰撞后不堆叠,我保存最后一个未碰撞的点,如果碰撞原告,我恢复最后一个位置。

- (void)handlePan:(UIPanGestureRecognizer *)recognizer {
    BOOL rectsColide = NO;

    for (RandomColorRect* buttonRectInStoredRects in arreyOfPaths) {
        if (buttonRectInStoredRects.tag != recognizer.view.tag) {
            if ([self view:buttonRectInStoredRects intersectsWith:recognizer.view]) {
                rectsColide = YES;
            }
        }
    }

    CGPoint translation = [recognizer translationInView:self.view];

    if (!rectsColide) {
        lastPoint = recognizer.view.center;
        recognizer.view.center = CGPointMake(recognizer.view.center.x + translation.x,
                                             recognizer.view.center.y + translation.y);
    }else{
        recognizer.view.center = CGPointMake(lastPoint.x ,lastPoint.y);
    }

    [recognizer setTranslation:CGPointMake(0, 0) inView:self.view];
}



- (void)projectionOfPolygon:(CGPoint *)poly count:(int)count onto:(CGPoint)perp min:(CGFloat *)minp max:(CGFloat *)maxp
{
    CGFloat minproj = MAXFLOAT;
    CGFloat maxproj = -MAXFLOAT;
    for (int j = 0; j < count; j++) {
        CGFloat proj = poly[j].x * perp.x + poly[j].y * perp.y;
        if (proj > maxproj)
            maxproj = proj;
        if (proj < minproj)
            minproj = proj;
    }
    *minp = minproj;
    *maxp = maxproj;
}

-(BOOL)convexPolygon:(CGPoint *)poly1 count:(int)count1 intersectsWith:(CGPoint *)poly2 count:(int)count2
{
    for (int i = 0; i < count1; i++) {
        // Perpendicular vector for one edge of poly1:
        CGPoint p1 = poly1[i];
        CGPoint p2 = poly1[(i+1) % count1];
        CGPoint perp = CGPointMake(- (p2.y - p1.y), p2.x - p1.x);

        // Projection intervals of poly1, poly2 onto perpendicular vector:
        CGFloat minp1, maxp1, minp2, maxp2;
        [self projectionOfPolygon:poly1 count:count1 onto:perp min:&minp1 max:&maxp1];
        [self projectionOfPolygon:poly2 count:count1 onto:perp min:&minp2 max:&maxp2];

        // If projections do not overlap then we have a "separating axis"
        // which means that the polygons do not intersect:
        if (maxp1 < minp2 || maxp2 < minp1)
            return NO;
    }

    // And now the other way around with edges from poly2:
    for (int i = 0; i < count2; i++) {
        CGPoint p1 = poly2[i];
        CGPoint p2 = poly2[(i+1) % count2];
        CGPoint perp = CGPointMake(- (p2.y - p1.y), p2.x - p1.x);

        CGFloat minp1, maxp1, minp2, maxp2;
        [self projectionOfPolygon:poly1 count:count1 onto:perp min:&minp1 max:&maxp1];
        [self projectionOfPolygon:poly2 count:count1 onto:perp min:&minp2 max:&maxp2];

        if (maxp1 < minp2 || maxp2 < minp1)
            return NO;
    }

    // No separating axis found, then the polygons must intersect:
    return YES;
}

- (BOOL)view:(UIView *)view1 intersectsWith:(UIView *)view2
{
    CGPoint poly1[4];
    CGRect bounds1 = view1.bounds;
    poly1[0] = [view1 convertPoint:bounds1.origin toView:nil];
    poly1[1] = [view1 convertPoint:CGPointMake(bounds1.origin.x + bounds1.size.width, bounds1.origin.y) toView:nil];
    poly1[2] = [view1 convertPoint:CGPointMake(bounds1.origin.x + bounds1.size.width, bounds1.origin.y + bounds1.size.height) toView:nil];
    poly1[3] = [view1 convertPoint:CGPointMake(bounds1.origin.x, bounds1.origin.y + bounds1.size.height) toView:nil];

    CGPoint poly2[4];
    CGRect bounds2 = view2.bounds;
    poly2[0] = [view2 convertPoint:bounds2.origin toView:nil];
    poly2[1] = [view2 convertPoint:CGPointMake(bounds2.origin.x + bounds2.size.width, bounds2.origin.y) toView:nil];
    poly2[2] = [view2 convertPoint:CGPointMake(bounds2.origin.x + bounds2.size.width, bounds2.origin.y + bounds2.size.height) toView:nil];
    poly2[3] = [view2 convertPoint:CGPointMake(bounds2.origin.x, bounds2.origin.y + bounds2.size.height) toView:nil];

    return [self convexPolygon:poly1 count:4 intersectsWith:poly2 count:4];
}

【讨论】:

    【解决方案2】:

    如果我理解你的问题,那么为了检查 2 CGRects 是否满足你更好的使用:

     /* Return the intersection of `r1' and `r2'. This may return a null rect. */
     CG_EXTERN CGRect CGRectIntersection(CGRect r1, CGRect r2)
    
    For example:
     CGRect rect1 = CGRectMake(0, 0, 10, 10);
     CGRect rect2 = CGRectMake(5, 5, 10, 10);
     CGRect rect3 = CGRectMake(20, 20, 10, 10);
    
    
     CGRect r1 = CGRectIntersection(rect1, rect2);   // Returns a CGRect with (0,0,5,5)
    
     CGRect r2 = CGRectIntersection(rect1, rect3);   // Returns a CGRect with (Inf,Inf,0,0)
     if (CGSizeEqualToSize(r2.size,CGSizeZero)) {
         //   rect1 rect3 Intersects at CGSizeZero == Do not Intersect
     }
    

    【讨论】:

    • 亲爱的 Tarek :) 它不是 2 个矩形,而是 2 个具有矩形形状并旋转的视图。但是谢谢你:-*
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-13
    • 2023-03-14
    • 1970-01-01
    相关资源
    最近更新 更多