iPhone黄金長方形 三角形から作る

比率(1 : 2 : √5)の直角三角形ABCから黄金長方形の作成過程を動画で表示するiPhoneアプリを作っていきます。辺ABを半径にした円弧を描きます、円と辺ACの交点を点Dとして、CからDまでの長さを半径にした円をまた描きます辺BCとの交点をEとすると、黄金分割、BE:EC = 1:1.618 の出来上がり。


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

ポイント
画面の下の方に、書き方の説明と、次の手順に進むためのボタンを表示してみました。三角形は、画面の上部に表示しておいて、線はUIBezierPathとCAShapeLayerで描いています。次へをタップするタイミングで、UIBezierPathにアニメーションをかけています。

サンプルコード

#import “ViewController.h”

#import <QuartzCore/QuartzCore.h>

@interface ViewController () {

    UILabel *console;

    int page;

    CGPoint A, B, C, D, E;

    float angleA;

}

@end

@implementation ViewController

– (void)viewDidLoad

{

    [super viewDidLoad];

    self.view.backgroundColor = [UIColor colorWithWhite:0.9 alpha:1];

    

    [self createGridSheet];

    

    // 1.  AB:AC = 1:2の直角三角形 ABC

    [self createRightTriangle];

    

    [self createConsole];

}

– (void)createGridSheet

{

    UIBezierPath *path = [UIBezierPath bezierPath];

    float size = 16;

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

        [path moveToPoint:CGPointMake(i * size, 0)];

        [path addLineToPoint:CGPointMake(i * size, 568)];

    }

    

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

        [path moveToPoint:CGPointMake(0, i*size)];

        [path addLineToPoint:CGPointMake(320, i*size)];

    }

    

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

    sl.fillColor = [UIColor clearColor].CGColor;

    sl.strokeColor = [UIColor colorWithRed:0 green:1 blue:0 alpha:0.5].CGColor;

    sl.lineWidth = 1;

    sl.path = path.CGPath;

    

    [self.view.layer addSublayer:sl];

}

– (void)createRightTriangle

{

    A = CGPointMake(50, 80);

    B = CGPointMake(50, 190);

    C = CGPointMake(270, 190);

    

    // for D

    angleA = atan2f(2, 1);

    D = CGPointMake(A.x + 110.0 * sin(angleA), A.y + 110.0 * cos(angleA));

    

    // for E

    E = CGPointMake((220.0 / 2.618) + 50, 190);

    

    // 1:2:√5

    UIBezierPath *path = [UIBezierPath bezierPath];

    [path moveToPoint:A];

    [path addLineToPoint:B];

    [path addLineToPoint:C];

    [path closePath];

    

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

    sl.fillColor = [UIColor colorWithWhite:0 alpha:0.1].CGColor;

    sl.strokeColor = [UIColor colorWithWhite:0 alpha:0.6].CGColor;

    sl.lineWidth = 1;

    sl.path = path.CGPath;

    

    [self.view.layer addSublayer:sl];

    

    

    // Label

    UILabel *la = [[UILabel alloc] init];

    la.font = [UIFont boldSystemFontOfSize:20];

    la.text = @”A”;

    la.textColor = [UIColor purpleColor];

    la.backgroundColor = [UIColor clearColor];

    [la sizeToFit];

    la.center = CGPointMake(A.x10, A.y10);

    [self.view addSubview:la];

    

    UILabel *lb = [[UILabel alloc] init];

    lb.font = [UIFont boldSystemFontOfSize:20];

    lb.text = @”B”;

    lb.textColor = [UIColor orangeColor];

    lb.backgroundColor = [UIColor clearColor];

    [lb sizeToFit];

    lb.center = CGPointMake(B.x10, B.y + 10);

    [self.view addSubview:lb];

    

    UILabel *lc = [[UILabel alloc] init];

    lc.font = [UIFont boldSystemFontOfSize:20];

    lc.text = @”C”;

    lc.textColor = [UIColor blueColor];

    lc.backgroundColor = [UIColor clearColor];

    [lc sizeToFit];

    lc.center = CGPointMake(C.x + 10, C.y + 10);

    [self.view addSubview:lc];

    

}

– (void)createConsole

{

    console = [[UILabel alloc] initWithFrame:CGRectMake(20, 400, 280, 100)];

    console.text = @”1 : 2 : √5 の三角形を描きます。;

    console.font = [UIFont systemFontOfSize:15];

    console.textAlignment = 1;

    console.backgroundColor = [UIColor colorWithWhite:0.3 alpha:0.3];

    console.layer.cornerRadius = 10;

    [self.view addSubview:console];

    

    UILabel *next = [[UILabel alloc] initWithFrame:CGRectMake(200, 60, 80, 50)];

    next.backgroundColor = [UIColor colorWithWhite:0 alpha:0.01];

    next.text = @”- 次へ -“;

    next.textAlignment = 1;

    next.font = [UIFont boldSystemFontOfSize:15];

    [console addSubview:next];

    

    CABasicAnimation *ba = [CABasicAnimation animationWithKeyPath:@”opacity”];

    ba.fromValue = @0.3;

    ba.toValue = @1;

    ba.duration = 1.0;

    ba.repeatCount = 1000;

    [next.layer addAnimation:ba forKey:nil];

    

    console.userInteractionEnabled = YES;

    next.userInteractionEnabled = YES;

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

    [next addGestureRecognizer:tap];

}

– (void)next:(UITapGestureRecognizer*)gr

