Skip to content

About

🤖 A Swift port of Mapbox's earcut.js library

Topics

Resources

Stars

10 stars

Watchers

1 watching

Forks

Repository files navigation

SwiftEarcut

A Swift port of Mapbox's earcut.js polygon triangulation library.

Table of Contents

  1. License
  2. Installation
  3. Documentation
  4. Quick Start
  5. Holes
  6. Delaunay refinement
  7. Triangulating many polygons
  8. Upgrading from 1.x

Release notes are in CHANGELOG.md.

License

Mapbox's earcut.js is governed by an ISC license while this Swift port is governed by an MIT license.

Installation

Swift Package Manager

Add the following dependency

.package(url: "https://github.com/measuredweighed/SwiftEarcut.git", from: "2.0.0"),

Documentation

Comprehensive documentation for SwiftEarcut can be found on the Swift Package Index (click on Documentation).

Quick Start

Pass Earcut a flat array of vertex coordinates, and tessellate returns a flat array of triangle indices (three per triangle).

let result = Earcut.tessellate([10, 0, 0, 50, 60, 60, 70, 10])

// result: [1, 0, 3, 1, 3, 2]

Indices are UInt32, so the result uploads directly as a GPU index buffer.

Holes

Hole rings follow the outer ring in the same array, with holeIndices giving the vertex index each one starts at. flatten builds both from GeoJSON-style nested rings.

let (vertices, holes, dimensions) = Earcut.flatten(geoJSONPolygon.coordinates)
let indices = Earcut.tessellate(vertices, holeIndices: holes, dim: dimensions)

dim is the number of coordinates per vertex. Earcut is a 2D algorithm: with dim: 3 it triangulates the XY projection and ignores Z.

A single-vertex hole is treated as a Steiner point.

Delaunay refinement

var indices = Earcut.tessellate(vertices, holeIndices: holes, dim: dimensions)
Earcut.refine(&indices, coords: vertices, dim: dimensions)

Triangulating many polygons

Tessellator keeps its working buffers between calls, so it's often more efficient to use the same Tesselator when triangulating a lot of geometry.

let tessellator = Tessellator()
var indices = [UInt32]()

for polygon in polygons {
    tessellator.tessellate(polygon.vertices, holeIndices: polygon.holes, into: &indices)
    render(indices)
}

(Note: Tessellator is not Sendable. Use one per thread, or one per task.)

Upgrading from 1.x

Some signatures have changed between 1.x and 2.x, but the 1.x variants remain in the project (with deprecation warnings). Perhaps the largest breaking change is that indices are now returned as UInts.

To resolve deprecation warnings move off of the follow signatures:

1.x 2.0
tessellate(data:holeIndices:dim:) -> [Int] tessellate(_:holeIndices:dim:) -> [UInt32]
flatten(data:) -> (vertices:holes:dim:) flatten(_:) -> (vertices:holes:dimensions:)
deviation(data:holeIndices:dim:indices:) deviation(_:holeIndices:dim:triangles:)

Worth also noting that triangle output also changes in 2.x. Don't expect the returned indices to match 1.x, even with identical inputs.

See CHANGELOG.md for the full list of changes.

About

🤖 A Swift port of Mapbox's earcut.js library

Topics

Resources

Stars

10 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages