Point in Polygon in C

Last Updated : 26 Jul, 2024

In computational geometry, we come across a problem to determine whether a given point lies inside, outside, or on the boundary of a polygon. This problem, known as the "Point in Polygon" (PIP) problem. It has numerous applications in computer graphics, geographic information systems (GIS), and robotics.

In this article, we will learn how to check if a given point lies inside or outside a polygon in C language. We will also look at different methods to achieve this.

Example:

Input: 
Polygon: { { 0, 0 }, { 10, 0 }, { 10, 10 }, { 0, 10 } }
Point: {20, 20};

Output:
Point is outside the polygon.
stark
Point in Polygon

Method 1: Using Ray Casting Algorithm

In this method, we first cast a horizontal ray from the point in question to infinity and count how many times the ray intersects the edges of the polygon. If the number of intersections is odd, the point is inside the polygon. If even, the point is outside.

As seen in below diagram Point A and C has one intersection with polygon edges which is odd in number thus the point A and C are inside the polygon whereas Point B and D have two intersections with polygon edges which is even thus the point B and D are outside the polygon and also Point E has 0 intersection with polygon edges which is also even and thus lying outside the polygon. We can confirm above speculation from the diagram are true.

stark

Approach

  • Initialize a counter for intersections to zero.
  • For each edge of the polygon:
    • Check if the edge intersects the horizontal ray extending to the right from the point.
    • If it does, increment the intersection counter.
  • If the intersection counter is odd, the point is inside the polygon; if even, it is outside.

C Program to Check Point in Polygon using Ray Casting Algorithm

The below program demonstrates how we can check if a point lies inside or outside a polygon using ray casting algorithmin C.

C
// C program to check if a point is inside a polygon using
// ray-casting algorithm

#include <float.h>
#include <math.h>
#include <stdio.h>

// Structure for a point
typedef struct {
    double x, y;
} Point;

// Function to check if a point is on the boundary of a
// polygon edge
int onSegment(Point p, Point q, Point r)
{
    if (q.x <= fmax(p.x, r.x) && q.x >= fmin(p.x, r.x)
        && q.y <= fmax(p.y, r.y) && q.y >= fmin(p.y, r.y))
        return 1;
    return 0;
}

// Function to find the orientation of the triplet (p, q, r)
// 0 --> p, q and r are collinear
// 1 --> Clockwise
// 2 --> Counterclockwise
int orientation(Point p, Point q, Point r)
{
    double val = (q.y - p.y) * (r.x - q.x)
                 - (q.x - p.x) * (r.y - q.y);
    // collinear
    if (val == 0)
        return 0;
    // clock or counterclock wise
    return (val > 0) ? 1 : 2;
}

// Function to check if two line segments intersect
int doIntersect(Point p1, Point q1, Point p2, Point q2)
{
    int o1 = orientation(p1, q1, p2);
    int o2 = orientation(p1, q1, q2);
    int o3 = orientation(p2, q2, p1);
    int o4 = orientation(p2, q2, q1);

    // General case
    if (o1 != o2 && o3 != o4)
        return 1;

    // Special Cases
    // p1, q1 and p2 are collinear and p2 lies on segment
    // p1q1
    if (o1 == 0 && onSegment(p1, p2, q1))
        return 1;

    // p1, q1 and p2 are collinear and q2 lies on segment
    // p1q1
    if (o2 == 0 && onSegment(p1, q2, q1))
        return 1;

    // p2, q2 and p1 are collinear and p1 lies on segment
    // p2q2
    if (o3 == 0 && onSegment(p2, p1, q2))
        return 1;

    // p2, q2 and q1 are collinear and q1 lies on segment
    // p2q2
    if (o4 == 0 && onSegment(p2, q1, q2))
        return 1;

    return 0; // Doesn't fall in any of the above cases
}

// Function to check if the point p is inside the polygon
int isInside(Point polygon[], int n, Point p)
{
    // Create a point for the ray (a point far outside the
    // polygon)
    Point extreme = { DBL_MAX, p.y };
    int count = 0, i = 0;
    do {
        int next = (i + 1) % n;
        if (doIntersect(polygon[i], polygon[next], p,
                        extreme)) {
            if (orientation(polygon[i], p, polygon[next])
                == 0)
                return onSegment(polygon[i], p,
                                 polygon[next]);
            count++;
        }
        i = next;
    } while (i != 0);
    // Return true if count is odd, false otherwise
    return count & 1;
}

