Have used (a dotnet wrapper of) this to generate colour-coded round area polygons for municipal waste collections for many years now. works flawlessly and fast.
Hey Evgen, Earcut author here — thanks for the writeup and a really cool library! I need to see if there are any tricks to borrow for Earcut's JS version. :)
One thing to note is that I deliberately had to reject some of the potential optimizations to keep the library small, so that bundle size doesn't blow up — for most practical applications (e.g. Mapbox GL JS), it's already fast enough (and 4.1k min/gz). Curious how big the WASM build of Earstrip is.
On the C++ side, Mapbox now uses a hybrid approach where small polygons are processed with earcut.hpp, while big and complex polygon switch to a different algorithm based on monotone decomposition, because while it has higher constants in algorithmic complexity, it scales much better with input size.
Hey! Thanks for Leaflet, earcut and all your other work. I hope some of these ideas turn out useful. Take a look at the branch-free dent count: it's what let us outperform earcut, and it's a big part of why the wasm build is that fast.
The wasm module is 27 KB gzipped, about 41 KB with the base64 wrapper in the npm package.
Not familiar with triangularization algorithms but is it causing issues when it picks long and narrow triangles? I assume a human doing it would in general try to go for more "balanced" ones?
Having more balanced triangles in this case would only increase the number of vertices. Which means you need more memory on the GPU and the vertex pipeline has more work to do.
Because the polygons are quite small, there's also no culling advantage by having smaller triangles, being able to discard them early in the rendering process.
You don't need to increase the number of vertices to get more balanced triangles. None of the methods in the article add vertices, but the Delaunay triangulation is better than the others at creating balanced triangles. It's just also the slowest, so there's a tradeoff between triangle quality and speed.
Triangles that repeatedly cover the same pixel are a performance issue also. Super thin strips are not great for performance and more than offset the memory cost.
Interesting optimisation, curious if you are willing to divulge which of the optimisation steps the LLM came up with, versus which it needed human assistance with?
I'm not sure, but "This post is about how we got there.\nA GPU fills triangles and nothing else." is very Claude-ish. So does "[I created] one commit per idea, and timed every commit on those same 3.7 million polygons, so each section below ends with a number." And "A triangle needs no cutting at all".
My experience is that Claude Opus 5 and 5.5 are very good at implementing optimizations, reasonably good at suggesting approaches to try, and not very inclined to identify slow runtime as a problem. It tends to go for simple implementations until I ask about speed, which is certainly conventional wisdom for development.
The obsession with triangles comes from Microsoft, who around 1995 chose to support only triangles in DirectX.
As a consequence of that, the GPU vendors designed then GPUs supporting only triangles in hardware, abandoning earlier attempts to also support other figures.
That has been inherited until today, so any program that wants to use not only the general-purpose computing features of a GPU, but also the dedicated graphics hardware from it, must convert any other kinds of graphics primitives into triangles, before rendering on the GPU.
Should mention the mother of all triangulators:
https://www.cs.cmu.edu/~quake/triangle.html
Have used (a dotnet wrapper of) this to generate colour-coded round area polygons for municipal waste collections for many years now. works flawlessly and fast.
Hey Evgen, Earcut author here — thanks for the writeup and a really cool library! I need to see if there are any tricks to borrow for Earcut's JS version. :)
One thing to note is that I deliberately had to reject some of the potential optimizations to keep the library small, so that bundle size doesn't blow up — for most practical applications (e.g. Mapbox GL JS), it's already fast enough (and 4.1k min/gz). Curious how big the WASM build of Earstrip is.
On the C++ side, Mapbox now uses a hybrid approach where small polygons are processed with earcut.hpp, while big and complex polygon switch to a different algorithm based on monotone decomposition, because while it has higher constants in algorithmic complexity, it scales much better with input size.
Hey! Thanks for Leaflet, earcut and all your other work. I hope some of these ideas turn out useful. Take a look at the branch-free dent count: it's what let us outperform earcut, and it's a big part of why the wasm build is that fast. The wasm module is 27 KB gzipped, about 41 KB with the base64 wrapper in the npm package.
I'd be interested if it benchmarked well against iShape-rust, the overlay engine in GeoRust:
https://github.com/ishape-rust/ioverlay
Not really apples to apples. iOverlay is more like a topology toolkit - things like set operations and buffering. pretty different from triangulation.
Not familiar with triangularization algorithms but is it causing issues when it picks long and narrow triangles? I assume a human doing it would in general try to go for more "balanced" ones?
It depends on the use case.
Having more balanced triangles in this case would only increase the number of vertices. Which means you need more memory on the GPU and the vertex pipeline has more work to do.
Because the polygons are quite small, there's also no culling advantage by having smaller triangles, being able to discard them early in the rendering process.
You don't need to increase the number of vertices to get more balanced triangles. None of the methods in the article add vertices, but the Delaunay triangulation is better than the others at creating balanced triangles. It's just also the slowest, so there's a tradeoff between triangle quality and speed.
Triangles that repeatedly cover the same pixel are a performance issue also. Super thin strips are not great for performance and more than offset the memory cost.
the resulting topology is somewhat.. violent, no? that said, i wonder how much of an impact it actually has on rendering.
either way, neat stuff, and the write up itself is excellent.
Interesting optimisation, curious if you are willing to divulge which of the optimisation steps the LLM came up with, versus which it needed human assistance with?
I'm not sure, but "This post is about how we got there.\nA GPU fills triangles and nothing else." is very Claude-ish. So does "[I created] one commit per idea, and timed every commit on those same 3.7 million polygons, so each section below ends with a number." And "A triangle needs no cutting at all".
My experience is that Claude Opus 5 and 5.5 are very good at implementing optimizations, reasonably good at suggesting approaches to try, and not very inclined to identify slow runtime as a problem. It tends to go for simple implementations until I ask about speed, which is certainly conventional wisdom for development.
[flagged]
[flagged]
Why the obsession with triangles?
If you just want areas, or to know if a point is inside or outside the shape there is a better way.
Given a simple closed curve, points (ax, ay) (bx, by) (cx, cy) (dx, dy) as a trivial example.
Line them up a,b,c,d,a vertically and take the "determinant" as we were taught.
Axby - aybx + bxcy - bycx etc etc.
Divide the result by -2 and you have the are, positive is clockwise, negative is anticlockwise.
Put an anticlockwise shape inside a clockwise shape and you have a donut.
There is more, have to go to dinner.
The obsession with triangles comes from Microsoft, who around 1995 chose to support only triangles in DirectX.
As a consequence of that, the GPU vendors designed then GPUs supporting only triangles in hardware, abandoning earlier attempts to also support other figures.
That has been inherited until today, so any program that wants to use not only the general-purpose computing features of a GPU, but also the dedicated graphics hardware from it, must convert any other kinds of graphics primitives into triangles, before rendering on the GPU.
Obsession with triangles so the GPU can show millions of polygons on a webmap.
There’s this thing called rendering, pretty important for maps.