核心图形在笔划填充内形状复杂

时间:2012-05-09 17:18:20

标签: iphone objective-c ios core-graphics

我正在尝试使用Core Graphics在我的应用中绘制一些形状,并且我在理解将多个形状屏蔽成一个的最佳实践时遇到了一些问题。

这是我想要的形状(包括颜色)。

Circle http://www.myquapps.com/help/lvl1Circle1.png

到目前为止,我已经用正确的笔划绘制了一个相同大小的圆圈,如下所示: -

    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGContextClearRect(ctx, rect);
    CGContextSetRGBFillColor(ctx, 0, 0, 0, 1);
    CGFloat red[4] = {1.0f, 0.0f, 0.0f, 1.0f};
    CGContextSetStrokeColor(ctx, red);
    CGContextSetLineWidth(ctx, 18);
    CGContextStrokeEllipseInRect(ctx, CGRectMake(9, 9, 232, 232));
    CGContextFillPath(ctx);

这里的任何帮助将不胜感激!这是我第一次使用Core Graphics,它看起来正是我需要的!

2 个答案:

答案 0 :(得分:4)

问我一点,但是你去了(所有贝塞尔路径都是实例变量):

编辑:让圆圈的内部透明,但支撑自己,这会变得很难看!

#define LARGE_RADIUS 200
#define SMALL_RADIUS 160

#define RADIANS(degrees) ((degrees) / (180.0 / M_PI))

@implementation MyView
{
    UIBezierPath *largeCircle;
    UIBezierPath *orangeWedge;
    UIBezierPath *yellowWedge;
    UIBezierPath *greenWedge;
    UIBezierPath *whiteCircle;

    UIImage *image;
    void *_imageData;
}

-(void) createPaths {
    largeCircle = [UIBezierPath bezierPathWithArcCenter:self.center radius:LARGE_RADIUS startAngle:0 endAngle:RADIANS(360) clockwise:YES];
    whiteCircle = [UIBezierPath bezierPathWithArcCenter:self.center radius:SMALL_RADIUS startAngle:0 endAngle:RADIANS(360) clockwise:YES];    

    orangeWedge = [UIBezierPath bezierPath];
    [orangeWedge moveToPoint:self.center];

    double startAngle = RADIANS(45);
    double endAngle = RADIANS(135);

    [orangeWedge addLineToPoint:CGPointMake(sin(startAngle) + self.center.x, cos(startAngle) + self.center.y)];
    [orangeWedge addArcWithCenter:self.center radius:LARGE_RADIUS startAngle:startAngle endAngle:endAngle clockwise:YES];
    [orangeWedge addLineToPoint:self.center];

    startAngle = RADIANS(60);
    endAngle = RADIANS(120);

    yellowWedge = [UIBezierPath bezierPath];
    [yellowWedge moveToPoint:self.center];

    [yellowWedge addLineToPoint:CGPointMake(sin(startAngle) + self.center.x, cos(startAngle) + self.center.y)];
    [yellowWedge addArcWithCenter:self.center radius:LARGE_RADIUS startAngle:startAngle endAngle:endAngle clockwise:YES];
    [yellowWedge addLineToPoint:self.center];

    startAngle = RADIANS(75);
    endAngle = RADIANS(105);

    greenWedge = [UIBezierPath bezierPath];
    [greenWedge moveToPoint:self.center];

    [greenWedge addLineToPoint:CGPointMake(sin(startAngle) + self.center.x, cos(startAngle) + self.center.y)];
    [greenWedge addArcWithCenter:self.center radius:LARGE_RADIUS startAngle:startAngle endAngle:endAngle clockwise:YES];
    [greenWedge addLineToPoint:self.center];
}

