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 🙏

© 2026 – Pkg Stats / Ryan Hefner

bim-tile-overlay

v1.0.0

Published

Overlay web map tiles (OSM, aerial imagery, custom XYZ) onto Autodesk APS Viewer as a camera-synced 3D ground plane

Downloads

132

Readme

bim-tile-overlay

Overlay web map tiles (OSM, aerial imagery, custom XYZ) onto an Autodesk APS Viewer as a camera-synced 3D ground plane.

Infra Plan

By Infra Plan

Demo

The Problem

Placing geographic map tiles under a BIM model in Autodesk Viewer requires:

  1. Extracting the camera frustum and projecting it onto a ground plane
  2. Converting between the viewer's internal coordinate system and WGS84
  3. Figuring out which map tiles cover the visible area at the right zoom level
  4. Fetching, stitching, and caching those tiles into a GPU-friendly texture
  5. Positioning a THREE.js plane in 3D space aligned with the geographic bounds
  6. Updating everything in real-time as the camera moves

This library handles all of that in ~500 lines of code.

Quick Start

npm install bim-tile-overlay proj4
import { TileOverlay, CoordinateTransformer } from 'bim-tile-overlay';

// After viewer has loaded a model:
const transformer = CoordinateTransformer.fromAPSViewer(
    viewer,
    // proj4 definition for your local CRS (this example uses Croatia HTRS96/TM)
    '+proj=tmerc +lat_0=0 +lon_0=16.5 +k=0.9999 +x_0=500000 +y_0=0 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs'
);

const overlay = new TileOverlay(viewer, transformer, {
    urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
    zoomRange: [14, 19],
    maxBounds: transformer.getModelBoundsLL84(),
});

await overlay.enable();

How It Works

Camera frustum corners
  → Ray-cast to ground plane (Z elevation)
  → Convert hit points to WGS84 lon/lat
  → Determine visible geographic bounds
  → Calculate optimal tile zoom level
  → Fetch XYZ tiles in parallel
  → Stitch into single canvas texture
  → Map onto THREE.js plane in viewer space
  → Update on camera change (debounced)

Coordinate pipeline:

WGS84 (lon, lat)
  ↔ Local CRS (meters) → via proj4
  ↔ CRS in feet → × 3.28084
  ↔ BIM internal coords → via refPointTransform rotation + translation
  ↔ Viewer display coords → minus globalOffset

API Reference

TileOverlay

Main class. Creates a map tile overlay on the viewer.

const overlay = new TileOverlay(viewer, transformer, options);

Options:

| Option | Type | Default | Description | |--------|------|---------|-------------| | urlTemplate | string | required | Tile URL with {z}, {x}, {y} placeholders | | zoomRange | [number, number] | required | Min and max zoom levels | | maxBounds | GeoBounds | required | Geographic bounds to clip tile fetching | | groundZ | number | modelBBox.min.z - 5 | Z elevation of the ground plane | | debounceMs | number | 150 | Camera change debounce delay (ms) | | maxCacheSize | number | 6 | Max cached stitched tile canvases | | zoomScaleFactor | number | 12 | Tile detail vs. camera distance. Higher = more detail | | progressInterval | number | 5 | Texture refresh frequency during tile loading (every N tiles). Always fires on the last tile. Set to 1 for per-tile updates. | | sceneName | string | 'bim-tile-overlay' | Viewer overlay scene name |

Methods:

| Method | Description | |--------|-------------| | enable() | Show the overlay and start tracking camera | | disable() | Hide the overlay, preserve cache for re-enabling | | destroy() | Fully dispose all GPU resources and cache | | update() | Force an immediate tile refresh |

CoordinateTransformer

Converts between WGS84 and the viewer's coordinate system.

// From viewer (recommended):
const transformer = CoordinateTransformer.fromAPSViewer(viewer, crsDefinition);

// Manual config:
const transformer = new CoordinateTransformer({
    crs: '+proj=tmerc +lat_0=0 +lon_0=16.5 ...',
    refPointTransform: [...],  // From model metadata
    globalOffset: { x, y, z },
    modelBBox: { min: { x, y, z }, max: { x, y, z } },
});

Methods:

| Method | Description | |--------|-------------| | lonLatToViewer(lon, lat, z?) | WGS84 → viewer coordinates | | viewerToLonLat(x, y, z?) | Viewer coordinates → WGS84 | | getModelBoundsLL84() | Model bounding box in WGS84 |

Utility Functions

import { lonLatToTile, tileToLonLat, getViewportBounds, createTileCache } from 'bim-tile-overlay';

| Function | Description | |----------|-------------| | lonLatToTile(lon, lat, zoom) | WGS84 → tile {x, y} coordinates | | tileToLonLat(x, y, zoom) | Tile coordinates → WGS84 (NW corner) | | getViewportBounds(camera, transformer, options) | Camera frustum → geographic bounds + zoom | | createTileCache(maxSize?) | LRU cache that frees bitmap memory on eviction |

Finding Your CRS

Your BIM model needs a local Coordinate Reference System (CRS) for accurate positioning. Common ones:

| Region | CRS | Code | |--------|-----|------| | Croatia | HTRS96/TM | EPSG:3765 | | UK | British National Grid | EPSG:27700 | | Germany | ETRS89/UTM zone 32N | EPSG:25832 | | US (New York) | NAD83/NY Long Island | EPSG:2263 |

Find your CRS definition at epsg.io and pass the proj4 string.

Requirements

  • Autodesk Viewer (APS / Forge) with a loaded, georeferenced model — the Viewer script provides THREE.js and Autodesk globals that this library uses internally; you do not need to install them separately
  • proj4 (peer dependency) — npm install proj4
  • The BIM model must have refPointTransform in its metadata (set via Revit's survey/project point)

Contributing

Contributions are welcome! Please open an issue or pull request.

License

MIT - Infra Plan