iPhoneアプリでtouch処理を使用する場合、画面上で既に表示されている物を、
認識させる必要があります。
種々の方法がありますが、その中で直線を認識させる方法についてです。
直線を数式で表すと、下記の数式1)に成ります。
数式1) Y=aX+b
結論から言えば、数式1)のbの値に範囲を与え、その範囲でX、Yの等式が成立
するか判断すれば、直線の認識処理は完成です。
上の画像の青い円の中心にある線の1点を認識しようとしています。
両側の円は、該当線をtouchしたと認識させたい範囲を表し、中央の円は認識
した位置です。
こういった面倒な方法を行う理由ですが、上の画像のように直線式が垂直に近く
成る程、Xの値に対するYの値の(逆も同様です)範囲が広くなり実際のtouch
処理で正しい場所をtouchしたと認識させるのが難しくなるからです。
(画像上の赤線がXの座標に対するY座標の取り得る範囲に成ります)
ダウンロードはこちらから
(プログラム例) ダウンロードファイルと同じです
//
// xxxx.h
//
// Created by 水谷 多加志 on 11/02/13.
// Copyright 2011. All rights reserved.
//
#import <UIKit/UIKit.h>
int kvStartX[10];
int kvStartY[10];
@interface xxxx : UIView {
}
@end
//
// xxxx.m
//
// Created by 水谷 多加志 on 11/02/13.
// Copyright 2011. All rights reserved.
//
#import "xxx.h"
@implementation xxxx
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
// Initialization code.
}
return self;
}
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
// コンテキストを設定
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(context,1.0);
// 外枠
CGContextMoveToPoint(context,108.8f,0);
CGContextAddLineToPoint(context,51.2f,1728);
CGContextStrokePath(context);
CGContextMoveToPoint(context,207.8f+58.0f,0);
CGContextAddLineToPoint(context,268.8+58.0f,1728);
CGContextStrokePath(context);
// 線分1
CGContextMoveToPoint(context,134.4f,0);
CGContextAddLineToPoint(context,83.2f,1728);
CGContextStrokePath(context);
// 線分2
CGContextMoveToPoint(context,118.2f+58.0f,0);
CGContextAddLineToPoint(context,95.6f+58.0f,1728);
CGContextStrokePath(context);
// 線分3
CGContextMoveToPoint(context,153.4f+58.0f,0);
CGContextAddLineToPoint(context,166.0f+58.0f,1728);
CGContextStrokePath(context);
// 線分4
CGContextMoveToPoint(context,185.4f+58.0f,0);
CGContextAddLineToPoint(context,236.4f+58.0f,1728);
CGContextStrokePath(context);
// touchした部分に円を描画
CGContextStrokeEllipseInRect(context, CGRectMake(kvStartX[0]+2, kvStartY[0]+2, 4, 4));
}
- (void)dealloc {
[super dealloc];
}
- (void)touchesBegan:(NSSet *) touches withEvent:(UIEvent *)event {
// Mult touch
NSSet *touchCnt = [event allTouches];
int cnt = [touchCnt count];
for (int i=0; i<cnt; i++) {
// touch座標点
UITouch *touch = [[touchCnt allObjects] objectAtIndex:i];
CGPoint touchLocation = [touch locationInView:self];
kvStartX[i] = touchLocation.x;
kvStartY[i] = touchLocation.y;
}
// touchした部分を判断
for (int i=0; i<cnt; i++) {
float wX;
float wY;
float wM1;
float wM2;
wX = (float)kvStartX[i];
wY = (float)kvStartY[i];
NSLog(@"x=%f,y=%f",wX,wY);
// 線判断
wM1 = -33.75f*wX+4136.0f;
wM2 = -33.75f*wX+4936.0f;
NSLog(@"wM1=%f",wM1);
NSLog(@"wM2=%f",wM2);
// 範囲判断
if (wY>wM1 && wY<wM2 ) {
NSLog(@"線分1OK!");
break;
}
wM1 = -90.0f*wX+13952.0f;
wM2 = -90.0f*wX+17152.0f;
NSLog(@"wM1=%f",wM1);
NSLog(@"wM2=%f",wM2);
// 範囲判断
if (wY>wM1 && wY<wM2 ) {
NSLog(@"1 OK");
break;
}
// 範囲判断
wM1 = 108.0f*wX-21064.0f;
wM2 = 108.0f*wX-23864.0f;
NSLog(@"wM1=%f",wM1);
NSLog(@"wM2=%f",wM2);
if (wY<wM1 && wY>wM2 ) {
NSLog(@"2 OK");
break;
}
wM1 = 31.8f*wX-7324.0f;
wM2 = 31.8f*wX-7924.0f;
NSLog(@"wM1=%f",wM1);
NSLog(@"wM2=%f",wM2);
if (wY<wM1 && wY>wM2 ) {
NSLog(@"3 OK");
break;
}
}
// touchした部分を描画
[self setNeedsDisplay];
}
@end