Find Simple Closed Path for a given set of points (original) (raw)

Last Updated : 23 Jul, 2025

Given a set of points, connect the dots without crossing.

Simple Closed Path for a given set of points 1Simple Closed Path for a given set of points 2

Example:

Input: points[] = {(0, 3), (1, 1), (2, 2), (4, 4), (0, 0), (1, 2), (3, 1}, {3, 3}};

Output: Connecting points in following order would not cause any crossing {(0, 0), (3, 1), (1, 1), (2, 2), (3, 3), (4, 4), (1, 2), (0, 3)}

We strongly recommend you to minimize your browser and try this yourself first.
The idea is to use sorting.

find the bottom-most point by comparing y coordinate of all points

traversing the sorted array

How to compute angles?
One solution is to use trigonometric functions.
Observation: We don’t care about the actual values of the angles. We just want to sort by angle.
Idea: Use the orientation to compare angles without actually computing them!

Below is C++ implementation of above idea.

C++ `

// A C++ program to find simple closed path for n points // for explanation of orientation() #include <bits/stdc++.h> using namespace std;

struct Point { int x, y; };

// A global point needed for sorting points with reference // to the first point. Used in compare function of qsort() Point p0;

// A utility function to swap two points int swap(Point &p1, Point &p2) { Point temp = p1; p1 = p2; p2 = temp; }

// A utility function to return square of distance between // p1 and p2 int dist(Point p1, Point p2) { return (p1.x - p2.x)(p1.x - p2.x) + (p1.y - p2.y)(p1.y - p2.y); }

// To find orientation of ordered triplet (p, q, r). // The function returns following values // 0 --> p, q and r are collinear // 1 --> Clockwise // 2 --> Counterclockwise int orientation(Point p, Point q, Point r) { int 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 counterclock wise

}

// A function used by library function qsort() to sort // an array of points with respect to the first point int compare(const void *vp1, const void *vp2) { Point *p1 = (Point *)vp1; Point *p2 = (Point *)vp2;

// Find orientation int o = orientation(p0, *p1, *p2); if (o == 0) return (dist(p0, *p2) >= dist(p0, *p1))? -1 : 1;

return (o == 2)? -1: 1; }

// Prints simple closed path for a set of n points. void printClosedPath(Point points[], int n) { // Find the bottommost point int ymin = points[0].y, min = 0; for (int i = 1; i < n; i++) { int y = points[i].y;

 // Pick the bottom-most. In case of tie, choose the
 // left most point
 if ((y < ymin) || (ymin == y &&
     points[i].x < points[min].x))
    ymin = points[i].y, min = i;

}

// Place the bottom-most point at first position swap(points[0], points[min]);

// Sort n-1 points with respect to the first point. // A point p1 comes before p2 in sorted output if p2 // has larger polar angle (in counterclockwise // direction) than p1 p0 = points[0]; qsort(&points[1], n-1, sizeof(Point), compare);

// Now stack has the output points, print contents // of stack for (int i=0; i<n; i++) cout << "(" << points[i].x << ", " << points[i].y <<"), "; }

// Driver program to test above functions int main() { Point points[] = {{0, 3}, {1, 1}, {2, 2}, {4, 4}, {0, 0}, {1, 2}, {3, 1}, {3, 3}}; int n = sizeof(points)/sizeof(points[0]); printClosedPath(points, n); return 0; }

Java

import java.util.*;

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

class ConvexHull { static Point p0;

static void swap(Point p1, Point p2) {
    Point temp = p1;
    p1 = p2;
    p2 = temp;
}

static int dist(Point p1, Point p2) {
    return (int)Math.pow(p1.x - p2.x, 2) +
           (int)Math.pow(p1.y - p2.y, 2);
}

static int orientation(Point p, Point q, Point r) {
    int 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; 
}

static int compare(Point p1, Point p2) {
    int o = orientation(p0, p1, p2);
    if (o == 0)
        return (dist(p0, p2) >= dist(p0, p1))? -1 : 1;
    return (o == 2)? -1: 1;
}

static void printClosedPath(Point points[], int n) {
    int ymin = points[0].y, min = 0;
    for (int i = 1; i < n; i++) {
        int y = points[i].y;
        if ((y < ymin) || (ymin == y &&
            points[i].x < points[min].x))
            ymin = points[i].y;
            min = i;
    }
    swap(points[0], points[min]);
    p0 = points[0];
    Arrays.sort(points, 1, n, (p1, p2) -> compare(p1, p2));
    for (int i=0; i<n; i++)
        System.out.println("(" + points[i].x + ", " + points[i].y + "), ");
}

public static void main(String[] args) {
    Point[] points = {new Point(0, 3), new Point(1, 1), new Point(2, 2), new Point(4, 4),
                      new Point(0, 0), new Point(1, 2), new Point(3, 1), new Point(3, 3)};
    int n = points.length;
    printClosedPath(points, n);
}

}

Python3

from functools import cmp_to_key

A Python program to find simple closed path for n points

for explanation of orientation()

A global point needed for sorting points with reference

to the first point. Used in compare function of qsort()

p0 = None

A utility function to return square of distance between

p1 and p2

def dist(p1, p2): return (p1[0] - p2[0])(p1[0] - p2[0]) + (p1[1] - p2[1])(p1[1] - p2[1])

To find orientation of ordered triplet (p, q, r).

The function returns following values

0 --> p, q and r are collinear

1 --> Clockwise

2 --> Counterclockwise

def orientation(p, q, r): val = (q[1] - p[1]) * (r[0] - q[0]) - (q[0] - p[0]) * (r[1] - q[1])

if val == 0: return 0  # collinear
return 1 if val > 0 else 2 # clockwise or counterclock wise

A function used by library function qsort() to sort

an array of points with respect to the first point

def compare(vp1, vp2): p1 = vp1 p2 = vp2

# Find orientation
o = orientation(p0, p1, p2)
if o == 0:
    return -1 if dist(p0, p2) >= dist(p0, p1) else 1

return -1 if o == 2 else 1

Prints simple closed path for a set of n points.

def printClosedPath(points, n): global p0 # Find the bottommost point ymin = points[0][1] min = 0 for i in range(1,n): y = points[i][1]

    # Pick the bottom-most. In case of tie, choose the
    # left most point
    if (y < ymin) or (ymin == y and points[i][0] < points[min][0]):
        ymin = points[i][1]
        min = i

# Place the bottom-most point at first position
temp = points[0]
points[0] = points[min]
points[min] = temp

# Sort n-1 points with respect to the first point.
# A point p1 comes before p2 in sorted output if p2
# has larger polar angle (in counterclockwise
# direction) than p1
p0 = points[0]
points.sort(key=cmp_to_key(compare))

# Now stack has the output points, print contents
# of stack
for i in range(n):
    print("(",points[i][0],",",points[i][1],"), ", end="")

Driver program to test above functions

points = [[0, 3], [1, 1], [2, 2], [4, 4], [0, 0], [1, 2], [3, 1], [3, 3]] n = len(points)

printClosedPath(points, n)

C#

using System; using System.Collections.Generic;

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

public class ClosestPath { static Point p0;

static int dist(Point p1, Point p2)
{
    return (p1.x - p2.x) * (p1.x - p2.x)
        + (p1.y - p2.y) * (p1.y - p2.y);
}

static int orientation(Point p, Point q, Point r)
{
    int 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
}

static int compare(Point p1, Point p2)
{
    int o = orientation(p0, p1, p2);
    if (o == 0)
        return (dist(p0, p2) >= dist(p0, p1)) ? -1 : 1;
    return (o == 2) ? -1 : 1;
}

static void printClosedPath(List<Point> points, int n)
{
    // Find the bottommost point
    int ymin = points[0].y;
    int min = 0;
    for (int i = 1; i < n; i++) {
        int y = points[i].y;
        if ((y < ymin)
            || (ymin == y
                && points[i].x < points[min].x)) {
            ymin = points[i].y;
            min = i;
        }
    }

    // Place the bottom-most point at first position
    Point temp = points[0];
    points[0] = points[min];
    points[min] = temp;

    // Sort n-1 points with respect to the first point.
    // A point p1 comes before p2 in sorted output if p2
    // has larger polar angle (in counterclockwise
    // direction) than p1
    p0 = points[0];
    points.Sort(compare);

    // Now stack has the output points, print contents
    // of stack
    for (int i = 0; i < n; i++) {
        Console.Write("(" + points[i].x + ", "
                      + points[i].y + "), ");
    }
}

public static void Main()
{
    List<Point> points = new List<Point>() {
        new Point(0, 3), new Point(1, 1),
            new Point(2, 2), new Point(4, 4),
            new Point(0, 0), new Point(1, 2),
            new Point(3, 1), new Point(3, 3)
    };
    int n = points.Count;

    printClosedPath(points, n);
}

} // This code is contributed by user_dtewbxkn77n

JavaScript

// A javascript program to find simple closed path for n points // for explanation of orientation()

// A global point needed for sorting points with reference // to the first point. Used in compare function of qsort() let p0;

// A utility function to return square of distance between // p1 and p2 function dist(p1, p2) { return (p1[0] - p2[0])(p1[0] - p2[0]) + (p1[1] - p2[1])(p1[1] - p2[1]); }

// To find orientation of ordered triplet (p, q, r). // The function returns following values // 0 --> p, q and r are collinear // 1 --> Clockwise // 2 --> Counterclockwise function orientation(p, q, r) { let val = (q[1] - p[1]) * (r[0] - q[0]) - (q[0] - p[0]) * (r[1] - q[1]);

if (val == 0) return 0;  // collinear
return (val > 0)? 1: 2; // clockwise or counterclock wise

}

// A function used by library function qsort() to sort // an array of points with respect to the first point function compare(vp1, vp2) { let p1 = vp1; let p2 = vp2;

// Find orientation let o = orientation(p0, p1, p2); if (o == 0) return (dist(p0, p2) >= dist(p0, p1))? -1 : 1;

return (o == 2)? -1: 1; }

// Prints simple closed path for a set of n points. function printClosedPath(points, n) { // Find the bottommost point let ymin = points[0][1]; let min = 0; for (let i = 1; i < n; i++) { let y = points[i][1];

 // Pick the bottom-most. In case of tie, choose the
 // left most point
 if ((y < ymin) || (ymin == y && points[i][0] < points[min][0])){
    ymin = points[i][1];
    min = i;
 }

}

// Place the bottom-most point at first position let temp = points[0]; points[0] = points[min]; points[min] = temp;

// Sort n-1 points with respect to the first point. // A point p1 comes before p2 in sorted output if p2 // has larger polar angle (in counterclockwise // direction) than p1 p0 = points[0]; points.sort(compare);

// Now stack has the output points, print contents // of stack for (let i=0; i<n; i++) console.log("(" + points[i][0] + "," + points[i][1] + "), "); }

// Driver program to test above functions let points = [[0, 3], [1, 1], [2, 2], [4, 4], [0, 0], [1, 2], [3, 1], [3, 3]]; let n = points.length;

printClosedPath(points, n);

// The code is contributed by Nidhi goel.

`

Output:

(0, 0), (3, 1), (1, 1), (2, 2), (3, 3), (4, 4), (1, 2), (0, 3),

Time complexity of above solution is O(n Log n) if we use a O(nLogn) sorting algorithm for sorting points.
Auxiliary Space: O(1), since no extra space has been taken.

Source:
https://www.dcs.gla.ac.uk/~pat/52233/slides/Geometry1x1.pdf