gods-eye-view/tools/README.md

6.9 KiB

Tools

CLI scripts for fetching, rendering, and reprojecting geospatial imagery. All tools read the Google Maps API key from .env automatically.

Output files go to output/ by default (gitignored).

Prerequisites

  • Node.js (via mise)
  • sharp and puppeteer (devDependencies — npm install)
  • Google Maps API key in .env as GOOGLE_MAPS_API_KEY
  • APIs enabled on your Google Cloud project: Map Tiles API, Street View Static API

sat-ortho.mjs

Stitches satellite tiles from the Map Tiles API into a single ortho image centered on a lat/lon.

# 2K ortho at zoom 21 (~6.4 cm/pixel, ~132m coverage)
node tools/sat-ortho.mjs --lat 30.266476 --lon -97.73719

# Zoom 20 for wider coverage (~264m), or zoom 22 for max detail (~3.7 cm/pixel)
node tools/sat-ortho.mjs --lat 30.266476 --lon -97.73719 --zoom 20 --size 2048
node tools/sat-ortho.mjs --lat 30.266476 --lon -97.73719 --zoom 22 --size 2048
Option Default Description
--lat Center latitude (required)
--lon Center longitude (required)
--zoom 21 Tile zoom level (max typically 22)
--size 2048 Output square size in pixels

Reports GSD, ground coverage, and NW/SE corner coordinates for georeferencing.


streetview-headings.mjs

Fetches 8 Street View static images (one per compass heading) at a location, with optional first-order neighbor traversal.

# 8 images at the intersection
node tools/streetview-headings.mjs --lat 30.266476 --lon -97.73719

# Include all first-order neighbor locations (auto-deduped)
node tools/streetview-headings.mjs --lat 30.266476 --lon -97.73719 --neighbors

# Custom FOV and pitch
node tools/streetview-headings.mjs --lat 30.266476 --lon -97.73719 --fov 120 --pitch -10
Option Default Description
--lat Latitude (required)
--lon Longitude (required)
--fov 90 Field of view in degrees (10-120)
--pitch 0 Camera pitch (-90 to 90)
--size 640x640 Image size (max 640 per axis)
--step 45 Heading step in degrees
--neighbors off Also fetch images from nearby Street View locations

The --neighbors flag queries Google's panorama metadata for linked locations, deduplicates them by pano ID via the metadata API, and fetches 8 heading images from each unique neighbor within 15m.


streetview-panorama.mjs

Fetches and stitches a full equirectangular panorama from the Map Tiles API (Street View tiles endpoint).

# Default zoom 3 → 4096x2048 panorama
node tools/streetview-panorama.mjs --lat 30.266476 --lon -97.73719

# Max resolution (zoom 5 → up to 16384x8192)
node tools/streetview-panorama.mjs --lat 30.266476 --lon -97.73719 --zoom 5
Option Default Description
--lat Latitude (required)
--lon Longitude (required)
--zoom 3 Tile zoom 0-5 (higher = larger pano)
--radius 50 Search radius in meters for nearest panorama

Output is a standard equirectangular JPEG suitable as input for pano-pinhole.mjs.


pano-pinhole.mjs

Reprojects an equirectangular panorama into pinhole (perspective) camera views. Uses inverse mapping with bilinear interpolation — every output pixel is sampled from the panorama, so there are no holes.

# Single view: looking west, 90 deg FOV, 1920x1080
node tools/pano-pinhole.mjs --input output/panorama_30.266476_-97.73719.jpg --heading 270 --hfov 90

# All 8 compass headings from one panorama
node tools/pano-pinhole.mjs --input output/panorama_30.266476_-97.73719.jpg --all --hfov 90

# 2K output with narrow FOV
node tools/pano-pinhole.mjs --input output/panorama_30.266476_-97.73719.jpg --heading 180 --hfov 60 --width 2560 --height 1440

# Specify focal length instead of FOV
node tools/pano-pinhole.mjs --input output/panorama_30.266476_-97.73719.jpg --heading 90 --focal 2000

# 12 views at 30-degree steps
node tools/pano-pinhole.mjs --input output/panorama_30.266476_-97.73719.jpg --all --step 30 --hfov 90
Option Default Description
--input Equirectangular panorama JPEG (required)
--heading 0 Compass heading (0=N, 90=E, 180=S, 270=W)
--pitch 0 Pitch in degrees (positive=up)
--roll 0 Roll in degrees (positive=clockwise)
--hfov 90 Horizontal field of view in degrees
--focal Focal length in pixels (overrides --hfov)
--width 1920 Output width
--height 1080 Output height
--all off Render all compass headings (ignores --heading)
--step 45 Heading step for --all mode

Reports horizontal, vertical, and diagonal FOV plus equivalent focal length.


cesium-render.mjs

Renders a CesiumJS 3D view to JPEG via headless Chromium with Google Photorealistic 3D tiles. Requires SwiftShader (no GPU).

# Look-at mode: camera looks at a target point from above
node tools/cesium-render.mjs --lookat-lat 30.266476 --lookat-lon -97.73719 --heading 180 --pitch -30 --height 25

# Top-down view at 80m
node tools/cesium-render.mjs --lookat-lat 30.266476 --lookat-lon -97.73719 --pitch -90 --height 80 --fov 90

# 2K output
node tools/cesium-render.mjs --lookat-lat 30.266476 --lookat-lon -97.73719 --heading 180 --pitch -30 --height 25 --width 2560 --height-px 1440

# Direct mode: camera placed at coordinates
node tools/cesium-render.mjs --lat 30.266476 --lon -97.73719 --heading 270 --pitch -15 --height 8
Option Default Description
--lat/--lon Camera position (direct mode)
--lookat-lat/--lookat-lon Target to look at (lookat mode)
--heading 0 Compass heading
--pitch -10 Camera pitch (must be negative in lookat mode)
--height 8 Meters above ground
--fov 60 Vertical field of view
--width 1280 Image width
--height-px 720 Image height
--sse 2 Screen-space error (lower = sharper, slower)
--timeout 30 Max wait in seconds

Uses progressive SSE refinement and automatic ground-height sampling. Street-level views are limited by Google's photogrammetry tile resolution.


Typical Workflow

# 1. Get a satellite ortho of an intersection
node tools/sat-ortho.mjs --lat 30.266476 --lon -97.73719 --zoom 21

# 2. Fetch a 4K panorama at the same location
node tools/streetview-panorama.mjs --lat 30.266476 --lon -97.73719

# 3. Extract 8 pinhole views from the panorama
node tools/pano-pinhole.mjs --input output/panorama_30.266476_-97.73719.jpg --all --hfov 90

# 4. Also grab the Street View static API versions for comparison
node tools/streetview-headings.mjs --lat 30.266476 --lon -97.73719

# 5. Render a 3D view of the same location from above
node tools/cesium-render.mjs --lookat-lat 30.266476 --lookat-lon -97.73719 --pitch -90 --height 50 --fov 90 --width 2560 --height-px 1440