1.0.0 • Published 3 years ago

triangle-wasm v1.0.0

Weekly downloads
2
License
MIT
Repository
github
Last release
3 years ago

Triangle-wasm

Javascript wrapper around Triangle - A Two-Dimensional Quality Mesh Generator and Delaunay Triangulator.

Triangle generates exact Delaunay triangulations, constrained Delaunay triangulations, conforming Delaunay triangulations, Voronoi diagrams, and high-quality triangular meshes. The latter can be generated with no small or large angles, and are thus suitable for finite element analysis.

Triangle was created at the Carnegie Mellon University by Jonathan Shewchuk.

This is a Javascript wrapper around the original C library, compiled to WebAssembly using Emscripten. The API was preserved, consisting of a single method triangulate() and an input/output object triangulateio. Other methods were added to bridge WASM and Javascript.

Planar Straight Line GraphDelaunay triangulationConstrained Delaunay triangulation
PSLGDTCDT
inputoutputoutput -p
Quality mesh (minimum angle)Conforming constrained Delaunay triangulationQuality mesh (maximum area)
PSLGmin.anglemax.area
output -pqoutput -pqDoutput -pqDa0.2

Install

npm install triangle-wasm

Example

const Triangle = require('triangle-wasm');

const data = { pointlist: [-1, -1, 1, -1, 1, 1, -1, 1] };

Triangle.init().then(() => {
  const input = Triangle.makeIO(data);
  const output = Triangle.makeIO();
  
  Triangle.triangulate({ pslg: false, quality: true }, input, output);
  
  // draw output
  // ...
  
  Triangle.freeIO(input, true);
  Triangle.freeIO(output);
});

Demo

API

init(path)

Initialises the WASM module.

Returns a Promise which resolves when the .wasm module is ready.

triangulate(switches, input, output, vorout = null)

Triangulates the data passed in as input and writes the result to ouput (and the optional Voronoi result to vorout).

  • switches an object or a string of switches
  • input an instance of TriangulateIO - the input data
  • output an instance of TriangulateIO - initialised, but empty
  • vorout an instance of TriangulateIO - initialised, but empty (optional)

Returns null

makeIO(data = null)

Creates an instance of TriangulateIO and allocates memory on the heap. data is only required when creating an input instance.

  • data input data i.e. from a parsed .poly or .svg

Returns an instance of TriangulateIO

freeIO(io, all = false)

Releases the allocated memory for an input/output instance.

  • io reference to the stored i/o object
  • all release all copied pointers

Returns null

Switches

Switches can be either an object or a string.

// i.e. the following calls are identical
Triangle.triangulate({ quality: true, convexHull: true }, input, output);
Triangle.triangulate('pzQqc', input, output);
stringswitchtypedescription
-ppslgbooleanRead input as a Planar Straight Line Graph. (default true)
-qqualitybooleanornumberQuality mesh generation by Delaunay refinement.Adds vertices to the mesh to ensure that all angles are between 20 and 140 degrees.A minimum angle can be set by passing a number. Guaranteed to terminate for 28.6 degrees or smaller. Often succeeds up to 34 degrees.
-aareabooleanornumberImposes a maximum triangle area.A maximum area can be set by passing a number.If true reads maximum area from the input (i.e. a .poly file)
-DccdtbooleanConforming constrained Delaunay triangulation
-rrefinebooleanRefine a previously generated mesh.
-cconvexHullbooleanCreate segments on the convex hull of the triangulation.Beware: if you are not careful, this switch can cause the introduction of an extremely thin angle between a PSLG segment and a convex hull segment, which can cause overrefinement (and possibly failure if Triangle runs out of precision).
-jjettisonbooleanPrevent duplicated input vertices, or vertices 'eaten' by holes, from appearing in the output. If any vertices are jettisoned, the vertex numbering in the output differs from that of the input.
-eedgesbooleanOutput a list of edges of the triangulation.
-nneighborsbooleanOutput a list of triangles neighboring each triangle.
-o2quadraticbooleanGenerate second-order subparametric elements with six nodes each.
-AregionAttrbooleanAssign an additional floating-point attribute to each triangle that identifies what segment-bounded region each triangle belongs to.
-BbndMarkersbooleanOutput boundary markers. (default true)Attention: -B works the other way around, if present it suppresses boundary markers.
-OholesbooleanRead holes from the input. (default true)Attention: -O works the other way around, if present it ignores holes.
-SsteinernumberMaximum number of Steiner points - vertices that are not in the input, but are added to meet the constraints on minimum angle and maximum area. (default unlimited)
-QquietbooleanSuppress all explanation of what Triangle is doing, unless an error occurs. (default true)
-vautoWhen vorout is provided, output the Voronoi diagram associated with the triangulation. (set automatically)
-zautoZero based indices, always true. (set automatically)

