npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

nav2d

v1.4.0

Published

2d navigation meshes with pathfinding and funneling

Downloads

1,193

Readme

Nav2d

npm version License: MIT minzipped size Tests codecov

This is a high-quality implementation of a 2D polygonal navigation mesh with A* path finding and funneling (e.g. finding not only the mesh nodes but also the actual path across polygons).

Path finding examples

Why this package

This package was created due to the lack of generic 2D navigation mesh packages able to handle polygonal nodes of any shape and integrating a robust funnel algorithm. Furthermore, some packages require specific file formats for the meshes, limiting the choices of editors.

This package aims to:

  • Work on node and the browser.
  • Provide robust and fast implementation of a generic polygonal navigation mesh with A* path finding and funneling.
  • Provide a simple user interface:
    • Accept multiple formats to specify points (for interoperability with other libraries).
    • Accept any polygon (even convex and defined either in clockwise and counterclockwise order) and automatically triangulate.
    • Automatic neighbor search means that only polygons are needed, the relations will be automatically computed (polygon with a shared edges are considered neighbors).
    • All geometric operations and comparisons are tolerant to floating point errors.
    • Support disconnected navigation meshes.
  • Have good test coverage.

Install

There are multiple ways to install nav2d. If you are using npm, and building your game with wepback, you can install and use the package directly:

$ npm i nav2d

