Search code examples
iosatan2

How to detect area while tapping inside circle in ios


enter image description hereI want to find the area while tapping inside the circle. Actually I have done one calculation, but that was not accurate.

Check the code snippet I wrote, in order to find the position of the tab in my cycle view.

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event" this method

     float  dx = touchLocation.x -160;
     float  dy = touchLocation.y - 240;
     double angle = atan2(touchLocation.x,touchLocation.y);
 /* Device is iPad */
            if (count==4) {


                if(angle>-1.639&&angle<=0.775)
                {
                    area=1;
                    NSLog(@"touched here  1 ********************************** ");
                }
                else if(angle>0.775&&angle<=1.579)
                {
                    area=2;
                    NSLog(@"touched here   2********************************** ");
                }
                else if(angle>1.579&&angle<=2.466)
                {
                    area=3;NSLog(@"touched here   3********************************** ");
                }
                else
                {
                    area=4;NSLog(@"touched here  4 ********************************** ");
                }


            }
            else  if (count==5) {


                if(angle>-1.520&&angle<=0.553)
                {
                    area=1;
                    NSLog(@"touched here  1 ********************************** ");
                }
                else if(angle>0.553&&angle<=1.262)
                {
                    area=2;
                    NSLog(@"touched here   2********************************** ");
                }
                else if(angle>1.262&&angle<=1.884)
                {
                    area=3;NSLog(@"touched here   3********************************** ");
                }
                else if(angle>1.884&&angle<=2.644)
                {
                    area=4;NSLog(@"touched here  4 ********************************** ");
                }

                else
                {
                    area=5;NSLog(@"touched here  5 ********************************** ");
                }


            }
            else  if (count==6) {


                if(angle>-1.5707&&angle<=0.4692)
                {
                    area=1;
                    NSLog(@"touched here  1 ********************************** ");
                }
                else if(angle>0.4692&&angle<=1.0219)
                {
                    area=2;
                    NSLog(@"touched here   2********************************** ");
                }
                else if(angle>1.0219&&angle<=1.5707)
                {
                    area=3;NSLog(@"touched here   3********************************** ");
                }
                else if(angle>1.5707&&angle<=2.1147)
                {
                    area=4;NSLog(@"touched here  4 ********************************** ");
                }
                else if(angle>2.1147&&angle<=2.7245)
                {
                    area=5;NSLog(@"touched here  5 ********************************** ");
                }
                else
                {
                    area=6;NSLog(@"touched here  6 ********************************** ");
                }


            }
            else  if (count==7) {


                if(angle>-1.5707&&angle<=0.3992)
                {
                    area=1;
                    NSLog(@"touched here  1 ********************************** ");
                }
                else if(angle>0.3992&&angle<=0.8602)
                {
                    area=2;
                    NSLog(@"touched here   2********************************** ");
                }
                else if(angle>0.8602&&angle<=1.346)
                {
                    area=3;NSLog(@"touched here   3********************************** ");
                }
                else if(angle>1.346&&angle<=1.812)
                {
                    area=4;NSLog(@"touched here  4 ********************************** ");
                }
                else if(angle>1.812&&angle<=2.304)
                {
                    area=5;NSLog(@"touched here  5 ********************************** ");
                }
                else if(angle>2.304&&angle<=2.828)
                {
                    area=6;NSLog(@"touched here  6 ********************************** ");
                }

                else
                {
                    area=7;NSLog(@"touched here  7 ********************************** ");
                }


            }
            else if (count==8){

                if(angle>-1.40&&angle<=0.45)
                {
                    area=1;
                    NSLog(@"touched here  1 ********************************** ");
                }
                else if(angle>.45&&angle<=.73)
                {
                    area=2;
                    NSLog(@"touched here   2********************************** ");
                }
                else if(angle>.73&&angle<=1.15)
                {
                    area=3;NSLog(@"touched here   3********************************** ");
                }
                else if(angle>1.15&&angle<=1.55){
                    area=4;NSLog(@"touched here  4 ********************************** ");
                }
                else if(angle>-1.55&&angle<=1.95){
                    area=5;NSLog(@"touched here  5 ********************************** ");
                }
                else if(angle>-1.95&&angle<=2.43){
                    area=6;NSLog(@"touched here  6 ********************************** ");
                }
                else if(angle>2.43&&angle<=2.98){
                    area=7;NSLog(@"touched here   7********************************** ");
                }

                //     else if(angle>2.98&&angle<=-1.40){
                else
                {
                    area=8;NSLog(@"touched here  8 ********************************** ");
                }

            } 

