iOS programmatically create UIImage of a circle sector given the angle and radius

EDIT: there are a few other questions on SO but they all help you draw either a circle or an arc within a UIView. I need a sector which is also as a UIImage and not UIView.

iOS programmatically create UIImage of a circle sector given the angle and radius

I am trying to create a UIImage of a circle sector given the angle and radius. The end result should be a mono-colored version of this image. I don't need the gradient which this image has. A single color is fine.

I need to create many of such segments with different colors.

enter image description here

Here's what I have tried so far but it ends up looking like this which I have no clue:

enter image description here

Call:

[self getSegmentImageOfRadius:177.5 andAngleRadians:0.63]

Method:

-(UIImage*)getSegmentImageOfRadius:(CGFloat)radius andAngleRadians:(CGFloat)angleRadians{

    UIBezierPath *sector = [UIBezierPath
                            bezierPathWithArcCenter:CGPointMake(0, 0) radius:radius startAngle:0 endAngle:angleRadians clockwise:YES];
    UIGraphicsBeginImageContext(CGSizeMake(radius,radius));
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetFillColorWithColor(context, [UIColor greenColor].CGColor);
    [sector fill];
    UIImage *mage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return mage;
}

Upvotes: 1

Views: 1296

Answers (3)

Vignesh Kumar
Vignesh Kumar

Reputation: 598

I have created the circle view with radius, start angle and end angle.

      240 
       |
180 ---|--- 0 - Start Angle point in my code.
       |
       90

       #define DEGREES_TO_RADIANS(d) ((d) * 0.0174532925199432958f)


       // Sample image view.

           UIImageView *circleView = [[UIImageView alloc] initWithFrame:CGRectMake(50.0f, 382.0f, 120.0f,120.0f)];
            circleView.image = [self getSegmentImageOfRadius:30 startAngle:90 andEndAngle:180 withFrame:circleView.frame.size];
            [self.view addSubview:circleView];


        -(UIImage*)getSegmentImageOfRadius:(CGFloat)radius startAngle:(CGFloat)startAngle andEndAngle:(CGFloat)endAngle withFrame :(CGSize) size {

            // Create View with frame of radius
            UIView *circleView = [[UIView alloc] initWithFrame:CGRectMake(radius, radius, radius*2, radius*2)];

            // Create new object for UIBezierPath
            UIBezierPath *bezierPath = [UIBezierPath bezierPath];

            // Find  the center point of the view.
            CGPoint center = CGPointMake(CGRectGetMidX(circleView.frame), CGRectGetMidY(circleView.frame));
            // Add the arc with given properties.
            [bezierPath addArcWithCenter:center radius:radius startAngle:DEGREES_TO_RADIANS(startAngle) endAngle: DEGREES_TO_RADIANS(endAngle) clockwise:YES];

            // Add the shape layer.
            CAShapeLayer *progressLayer = [[CAShapeLayer alloc] init];
            [progressLayer setPath:bezierPath.CGPath];
            [progressLayer setStrokeColor:[UIColor blueColor].CGColor];
            [progressLayer setFillColor:[UIColor clearColor].CGColor];
            [progressLayer setLineWidth:circleView.frame.size.width];
            [circleView.layer addSublayer:progressLayer];

            // Convert and render UIView into UIImage.
            UIGraphicsBeginImageContext(size);
            CGContextRef context = UIGraphicsGetCurrentContext();
            [circleView.layer renderInContext:context];
            UIImage *saveImage;

            saveImage = UIGraphicsGetImageFromCurrentImageContext();
            UIGraphicsEndImageContext();
            return saveImage;
        }

Refer : 2DDrawing

Upvotes: 1

Shebin Koshy
Shebin Koshy

Reputation: 1192

Try this..

create an imageView with width almost 190 (based on your requirement)

#define pi 3.14159265359
#define DEGREES_TO_RADIANS(degrees) ((pi * degrees) / 180)

In viewDidLoad

UIImage *image = [self getSegmentImageOfRadius:_imageView.frame.size.width/2 startAngle:160 andEndAngle:200];
_imageView.image = image;

Change the method as below

-(UIImage*)getSegmentImageOfRadius:(CGFloat)radius startAngle:(CGFloat)startAngle andEndAngle:(CGFloat)endAngle
{
    CGPoint center = CGPointMake(_imageView.frame.size.width/2, _imageView.frame.size.height/2);
    UIBezierPath *path = [UIBezierPath bezierPath];
   [path moveToPoint:center];
   [path addArcWithCenter:center radius:radius startAngle:DEGREES_TO_RADIANS(startAngle) endAngle:DEGREES_TO_RADIANS(endAngle) clockwise:YES];
   [path closePath];

   CAShapeLayer *layer = [CAShapeLayer layer];
   layer.frame = _imageView.bounds;
   layer.path = path.CGPath;
   layer.fillColor = [UIColor redColor].CGColor;
   UIGraphicsBeginImageContextWithOptions(layer.frame.size, NO, 0);

   [layer renderInContext:UIGraphicsGetCurrentContext()];
   UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext();

   UIGraphicsEndImageContext();

   return outputImage;
}

If you doesn't need as an image, you can add shape to your view's layer as shown below

CGPoint center = CGPointMake(self.view.frame.size.width/2, self.view.frame.size.height/2);
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:center];
[path addArcWithCenter:center radius:radius startAngle:DEGREES_TO_RADIANS(startAngle) endAngle:DEGREES_TO_RADIANS(endAngle) clockwise:YES];
[path closePath];

CAShapeLayer *layer = [CAShapeLayer layer];    
layer.path = path.CGPath;
layer.fillColor = [UIColor redColor].CGColor;
[self.view.layer addSublayer:layer];

Upvotes: 2

Vignesh Kumar
Vignesh Kumar

Reputation: 598

You method is working fine. But, I felt your input are wrong to your function.

    // 1 -  Test

     UIImageView *sample = [[UIImageView alloc] initWithFrame:CGRectMake(20.0f, 122.0f, 50.0f,50.0f)];
    sample.image = [self getSegmentImageOfRadius:50 andAngleRadians:50];

    [self.view addSubview:sample];

    // Add this funciton to your view controller
    -(UIImage*)getSegmentImageOfRadius:(CGFloat)radius andAngleRadians:(CGFloat)angleRadians{

        UIBezierPath *sector = [UIBezierPath
                                bezierPathWithArcCenter:CGPointMake(0, 0) radius:radius startAngle:0 endAngle:angleRadians clockwise:YES];

        UIGraphicsBeginImageContext(CGSizeMake(radius,radius)); 
        CGContextRef context = UIGraphicsGetCurrentContext();
        CGContextSetFillColorWithColor(context, [UIColor greenColor].CGColor); // Fill color.
        [sector fill];
        UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); // Create image form curent context.
        UIGraphicsEndImageContext();
        return image;
    }

Output :

Output above code

Upvotes: 0

Related Questions