iPhone黄金螺旋

今回は、「正方形の一辺 = 弧の半径」をキーワードに、iPhoneアプリのプログラミングで黄金螺旋の作図をしてみます。黄金螺旋は、黄金長方形を分割した図を使って作成していきます。ノーモン(黄金長方形を分割してできる正方形)の辺を半径として弧を描いていきます。

動作イメージ
XcodeからiOS6 iPhone Simulatorで動かすとこんな感じになります。

ポイント
黄金長方形、黄金螺旋共に同じような仕組みで作図をしています。ループの内部で、黄金長方形は、正方形を描くために、UIBezierPathのaddLineToPointを、黄金螺旋はUIBezierPathのaddArcWithCenterを使用しました。図形を描く開始位置、線を描き始める角度をループの中で更新することでうまく渦を巻いていきます。

サンプルコード

#import “ViewController.h”

#import <QuartzCore/QuartzCore.h>

@interface ViewController () {

    CAShapeLayer *spiral;

}

@end

@implementation ViewController

– (void)viewDidLoad

{

    [super viewDidLoad];

    self.view.backgroundColor = [UIColor whiteColor];

    [self createGoldenRectangle];

    [self createGoldenSpiral];

    

    [self createButton];

}

– (void)createGoldenRectangle

{

    

    float r = 160;

    CGPoint o = CGPointMake(190, 150);

    UIBezierPath *path = [UIBezierPath bezierPath];

    

    float startAngle = M_PI;

    for (int i=0; i<7; i++) {

        float endAngle = startAngle – (M_PI/2.0);

        

        [path moveToPoint:o];

        [path addLineToPoint:CGPointMake(o.x + r * cos(startAngle), o.y + r * sin(startAngle))];

        [path addLineToPoint:CGPointMake(o.x + r * (cos(startAngle) + cos(endAngle)), o.y + r * (sin(startAngle) + sin(endAngle)))];

        [path addLineToPoint:CGPointMake(o.x + r * cos(endAngle), o.y + r * sin(endAngle))];

        [path addLineToPoint:o];

        

        float d = r * (1.01.0/1.618);

        o = CGPointMake(o.x + d * cos(endAngle), o.y + d * sin(endAngle));        

        r = r / 1.618;

        startAngle = endAngle;

    }

    

    CAShapeLayer *sl = [[CAShapeLayer alloc] init];

    sl.fillColor = [UIColor clearColor].CGColor;

    sl.strokeColor = [UIColor lightGrayColor].CGColor;

    sl.lineWidth = 1;

    sl.path = path.CGPath;

    

    [self.view.layer addSublayer:sl];

}

– (void)createGoldenSpiral

{

    float r = 160;

    CGPoint o = CGPointMake(190, 150);

    UIBezierPath *path = [UIBezierPath bezierPath];

    

    float startAngle = M_PI;

    for (int i=0; i<8; i++) {

        float endAngle = startAngle – (M_PI/2.0);

        [path addArcWithCenter:o radius:r startAngle:startAngle endAngle:endAngle clockwise:NO];

        

        float d = r * (1.01.0/1.618);

        o = CGPointMake(o.x + d * cos(endAngle), o.y + d * sin(endAngle));

        

        r = r / 1.618;

        startAngle = endAngle;

    }

    

    spiral = [[CAShapeLayer alloc] init];

    spiral.fillColor = [UIColor clearColor].CGColor;

    spiral.strokeColor = [UIColor blueColor].CGColor;

    spiral.lineWidth = 3;

    spiral.path = path.CGPath;

    

    [self.view.layer addSublayer:spiral];

}

– (void)createButton

{

    float w = 320 / 1.618;

    float h = w / 1.618 / 1.618;

    UILabel *btn = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, w, h)];

    btn.center = CGPointMake(160, 400);

    btn.text = @”Draw”;

    btn.font = [UIFont fontWithName:@”Marker Felt” size:50];

    btn.textColor = [UIColor whiteColor];

    btn.backgroundColor = [UIColor blueColor];

    btn.textAlignment = 1;

    [self.view addSubview:btn];

    

    btn.userInteractionEnabled = YES;

    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(startDraw)];

    [btn addGestureRecognizer:tap];

}

– (void)startDraw

{

    CABasicAnimation *a = [CABasicAnimation animationWithKeyPath:@”strokeEnd”];

    a.duration = 3.0;

    a.fromValue = [NSNumber numberWithFloat:0.0f];

    a.toValue = [NSNumber numberWithFloat:1.0f];

    [spiral addAnimation:a forKey:@”strokeEnd”];

}

– (void)didReceiveMemoryWarning

{

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}

@end