mathematics – Octagon border algorithm

I work on an open source game since 2 years and I’m very bad at math (it is not every time easy haha). My game permit to move a character on octagon. When character reach border coordinate (colored in yellow), I permit him to travel on a “new octagon”:

enter image description here

So, the algorithm goal is to know if an x, y tile coordinate is on a “yellow” tile, which direction is (North or North-Est or Est …) depending on map width and height.

I wrote this algorithm many times and in two different language, example with Rust:

pub fn get_corner(width: i16, height: i16, new_row_i: i16, new_col_i: i16) -> Option<CornerEnum> {
    let left_col_i_end = width / 3;
    let right_col_i_start = (width / 3) * 2;
    let top_row_i_end = height / 3;
    let bottom_row_i_start = (height / 3) * 2;
    let mut more = if new_row_i >= 0 { new_row_i } else { 0 };
    #(allow(unused_assignments))
    let mut right_col_i = 0;
    #(allow(unused_assignments))
    let mut left_col_i = 0;

    if new_row_i < top_row_i_end {
        right_col_i = right_col_i_start + more;
        left_col_i = left_col_i_end - more;
    } else {
        if new_row_i >= bottom_row_i_start {
            more = (height / 3) - (new_row_i - bottom_row_i_start + 1);
            more = if more >= 0 { more } else { 0 };
            right_col_i = right_col_i_start + more;
            left_col_i = left_col_i_end - more;
        } else {
            left_col_i = left_col_i_end;
            right_col_i = right_col_i_start;
        }
    }

    if new_col_i < left_col_i && new_row_i < top_row_i_end {
        return Some(CornerEnum::TopLeft);
    }
    if new_row_i < 0 && left_col_i <= new_col_i {
        return Some(CornerEnum::Top);
    }
    if new_col_i >= right_col_i && new_row_i < top_row_i_end {
        return Some(CornerEnum::TopRight);
    }
    if new_col_i > width - 1 && top_row_i_end <= new_row_i {
        return Some(CornerEnum::Right);
    }
    if new_col_i >= right_col_i && new_row_i >= bottom_row_i_start {
        return Some(CornerEnum::BottomRight);
    }
    if new_row_i > height - 1 && left_col_i_end <= new_col_i {
        return Some(CornerEnum::Bottom);
    }
    if new_col_i < left_col_i && new_row_i >= bottom_row_i_start {
        return Some(CornerEnum::BottomLeft);
    }
    if new_col_i < 0 && top_row_i_end <= new_row_i {
        return Some(CornerEnum::Left);
    }

    None
}

But it is not working well … I curse my math. I’m sure it’s not that complicated but i fail at each time in two years. So, i’m here to ask help, or for solution. That would be greatly appreciated!

c ++: you need a better way to find the overlapping area of ​​the octagon

Here is my problem statement:

There is an array of octagons, for example, 4 octagons in a row and 3 of those rows. Then 4 columns and 3 rows of octagons. But they are not arranged in a perfect rectangular shape.

Case 1:

Octagon Matrix

The first octagon, O (0,0) has coordinates (0,0), while the one on the right and the one on the bottom have a bit offset. Then O (0,1) has coordinates (15,50) and O (1,0) has coordinates (30,15). This information is sufficient to define the complete set of octagons. Now, the next requirement is to find out how much is the net visible area of ​​these octagons. In the first example, since the coordinates are far away, there would be no overlap and the total visible area is simply …

Total_Visible_Area = Area_of_Single_Octagon * No_Of_Rows * No_Of_Columns

But when the coordinates are not very complex, for example, Case 2:
enter the description of the image here
Here, the distance between adjacent octagons is smaller than their width and, therefore, overlap. The coordinates are also negative (which doesn't really matter much, just something to keep in mind). Now to determine the visible area for this I wrote the following function.

//Inputs of the function:
//S = Side of the octagon/2, 5*Accuracy_Factor for every case
//G = Total Width of the octagon/2, 5*2.41*Accuracy_Factor for every case
//NSX = X distance of the octagon O(1,0), 8.09*Accuracy_Factor in Case 2
//NSY = Y distance of the octagon O(1,0), -20.98*Accuracy_Factor in Case 2
//EWX = X distance of the octagon O(0,1), 17.37*Accuracy_Factor in Case 2
//EWY = Y distance of the octagon O(0,1), 12*Accuracy_Factor in Case 2
//NSCount = Total no of rows, 4 in this example
//EWCount = Total no of columns, 3 in this example

//The following function imagines a big 2D array. Each pixel of the octagon is one
//element of the array. Program calculates coordinates of all octagons. Picking the 
//octagons one by one, it forms an octagon around that coordinate in the 
//2D array by allotting 1 to the array. At the end I find a total number 
//of 1s ant that's my total visible area. I don't need to initialize the 
//array, unless I want to visualize the formation.

double OverlapArea(double S, double G, double NSX, double NSY, double EWX, double EWY, int NSCount, int EWCount)
{
    int count = 0, i, j, x, y, TotalArea=0;
    double A, B, Ai, Bi;
    A = Ai = G;    //X Coordinate of O(0,0)
    B = Bi = G;    //Y Coordinate of O(0,0)

    //following is the loop that generates the octagon, pixel by 
    //pixel (element by element).

    for (i = 0; i < NSCount; i++)
    {
        for (j = 0; j < EWCount; j++)
        {
            for (x = A - G; x < A + G; x++)
            {
                for (y = B - G; y < B + G; y++)
                {
                    if ((x - y >= A - B - S - G) && (y <= B + G) && (x + y <= A + B + S + G) && (x <= A + G) && (x - y <= A + G - B + S) && (y >= B - G) && (x + y >= A + B - S - G) && (x >= A - G))
                    {
                        //Area(x)(y) = 1; I use this to visualize at Accuracy = 1. To use this I also have to add some 20 lines of code to find the dimensions and initialize a 2D array.
                        TotalArea++; //This is an optimum way. I don't need to define an array at all. 
                    }
                }
            }
            A = Ai + EWX * (j+1);
            B = Bi + EWY * (j+1);
        }
        A = Ai + NSX;
        B = Bi + NSY;
        Ai = A;
        Bi = B;
    }
    return TotalArea;
}

Now the problem with this method:

  1. The precision factor that I set in the main function determines the accuracy of this method. The more accurate, the greater the time to calculate. It is as simple as increasing the resolution.
  2. I can only use the forms that I can define with equations. Rectangle, circle, octagon triangle, etc. If it is an irregular shape, I will have difficulty defining which pixel to count and which not.

I would like to know other methods to calculate the visible area. One thing that occurs to me is to enter the shape as an image, overlay it and then calculate the pixels at the end. But I'm not sure if there is a simpler way.