开发者

Ring of circles within a circle, dynamically sized

开发者 https://www.devze.com 2023-03-03 19:11 出处:网络
all. Sorry if this has been asked and answered already, I couldn\'t find this specific problem when I did my search.

all. Sorry if this has been asked and answered already, I couldn't find this specific problem when I did my search.

I am trying to create a circle class that dynamically creates a ring of circles within a circle, and am having issues with the trig behind it all. The idea is to create an image for a rotary phone, but I want to be able to reuse this class for other similar images (circles for loading images, etc.).

From my viewcontroller, I call CustomCircleView, and it creates the base circle fine (I am using this circle for the background color, so that I can adjust it's hue separately). I then call my DialView class, which also creates the base circle fine, but my cutouts are not appearing where I expect them to.

What I want to happen is to have 12 evenly spaced circles, and have them transparent using EOFill. EOFill is working properly, and everything is displaying without errors, but my circles are not showing up where I am expecting them to; likely, this means there is something wrong with my math.

Here's the relevant code:

- (void)drawRect:(CGRect)rect
{
    int inset = 2;  // space between cutouts and edge of dial
    int circleDiameter = self.bounds.size.width - inset * 2;
    float circleRadius = circleDiameter / 2;
    float holeDiameter = circleDiameter * 0.15;  // wrong size; is there a formula for this?
    float holeRadius = holeDiameter / 2;
    int holePadding = 2;  // space between cutouts
    float hypotenuse = circleRadius - holeRadius - holePadding;
    float dispX;
    float dispY;

    // Set context.
    CGContextRef context = UIGraphicsGetCurrentContext();

    // Set line stroke parameters.
    CGContextSetLineWidth(context, 2.0);
    CGContextSetStrokeColorWithColor(context, [UIColor colorWithHue:0.6 saturation:1.0 brightness:1.0 alpha:1.0].CGColor);
    CGContextSetFillColorWithColor(context, self.dialColor.CGColor);

    // main dial circle; this will remain visible
    CGRect ellipse = CGRectMake(self.bounds.origin.x + inset, self.bounds.origin.y + inset, circleDiameter, circleDiameter);
    CGContextAddEllipseInRect(context, ellipse);

    // grid for debugging; remove once circles line up properly
    CGContextMoveToPoint(context, 0, 0);
    CGContextAddLineToPoint(context, self.bounds.size.width, self.bounds.size.height);
    CGContextMoveToPoint(context, 0, self.bounds.size.height);
    CGContextAddLineToPoint(context, self.bounds.size.width, 0);
    CGContextStrokePath(context);

    // circle spacing based on 12 circles
    // hole diameter should be proportional to that of dial diameter

    // 1
    dispX = (self.bounds.size.width / 2)  + (cosf(45) * hypotenuse) - (holeRadius);
    dispY = (self.bounds.size.height / 2) - (sinf(45) * hypotenuse) - (holeRadius);
    CGRect hole = CGRectMake(dispX, dispY, holeDiameter, holeDiameter);
    CGContextAddEllipseInRect(context, hole);

    // 2
    dispX = (self.bounds.size.width / 2)  + (cosf(75) * hypotenuse) - (holeRadius);
    dispY = (self.bounds.size.height / 2) - (sinf(75) * hypotenus开发者_Python百科e) - (holeRadius);
    hole = CGRectMake(dispX, dispY, holeDiameter, holeDiameter);
    CGContextAddEllipseInRect(context, hole);

    // 3
    dispX = (self.bounds.size.width / 2)  - (cosf(75) * hypotenuse) - (holeRadius);
    dispY = (self.bounds.size.height / 2) - (sinf(75) * hypotenuse) - (holeRadius);
    hole = CGRectMake(dispX, dispY, holeDiameter, holeDiameter);
    CGContextAddEllipseInRect(context, hole);

    // 4
    dispX = (self.bounds.size.width / 2)  - (cosf(45) * hypotenuse) - (holeRadius);
    dispY = (self.bounds.size.height / 2) - (sinf(45) * hypotenuse) - (holeRadius);
    hole = CGRectMake(dispX, dispY, holeDiameter, holeDiameter);
    CGContextAddEllipseInRect(context, hole);

    // 5
    dispX = (self.bounds.size.width / 2)  - (cosf(15) * hypotenuse) - (holeRadius);
    dispY = (self.bounds.size.height / 2) - (sinf(15) * hypotenuse) - (holeRadius);
    hole = CGRectMake(dispX, dispY, holeDiameter, holeDiameter);
    CGContextAddEllipseInRect(context, hole);

    // 6
    dispX = (self.bounds.size.width / 2)  - (cosf(15) * hypotenuse) - (holeRadius);
    dispY = (self.bounds.size.height / 2) + (sinf(15) * hypotenuse) - (holeRadius);
    hole = CGRectMake(dispX, dispY, holeDiameter, holeDiameter);
    CGContextAddEllipseInRect(context, hole);

    // 7
    dispX = (self.bounds.size.width / 2)  - (cosf(45) * hypotenuse) - (holeRadius);
    dispY = (self.bounds.size.height / 2) + (sinf(45) * hypotenuse) - (holeRadius);
    hole = CGRectMake(dispX, dispY, holeDiameter, holeDiameter);
    CGContextAddEllipseInRect(context, hole);

    // 8
    dispX = (self.bounds.size.width / 2)  - (cosf(75) * hypotenuse) - (holeRadius);
    dispY = (self.bounds.size.height / 2) + (sinf(75) * hypotenuse) - (holeRadius);
    hole = CGRectMake(dispX, dispY, holeDiameter, holeDiameter);
    CGContextAddEllipseInRect(context, hole);

    // 9
    dispX = (self.bounds.size.width / 2)  + (cosf(75) * hypotenuse) - (holeRadius);
    dispY = (self.bounds.size.height / 2) + (sinf(75) * hypotenuse) - (holeRadius);
    hole = CGRectMake(dispX, dispY, holeDiameter, holeDiameter);
    CGContextAddEllipseInRect(context, hole);

    // 0
    dispX = (self.bounds.size.width / 2)  + (cosf(45) * hypotenuse) - (holeRadius);
    dispY = (self.bounds.size.height / 2) + (sinf(45) * hypotenuse) - (holeRadius);
    hole = CGRectMake(dispX, dispY, holeDiameter, holeDiameter);
    CGContextAddEllipseInRect(context, hole);


    CGContextEOFillPath(context);
}


Figured it out. I was using degrees with the trig functions, not radians.

If anyone else is trying to do the same thing I am, look into Steiner chains for help with finding your radii ratio.

0

精彩评论

暂无评论...
验证码 换一张
取 消