int main()
{
    Point polygon[]
        = { { 0, 0 }, { 10, 0 }, { 10, 10 }, { 0, 10 } };
    int n = sizeof(polygon) / sizeof(polygon[0]);
    Point p = { 20, 20 };
    isInside(polygon, n, p)
        ? printf("Point is inside the polygon.\n")
        : printf("Point is outside the polygon.\n");
    return 0;
}


Output

Point is outside the polygon.

Time Complexity: O(n), where n is the number of vertices in the polygon.
Auxiliary Space: O(1)

Method 2: Using Winding Number Algorithm

In this method we count the number of times the polygon winds around the point. If the winding number is non-zero, the point is inside; otherwise, it is outside. This method is robust and handles complex polygons, including those with holes.

Approach

  • Initialize the winding number to zero.
  • For each edge of the polygon:
    • Check the edge direction (upwards or downwards) and whether the point is between the edge's y-coordinates.
    • Adjust the winding number based on the edge direction and whether the point lies to the left or right of the edge.
  • If the winding number is non-zero, the point is inside the polygon; otherwise, it is outside.

C Program to Check Point in Polygon using Winding Number Algorithm

The below program demonstrates how we can check if a point lies inside or outside a polygon using Winding Number Algorithm in C.

C
// C program to check if a point lies inside a polygon using
// the winding number algorithm

#include <math.h>
#include <stdio.h>

// Point structure
typedef struct {
    double x;
    double y;
} Point;

// Function to calculate the minimum of two numbers
double my_min(double a, double b) { return a < b ? a : b; }

// Function to calculate the maximum of two numbers
double my_max(double a, double b) { return a > b ? a : b; }

// Function to calculate the cross product of vectors AB and
// AC
double cross_product(Point A, Point B, Point C)
{
    return (B.x - A.x) * (C.y - A.y)
           - (B.y - A.y) * (C.x - A.x);
}

// Function to determine if a point P is on segment AB
int is_point_on_segment(Point P, Point A, Point B)
{
    if (P.x >= my_min(A.x, B.x) && P.x <= my_max(A.x, B.x)
        && P.y >= my_min(A.y, B.y)
        && P.y <= my_max(A.y, B.y)) {
        return 1;
    }
    else {
        return 0;
    }
}

// Function to check if a point P lies inside the polygon
// defined by vertices poly with 'n' vertices
int is_point_inside_polygon(Point P, Point poly[], int n)
{
    int winding_number = 0;

    for (int i = 0; i < n; i++) {
        Point current_vertex = poly[i];
        Point next_vertex = poly[(i + 1) % n];

        // Check if P is on the edge
        if (is_point_on_segment(P, current_vertex,
                                next_vertex)) {
            // Point P is on the boundary of the polygon
            return 1;
        }

        // Calculate the cross product
        double cross_product_value
            = cross_product(current_vertex, next_vertex, P);

        // Determine the relative position of P to the edge
        if (current_vertex.y <= P.y) {
            if (next_vertex.y > P.y
                && cross_product_value > 0) {
                winding_number++;
            }
        }
        else {
            if (next_vertex.y <= P.y
                && cross_product_value < 0) {
                winding_number--;
            }
        }
    }

    // If winding number is non-zero, P is inside the
    // polygon; otherwise, it's outside
    return (winding_number != 0);
}

// Example usage
int main()
{
    // Define a polygon (example triangle)
    Point polygon[]
        = { { 0, 0 }, { 10, 0 }, { 10, 10 }, { 0, 10 } };
    int n = sizeof(polygon) / sizeof(polygon[0]);

    // Test point
    Point test_point = { 20, 20 };

    // Check if the test point is inside the polygon
    if (is_point_inside_polygon(test_point, polygon, n)) {
        printf(
            "Point (%.1f, %.1f) is inside the polygon.\n",
            test_point.x, test_point.y);
    }
    else {
        printf(
            "Point (%.1f, %.1f) is outside the polygon.\n",
            test_point.x, test_point.y);
    }

    return 0;
}

Output
Point (20.0, 20.0) is outside the polygon.

Time Complexity: O(n), where n is the number of vertices in the polygon.
Auxiliary Space: O(1)

Method 3: Using Crossing Number Algorithm

The Crossing Number algorithm is similar to the Ray-Casting algorithm but uses a vertical ray instead. It counts the number of times the vertical ray from the point intersects the polygon’s edges. If the count is odd, the point is inside; if even, it is outside.

