Polygon convexity test
The rectangle (0, 0), (4, 0), (4, 3), (0, 3) is convex: every corner turns the same way, counterclockwise. The dart (0, 0), (3, 1), (0, 2), (1, 1) mixes left and right turns, so it has a dent and is concave. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
A polygon convexity test answers a fundamental computational-geometry question: given an ordered ring of Cartesian vertices, does every interior angle stay at most one hundred eighty degrees so the shape never dents inward? Surveyors validating cadastral parcels, game developers authoring collision hulls, GIS teams cleaning geofence polygons, CAD exporters enforcing convex constraints, and classroom tools grading simple-polygon exercises all need a deterministic yes-or-no answer without standing up a full geometry library. This capability accepts an ordered list of vertices, walks the closed ring once, and compares the two-dimensional cross product of each pair of consecutive edges. When every non-zero cross product shares the same sign, every turn goes the same way and the polygon is convex; mixed signs mean at least one reflex angle and the polygon is concave. Zero cross products mark collinear vertices and are allowed without breaking convexity.
How consecutive edge cross products decide convexity
Label the ordered vertices V zero through V n minus one and close the ring by treating the edge from the last vertex back to the first as present even when the caller does not repeat the starting point. At each vertex B with previous vertex A and next vertex C, form the outgoing vectors from A to B and from B to C. Their two-dimensional cross product is the scalar z equals (B.x minus A.x) times (C.y minus B.y) minus (B.y minus A.y) times (C.x minus B.x).
The sign of z is the turn direction at B: positive for a left turn when the plane is oriented with y up and x right (counterclockwise boundary walk), negative for a right turn (clockwise walk), and zero when A, B, and C are collinear. A simple polygon is convex if and only if every non-zero turn shares the same sign, which means every interior angle is at most one hundred eighty degrees and the boundary never reverses its turning sense.
Mixed positive and negative turns prove a reflex interior angle somewhere on the ring, so the polygon is concave. The algorithm is strictly O(n) in the number of vertices after a single normalization pass that drops a trailing duplicate of the first point when the caller already closed the ring.
Where a quick convexity check helps
Mapping and GIS pipelines use a polygon convexity test before algorithms that assume convex input—clipping against a convex window, decomposing complex regions, or feeding solvers that reject reflex vertices. Game and simulation engines validate designer-authored collision meshes so a single dent does not break separating-axis or GJK assumptions later. CAD and manufacturing exporters enforce convexity constraints on stock blanks and support polygons before sending geometry to a cutter.
Education platforms grade “is this polygon convex?” items with a deterministic oracle that treats collinear mid-edge vertices consistently instead of relying on floating eyeball judgment. Failed validation does not consume balance.
What you can do with it
GIS geofence and parcel validation
Reject or flag concave cadastral and geofence rings before pipelines that assume convex polygons for clipping, buffering, or area routines.
Game collision hull checks
Validate designer-authored 2D collision polygons so convexity-dependent collision algorithms never receive a dented hull at runtime.
Classroom and exam auto-grading
Mark “is this polygon convex?” items with a deterministic cross-product oracle that agrees with textbook turn-direction definitions.
FAQ
How do I test whether a polygon is convex?
Send ordered vertices as {x, y} or [x, y] pairs (at least three).
What if some consecutive vertices are collinear?
Zero cross products are allowed. Collinear mid-edge points do not break convexity by themselves; only mixed left and right turns mark a concave polygon.
Does vertex order (clockwise vs counterclockwise) matter?
Either consistent orientation is fine. The response reports orientation as clockwise or counterclockwise when convex, and mixed when turns disagree.
What happens with fewer than three vertices?
A polygon convexity test needs at least three vertices; invalid input is not billed.
What does the result tell me besides yes or no?
It gives the turning direction of the ring: counterclockwise, clockwise, mixed for a concave shape, or collinear when all points sit on one line. It also counts the real turns and the straight-through vertices.
Related tools
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/geo/polygon-is-convex \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"vertices":[{"x":0,"y":0},{"x":4,"y":0},{"x":4,"y":3},{"x":0,"y":3}]}'const res = await fetch("https://api.kit.forhosting.com/geo/polygon-is-convex", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"vertices": [
{
"x": 0,
"y": 0
},
{
"x": 4,
"y": 0
},
{
"x": 4,
"y": 3
},
{
"x": 0,
"y": 3
}
]
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/geo/polygon-is-convex",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"vertices": [
{
"x": 0,
"y": 0
},
{
"x": 4,
"y": 0
},
{
"x": 4,
"y": 3
},
{
"x": 0,
"y": 3
}
]
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/geo/polygon-is-convex", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"vertices":[{"x":0,"y":0},{"x":4,"y":0},{"x":4,"y":3},{"x":0,"y":3}]}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"vertices":[{"x":0,"y":0},{"x":4,"y":0},{"x":4,"y":3},{"x":0,"y":3}]}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/geo/polygon-is-convex", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"vertices": [
{
"x": 0,
"y": 0
},
{
"x": 4,
"y": 0
},
{
"x": 4,
"y": 3
},
{
"x": 0,
"y": 3
}
]
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "geo.polygon_is_convex",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |
Technical notes
How consecutive edge cross products decide convexity
When every cross product is zero the vertices lie on a single line; the shape has no area and this endpoint reports is_convex false with orientation collinear rather than inventing a convex hull.
Input contract, response shape, and error behaviour
A trailing vertex identical to the first is dropped automatically so GeoJSON-style closed rings and open classroom lists both work. Example: the unit square (0,0), (4,0), (4,3), (0,3) is convex with counterclockwise orientation. POST a JSON body with one required field: vertices, an ordered array of at least three points. Each point may be an object with finite x and y (or lon and lat aliases) or a two-element array [x, y]. Aliases points, polygon, and coords are accepted with the same meaning so existing GIS payloads drop in without renaming. Fewer than three vertices after that normalization, non-array payloads, missing coordinates, and non-finite numbers fail with invalid_input and are not billed. On success the body includes is_convex as a boolean; n as the normalized vertex count; orientation as counterclockwise, clockwise, mixed, or collinear; turn_count as the number of non-zero turns; zero_turns as the collinear count; a formula string restating the cross-product identity; and vertices echoed as {x, y} objects in ring order. The concave dart (0,0), (3,1), (0,2), (1,1) mixes turn signs and returns is_convex false. Pair the boolean with your own drawing code if you need a sketch; this endpoint classifies convexity only and does not emit plots, hulls, or triangulation.
Where a polygon convexity API earns its keep
Keep rings modest, pin is_convex and orientation in tests, and you get reproducible convexity labels for geofences, classroom checks, and edge workers without shipping a full computational-geometry stack of your own.
Technical questions
What does the polygon convexity test cost?
The browser tool is free. API requests use prepaid KIT balance at $0.002 per successful call; invalid input is not billed.