You can also directly include the library from the unpkg CDN into your page. There are two options here,

  1. You can use the version containing only the code of this library (you'll have to include all dependencies yourself):

    <script defer src="https://unpkg.com/nav2d/dist/nav2d.min.js"></script>
  2. You can use the deps bundle, which ships together with all dependencies, for hassle free experience:

    <script defer src="https://unpkg.com/nav2d/dist/nav2d_deps.min.js"></script>

How to use

First create the navigation mesh, by passing an array of polygons, each polygon being an array of points. Polygons that are not triangles will be triangulated automatically.

import { NavMesh } from "nav2d";

const navmesh = new NavMesh([
    [
        [0, 0],
        [0, 12],
        [12, 0],
    ],
    [
        [12, 8],
        [12, 4],
        [16, 6],
    ],
    [
        [12, 0],
        [6, 6],
        [12, 6],
    ],
    [
        [100, 100],
        [110, 100],
        [100, 110],
        [95, 107],
        [105, 102],
    ],
]);

You can pass points as arrays [x, y], as objects {x:x, y:y} or as Point(x, y) objects.

Warning: Instantiating the NavMesh object can be slow if you have a big mesh with lots of polygons, as the constructor has to triangulate the polygons and creates a neighbors cache to speed up neighbor lookup when searching. This is a one-time cost (e.g. the NavMesh class is optimized to be instantiated once and use multiple times). Ballpark performance numbers are 1.5 seconds for 1000 polygons and 15 seconds for 10_000 polygons (linearly dependent on polygon count).

If your mesh is made up of only triangles, for instance because you use an external triangulation algorithm, you can use new NavMesh(polygons, { triangulate: false }) to skip it, but there will still be some cost in caching neighboring triangles. If you disable triangulation on a mesh which isn't made of triangles, the library will return wrong results.

For games where the mesh is always the same (for instance the map does not change), the best option is to triangulate the navigation mesh when you create the map, load the map already triangulated and disable triangulation. This will be the fastest.

Now we can query paths:

const path = navmesh.findPath([1, 1], [14, 6]);
console.log(path); // -> [Point(1, 1), Point(14, 6)]

As you can see from the output, thanks to the funnel algorithm, the path will only contain the necessary path points (in this case a straight line). If no path can be found (disconnected islands or endpoints outside the mesh) null will be returned.

Warning: The path quality heavily depends on the quality of the triangulation. If your mesh has a lot of skinny triangles, it might not choose the path you would expect.

nav2d automatically triangulates the mesh with earcut, which is fast but sometimes generates non-optimal triangulations. If you have this problem, you can try triangulating your mesh manually with a library such as poly2tri, as some user successfully did.

If you manually triangulate, make sure to disable triangulation using the new NavMesh(polygons, { triangulate: false }) option to avoid unnecessary work.

To find the path, a optimized A* implementation is used. You can override the default the cost and heuristic functions, by passing an options object to the NavMesh constructor. For example, to implement a simpler breadth first search, we can do:

const costFunc = (polygon1, polygon2, portal) => 1;
const heuristicFunc = () => (polygon, to) => 0;
const navmesh = new NavMesh([...], { costFunc, heuristicFunc });
// Use as before

Instead, to implement Dijkstra’s Algorithm, you can:

const heuristicFunc = () => (polygon, to) => 0;
const navmesh = new NavMesh(
    [...],
    { heuristicFunc }
);

(Look here for an nice explanation of the algorithms above)

The cost function takes two neighboring polygons and a portal as parameters and returns the cost to go from the first to the second. Both polygons are Polygon objects. The portal is the edge shared between the two polygons.

The heuristic function takes two polygon: a polygon on the path and the final polygon, and returns an estimation of the distance between the two. Both of these are Polygon objects.

Note: The default functions compute the distance between polygons using the .centroidDistance() method (see below). This computes the Cartesian distance between the centroids.

This is basically it. This package does nothing more and nothing less.

The Editor

For those looking for an easy way to create, view and edit their navigation meshes, nav2d comes with a simple mesh viewer and editor, where you can also test the path finding.

The editor is accessible here

Editor screenshot

The editor lets you load, visualize and edit navigation meshes and then export the result. It also comes with built-in path finding, so that you can test your routes.

Editor path finding

To help while editing, a powerful snapping feature is also included.

Editor snap feature

API Reference

Point or Vector (aliases)

Note: In all places where points are accepted, nav2d also accepts arrays [x, y] or { x: x, y: y } objects.

Properties:

  • x - X coordinate
  • y - Y coordinate

Methods:

  • Vector(x, y) - Construct vector or point.
  • length() - Vector length.
  • add(other) - Add vectors, return new vector.
  • sub(other) - Subtract vectors, return new vector.
  • mul(other) - Multiply vectors, return new vector.
  • div(other) - Divide vectors, return new vector.
  • equals(other) - Check for equality.
  • angle(other) - Returns angle between vectors.
  • counterclockwiseAngle(other) - Return angle between vectors, using the current vector as reference (can be negative).

Functions:

  • dot(a, b) - Dot product.
  • cross(a, b) - Cross product.
  • isclose(a, b) - Return true if the given floats are close to each other.
  • clip(a, b, v) - Return true if v is in the range a, b range, the closest limit of the range otherwise.

Edge

Properties:

  • p1 - First edge point.
  • p2 - Last edge point.

Methods:

  • Edge(points) - Construct edge object (like a string between 2 points).
  • length() - Edge length.
  • direction() - Vector from p1 to p2.
  • onEdge(ppoint) - Whether point is on the edge.
  • parallel(otherEdge) - Whether the two edges are parallel (but might not be on the same line).
  • collinear(otherEdge) - Whether the two edges are collinear (parallel and on same line but might not overlap).
  • overlap(otherEdge) - Returns overlap between two edges, or null if they do not overlap (might be a null-length edge).
  • equals(otherEdge) - Whether the two edges are the same (have the same endpoints, even if reversed).

Polygon

Properties:

  • points - Polygon points.
  • bounds - Bounding box array: [minx, miny, maxx, maxy].

Methods:

  • Polygon(points) - Construct polygon object.
  • boundsSize() - Bounding box array: [x, y, width, height].
  • edges() - Edges of the polygon.
  • centroid() - Polygon centroid.
  • centroidDistance(otherPoly) - Distance from this polygon's centroid to otherPoly's.
  • contains(point) - Whether point is contained in the polygon.
  • onEdge(point) - Whether point is on an edge.
  • touches(edge) - Whether edge touches but doesn't intersect the polygon.

NavMesh

Properties:

  • polygons - Triangulated mesh polygons (triangles).
  • pointQuerySize - Square edge size to use to query the NavMes quad tree when checking for point to mesh intersection. This should be much smaller than the average triangle size in the mesh, and can freely be set according to your navigation mesh scale. Defaults to 0.01.

Methods:

  • NavMesh(polygons, options?) - Construct navigation mesh. Arguments:
    • polygons - A list of polygons, each polygon being a list of points.
    • options - Optional settings. This is the default:
      {
          // Boolean indicating whether to triangulate mesh or not.
          triangulate: true,
          // Threshold used to check triangle collision.
          // This should be much smaller that the typical
          // size of your mesh triangles too many checks.
          pointQuerySize: 0.01,
          // A cost function (see docs above).
          costFunc: euclideanDistance,
          // An heuristic function (see docs above)
          heuristicFunc: euclideanDistance,
      }
  • findPath(from, to) - Find path from from point to to point. Returns a list of points, or null if not found.

Changelog

See here.