For a full list of switches, see Command line switches.

For more detailed descriptions of all the switches, see Triangle's instructions.

The following are not part of the switches object, but can still be passed in as a string:

  • -u, -X, -Y, -V

The following switches have no effect in the Javascript version of Triangle:

  • -g, -P, -N, -E, -I, -i, -F, -l, -s, -C

Other examples of switches objects and their correspondent strings:

// default
switches = null; // pzQ

// quality mesh and conforming Delaunay
switches = { quality: true, ccdt: true }; // pzqDQ

// minimum angle, maximum area and output to console
switches = { quality: 20.5, area: 42.8, quiet: false }; // pzq20.5a42.8

// no boundary markers, no holes
switches = { bndMarkers: false, holes: false }; // pzQBO

TriangulateIO

The TriangulateIO structure used to pass data into and out of the triangulate() procedure.

All the parameters are optional, except for pointlist. All the numberof parameters are set automatically.

parameterformatdescription
pointlist2 floats per point[x, y, x, y ...]An array of point coordinates.
pointattributelistn floats per pointAn array of point attributes.
pointmarkerlist1 int per pointAn array of point markers.
trianglelist3 ints per triangle[a, b, c, a, b, c ...]An array of triangle corners.
triangleattributelistn floats per triangleAn array of triangle attributes.
trianglearealist1 floats per triangleAn array of triangle area constraints.Input only.
neighborlist3 ints per triangleAn array of triangle neighbors.Output only.
segmentlist2 ints per segment[p, q, p, q ...]An array of segment endpoints.
segmentmarkerlist1 int per segmentAn array of segment markers.
holelist2 floats per hole[x, y, x, y ...]An array of holes.Input only, copied to output.
regionlist4 floats per region[x, y, attr, area ...]An array of regional attributes and area constraints.Input only, copied to output.
edgelist2 ints per edge[p, q, p, q ...]An array of edge endpoints.Output only.
edgemarkerlist1 int per edgeAn array of edge markers.Output only.
normlist2 floats per vectorAn array of normal vectors, used for infinite rays in Voronoi diagrams.Output only.
numberofpointsint (readonly)Number of points.
numberofpointattributesint (readonly)Number of point attributes.
numberoftrianglesint (readonly)Number of triangles.
numberofcornersint (readonly)Number of triangle corners.
numberoftriangleattributesint (readonly)Number of triangle attributes.
numberofsegmentsint (readonly)Number of segments.
numberofholesint (readonly)Number of holes. Input only, copied to output.
numberofregionsint (readonly)Number of regions. Input only, copied to output.
numberofedgesint (readonly)Number of edges. Output only.

Releasing Memory

** IMPORTANT ** remember to destroy instances of TriangulateIO after using them to avoid memory leaks.

While JavaScript is fairly forgiving in cleaning up after itself, static languages such as C are definitely not. Debugging memory leaks in WebAssembly using Emscripten

When we call makeIO() we allocate memory ( malloc ) and it needs to be released after with freeIO() ( free ). To make matters even less convenient, Triangle copies pointers from input to output, so we need to be careful not to double-free. The solution is to call 'destroy all' freeIO(io, true) on one of the instances, either input or output.

// allocate memory
const input = Triangle.makeIO(data);
const output = Triangle.makeIO();

Triangle.triangulate(null, input, output);

// use output
// ...

// release memory
Triangle.freeIO(input, true);
Triangle.freeIO(output);

Voronoi Diagrams

This implementation does not use exact arithmetic to compute the Voronoi vertices, and does not check whether neighboring vertices are identical.

The result is a valid Voronoi diagram only if Triangle's output is a true Delaunay triangulation with no holes. The Voronoi output is usually meaningless (and may contain crossing edges and other pathology) if the output is a constrained Delaunay triangulation (CDT) or a conforming constrained Delaunay triangulation (CCDT), or if it has holes or concavities.

Distributing WASM

The .wasm file is distributed with the package, but it might be necessary to manually copy it out of /node_modules/triangle-wasm/ so it can be served as a static file or bundled with a loader. This might change in the future once it becomes clear what is the best way to distribute wasm libraries.

This repository doesn't contain the original C code for Triangle, only the compiled .wasm. The source code can be found here.

See Also

  • Triangle - A Two-Dimensional Quality Mesh Generator and Delaunay Triangulator
  • poly-parse - A parser for .poly and .node files used by Triangle.
  • svg-to-poly - Extracts a PSLG from .svg paths and prepares it for Triangle.
  • opentype.js - Read and write OpenType fonts using JavaScript.

License

MIT, see LICENSE for details.