Search code examples
objective-ciosgeometryquartz-core

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);
    }
}

Solution

  • 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