clipper-lib, delaunator, earcut, and polylabel are specialized JavaScript libraries for handling computational geometry tasks in web applications. clipper-lib performs boolean operations on polygons like union and intersection. delaunator generates Delaunay triangulations from point sets, useful for mesh generation. earcut triangulates polygons with holes for efficient WebGL rendering. polylabel finds the optimal visual center of a polygon for placing labels. Together, they cover the core needs of mapping, data visualization, and interactive graphics.
When building mapping tools, data visualizations, or interactive graphics, you often need to manipulate shapes, meshes, and labels. The packages clipper-lib, delaunator, earcut, and polylabel are industry-standard utilities for these specific geometric tasks. They are not general-purpose graphics libraries but rather focused engines that solve hard math problems so you don't have to.
Let's break down their specific roles, how they handle data, and where they fit in your architecture.
clipper-libclipper-lib is a JavaScript port of the famous Clipper library. It handles boolean operations on polygons. This means you can take two shapes and find their union, difference, intersection, or XOR.
This is essential for features like "brushing" on a map, combining geographic regions, or creating complex masks.
import ClipperLib from 'clipper-lib';
const subject = [{ X: 100, Y: 100 }, { X: 200, Y: 100 }, { X: 200, Y: 200 }, { X: 100, Y: 200 }];
const clip = [{ X: 150, Y: 150 }, { X: 250, Y: 150 }, { X: 250, Y: 250 }, { X: 150, Y: 250 }];
const clipper = new ClipperLib.Clipper();
clipper.AddPath(subject, ClipperLib.PolyType.ptSubject, true);
clipper.AddPath(clip, ClipperLib.PolyType.ptClip, true);
const solution = new ClipperLib.Paths();
clipper.Execute(ClipperLib.ClipType.ctIntersection, solution);
// solution contains the overlapping area
Key Constraint: clipper-lib works with integers, not floats. You must multiply your coordinates by a scaling factor (e.g., 1000) before passing them in, then divide the results by the same factor. This avoids floating-point errors during calculation.
earcut vs delaunatorTriangulation is the process of breaking shapes into triangles. Both earcut and delaunator do this, but they start from different inputs.
earcut: Polygons to Trianglesearcut takes a defined polygon (with optional holes) and breaks it into triangles. This is exactly what WebGL needs to render a shape. If you have a GeoJSON polygon and want to draw it on a canvas, this is your tool.
import earcut from 'earcut';
// Flat array of x,y coordinates
const vertices = [0, 0, 100, 0, 100, 100, 0, 100];
const holes = [];
const dimensions = 2;
const indices = earcut(vertices, holes, dimensions);
// indices: [0, 1, 2, 0, 2, 3] (ready for WebGL buffer)
delaunator: Points to Meshdelaunator takes a cloud of points and connects them into a mesh. It does not care about polygon boundaries initially. It creates a Delaunay triangulation, which maximizes the minimum angle of all triangles. This is great for terrain generation or connecting scatter plot points.
import Delaunator from 'delaunator';
// Array of [x, y] points
const points = [[0, 0], [100, 0], [50, 50], [0, 100]];
const delaunay = new Delaunator(points);
const triangles = delaunay.triangles;
// Uint32Array of indices connecting the points
Trade-off: Use earcut when you have a boundary (a shape). Use delaunator when you have a set of points and want to find the structure between them.
polylabelpolylabel solves a specific visual problem: where do I put the text "California" inside the shape of California? The geometric centroid often falls outside the shape or in a narrow arm. polylabel finds the "pole of inaccessibility" — the point furthest from any edge.
import polylabel from 'polylabel';
// Polygon as array of rings (first is outer, rest are holes)
const polygon = [
[[0, 0], [100, 0], [100, 100], [0, 100]] // Simple square
];
const [x, y] = polylabel(polygon, 1.0);
// Returns the best [x, y] for a label
It uses an iterative grid search to find the optimal spot. You can adjust the precision parameter to balance speed and accuracy.
These libraries are designed for speed, but they handle memory differently.
earcut and delaunator return typed arrays (Uint32Array). This is crucial for WebGL. You can pass these directly to GPU buffers without copying data. This makes them extremely fast for rendering thousands of features.clipper-lib uses JavaScript objects for points ({ X: 1, Y: 1 }). This creates more garbage collection pressure. For heavy-duty clipping in a loop, you may need to manage object reuse or consider a WASM alternative if performance lags.polylabel returns a simple array [x, y]. It is computationally heavier than triangulation because it searches iteratively. Use it sparingly — ideally once per polygon during data preparation, not every frame.You let users draw shapes that merge together.
clipper-lib// Merge existing region with new stroke
const merged = performClip(existingPaths, newStrokePaths, 'union');
You are building a map renderer like Mapbox GL.
earcut// Prepare geometry for WebGL
const vertices = flatten(polygonCoords);
const indices = earcut(vertices);
webglBuffer.setData(indices);
You have 10,000 data points and want to show density regions.
delaunator// Create mesh from scattered data
const mesh = new Delaunator(dataPoints);
renderTriangles(mesh.triangles);
You have a map of states and need to place names inside each state.
polylabel// Find safe label position
const labelPos = polylabel(statePolygon);
placeText(labelPos[0], labelPos[1], stateName);
| Feature | clipper-lib | delaunator | earcut | polylabel |
|---|---|---|---|---|
| Primary Input | Paths (Polygons) | Points (Cloud) | Vertices (Polygon) | Polygon (Rings) |
| Primary Output | Clipped Paths | Triangulation Mesh | Triangle Indices | Single Point [x,y] |
| Coordinate Type | Integers (Scaled) | Floats | Floats | Floats |
| Handles Holes | ✅ Yes | ❌ No | ✅ Yes | ✅ Yes |
| Use Case | Boolean Ops | Mesh Generation | Rendering | Label Placement |
These tools are complementary, not competitive. A complex visualization app might use all four.
clipper-lib to prepare and modify your geometry data (e.g., cutting a map view to a specific region).earcut to convert that prepared geometry into triangles for the GPU.delaunator if you are visualizing point data rather than predefined shapes.polylabel during the data loading phase to calculate where labels should go before rendering starts.Note on Maintenance: delaunator, earcut, and polylabel are maintained by Mapbox and are highly stable. clipper-lib is a community port of a C++ library. It is stable but receives fewer updates. For new projects requiring heavy clipping performance, evaluate if a WebAssembly port fits your needs better, but clipper-lib remains the standard for pure JavaScript environments.
Choose clipper-lib when you need to perform boolean operations on polygons, such as merging shapes, cutting holes, or calculating intersections. It is the standard choice for 2D polygon clipping in pure JavaScript. Be aware that it uses integer coordinates, so you must scale your data before processing and scale it back afterward.
Choose delaunator when you have a cloud of points and need to generate a mesh or Voronoi diagram from them. It is extremely fast and ideal for procedural generation or connecting scattered data points. It does not handle polygon holes or boolean logic, only point-based triangulation.
Choose earcut when you need to render complex polygons with holes in WebGL or Canvas. It converts polygon definitions into triangle indices that GPUs can draw efficiently. It is the go-to solution for map rendering and vector tile processing where performance is critical.
Choose polylabel when you need to place a text label or icon inside an irregular polygon without it overlapping the edges. It calculates the 'pole of inaccessibility', ensuring the label sits in the most spacious part of the shape. It is specifically designed for cartography and label placement.
forked from Javascript Clipper
The Javascript Clipper library performs clipping and offsetting for both lines and polygons. All four boolean clipping operations are supported - intersection, union, difference and exclusive-or. Polygons can be of any shape including self-intersecting polygons.
Javascript Clipper is a port of Angus Johnson's Clipper library: https://sourceforge.net/projects/polyclipping/
LIVE DEMO: http://jsclipper.sourceforge.net/6.2.1.0/main_demo.html
Information and examples: http://jsclipper.sourceforge.net/6.2.1.0/
Donate Javascript Clipper Project: https://sourceforge.net/p/jsclipper/wiki/Donations/
Use cases:
Algorithms, Graphics