-(void) drawPaths
{
    [[UIColor blackColor] setStroke];
    [[UIColor redColor] setFill];
    [largeCircle fill];
    [largeCircle stroke];
    [[UIColor orangeColor] setFill];
    [orangeWedge fill];
    [orangeWedge stroke];
    [[UIColor yellowColor] setFill];
    [yellowWedge fill];
    [yellowWedge stroke];
    [[UIColor greenColor] setFill];
    [greenWedge fill];
    [greenWedge stroke];

    [whiteCircle stroke];
}

-(int32_t *) pixelAt:(int) x :(int) y
{
    return &((int32_t *)_imageData)[x + (y * (int) self.frame.size.width)];
}

-(void) removeInnerCircle
{
    int32_t invisible = 0;

    int centerX = self.center.x;
    int centerY = self.center.y;

    for (int i = SMALL_RADIUS - 1; i > 0; i--) {
        float incr = (22.0 / i);

        for (float j = 0; j <= 360; j += incr) {
            float angle = RADIANS(j);

            *[self pixelAt:(sin(angle) * i + centerX) :(cos(angle) * i + centerY)] = invisible;
        }
    }
}

-(void) setUpContext
{
    size_t width  = self.frame.size.width;
    size_t height = self.frame.size.height;

    _imageData = malloc(4 * width * height);

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

    CGContextRef context = CGBitmapContextCreate(_imageData, width, height, 8, width * 4, colorSpace, kCGImageAlphaPremultipliedFirst);
    CGColorSpaceRelease(colorSpace);
    CGContextTranslateCTM(context, 0, height);
    CGContextScaleCTM(context, 1, -1);

    assert(context != NULL);

    UIGraphicsPushContext(context);

    CGContextRelease(context);
}

-(void) destroyContext
{
    CGImageRef imageRef = CGBitmapContextCreateImage(UIGraphicsGetCurrentContext());

    assert(imageRef != NULL);

    image = [UIImage imageWithCGImage:imageRef];

    UIGraphicsPopContext();

    free(_imageData);
    _imageData = NULL;
}

-(void) awakeFromNib
{    
    [self createPaths];

    [self setUpContext];

    [self drawPaths];
    [self removeInnerCircle];

    [self destroyContext];    
}

-(void) drawRect:(CGRect)rect
{
    [image drawInRect:self.frame];
}

@end

根据SMALL_RADIUS的值,您可能希望更改j-removeInnerCircle的增量,以便它不会执行超出必要的循环。< /秒>

更改代码以根据当前半径增加j,因此越接近中心,需要更改的像素就越少!

答案 1 :(得分:2)

我会通过创建圆形路径,设置粗线宽,然后使用CGContextReplacePathWithStrokedPath()将路径设置为环形本身。这将形成一条有效的两个同心圆的新路径。

CGContextBeginPath(ctx);
CGRect rect = CGRectMake(9, 9, 232, 232);
CGContextAddEllipseInRect(ctx, CGRectInset(rect, 16, 16));
CGContextSetLineWidth(ctx, 32);
CGContextReplacePathWithStrokedPath(ctx);

现在,您可以设置环的黑色边缘的线条粗细和颜色并对其进行描边。这会得到内部和外部的黑色同心圆:

CGContextSetLineWidth(ctx, 32);
CGContextSetGrayStrokeColor(ctx, 0, 1);
CGContextStrokePath(ctx);

设置填充颜色并填充:

CGContextSetRGBFillColor(ctx, 1, 0, 0, 1);
CGContextFillPath(ctx);

现在剪辑到它:

CGContextClip(ctx);

现在您可以绘制橙色,黄色和绿色形状,它们将被剪裁到环内。我不清楚理查德的代码是否能让这些形状完全正确。他使用以环形中心为中心的楔形物,但在你的画面中,边缘似乎并不都指向中心。 (另外,他描绘了一个白色圆圈来“擦除”内部部分,而你的照片在内部则是透明的。)设置剪辑后,你可以绘制三角形或任何最方便的方法来使这些边缘与你的方式成角度想要他们,他们会自动被限制在戒指上。