Approach

  • Initialize a boolean variable inside to false to keep a track whether the point is inside the polygon based on the number of edge crossings.
  • Start iterating through each edge of the polygon:
    • Determine if the point lies on the same side of the edge’s y-range as the polygon.
    • Count edge crossings from one side to the other using linear interpolation to find the x-coordinate where the ray crosses the edge.
  • If the number of crossings is odd, toggle the inside variable to true and if the number of crossings is even, the point remains outside the polygon.

C Program to Check Point in Polygon using Crossing Number Algorithm

The below program demonstrates how we can check if a point lies inside or outside a polygon using crossing numbw algorithm C.

C
#include <stdio.h>

// Structure to represent a point
typedef struct {
    double x, y;
} Point;

// Function to check if a point q lies on the segment pr
int onSegment(Point p, Point q, Point r) {
    // Check if q lies between p and r
    if (q.x <= fmax(p.x, r.x) && q.x >= fmin(p.x, r.x) &&
        q.y <= fmax(p.y, r.y) && q.y >= fmin(p.y, r.y)) {
        return 1;
    }
    return 0;
}

// Function to find the orientation of the ordered triplet (p, q, r)
// The function returns:
// 0 -> p, q, and r are collinear
// 1 -> Clockwise
// 2 -> Counterclockwise
int orientation(Point p, Point q, Point r) {
    double val = (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
    if (val == 0) return 0; // Collinear
    return (val > 0) ? 1 : 2; // Clockwise or Counterclockwise
}

// Function to check if two line segments p1q1 and p2q2 intersect
int doIntersect(Point p1, Point q1, Point p2, Point q2) {
    // Find the four orientations needed for the general and special cases
    int o1 = orientation(p1, q1, p2);
    int o2 = orientation(p1, q1, q2);
    int o3 = orientation(p2, q2, p1);
    int o4 = orientation(p2, q2, q1);

    // General case
    if (o1 != o2 && o3 != o4) return 1;

    // Special cases
    if (o1 == 0 && onSegment(p1, p2, q1)) return 1;
    if (o2 == 0 && onSegment(p1, q2, q1)) return 1;
    if (o3 == 0 && onSegment(p2, p1, q2)) return 1;
    if (o4 == 0 && onSegment(p2, q1, q2)) return 1;

    return 0; // Doesn't intersect
}

// Function to check if a point p lies inside the polygon with n vertices
int isPointInPolygon(Point polygon[], int n, Point p) {
    // There must be at least 3 vertices in polygon
    if (n < 3) return 0;

    // Create a point for the line segment from p to infinity
    Point extreme = {10000, p.y};

    // Count intersections of the above line with the sides of the polygon
    int count = 0, i = 0;
    do {
        int next = (i + 1) % n;

        // Check if the line segment from 'p' to 'extreme' intersects
        // with the line segment from 'polygon[i]' to 'polygon[next]'
        if (doIntersect(polygon[i], polygon[next], p, extreme)) {
            // If the point 'p' is collinear with line segment 'i-next',
            // then check if it lies on segment. If it lies, return true.
            if (orientation(polygon[i], p, polygon[next]) == 0) {
                return onSegment(polygon[i], p, polygon[next]);
            }
            count++;
        }
        i = next;
    } while (i != 0);

    // Return true if count is odd, false otherwise
    return count % 2 == 1;
}

// Main function
int main() {
    // Define the polygon as a list of points
    Point polygon[] = {{1, 1}, {1, 5}, {5, 5}, {5, 1}};
    int n = sizeof(polygon) / sizeof(polygon[0]);

    // Define the point to be checked
    Point p = {3, 3};

    // Check if the point is inside the polygon
    if (isPointInPolygon(polygon, n, p)) {
        printf("Point is inside the polygon.\n");
    } else {
        printf("Point is outside the polygon.\n");
    }

    return 0;
}

Time Complexity: O(n), where n is the number of vertices in the polygon.
Auxiliary Space: O(1)

Conclusion

In this article we understood that Point in Polygon (PIP) problem is fundamental in computational geometry with various practical applications, including computer graphics, geographic information systems (GIS), and robotics. Also, we discussed three methods —Ray Casting Algorithm, Winding Number Algorithm, and Edge Crossing Method—offer different approaches to determine whether a point lies inside a polygon.

Comment