Search code examples
iphoneiosobjective-ccocoa-touchcalayer

CAShapeLayer: Finding the intersected area of 3 circles


I have two questions:

  1. Is there any way, in CALayer, to know if two circles are intersecting?
  2. With three circles intersecting each other, is there any way to highlight the intersected area?

I am using CAShapeLayer to draw my circles:

- (CAShapeLayer *)circleForRadius:(CGFloat)iRadius withColor:(CGColorRef)iColor andDashPattern:(BOOL)isDashPattern {
CAShapeLayer *aSignalcircle = [CAShapeLayer layer];
aSignalcircle.path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, 2.0 * iRadius, 2.0 * iRadius) cornerRadius:iRadius].CGPath;
aSignalcircle.position = CGPointMake(0.0 - iRadius, 0.0 - iRadius);
aSignalcircle.fillColor = [UIColor clearColor].CGColor;
aSignalcircle.strokeColor = iColor;
aSignalcircle.lineWidth = kPSSignalStrokeWidth;

if (self.enableShadow) {
    aSignalcircle.shadowColor = [UIColor blackColor].CGColor;
    aSignalcircle.shadowOpacity = 0.5;
    aSignalcircle.shadowOffset = CGSizeMake(0, 0.25);
    aSignalcircle.shadowRadius = 0.5;
}

if (isDashPattern) {
    aSignalcircle.lineDashPattern = @[@1, @1];
}

return aSignalcircle;

}

I tried clipping the context path using the below code but the output is not coming as expected:

- (void)drawRect:(CGRect)rect
{
    CGFloat iRadius = 20.0;
    // Drawing code
    CGContextRef context = UIGraphicsGetCurrentContext();
    CAShapeLayer *aSignalcircle = [CAShapeLayer layer];
    aSignalcircle.path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, 2.0 * iRadius, 2.0 * iRadius) cornerRadius:iRadius].CGPath;
    aSignalcircle.position = CGPointMake(10.0 , 10.0);
    aSignalcircle.fillColor = [UIColor clearColor].CGColor;
    aSignalcircle.strokeColor = [UIColor redColor].CGColor;
    aSignalcircle.lineWidth = 1.0;
    CGContextAddPath(context, aSignalcircle.path);
    CGContextClip(context);

    CAShapeLayer *aSignalcircle1 = [CAShapeLayer layer];
    aSignalcircle1.path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, 2.0 * iRadius, 2.0 * iRadius) cornerRadius:iRadius].CGPath;
    aSignalcircle1.position = CGPointMake(30.0 , 10.0);
    aSignalcircle1.fillColor = [UIColor clearColor].CGColor;
    aSignalcircle1.strokeColor = [UIColor redColor].CGColor;
    aSignalcircle1.lineWidth = 1.0;
    CGContextAddPath(context, aSignalcircle1.path);
    CGContextClip(context);


    CAShapeLayer *aSignalcircle2 = [CAShapeLayer layer];
    aSignalcircle2.path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, 2.0 * iRadius, 2.0 * iRadius) cornerRadius:iRadius].CGPath;
    aSignalcircle2.position = CGPointMake(25.0 , 30.0);
    aSignalcircle2.fillColor = [UIColor clearColor].CGColor;
    aSignalcircle2.strokeColor = [UIColor redColor].CGColor;
    aSignalcircle2.lineWidth = 1.0;
    CGContextAddPath(context, aSignalcircle2.path);

    [[UIColor grayColor] set];
    CGContextFillPath(context);

// Temp addition to see how the circles are looking on screen
    [self.layer addSublayer:aSignalcircle];
    [self.layer addSublayer:aSignalcircle1];
    [self.layer addSublayer:aSignalcircle2];
}

I output is looking like:

enter image description here


Solution

  • For the second question, you can use the following code to highlight the intersected area:

    // Add first path and clip
    CGContextAddPath(context, circle1.path);
    CGContextClip(context);
    
    // Add second path and clip
    CGContextAddPath(context, circle2.path);
    CGContextClip(context);
    
    // Add third path and draw it. This means it'll be drawn within the clipping area
    CGContextAddPath(context, circle3.path);
    [[UIColor redColor] set];
    CGContextFillPath(context);