CSES Solutions Point in Polygon (original) (raw)

Last Updated : 23 Jul, 2025

You are given a polygon of **N vertices and a list of **M points. Your task is to determine for each point if it is inside, outside or on the boundary of the polygon.

The polygon consists of n vertices (x1,y1),(x2,y2),...,(xn,yn). The vertices (xi,yi) and (xi+1,yi+1) are adjacent for i=1,2,...,n-1, and the vertices (x1,y1) and (xn,yn) are also adjacent.

**Examples:

**Input: N = 4, M = 3, vertices = {{1, 1}, {4, 2}, {3, 5}, {1, 4}}, points = {{2, 3}, {3, 1}, {1, 3}}
**Output:
INSIDE
OUTSIDE
BOUNDARY

**Input: N = 4, M = 3, vertices = {{1, 3}, {1, 2}, {2, 5}, {2, 4}}, points = {{3, 3}, {1, 1}, {1, 3}}
**Output:
OUTSIDE
OUTSIDE
BOUNDARY

**Approach: To solve the problem, follow the below idea:

The idea is to use **cross product is used to determine the orientation of three points. If the cross product is positive, the points are in counterclockwise order. If it's negative, they are in clockwise order. If it's zero, the points are collinear. We'll Sort Points by their X-coordinates to simplify the comparison process.

**Step-by-step algorithm:

Below is the implementation of the algorithm:

