I have a question related to cutting up an image to know which part is tapped by the user. It’s a rather simple exercise for some, I think, but I’ve been cracking my head over this and can’t find a proper way.
What I would like to do is tap a body part on this image and have the device tell me what body part it is:
But I have absolutely no clue on how to program this.
-
I’ve been thinking on setting an array of outline CGPoints for every body part, but how to get those? Photoshop coordinates? And then calculate the touched point onto the closest CGPoint?
-
Somebody gave me the idea to cut up the image in the different zones, different images for every body part. But here the problem is that every image is a rectangle, which makes it very hard to know what exactly got touched. Would also need an array of points, especially for the overlapping images.
-
Another person told me this would only be possible using SpriteKit.
Let me know, smart peeps 🙂
UPDATE:
I figured it out! I’m making a lot of arrays that contain the points to the hand, the legs, … An example:
CGPoint p1 = CGPointMake(x + 432, y + 200);
CGPoint p2 = CGPointMake(x + 523, y + 188);
CGPoint p3 = CGPointMake(x + 530, y + 277);
CGPoint p4 = CGPointMake(x + 432, y + 277);
CGPoint p5 = CGPointMake(x + 523, y + 367);
CGPoint p6 = CGPointMake(x + 432, y + 354);
CGPoint p7 = CGPointMake(x + 325, y + 355);
CGPoint p8 = CGPointMake(x + 296, y + 362);
NSArray *handL = [NSArray arrayWithObjects:
[NSValue valueWithCGPoint:p1],
[NSValue valueWithCGPoint:p2],
[NSValue valueWithCGPoint:p3],
[NSValue valueWithCGPoint:p4], nil];
[shapes addObject:@{@"name":NSLocalizedString(@"Left Hand", @""), @"points":handL}];
NSArray *handR = [NSArray arrayWithObjects:
[NSValue valueWithCGPoint:p5],
[NSValue valueWithCGPoint:p6],
[NSValue valueWithCGPoint:p7],
[NSValue valueWithCGPoint:p8], nil];
[shapes addObject:@{@"name":NSLocalizedString(@"Right Hand", @""), @"points": handR}];
Afterwards in I read these values and layer them:
NSArray *shapes = [[NumbersHelper sharedNumbersHelper] getScreenThreeShapes];
for (int outside = 0; outside < [shapes count]; outside++) {
CAShapeLayer *shape = [[CAShapeLayer alloc] init];
[self.scrollView.layer addSublayer:shape];
shape.opacity = 0.5;
shape.lineWidth = 2;
shape.lineJoin = kCALineJoinRound;
NSArray *points = [[[shapes valueForKey:@"points"] allObjects] objectAtIndex:outside];
UIBezierPath *path = [[UIBezierPath alloc] init];
for (int inside = 0; inside < points.count; inside++) {
if (inside == 0) {
[path moveToPoint:[[points objectAtIndex:inside] CGPointValue]];
} else {
[path addLineToPoint:[[points objectAtIndex:inside] CGPointValue]];
}
}
[path closePath];
shape.path = [path CGPath];
shape.name = [[[shapes valueForKey:@"name"] allObjects] objectAtIndex:outside];
}
When the user taps the view I do this:
- (void)tappedOnView:(UITapGestureRecognizer *)sender
{
if ([sender locationInView:self.scrollView].x > 2048 && [sender locationInView:self.scrollView].x < 3072) {
screenTwoTouchedPoint = [sender locationInView:self.scrollView];
CGPoint touchPoint = [sender locationInView:self.scrollView];
NSString *name;
for (id sublayers in self.scrollView.layer.sublayers) {
if ([sublayers isKindOfClass:[CAShapeLayer class]]) {
CAShapeLayer *shape = sublayers;
if (CGPathContainsPoint(shape.path, 0, touchPoint, YES)) {
name = shape.name;
break;
}
}
}
[self tappedBody:sender onPart:name];
}
}
2
Answers
A solution that worked for me. Create a 2d array for the entire size of the image. If the image is 250×250, your array would be the same.
Fill this array with NSObjects, having and
int
bodyInteger
Then drag your finger on the hand of the image, and in your
touchesMoved
take the co-ordinates from location, and pick the object from your 2d array by using the co-ordinates and setting its bodyInteger to 1.Now when someone puts finger on hand, you take the respective object from 2d array and see what bodyInteger it has.
If you have memory constraints, you can create a structure instead of an NSObject and save only for the points that are within the body.
Alternatively, you can create a boundary for each body part and save it. When user touches with finger, you can see if the point is within a saved polygon or not.
A crude but simple way would be to have transparent buttons over various body parts. In case a body part is not covered properly by a single button, add multiple smaller buttons.
You can add tag to the buttons to identify which button/body part got tapped or connect them to unique Actions.