{"_id":"@allmaps/frame","name":"@allmaps/frame","dist-tags":{"latest":"1.0.0-beta.2"},"versions":{"1.0.0-beta.2":{"name":"@allmaps/frame","version":"1.0.0-beta.2","contributors":[{"name":"Bert Spaan","email":"hello@bertspaan.nl","url":"https://bertspaan.nl"}],"description":"Find optimal viewport frames for georeferenced map previews","type":"module","exports":"./dist/index.js","publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/allmaps/allmaps.git","directory":"packages/frame"},"homepage":"https://allmaps.org","keywords":["allmaps","frame","viewport","crop"],"scripts":{"watch":"tsc --watch --noCheck","build":"tsc --noCheck","test":"NODE_ENV=test vitest run","lint":"prettier --ignore-path ../../.gitignore --check src test && eslint src test --ext .js,.ts","format":"prettier --ignore-path ../../.gitignore --write src test","types":"tsc --noEmit"},"license":"MIT","dependencies":{"@allmaps/stdlib":"^1.0.0-beta.41","@allmaps/types":"^1.0.0-beta.23","@turf/area":"^7.2.0","@turf/centroid":"^7.2.0","@turf/helpers":"^7.2.0","@turf/intersect":"^7.2.0","polylabel":"^2.0.0"},"devDependencies":{"@types/eslint":"^8.56.0","@types/node":"^24","@types/polylabel":"^1.1.3","@typescript-eslint/eslint-plugin":"^7.0.0","@typescript-eslint/parser":"^7.0.0","eslint":"^8.56.0","eslint-config-prettier":"^9.1.0","prettier":"^3.6.2","typescript":"^5.9.3","vitest":"^4.0.4"},"gitHead":"0776371fa222f670b893d87b302c6334e825ac3e","_id":"@allmaps/frame@1.0.0-beta.2","bugs":{"url":"https://github.com/allmaps/allmaps/issues"},"_nodeVersion":"25.8.0","_npmVersion":"lerna/4.9.4/node@v25.8.0+arm64 (darwin)","dist":{"integrity":"sha512-j9Ymhys0xzNLSnxisW2fzNVx4uHBri6mWzB6DGsnZPNXSDcODRw+XRy7MWzdd5KXeMAG6snHSTCjEtlI4eLaYQ==","shasum":"0f889179f35372298d9f451c626dc6b6b8fbda17","tarball":"https://registry.npmjs.org/@allmaps/frame/-/frame-1.0.0-beta.2.tgz","fileCount":4,"unpackedSize":23680,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIEDPxeux95K7MQ6SfO4/MLWLa+6NxvSqwxVBROiG9udNAiEAq8PzprqE4bhCmIYdjbq6usvWhkZEYsQEG9W0nnWXTmA="}]},"_npmUser":{"name":"bertspaan","email":"hello@bertspaan.nl"},"directories":{},"maintainers":[{"name":"bertspaan","email":"hello@bertspaan.nl"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/frame_1.0.0-beta.2_1780001973691_0.00022749366121588288"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-28T20:59:33.535Z","1.0.0-beta.2":"2026-05-28T20:59:33.809Z","modified":"2026-05-28T20:59:34.054Z"},"maintainers":[{"name":"bertspaan","email":"hello@bertspaan.nl"}],"description":"Find optimal viewport frames for georeferenced map previews","homepage":"https://allmaps.org","keywords":["allmaps","frame","viewport","crop"],"repository":{"type":"git","url":"git+https://github.com/allmaps/allmaps.git","directory":"packages/frame"},"contributors":[{"name":"Bert Spaan","email":"hello@bertspaan.nl","url":"https://bertspaan.nl"}],"bugs":{"url":"https://github.com/allmaps/allmaps/issues"},"license":"MIT","readme":"# @allmaps/frame\n\nFind optimal viewport frames for georeferenced map previews.\n\n_This package and its algorithm was created with help from Claude Code / Sonnet 4.5. It works quite well, but needs improvement!_\n\n## What it does\n\n`@allmaps/frame` computes the best bounding box (frame) to show when generating preview images of georeferenced maps. It analyzes map polygon geometries and finds a viewport that:\n\n- **Minimizes background** (high fill - map pixels / viewport pixels)\n- **Shows meaningful content** (adequate coverage - visible map / total map)\n- **Handles complex cases** (scattered maps, irregular shapes, clusters)\n\n## Installation\n\n```bash\npnpm install @allmaps/frame\n```\n\n## Usage\n\n```typescript\nimport { findBestFrame } from '@allmaps/frame'\nimport type { Polygon, Size, Bbox } from '@allmaps/types'\n\nconst mapPolygons: Polygon[] = [\n  // Array of polygons representing your map geometry\n  // Each polygon is an array of rings (outer + holes)\n  // Each ring is an array of [lon, lat] coordinates\n]\n\nconst viewportSize: Size = [800, 600] // [width, height] in pixels\n\nconst mapBbox: Bbox = [minLon, minLat, maxLon, maxLat] // Overall bounding box\n\nconst optimalFrame = findBestFrame(mapPolygons, viewportSize, mapBbox)\n// Returns: [minLon, minLat, maxLon, maxLat] - optimal viewport bbox\n```\n\n## Algorithm\n\nThe function uses a multi-stage approach:\n\n1. **Spatial clustering** - Groups nearby polygons using union-find\n2. **Candidate generation** - Proposes multiple center points per cluster:\n   - Cluster bbox center\n   - Polygon centroids (top 8 by area)\n   - Midpoints between centroids\n   - Pole of inaccessibility\n3. **Scale optimization** - Samples 40 zoom levels for each candidate center\n4. **Scoring** - Evaluates each viewport by:\n   - `fill` = intersection area / viewport area (higher = less background)\n   - `coverage` = intersection area / cluster area (higher = more map shown)\n   - Enforces minimum thresholds (≥30% fill, cluster-dependent coverage)\n5. **Refinement** - Centers the viewport on the area-weighted centroid of visible content\n\n## Use cases\n\n- **Single large polygon** - Shows most of it with minimal background\n- **Scattered small maps** - Zooms into the densest cluster\n- **Long thin chains** - Shows a well-filled section\n- **Irregular polygon with outliers** - Focuses on the main mass\n\n## Dependencies\n\n- `@allmaps/stdlib` - Bbox utilities\n- `@allmaps/types` - TypeScript types\n- `@turf/*` - Geospatial operations\n- `polylabel` - Pole of inaccessibility\n\n## License\n\nMIT\n","readmeFilename":"README.md","_rev":"1-98a782a2e9a91ad56049f4ef1edcb3e7"}