enter image description here


Solution

  • Update: Complete working code added

    Here is some pseudocode to help you figure out where you tapped. This is with reference to the topmost figure. (I'm assuming your circle's center coincides with the view's center):

    (1) Find the direction of the line-segment from the center of the circle to the touch point:

    dx = touchPoint.x - circleCenter.x;
    dy = touchPoint.y - circleCenter.y;
    t = atan2(dy, dx); // some offsetting/direction adjustment might be required
    

    (2) Figure out which of the octants the touch point lies in.

    octant = floor(4 * t/M_PI); // will return a number between 0 and 7.
    

    If your sectors are not evenly sized (but you know the anglular size of each sector) you can use an if-else sequence.

    (3) The octants on the right hand side each have an "inner sector" and an annulus. If you want to test which of the two parts the touch took place in, you can first calculate the distance of the touch point from the center of the circle:

    dist = sqrtf(dx * dx + dy * dy);
    

    Obviously you'll need to know the inner radius of each octant, and then test

    if ( dist < innerRadius[i]) ... // again, you might need to adjust the angle calculations to ensure that the right indices correspond to the right sector. See (working) code below...
    

    innerRadius[8] is an array containing the inner radius of each octant.

    Here's some actual working code that programmatically generates a piechart and correctly detects the tap location. Simply replace the contents of ViewController.m in a "Single View Application" template with this:

    #import "ViewController.h"
    
    static float innerRadii[] = {50, 75, 100, 125, 150, 175, 200, 225};
    @implementation ViewController
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        float side = 600; // square view
        CGPoint center = CGPointMake(side/2, side/2);
        CGFloat radius = side/2 * 0.9;
    
        UIGraphicsBeginImageContextWithOptions(CGSizeMake(side, side), YES, 0.0);
        UIBezierPath *bgPath = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, side, side)];
        [[UIColor lightGrayColor] setFill];
        [bgPath fill];
        for (int i = 0; i < 8; i++)
        {
            UIBezierPath *sector = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:M_PI/4 * i endAngle:M_PI/4 * (i+1) clockwise:YES];
            [sector addLineToPoint:center];
            [sector closePath];
    #define VAL(x) x/2 + 0.25
    
            [[UIColor colorWithRed:VAL((float)(i % 2)) green:VAL((float)((i >> 1) % 2)) blue:VAL((float)((i >> 2) % 2)) alpha:1.0] setFill];
            [sector fill];
    
            UIBezierPath *innerSector = [UIBezierPath bezierPathWithArcCenter:center radius:innerRadii[i] startAngle:M_PI/4 * i endAngle:M_PI/4 * (i+1) clockwise:YES];
            [innerSector addLineToPoint:center];
            [innerSector closePath];
    #define VAL1(x) (1- x)/3 + 0.5
    
            [[UIColor colorWithRed:VAL1((float)(i  % 2)) green:VAL1((float)((i >> 1) % 2)) blue:VAL1((float)((i >> 2) % 2)) alpha:1.0] setFill];
            [innerSector fill];
    
        }
        UIImage *pieChartImg = UIGraphicsGetImageFromCurrentImageContext();
        UIImageView *pieChartView = [[UIImageView alloc] initWithImage:pieChartImg];
        pieChartView.center = self.view.center;
        [self.view addSubview:pieChartView];
    
        UITapGestureRecognizer *gr = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(identifyTappedSector:)];
        pieChartView.userInteractionEnabled = YES;
        [pieChartView addGestureRecognizer:gr];
    }
    
    - (void)identifyTappedSector:(UITapGestureRecognizer *)tgr
    {
        CGPoint touchPoint = [tgr locationInView:tgr.view];
        CGPoint circleCenter = CGPointMake(tgr.view.bounds.size.width/2, tgr.view.bounds.size.height/2);
        float dx = circleCenter.x - touchPoint.x;
        float dy = circleCenter.y - touchPoint.y;
        float t = atan2f(dy, dx) + M_PI;
        NSLog(@"angle = %f", t * 180.0/M_PI);
        int octant = floorf(4 * t/M_PI);
    
        NSLog(@"You tapped octant number: %d!", octant);
        float dist = sqrtf(dx * dx + dy * dy);
        if (dist <= innerRadii[octant])
            NSLog(@"\tYou tapped the inner sector!");
        else
            NSLog(@"\tYou tapped the annulus!");
    }
    
    
    @end