daveoncode daveoncode - 4 months ago 14
iOS Question

How to draw stars using Quartz Core?

I'm trying to adapt an example provided by Apple in order to programmatically draw stars in line, the code is the following:

CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(context, aSize);

for (NSUInteger i=0; i<stars; i++)
{

CGContextSetFillColorWithColor(context, aColor);
CGContextSetStrokeColorWithColor(context, aColor);

float w = item.size.width;
double r = w / 2;
double theta = 2 * M_PI * (2.0 / 5.0); // 144 degrees

CGContextMoveToPoint(context, 0, r);

for (NSUInteger k=1; k<5; k++)
{
float x = r * sin(k * theta);
float y = r * cos(k * theta);
CGContextAddLineToPoint(context, x, y);
}

CGContextClosePath(context);
CGContextFillPath(context);
}


The code above draws a perfect star, but is 1. displayed upside down 2. is black and without border. What I want to achive is to draw many stars on the same line and with the given style. I understand that I'm actually drawing the same path 5 times in the same position and that I have somehow to flip the context vertically, but after several tests I gave up! (I lack the necessary math and geometry skills :P)... could you please help me?

UPDATE:

Ok, thanks to CocoaFu, this is my refactored and working draw utility:

- (void)drawStars:(NSUInteger)count inContext:(CGContextRef)context;
{
// constants
const float w = self.itemSize.width;
const float r = w/2;
const double theta = 2 * M_PI * (2.0 / 5.0);
const float flip = -1.0f; // flip vertically (default star representation)

// drawing center for the star
float xCenter = r;

for (NSUInteger i=0; i<count; i++)
{
// get star style based on the index
CGContextSetFillColorWithColor(context, [self fillColorForItemAtIndex:i]);
CGContextSetStrokeColorWithColor(context, [self strokeColorForItemAtIndex:i]);

// update position
CGContextMoveToPoint(context, xCenter, r * flip + r);

// draw the necessary star lines
for (NSUInteger k=1; k<5; k++)
{
float x = r * sin(k * theta);
float y = r * cos(k * theta);
CGContextAddLineToPoint(context, x + xCenter, y * flip + r);
}

// update horizontal center for the next star
xCenter += w + self.itemMargin;

// draw current star
CGContextClosePath(context);
CGContextFillPath(context);
CGContextStrokePath(context);
}
}

Answer

Here is code that will draw 3 stars in a horizontal line, it's is not pretty but it may help:

-(void)drawRect:(CGRect)rect
{
    int aSize = 100.0;
    const CGFloat color[4] = { 0.0, 0.0, 1.0, 1.0 }; // Blue
    CGColorRef aColor = CGColorCreate(CGColorSpaceCreateDeviceRGB(), color);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetLineWidth(context, aSize);
    CGFloat xCenter = 100.0;
    CGFloat yCenter = 100.0;

    float  w = 100.0;
    double r = w / 2.0;
    float flip = -1.0;

    for (NSUInteger i=0; i<3; i++) 
    {
        CGContextSetFillColorWithColor(context, aColor);
        CGContextSetStrokeColorWithColor(context, aColor);

        double theta = 2.0 * M_PI * (2.0 / 5.0); // 144 degrees

        CGContextMoveToPoint(context, xCenter, r*flip+yCenter);

        for (NSUInteger k=1; k<5; k++) 
        {
            float x = r * sin(k * theta);
            float y = r * cos(k * theta);
            CGContextAddLineToPoint(context, x+xCenter, y*flip+yCenter);
        }
        xCenter += 150.0;
    }
    CGContextClosePath(context);
    CGContextFillPath(context);
}

enter image description here