C++ `

#include<bits/stdc++.h> using namespace std;

#define ll long long #define endl '\n'

// Define complex number type with long long components #define P complex

// Get real part of complex number #define X real()

// Get imaginary part of complex number #define Y imag()

// Define infinity constant const ll INF = 1e9 + 7;

// Function to calculate the cross product of three points ll cross(P a, P b, P c) { // Vector from a to b P u = b - a; // Vector from a to c P v = c - a; // Cross product of u and v ll cp = (conj(u)*v).Y; // Return sign of cross product return (cp > 0) - (cp < 0); }

// Function to compare two points by their X-coordinates bool comp(const P &a, const P &b) { // Compare points based on X-coordinate return (a.X == b.X) ? (a.Y < b.Y) : (a.X < b.X); }

// Function to check if a point is on the boundary of the polygon bool mid(P a, P b, P c) { // Create vector of points vector

v = {a, b, c}; // Sort points based on X-coordinate sort(v.begin(), v.end(), comp); // Check if the middle point is equal to c return (v[1] == c); }

// Function to check if a point is inside or outside the polygon bool check(P a, P b, P c, P d) { // Calculate cross product of vectors a-b and a-c ll cp1 = cross(a, b, c); // Calculate cross product of vectors a-b and a-d ll cp2 = cross(a, b, d); // Calculate cross product of vectors c-d and c-a ll cp3 = cross(c, d, a); // Calculate cross product of vectors c-d and c-b ll cp4 = cross(c, d, b); // Check if points c and d are on different sides of line a-b if (cp1 * cp2 < 0 && cp3 * cp4 < 0) return 1; // Check if point a lies on line c-d and b lies on opposite side of c-d if (cp3 == 0 && mid(c, d, a) && cp4 < 0) return 1; // Check if point b lies on line c-d and a lies on opposite side of c-d if (cp4 == 0 && mid(c, d, b) && cp3 < 0) return 1; // Otherwise, return false return 0; }

int main(){

// Provided input
ll n = 4, m = 3;
vector<pair<ll, ll>> vertices = {{1, 1}, {4, 2}, {3, 5}, {1, 4}};
vector<pair<ll, ll>> points = {{2, 3}, {3, 1}, {1, 3}};

// Vector to store the vertices of the polygon
vector<P> polygon;

// Input the vertices of the polygon
for (ll i = 0; i < n; i++) {
    // Add vertex to the polygon vector
    polygon.push_back({vertices[i].first, vertices[i].second});
}

// Add the first vertex to the end of the vector to make it a closed polygon
polygon.push_back(polygon[0]);

// Loop through the points and check if each point is inside, outside or on the boundary of the polygon
for (ll i = 0; i < m; i++) {
    // Create complex number representing the point
    P point = {points[i].first, points[i].second};
    // Create complex number representing infinity
    P infinity = {INF, INF};
    // Counter for number of intersections
    ll cnt = 0;
    // Flag to indicate if point lies on boundary
    ll flag = 0;
    for (ll j = 0; j < n; j++) {
        // Calculate cross product of vectors
        ll cp = cross(polygon[j], polygon[j+1], point);
        // If point lies on line segment
        if (cp == 0 && mid(polygon[j], polygon[j+1], point)) {
            // Set flag to indicate boundary
            flag = 1;
            // Exit loop
            break;
        }
        // Check for intersection
        cnt += check(polygon[j], polygon[j+1], point, infinity);
    }
    // If point lies on boundary, output "BOUNDARY"
    if (flag) cout << "BOUNDARY" << endl;
    // If odd number of intersections, point is inside, otherwise outside
    else cout << (cnt & 1 ? "INSIDE" : "OUTSIDE") << endl;
}

// Return 0 to indicate successful completion
return 0;

}

Java

import java.util.*;

class Point implements Comparable { long x, y;

Point(long x, long y) {
    this.x = x;
    this.y = y;
}

public int compareTo(Point p) {
    return Long.compare(this.x, p.x);
}

}

public class Main { static final long INF = (long)1e9 + 7;

static long cross(Point a, Point b, Point c) {
    Point u = new Point(b.x - a.x, b.y - a.y);
    Point v = new Point(c.x - a.x, c.y - a.y);
    long cp = u.x * v.y - u.y * v.x;
    return Long.signum(cp);
}

static boolean mid(Point a, Point b, Point c) {
    // Check if point c lies on the line segment formed by a and b
    if (c.x >= Math.min(a.x, b.x) && c.x <= Math.max(a.x, b.x) &&
        c.y >= Math.min(a.y, b.y) && c.y <= Math.max(a.y, b.y)) {
        // Calculate the cross product of vectors ac and ab
        long cp = cross(a, b, c);
        // If the cross product is zero, points a, b, and c are collinear
        if (cp == 0) {
            return true;
        }
    }
    return false;
}

static boolean check(Point a, Point b, Point c, Point d) {
    long cp1 = cross(a, b, c);
    long cp2 = cross(a, b, d);
    long cp3 = cross(c, d, a);
    long cp4 = cross(c, d, b);
    if (cp1 * cp2 < 0 && cp3 * cp4 < 0) return true;
    if (cp3 == 0 && mid(c, d, a) && cp4 < 0) return true;
    if (cp4 == 0 && mid(c, d, b) && cp3 < 0) return true;
    return false;
}

public static void main(String[] args) {
    long n = 4, m = 3;
    Point[] vertices = {new Point(1, 1), new Point(4, 2), new Point(3, 5), new Point(1, 4)};
    Point[] points = {new Point(2, 3), new Point(3, 1), new Point(1, 3)};

    List<Point> polygon = new ArrayList<>();
    for (int i = 0; i < n; i++) {
        polygon.add(vertices[i]);
    }
    polygon.add(polygon.get(0));

    for (int i = 0; i < m; i++) {
        Point point = points[i];
        Point infinity = new Point(INF, INF);
        long cnt = 0;
        long flag = 0;
        for (int j = 0; j < n; j++) {
            long cp = cross(polygon.get(j), polygon.get(j+1), point);
            if (cp == 0 && mid(polygon.get(j), polygon.get(j+1), point)) {
                flag = 1;
                break;
            }
            cnt += check(polygon.get(j), polygon.get(j+1), point, infinity) ? 1 : 0;
        }
        if (flag == 1) System.out.println("BOUNDARY");
        else System.out.println((cnt % 2 == 1) ? "INSIDE" : "OUTSIDE");
    }
}

}

Python3

class Point: def init(self, x, y): self.x = x self.y = y

def cross(a, b, c): u = Point(b.x - a.x, b.y - a.y) v = Point(c.x - a.x, c.y - a.y) cp = u.x * v.y - u.y * v.x return cp

def mid(a, b, c): if (c.x >= min(a.x, b.x) and c.x <= max(a.x, b.x) and c.y >= min(a.y, b.y) and c.y <= max(a.y, b.y)): cp = cross(a, b, c) if cp == 0: return True return False

def check(a, b, c, d): cp1 = cross(a, b, c) cp2 = cross(a, b, d) cp3 = cross(c, d, a) cp4 = cross(c, d, b) if cp1 * cp2 < 0 and cp3 * cp4 < 0: return True if cp3 == 0 and mid(c, d, a) and cp4 < 0: return True if cp4 == 0 and mid(c, d, b) and cp3 < 0: return True return False

n = 4 m = 3 vertices = [Point(1, 1), Point(4, 2), Point(3, 5), Point(1, 4)] points = [Point(2, 3), Point(3, 1), Point(1, 3)]

polygon = vertices + [vertices[0]]

INF = 10 ** 9 + 7

for point in points: cnt = 0 flag = 0 infinity = Point(INF, INF) for j in range(n): cp = cross(polygon[j], polygon[j + 1], point) if cp == 0 and mid(polygon[j], polygon[j + 1], point): flag = 1 break cnt += 1 if check(polygon[j], polygon[j + 1], point, infinity) else 0 if flag == 1: print("BOUNDARY") else: print("INSIDE" if cnt % 2 == 1 else "OUTSIDE")

JavaScript

class Point { constructor(x, y) { this.x = x; this.y = y; } }

function cross(a, b, c) { let u = new Point(b.x - a.x, b.y - a.y); let v = new Point(c.x - a.x, c.y - a.y); let cp = u.x * v.y - u.y * v.x; return cp; }

function mid(a, b, c) { if (c.x >= Math.min(a.x, b.x) && c.x <= Math.max(a.x, b.x) && c.y >= Math.min(a.y, b.y) && c.y <= Math.max(a.y, b.y)) { let cp = cross(a, b, c); if (cp === 0) { return true; } } return false; }

function check(a, b, c, d) { let cp1 = cross(a, b, c); let cp2 = cross(a, b, d); let cp3 = cross(c, d, a); let cp4 = cross(c, d, b); if (cp1 * cp2 < 0 && cp3 * cp4 < 0) { return true; } if (cp3 === 0 && mid(c, d, a) && cp4 < 0) { return true; } if (cp4 === 0 && mid(c, d, b) && cp3 < 0) { return true; } return false; }

let n = 4; let m = 3; let vertices = [new Point(1, 1), new Point(4, 2), new Point(3, 5), new Point(1, 4)]; let points = [new Point(2, 3), new Point(3, 1), new Point(1, 3)];

let polygon = vertices.concat([vertices[0]]);

const INF = 10 ** 9 + 7;

for (let point of points) { let cnt = 0; let flag = 0; let infinity = new Point(INF, INF); for (let j = 0; j < n; j++) { let cp = cross(polygon[j], polygon[j + 1], point); if (cp === 0 && mid(polygon[j], polygon[j + 1], point)) { flag = 1; break; } cnt += check(polygon[j], polygon[j + 1], point, infinity) ? 1 : 0; } if (flag === 1) { console.log("BOUNDARY"); } else { console.log(cnt % 2 === 1 ? "INSIDE" : "OUTSIDE"); } }

`

Output

INSIDE OUTSIDE BOUNDARY

**Time Complexity: O(nmlog(n)), n is the number of vertices in the polygon, m is the number of points to be checked
**Auxiliary Space: O(m), as it needs to store the m points in memory.