Search code examples
c++geometryrectangles

Find which sector a point lies in inside a rectangle split along it's diagonals


I have a program, which needs a function that returns an int (0 - 3) based on an x and y input. The return int should be based on the 'sector' that the point lies inside of a rectangle that has been cut on its diagonals. enter image description here

This is my current code

int liesIn(double x, double y, double w, double h){
    //x and y are relitive, so the top left corner can be thought of as the origin (0,0)
    double rectAspect = w / h;
    double pointAspect = x / y;
    if(rectAspect > pointAspect)//top of the topLeft-BottomRight line
    {
        if(y > x * rectAspect)
        {
            return 3;
        }else if(y < x * rectAspect){
            return 0;
        }
        return 4;
    }else if(rectAspect < pointAspect)
    {
        if(y > x * rectAspect)
        {
            return 2;
        }else if(y < x * rectAspect){
            return 1;
        }
        return 4;
    }else{
        return 4;//4 is the "false" condition, if the point lies on one of the 
    }
};

    std::cout << liesIn(0.25, 0.5, 1, 1) << std::endl; //should return 3, returns 3
    std::cout << liesIn(0.75, 0.1, 1, 2) << std::endl; //should return 1, returns 1
    std::cout << liesIn(0.5, 0.75, 1, 1) << std::endl; //should return 2, returns 3
    std::cout << liesIn(0.5, 0.25, 1, 1) << std::endl; //should return 0, returns 1

This is giving almost random results, which are not correct. What do I need to fix?


Solution

  • One diagonal (from 0,0) has equation

    y * w - x * h = 0
    

    Another diagonal has equation

    y * w + x * h - h * w = 0
    

    Substitution of point x,y into these equations gives quadrant (result sign tells us at what side of diagonal point does lie).

    int liesIn(double x, double y, double w, double h){
    
        if (y < 0 ||  y >= h || x < 0 || x >= w)
            return 5;  //outside result if needed
    
        if (y * w - x * h == 0 ||  y * w + x * h  - h * w  == 0)
            return 4;  //lies on diagonal 
                       //note possible issues due to float precision limitations
                       //better to compare fabs() with small epsylon value 
    
        int code = 0;
    
        if (y * w + x * h  - h * w > 0)
            code += 1;  //above second diagonal
    
        if (y * w - x * h > 0) {
            code += 2;    //above main diagonal
            code = 5 - code;    //flip 2/3 values to get your numbering
        }
        return code;
    };
    

    For your example gives 3 0 2 0 - note that your supposition about (0.75, 0.1, 1, 2) << std::endl; //should return 1, is wrong, 0 is correct result

    and clear examples:

     liesIn(1, 0.2, 2, 1)      0
     liesIn(1.5, 0.5, 2, 1)    1 
     liesIn(1, 0.8, 2, 1)      2
     liesIn(0.5, 0.5, 2, 1)    3
     liesIn(1, 0.5, 2, 1)      4