{

    page++;

    

    switch (page) {

        case 1:

            [self arcWithCenterA];

            console.text = @”ABを半径に円を描きます。;

            break;

        case 2:

            [self arcWithCenterC];

            console.text = @”CDを半径に円をまた描きます。;

            break;

        case 3:

            [self createGoldenRectangle];

            console.text = @”BE:EC = 1:1.618 ができました;

            break;

            

        default:

            break;

    }

}

– (void)arcWithCenterA

{

    UIBezierPath *path = [UIBezierPath bezierPath];

    [path moveToPoint:A];

    [path addLineToPoint:B];

    float radius = A.yB.y;

    [path addArcWithCenter:A radius:radius startAngle:-M_PI/2.0 endAngle:-M_PI clockwise:NO];

    

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

    s1.fillColor = [UIColor clearColor].CGColor;

    s1.strokeColor = [UIColor redColor].CGColor;

    s1.lineWidth = 2;

    s1.lineDashPattern = @[@5, @5];

    s1.path = path.CGPath;

    [self.view.layer addSublayer:s1];

    

    // animation UIBezierPath

    [self startDraw:s1 duration:2.0];

    

    UILabel *ld = [[UILabel alloc] init];

    ld.font = [UIFont boldSystemFontOfSize:20];

    ld.text = @”D”;

    ld.textColor = [UIColor darkGrayColor];

    ld.backgroundColor = [UIColor clearColor];

    [ld sizeToFit];

    ld.center = CGPointMake(D.x + 10, D.y10);

    [self.view addSubview:ld];

}

– (void)arcWithCenterC

{

    UIBezierPath *path = [UIBezierPath bezierPath];

    [path moveToPoint:C];

    [path addLineToPoint:D];

    float radius = hypotf(C.xD.x, C.yD.y);

    float start = M_PI + (M_PI/2.0angleA);

    [path addArcWithCenter:C radius:radius startAngle:start endAngle:start – M_PI * 0.2 clockwise:NO];

    

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

    s1.fillColor = [UIColor clearColor].CGColor;

    s1.strokeColor = [UIColor redColor].CGColor;

    s1.lineWidth = 2;

    s1.lineDashPattern = @[@5, @5];

    s1.path = path.CGPath;

    [self.view.layer addSublayer:s1];

    

    [self startDraw:s1 duration:2.0];

    

    UILabel *le = [[UILabel alloc] init];

    le.font = [UIFont boldSystemFontOfSize:20];

    le.text = @”E”;

    le.textColor = [UIColor darkGrayColor];

    le.backgroundColor = [UIColor clearColor];

    [le sizeToFit];

    le.center = CGPointMake(E.x, E.y + 10);

    [self.view addSubview:le];

}

– (void)createGoldenRectangle

{

    UIBezierPath *path = [UIBezierPath bezierPath];

    [path moveToPoint:CGPointMake(E.x, E.y + 50)];

    [path addLineToPoint:CGPointMake(E.x, E.y + 55)];

    [path moveToPoint:CGPointMake(E.x, E.y + 50)];

    [path addLineToPoint:CGPointMake(C.x, C.y + 50)];

    

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

    s1.fillColor = [UIColor clearColor].CGColor;

    s1.strokeColor = [UIColor redColor].CGColor;

    s1.lineWidth = 2;

    s1.path = path.CGPath;

    [self.view.layer addSublayer:s1];

    [self startDraw:s1 duration:0.5];

    

    [self performSelector:@selector(createGoldenRectangle2) withObject:nil afterDelay:1.0];

    

    [self performSelector:@selector(createGoldenRectangle3) withObject:nil afterDelay:2.0];

    

    [self performSelector:@selector(createGoldenRectangle4) withObject:nil afterDelay:3.0];

}

– (void)createGoldenRectangle2

{

    UIBezierPath *path = [UIBezierPath bezierPath];

    [path moveToPoint:CGPointMake(B.x, B.y + 50)];

    [path addLineToPoint:CGPointMake(E.x, E.y + 50)];

    

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

    s2.fillColor = [UIColor clearColor].CGColor;

    s2.strokeColor = [UIColor redColor].CGColor;

    s2.lineWidth = 2;

    s2.path = path.CGPath;

    [self.view.layer addSublayer:s2];

    

    [self startDraw:s2 duration:0.5];

}

– (void)createGoldenRectangle3

{

    CALayer *l = [self.view.layer.sublayers lastObject];

    CATransform3D t = l.transform;

    t = CATransform3DTranslate(t, E.x, E.y + 50, 0);

    t = CATransform3DRotate(t, – M_PI *0.5, 0, 0, 1);

    t = CATransform3DTranslate(t, –E.x, –E.y50, 0);

    

    [UIView animateWithDuration:0.5 animations:^{

        l.transform = t;

    }];

}

– (void)createGoldenRectangle4

{

    UIBezierPath *path = [UIBezierPath bezierPath];

    [path moveToPoint:CGPointMake(E.x, E.y + (E.xB.x + 50))];

    [path addLineToPoint:CGPointMake(C.x, C.y + (E.xB.x + 50))];

    [path addLineToPoint:CGPointMake(C.x, C.y + 50)];

    

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

    s2.fillColor = [UIColor clearColor].CGColor;

    s2.strokeColor = [UIColor redColor].CGColor;

    s2.lineWidth = 2;

    s2.path = path.CGPath;

    [self.view.layer addSublayer:s2];

    

    [self startDraw:s2 duration:0.5];

}

– (void)startDraw:(CALayer*)l duration:(float)duration

{

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

    a.duration = duration;

    a.fromValue = @0;

    a.toValue = @1;

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

}

– (void)didReceiveMemoryWarning

{

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}

@end