Jarvis March (also called Gift Wrapping) is one of the simplest algorithms for computing the Convex Hull of a set of 2D points.
A Convex Hull is the smallest convex polygon that contains all the given points — like stretching a rubber band around the outermost points.
Named after R.A. Jarvis (1973).
Real-World Analogy
Imagine hammering nails into a board at each point location.
Stretch a rubber band around all the nails and let it snap tight.
The shape the rubber band forms = the Convex Hull.
Advantages
Simple to understand and implement.
Output-sensitive — faster when the hull has few points (small h).
Works correctly for collinear points with proper orientation check.
Disadvantages
O(nh) — slow when hull has many points (worst case O(n²)).
Graham Scan and Chan’s Algorithm are faster for large inputs.
Core Concept — Orientation Test
Cross Product for Orientation
Given three points O, A, B — the cross product tells us their turn direction.
cross(O, A, B) = (A.x - O.x) * (B.y - O.y) - (A.y - O.y) * (B.x - O.x)
Result > 0 → Counter-clockwise (left turn)
Result = 0 → Collinear (no turn)
Result < 0 → Clockwise (right turn)
Jarvis March picks the point that makes the most counter-clockwise turn from the current direction.
Algorithm Steps
1. Find the leftmost point (smallest x) — guaranteed to be on the hull.
2. Set current = leftmost point.
3. Loop:
a. Add current to hull.
b. Set candidate = any other point (e.g., points[0]).
c. For every other point r:
- If cross(current, candidate, r) > 0 → r is more counter-clockwise → candidate = r
- If cross = 0 (collinear) → pick the farther point
d. current = candidate
4. Stop when current == leftmost point (hull is closed).
Visual Example:
Points: (0,0), (1,1), (2,0), (2,2), (0,2)
Start at (0,0) — leftmost
→ wrap to (2,0) → (2,2) → (0,2) → back to (0,0)
Hull = [(0,0), (2,0), (2,2), (0,2)]
C++ Implementation
Full Implementation
#include <iostream>#include <vector>#include <algorithm>struct Point { int x, y;};// Cross product of vectors OA and OB// > 0 : counter-clockwise// = 0 : collinear// < 0 : clockwiseint cross(Point O, Point A, Point B) { return (A.x - O.x) * (B.y - O.y) - (A.y - O.y) * (B.x - O.x);}std::vector<Point> jarvisMarch(std::vector<Point>& points) { int n = points.size(); if (n < 3) return points; // Find leftmost point int leftmost = 0; for (int i = 1; i < n; i++) if (points[i].x < points[leftmost].x) leftmost = i; std::vector<Point> hull; int current = leftmost; do { hull.push_back(points[current]); int candidate = (current + 1) % n; for (int i = 0; i < n; i++) { int c = cross(points[current], points[candidate], points[i]); if (c > 0) { // i is more counter-clockwise than candidate candidate = i; } else if (c == 0) { // collinear — pick farther point auto dx1 = points[i].x - points[current].x; auto dy1 = points[i].y - points[current].y; auto dx2 = points[candidate].x - points[current].x; auto dy2 = points[candidate].y - points[current].y; if (dx1*dx1 + dy1*dy1 > dx2*dx2 + dy2*dy2) candidate = i; } } current = candidate; } while (current != leftmost); return hull;}int main() { std::vector<Point> points = { {0,0}, {1,1}, {2,0}, {2,2}, {0,2}, {1,0} }; auto hull = jarvisMarch(points); std::cout << "Convex Hull points:\n"; for (auto& p : hull) std::cout << "(" << p.x << ", " << p.y << ")\n"; // (0,0) → (2,0) → (2,2) → (0,2) return 0;}
Python Implementation
def cross(O, A, B): """Cross product of OA and OB vectors. > 0: counter-clockwise, = 0: collinear, < 0: clockwise """ return (A[0] - O[0]) * (B[1] - O[1]) - (A[1] - O[1]) * (B[0] - O[0])def jarvis_march(points): n = len(points) if n < 3: return points # Start from leftmost point start = min(points, key=lambda p: p[0]) hull = [] current = start while True: hull.append(current) candidate = points[0] for point in points[1:]: c = cross(current, candidate, point) if c > 0: candidate = point elif c == 0: # Collinear — pick farther point d1 = (point[0]-current[0])**2 + (point[1]-current[1])**2 d2 = (candidate[0]-current[0])**2 + (candidate[1]-current[1])**2 if d1 > d2: candidate = point current = candidate if current == start: break return hull# Examplepoints = [(0,0), (1,1), (2,0), (2,2), (0,2), (1,0)]hull = jarvis_march(points)print("Convex Hull:", hull)# [(0,0), (2,0), (2,2), (0,2)]
Time & Space Complexity
Case Time Explanation
Best O(n) Hull has 3 points — only 3 outer iterations
Average O(nh) h = hull points, n = total points
Worst O(n²) All points on hull (e.g., circle of points)
Space O(h) Only hull points stored
h = number of points on the convex hull.
When h is small (e.g., 3–10), Jarvis March is very fast.
When h ≈ n (all points on hull), it degrades to O(n²).
Convex Hull Algorithm Comparison
Algorithm Time Notes
Jarvis March O(nh) Simple, output-sensitive
Graham Scan O(n log n) Sort-based, faster for large n
Chan's Algorithm O(n log h) Optimal output-sensitive
Quickhull O(n log n) Divide & conquer, fast in practice
Use Jarvis March when: simple implementation needed, h is small.
Use Graham Scan when: general purpose, n is large.
Use Chan’s when: optimal theoretical complexity needed.
Key Takeaways
Jarvis March = Gift Wrapping — start at leftmost, keep turning counter-clockwise.
Core operation: cross product to determine turn direction.
Time: O(nh) — output-sensitive, great when hull is small.
Handle collinear points by picking the farther point.
For large inputs with many hull points, prefer Graham Scan or Chan’s Algorithm.