1
votes

I am trying to draw an annotation for map , my view is a subclass of MKAnnotationView

I need a shape something like shown below enter image description here

What I am getting is like this :

enter image description here

Here is the code which I am using :

- (void)drawRect:(CGRect)rect
{
    CGContextRef ctx= UIGraphicsGetCurrentContext();
    UIGraphicsPushContext(ctx);

    CGRect bounds = [self bounds];

    CGPoint topLeft = CGPointMake(CGRectGetMinX(rect), CGRectGetMinY(rect));
    CGPoint topRight = CGPointMake(CGRectGetMaxX(rect), CGRectGetMinY(rect));
    CGPoint midBottom = CGPointMake(CGRectGetMidX(rect), CGRectGetMaxY(rect));

    CGFloat height = bounds.size.height;
    CGFloat width = bounds.size.width;

    //draw semi circle
    CGContextBeginPath(ctx);
    CGContextAddArc(ctx, width/2, height/2, width/2, 0 ,M_PI, YES);

    //draw bottom cone
    CGContextAddLineToPoint(ctx, midBottom.x, midBottom.y);
    CGContextAddLineToPoint(ctx, topRight.x, topRight.y + height/2);  // mid right
    CGContextClosePath(ctx);

    CGContextSetFillColorWithColor(ctx, [UIColor redColor].CGColor);
    CGContextFillPath(ctx);

    UIGraphicsPopContext();

}
1
But use your liked shape image for annotation.Darshan Kunjadiya
@DarshanKunjadiya I have to add some more stuff to this view , which cant be static so I need to draw this programmaticallyKunal Balani

1 Answers

1
votes

You can achieve the desired effect if you replace your lines with quad curves:

- (void)drawRect:(CGRect)rect
{
    CGContextRef ctx= UIGraphicsGetCurrentContext();
    UIGraphicsPushContext(ctx);

    CGRect bounds = [self bounds];

    CGPoint topLeft = CGPointMake(CGRectGetMinX(rect), CGRectGetMinY(rect));
    CGPoint topRight = CGPointMake(CGRectGetMaxX(rect), CGRectGetMinY(rect));
    CGPoint midBottom = CGPointMake(CGRectGetMidX(rect), CGRectGetMaxY(rect));

    CGFloat height = bounds.size.height;
    CGFloat width = bounds.size.width;

    //draw semi circle
    CGContextBeginPath(ctx);
    CGContextAddArc(ctx, width/2, height/2, width/2, 0 ,M_PI, YES);

    //draw bottom cone
    CGContextAddQuadCurveToPoint(ctx, topLeft.x, height * 2 / 3, midBottom.x, midBottom.y);
    CGContextAddQuadCurveToPoint(ctx, topRight.x, height * 2 / 3, topRight.x, topRight.y + height/2);
    // CGContextAddLineToPoint(ctx, midBottom.x, midBottom.y);
    // CGContextAddLineToPoint(ctx, topRight.x, topRight.y + height/2);  // mid right
    CGContextClosePath(ctx);

    CGContextSetFillColorWithColor(ctx, [UIColor redColor].CGColor);
    CGContextFillPath(ctx);

    UIGraphicsPopContext();

}

This employs a quadratic bezier curve, which is a good curve when you don't want inflection points. You can achieve a similar curve with the cubic bezier, but if you're not careful with your control points, you can get undesired inflection points. The quadratic curve is just a little easier with only one control point per curve.

By choosing control points with x values the same as the start and end of the semicircle, it ensures a smooth transition from the circle to the curve leading down to the point. By choosing y values for those control points which are relatively close to the start and end of the semicircle, it ensures that the curve will transition quickly from the semicircle to the point. You can adjust these control points, but hopefully this illustrates the idea.

For illustration of the difference between these two types of curves, see the Curves section of the Paths chapter of the Quartz 2D Programming Guide.

example