earcut 3.0.2 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +71 -56
- package/dist/earcut.dev.js +372 -165
- package/dist/earcut.min.js +1 -1
- package/package.json +15 -16
- package/src/earcut.d.ts +73 -0
- package/src/earcut.js +372 -165
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -1,16 +1,31 @@
|
|
|
1
|
-
|
|
1
|
+
# Earcut
|
|
2
2
|
|
|
3
|
-
The fastest and smallest JavaScript polygon triangulation library.
|
|
3
|
+
The fastest and smallest JavaScript **polygon triangulation** library. 3.5KB gzipped.
|
|
4
|
+
|
|
5
|
+
It is designed to be fast enough for real-time triangulation in the browser,
|
|
6
|
+
sacrificing triangulation quality for raw speed and simplicity,
|
|
7
|
+
while being robust enough to handle most practical datasets without crashing or producing garbage.
|
|
8
|
+
Originally built for [Mapbox GL JS](https://www.mapbox.com/mapbox-gljs) (WebGL-based interactive maps),
|
|
9
|
+
it's now also used by [Three.js](https://threejs.org/) and many other projects.
|
|
10
|
+
|
|
11
|
+

|
|
4
12
|
|
|
5
13
|
[](https://github.com/mapbox/earcut/actions/workflows/node.yml)
|
|
6
14
|
[](http://isitmaintained.com/project/mapbox/earcut "Average time to resolve an issue")
|
|
7
15
|
[](http://isitmaintained.com/project/mapbox/earcut "Percentage of issues still open")
|
|
8
16
|
[](https://github.com/mourner/projects)
|
|
9
17
|
|
|
10
|
-
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
```js
|
|
21
|
+
import earcut from 'earcut';
|
|
22
|
+
const triangles = earcut([10,0, 0,50, 60,60, 70,10]); // returns [1,0,3, 3,2,1]
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Algorithm
|
|
11
26
|
|
|
12
27
|
The library implements a modified ear slicing algorithm,
|
|
13
|
-
optimized by [z-order curve](http://en.wikipedia.org/wiki/Z-order_curve) hashing
|
|
28
|
+
optimized by [z-order curve](http://en.wikipedia.org/wiki/Z-order_curve) and spatial hashing
|
|
14
29
|
and extended to handle holes, twisted polygons, degeneracies and self-intersections
|
|
15
30
|
in a way that doesn't _guarantee_ correctness of triangulation,
|
|
16
31
|
but attempts to always produce acceptable results for practical data.
|
|
@@ -19,39 +34,59 @@ It's based on ideas from
|
|
|
19
34
|
[FIST: Fast Industrial-Strength Triangulation of Polygons](http://www.cosy.sbg.ac.at/~held/projects/triang/triang.html) by Martin Held
|
|
20
35
|
and [Triangulation by Ear Clipping](http://www.geometrictools.com/Documentation/TriangulationByEarClipping.pdf) by David Eberly.
|
|
21
36
|
|
|
22
|
-
|
|
37
|
+
## Performance
|
|
23
38
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
39
|
+
Earcut is heavily optimized for its primary workload — triangulating polygons from
|
|
40
|
+
[Mapbox Vector Tiles](https://github.com/mapbox/vector-tile-spec). On a representative
|
|
41
|
+
benchmark of **119,680 real-world polygons** (1.9M vertices) drawn from a window of map tiles
|
|
42
|
+
through zooms 4–16, it triangulates the whole set in **~480 ms** on a Macbook Pro M1 Pro (2021).
|
|
43
|
+
You can run the benchmark yourself with `npm run bench`.
|
|
44
|
+
|
|
45
|
+
## Robustness
|
|
29
46
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
47
|
+
Earcut does **not** guarantee a correct triangulation on arbitrary input — it trades quality
|
|
48
|
+
for speed, aiming to always produce an acceptable result on practical data without crashing or
|
|
49
|
+
emitting garbage. The input is assumed to be a valid polygon: rings that don't self-cross or
|
|
50
|
+
overlap, holes that stay inside the outer ring, and no duplicate or zero-length edges. On input
|
|
51
|
+
that breaks these assumptions, the result can be noticeably wrong — overlapping triangles, gaps,
|
|
52
|
+
or triangles outside the polygon. If correctness matters, clean your input first; for a
|
|
53
|
+
guaranteed-correct triangulation even on bad data, see
|
|
54
|
+
[libtess.js](https://github.com/brendankenny/libtess.js) (slower and larger).
|
|
37
55
|
|
|
38
|
-
The
|
|
56
|
+
The output is also not _conforming_ — a vertex may land in the middle of another triangle's edge
|
|
57
|
+
(a T-junction). This is harmless for rendering but can break navmesh or FEM use; if you need a
|
|
58
|
+
conforming mesh, [remove T-junctions in a post-process](https://github.com/mapbox/earcut/issues/74#issuecomment-4826113682).
|
|
39
59
|
|
|
40
|
-
|
|
41
|
-
and earcut is not precise enough, take a look at [libtess.js](https://github.com/brendankenny/libtess.js).
|
|
60
|
+
## Install
|
|
42
61
|
|
|
43
|
-
|
|
62
|
+
Install with NPM: `npm install earcut`, then import as a module:
|
|
44
63
|
|
|
45
64
|
```js
|
|
46
|
-
|
|
65
|
+
import earcut, {flatten, deviation} from 'earcut';
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Or use as a module directly in the browser with [jsDelivr](https://www.jsdelivr.com/esm):
|
|
69
|
+
|
|
70
|
+
```html
|
|
71
|
+
<script type="module">
|
|
72
|
+
import earcut from 'https://cdn.jsdelivr.net/npm/earcut/+esm';
|
|
73
|
+
</script>
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Alternatively, there's a UMD browser bundle with an `earcut` global variable (exposing the main function as `earcut.default`):
|
|
77
|
+
|
|
78
|
+
```html
|
|
79
|
+
<script src="https://cdn.jsdelivr.net/npm/earcut/dist/earcut.min.js"></script>
|
|
47
80
|
```
|
|
48
81
|
|
|
49
|
-
|
|
82
|
+
## API
|
|
83
|
+
|
|
84
|
+
### `earcut(vertices[, holes, dimensions = 2])`
|
|
50
85
|
|
|
51
86
|
* `vertices` is a flat array of vertex coordinates like `[x0,y0, x1,y1, x2,y2, ...]`.
|
|
52
87
|
* `holes` is an array of hole _indices_ if any
|
|
53
88
|
(e.g. `[5, 8]` for a 12-vertex input would mean one hole with vertices 5–7 and another with 8–11).
|
|
54
|
-
* `dimensions` is the number of coordinates per vertex in the input array (`2` by default).
|
|
89
|
+
* `dimensions` is the number of coordinates per vertex in the input array (`2` by default). Earcut is a **2D** algorithm: only `x` and `y` are used for triangulation, and any extra coordinates are ignored (3D data is treated as projected onto the XY plane).
|
|
55
90
|
|
|
56
91
|
Each group of three vertex indices in the resulting array forms a triangle.
|
|
57
92
|
|
|
@@ -67,55 +102,35 @@ earcut([10,0,1, 0,50,2, 60,60,3, 70,10,4], null, 3);
|
|
|
67
102
|
|
|
68
103
|
If you pass a single vertex as a hole, Earcut treats it as a Steiner point.
|
|
69
104
|
|
|
70
|
-
|
|
105
|
+
Output triangles always have a consistent **winding order** regardless of the input polygon's winding — counter-clockwise in a y-up coordinate system (clockwise in y-down/screen space). If you need the opposite orientation (e.g. for back-face culling or normals in 3D), call `.reverse()` on the result.
|
|
106
|
+
|
|
107
|
+
### `flatten(data)`
|
|
71
108
|
|
|
72
109
|
If your input is a multi-dimensional array (e.g. [GeoJSON Polygon](http://geojson.org/geojson-spec.html#polygon)),
|
|
73
|
-
you can convert it to the format expected by Earcut with `
|
|
110
|
+
you can convert it to the format expected by Earcut with `flatten`:
|
|
74
111
|
|
|
75
112
|
```js
|
|
76
|
-
const data =
|
|
113
|
+
const data = flatten(geojson.geometry.coordinates);
|
|
77
114
|
const triangles = earcut(data.vertices, data.holes, data.dimensions);
|
|
78
115
|
```
|
|
79
116
|
|
|
80
|
-
|
|
117
|
+
### `deviation(vertices, holes, dimensions, triangles)`
|
|
118
|
+
|
|
119
|
+
After getting a triangulation, you can verify its correctness with `deviation`:
|
|
81
120
|
|
|
82
121
|
```js
|
|
83
|
-
const
|
|
122
|
+
const d = deviation(vertices, holes, dimensions, triangles);
|
|
84
123
|
```
|
|
85
124
|
|
|
86
125
|
Returns the relative difference between the total area of triangles and the area of the input polygon.
|
|
87
126
|
`0` means the triangulation is fully correct.
|
|
88
127
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
Install with NPM: `npm install earcut`, then import as a module:
|
|
92
|
-
|
|
93
|
-
```js
|
|
94
|
-
import earcut from 'earcut';
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
Or use as a module directly in the browser with [jsDelivr](https://www.jsdelivr.com/esm):
|
|
98
|
-
|
|
99
|
-
```html
|
|
100
|
-
<script type="module">
|
|
101
|
-
import earcut from 'https://cdn.jsdelivr.net/npm/earcut/+esm';
|
|
102
|
-
</script>
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
Alternatively, there's a UMD browser bundle with an `earcut` global variable (exposing the main function as `earcut.default`):
|
|
106
|
-
|
|
107
|
-
```html
|
|
108
|
-
<script src="https://cdn.jsdelivr.net/npm/earcut/dist/earcut.min.js"></script>
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-

|
|
112
|
-
|
|
113
|
-
#### Ports to other languages
|
|
128
|
+
## Ports to other languages
|
|
114
129
|
|
|
115
130
|
- [mapbox/earcut.hpp](https://github.com/mapbox/earcut.hpp) (C++11)
|
|
116
131
|
- [JaffaKetchup/dart_earcut](https://github.com/JaffaKetchup/dart_earcut) (Dart)
|
|
117
132
|
- [earcut4j/earcut4j](https://github.com/earcut4j/earcut4j) (Java)
|
|
118
|
-
- [the3deers/earcut-java](https://github.com/the3deers/earcut-java) (Java)
|
|
119
133
|
- [Larpon/earcut](https://github.com/Larpon/earcut) (V)
|
|
120
|
-
- [Cawfree/earcut-j](https://github.com/Cawfree/earcut-j) (Java, outdated)
|
|
121
134
|
- [measuredweighed/SwiftEarcut](https://github.com/measuredweighed/SwiftEarcut) (Swift)
|
|
135
|
+
- [goswinr/Earcut](https://github.com/goswinr/Earcut/)(F# / .NET)
|
|
136
|
+
- [tenyoru/earcut.zig](https://github.com/tenyoru/earcut.zig) (Zig)
|