矩形の重なりを求めるプログラム
二つの矩形の重なり領域を求めるには、次の方法で求められるようだ。
// 二つの矩形の重なり部分を求める。 static CGRect intersect(CGRect a, CGRect b) { float sx = MAX(a.origin.x, b.origin.x); float sy = MAX(a.origin.y, b.origin.y); float ex = MIN(a.origin.x + a.size.width, b.origin.x + b.size.width); float ey = MIN(a.origin.y + a.size.height, b.origin.y + b.size.height); float w = ex - sx; float h = ey - sy; if (w > 0 && h > 0) { return CGRectMake(sx, sy, w, h); } return CGRectMake(0, 0, 0, 0); // 重なっていない }
二つの矩形の重なり領域を求めるiPhoneアプリを作ってみよう。次の順番にプログラムを作成していく。
- 矩形を描画する
- タッチ座標を取得して、その位置に矩形を描画する。
- 画面中央に固定の矩形を描画、タッチ位置にもうひとつの矩形を描画。二つの矩形の重なり領域を描画。
はじめに矩形の描画から。CGContextStrokeRectを使うと矩形が描画される。
- (void)drawRect:(CGRect)rect { CGContextRef c = UIGraphicsGetCurrentContext(); CGContextSetRGBStrokeColor(c, 0, 0, 0, 1); CGContextSetLineWidth(c, 1); CGContextStrokeRect(c, CGRectMake(10, 10, 100, 100)); }
次にタッチ座標の取得して、その位置に矩形を描画する。
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { UITouch* touch = [touches anyObject]; _point = [touch locationInView:self]; [self setNeedsDisplay]; } - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { UITouch* touch = [touches anyObject]; _point = [touch locationInView:self]; [self setNeedsDisplay]; }
変数_pointにタッチ位置を保存している。setNeedsDisplayを呼び出して再描画を要求し、drawRect:の中で_pointの値を参照してタッチ位置に矩形を描画する。
drawRect:では、二つの矩形を描画し、その二つの矩形の重なり領域を求めている。
- (void)drawRect:(CGRect)rect { CGContextRef c = UIGraphicsGetCurrentContext(); CGContextSetRGBStrokeColor(c, 0, 0, 0, 1); CGContextSetLineWidth(c, 1); CGContextStrokeRect(c, _rect1); // タッチ位置に矩形を描画する float x = _point.x - _size.width / 2; float y = _point.y - _size.height / 2; CGRect rect2 = CGRectMake(x, y, _size.width, _size.height); CGContextStrokeRect(c, rect2); // 重なり部分を描画 CGRect r = intersect(_rect1, rect2); if (r.size.width > 0) { CGContextFillRect(c, r); } }
以上で完成です。下のスクリーンショットのような感じで、重なり領域は黒で塗りつぶしています。
完成コードは以下です。
#import "MyView.h" // 二つの矩形の重なり部分を求める。 static CGRect intersect(CGRect a, CGRect b) { float sx = MAX(a.origin.x, b.origin.x); float sy = MAX(a.origin.y, b.origin.y); float ex = MIN(a.origin.x + a.size.width, b.origin.x + b.size.width); float ey = MIN(a.origin.y + a.size.height, b.origin.y + b.size.height); float w = ex - sx; float h = ey - sy; if (w > 0 && h > 0) { return CGRectMake(sx, sy, w, h); } return CGRectMake(0, 0, 0, 0); // 重なっていない } @implementation MyView - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { _point = CGPointMake(0, 0); // タッチ座標 _size = CGSizeMake(200, 30); // タッチ座標に描画する矩形のサイズ _rect1 = CGRectMake(100, 100, 90, 90); // 固定位置に描画する矩形 } return self; } - (void)drawRect:(CGRect)rect { CGContextRef c = UIGraphicsGetCurrentContext(); CGContextSetRGBStrokeColor(c, 0, 0, 0, 1); CGContextSetLineWidth(c, 1); CGContextStrokeRect(c, _rect1); // タッチ位置に矩形を描画する float x = _point.x - _size.width / 2; float y = _point.y - _size.height / 2; CGRect rect2 = CGRectMake(x, y, _size.width, _size.height); CGContextStrokeRect(c, rect2); // 重なり部分を描画 CGRect r = intersect(_rect1, rect2); if (r.size.width > 0) { CGContextFillRect(c, r); } } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { UITouch* touch = [touches anyObject]; _point = [touch locationInView:self]; [self setNeedsDisplay]; } - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { UITouch* touch = [touches anyObject]; _point = [touch locationInView:self]; [self setNeedsDisplay]; } @end