{"id":49438590,"url":"https://github.com/a0a7/fastgeotoolkit","last_synced_at":"2026-04-29T19:05:48.956Z","repository":{"id":301647085,"uuid":"1009861979","full_name":"a0a7/fastgeotoolkit","owner":"a0a7","description":"Performant JS library for GPS route density mapping","archived":false,"fork":false,"pushed_at":"2026-04-23T21:19:34.000Z","size":3336,"stargazers_count":3,"open_issues_count":2,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-23T23:27:11.799Z","etag":null,"topics":["geospatial","gis","gpx","npm","polyline","python","route-density","rust","typescript","wasm","webassembly"],"latest_commit_sha":null,"homepage":"https://fastgeotoolkit-demo.pages.dev/","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/a0a7.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-06-27T21:04:25.000Z","updated_at":"2026-03-06T18:32:51.000Z","dependencies_parsed_at":"2025-08-02T02:44:11.197Z","dependency_job_id":"f3d9dbad-72a3-4c74-857f-f580a449902d","html_url":"https://github.com/a0a7/fastgeotoolkit","commit_stats":null,"previous_names":["strava-tools/heatmap","motiongis/activityheatmap","a0a7/fast-line-heatmap","a0a7/fastgeotoolkit"],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/a0a7/fastgeotoolkit","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/a0a7%2Ffastgeotoolkit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/a0a7%2Ffastgeotoolkit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/a0a7%2Ffastgeotoolkit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/a0a7%2Ffastgeotoolkit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/a0a7","download_url":"https://codeload.github.com/a0a7/fastgeotoolkit/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/a0a7%2Ffastgeotoolkit/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32439372,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-29T18:12:22.909Z","status":"ssl_error","status_checked_at":"2026-04-29T18:11:33.322Z","response_time":110,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["geospatial","gis","gpx","npm","polyline","python","route-density","rust","typescript","wasm","webassembly"],"created_at":"2026-04-29T19:05:47.972Z","updated_at":"2026-04-29T19:05:48.949Z","avatar_url":"https://github.com/a0a7.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# fastgeotoolkit  [![npm](https://img.shields.io/npm/v/fastgeotoolkit)](https://www.npmjs.com/package/fastgeotoolkit) [![Docs](https://img.shields.io/badge/Documentation-skyblue?logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2NDAgNjQwIj48IS0tIUZvbnQgQXdlc29tZSBGcmVlIDcuMC4wIGJ5IEBmb250YXdlc29tZSAtIGh0dHBzOi8vZm9udGF3ZXNvbWUuY29tIExpY2Vuc2UgLSBodHRwczovL2ZvbnRhd2Vzb21lLmNvbS9saWNlbnNlL2ZyZWUgQ29weXJpZ2h0IDIwMjUgRm9udGljb25zLCBJbmMuLS0+PHBhdGggZD0iTTQ4MCA1NzZMMTkyIDU3NkMxMzkgNTc2IDk2IDUzMyA5NiA0ODBMOTYgMTYwQzk2IDEwNyAxMzkgNjQgMTkyIDY0TDQ5NiA2NEM1MjIuNSA2NCA1NDQgODUuNSA1NDQgMTEyTDU0NCA0MDBDNTQ0IDQyMC45IDUzMC42IDQzOC43IDUxMiA0NDUuM0w1MTIgNTEyQzUyOS43IDUxMiA1NDQgNTI2LjMgNTQ0IDU0NEM1NDQgNTYxLjcgNTI5LjcgNTc2IDUxMiA1NzZMNDgwIDU3NnpNMTkyIDQ0OEMxNzQuMyA0NDggMTYwIDQ2Mi4zIDE2MCA0ODBDMTYwIDQ5Ny43IDE3NC4zIDUxMiAxOTIgNTEyTDQ0OCA1MTJMNDQ4IDQ0OEwxOTIgNDQ4ek0yMjQgMjE2QzIyNCAyMjkuMyAyMzQuNyAyNDAgMjQ4IDI0MEw0MjQgMjQwQzQzNy4zIDI0MCA0NDggMjI5LjMgNDQ4IDIxNkM0NDggMjAyLjcgNDM3LjMgMTkyIDQyNCAxOTJMMjQ4IDE5MkMyMzQuNyAxOTIgMjI0IDIwMi43IDIyNCAyMTZ6TTI0OCAyODhDMjM0LjcgMjg4IDIyNCAyOTguNyAyMjQgMzEyQzIyNCAzMjUuMyAyMzQuNyAzMzYgMjQ4IDMzNkw0MjQgMzM2QzQzNy4zIDMzNiA0NDggMzI1LjMgNDQ4IDMxMkM0NDggMjk4LjcgNDM3LjMgMjg4IDQyNCAyODhMMjQ4IDI4OHoiLz48L3N2Zz4=)](https://fastgeotoolkit.pages.dev/) [![Demo](https://img.shields.io/badge/Try%20the%20demo-lightblue)](https://fastgeotoolkit-demo.pages.dev/)\n\n\n\u003c!--[![codecov](https://codecov.io/gh/a0a7/fastgeotoolkit/branch/main/graph/badge.svg)](https://codecov.io/gh/a0a7/fastgeotoolkit)--\u003e\n[![Rust Tests](https://github.com/a0a7/fastgeotoolkit/actions/workflows/rust-tests.yml/badge.svg)](https://github.com/a0a7/fastgeotoolkit/actions/workflows/rust-tests.yml)\n[![JavaScript Tests](https://github.com/a0a7/fastgeotoolkit/actions/workflows/javascript-tests.yml/badge.svg)](https://github.com/a0a7/fastgeotoolkit/actions/workflows/javascript-tests.yml)\n[![CodeQL](https://github.com/a0a7/fastgeotoolkit/actions/workflows/github-code-scanning/codeql/badge.svg)](https://github.com/a0a7/fastgeotoolkit/actions/workflows/github-code-scanning/codeql)\n![License](https://img.shields.io/badge/license-MIT-blue)\n\nfastgeotoolkit is a library for GPS data processing and route density mapping. The core of the library is written in Rust and it's compiled to webassembly for use in the browser and node.\n\n\u003e [!NOTE]\n\u003e Only Javascript/Typescript is supported at the moment. Rust and Python releases are planned.\n\n## What it does\n\nThe main use case is creating route heatmaps where you want to see which paths/routes are used most frequently. You can test this functionality at [https://fastgeotoolkit-demo.pages.dev/](https://fastgeotoolkit-demo.pages.dev/), using either your own data or sample data. This is an example of what a heatmap produced using fastgeotoolkit looks like:\n![https://i.ibb.co/MxpHbVdp/image.png](https://i.ibb.co/MxpHbVdp/image.png)\n\nHowever, beyond this primary usecase, this library helps you:\n- Analyze GPS tracks (distance, statistics, intersections)\n- Decode Google polylines \n- Convert between GPS data formats\n\n## Documentation\n\nDocs are available at https://fastgeotoolkit.pages.dev/. \n\n## Installation\n\n```bash\nnpm install fastgeotoolkit\n# or \npnpm i fastgeotoolkit\n```\n\n## Basic Usage\n\n\n```typescript\nimport { processGpxFiles } from 'fastgeotoolkit';\n\n// Process GPX files into a heatmap\nconst gpxFile1 = new Uint8Array(/* your GPX file data */);\nconst gpxFile2 = new Uint8Array(/* another GPX file */);\n\nconst result = await processGpxFiles([gpxFile1, gpxFile2]);\n\n// Result contains tracks with frequency data\nconsole.log(`Found ${result.tracks.length} unique track segments`);\nconsole.log(`Maximum frequency: ${result.max_frequency}`);\n\nresult.tracks.forEach(track =\u003e {\n  console.log(`Track with ${track.coordinates.length} points, used ${track.frequency} times`);\n});\n```\n\n## Working with Polylines\n\n```typescript\nimport { decodePolyline, processPolylines } from 'fastgeotoolkit';\n\n// Decode a single polyline\nconst coords = await decodePolyline('_p~iF~ps|U_ulLnnqC_mqNvxq`@');\nconsole.log(coords); // [[lat, lng], [lat, lng], ...]\n\n// Process multiple polylines into a heatmap\nconst polylines = [\n  '_p~iF~ps|U_ulLnnqC_mqNvxq`@',\n  'another_encoded_polyline',\n  'yet_another_one'\n];\nconst heatmap = await processPolylines(polylines);\n```\n\n## Track Analysis\n\n```typescript\nimport { calculateTrackStatistics, validateCoordinates } from 'fastgeotoolkit';\n\nconst coordinates = [[37.7749, -122.4194], [37.7849, -122.4094]]; // [lat, lng] pairs\n\n// Get basic statistics\nconst stats = await calculateTrackStatistics(coordinates);\nconsole.log(`Distance: ${stats.distance_km.toFixed(2)} km`);\nconsole.log(`${stats.point_count} GPS points`);\nconsole.log(`Bounds: ${stats.bounding_box}`); // [min_lat, min_lng, max_lat, max_lng]\n\n// Validate coordinates\nconst validation = await validateCoordinates(coordinates);\nconsole.log(`${validation.valid_count} out of ${validation.total_count} coordinates are valid`);\nif (validation.issues.length \u003e 0) {\n  console.log('Issues found:', validation.issues);\n}\n```\n\n## Data Conversion\n\n```typescript\nimport { coordinatesToGeojson, exportToGpx } from 'fastgeotoolkit';\n\n// Convert to GeoJSON\nconst geojson = await coordinatesToGeojson(coordinates, {\n  name: 'My Route',\n  activity: 'cycling'\n});\n\n// Export multiple tracks as GPX\nconst tracks = [track1_coordinates, track2_coordinates];\nconst gpxString = await exportToGpx(tracks, {\n  creator: 'My App',\n  name: 'Route Collection'\n});\n```\n\n## Real-world Example\n\nHere's an example of how you might use this in a web app to show route popularity:\n\n```typescript\nimport { processGpxFiles } from 'fastgeotoolkit';\n\nasync function createHeatmap(gpxFiles) {\n  // Convert files to Uint8Array\n  const fileBuffers = await Promise.all(\n    gpxFiles.map(file =\u003e file.arrayBuffer().then(buf =\u003e new Uint8Array(buf)))\n  );\n  \n  // Process into heatmap\n  const heatmap = await processGpxFiles(fileBuffers);\n  \n  // Render on map (example with any mapping library)\n  heatmap.tracks.forEach(track =\u003e {\n    const intensity = track.frequency / heatmap.max_frequency;\n    const color = `hsl(${(1-intensity) * 240}, 100%, 50%)`; // blue to red\n    \n    drawLineOnMap(track.coordinates, {\n      color: color,\n      weight: Math.max(2, intensity * 8)\n    });\n  });\n}\n\n// Usage\ndocument.getElementById('file-input').addEventListener('change', async (e) =\u003e {\n  const files = Array.from(e.target.files);\n  await createHeatmap(files);\n});\n```\n\n## TypeScript Support\n\nThe library includes full TypeScript definitions:\n\n```typescript\nimport type { \n  Coordinate,        // [number, number] - [lat, lng]\n  HeatmapResult,     // { tracks: HeatmapTrack[], max_frequency: number }\n  HeatmapTrack,      // { coordinates: Coordinate[], frequency: number }\n  TrackStatistics,   // distance, bounds, point count, etc.\n  ValidationResult,  // validation results with issues\n  FileInfo          // file format information\n} from 'fastgeotoolkit';\n```\n\n## JavaScript Utilities\n\nFor simple operations that don't rely on WebAssembly:\n\n```typescript\nimport { utils } from 'fastgeotoolkit';\n\n// Basic coordinate validation\nif (utils.isValidCoordinate(37.7749, -122.4194)) {\n  console.log('Valid GPS coordinate');\n}\n\n// Calculate distance between two points\nconst distance = utils.haversineDistance(37.7749, -122.4194, 37.7849, -122.4094);\nconsole.log(`Distance: ${distance.toFixed(2)} km`);\n\n// Get bounding box\nconst bounds = utils.getBoundingBox(coordinates);\nconsole.log(`Bounds: ${bounds}`); // [min_lat, min_lng, max_lat, max_lng]\n```\n\n## Browser vs Node.js\n\nWorks the same in both environments:\n\n```javascript\n// Browser\nimport { processGpxFiles } from 'fastgeotoolkit';\n\n// Node.js  \nconst { processGpxFiles } = require('fastgeotoolkit');\n// or with ES modules:\nimport { processGpxFiles } from 'fastgeotoolkit';\n```\n\n## Performance Notes\n\n- WebAssembly provides near-native performance for GPS processing\n- Large datasets (thousands of tracks) process quickly\n- First function call initializes WebAssembly (adds ~100ms startup time)\n\n## Common Issues\n\n**\"Cannot resolve module\"** errors: Make sure your bundler supports WebAssembly. Modern bundlers (Vite, Webpack 5+, etc.) work out of the box.\n\n**TypeScript errors**: Ensure you're using TypeScript 4.0+ for proper WebAssembly typing support.\n\n**File reading**: Remember to convert File objects to Uint8Array:\n```javascript\nconst buffer = await file.arrayBuffer();\nconst uint8Array = new Uint8Array(buffer);\n```\n\n## Development \u0026 Maintenance\n\nThis project consists of Rust code compiled to WebAssembly with JavaScript/TypeScript bindings.\n\n### Project Structure\n\n- `/src/` - Rust source code\n- `/dist/javascript/` - JavaScript/TypeScript bindings and NPM package\n- `/dist/wasm/` - Generated WebAssembly files\n- `/demo/` - Demo application (SvelteKit)\n- `/docs/` - Generated documentation\n\u003e [!NOTE]\n\u003e `/dist/python` and `/dist/rust/` contain WIP releases for their respective ecosystems, but they're not in working order yet.\n\n### Compiling Rust to WebAssembly\n\nTo compile the Rust code to WebAssembly:\n\n```bash\n# Install wasm-pack if you haven't already\ncargo install wasm-pack\n\n# Build the WebAssembly module\nwasm-pack build --target web --out-dir dist/wasm\n```\n\n### Building the NPM Package\n\nTo build the complete NPM package with all bindings:\n\n```bash\n# From the root directory\nnpm run build\n\n# Or build individual components:\nnpm run build:wasm    # Build WebAssembly\nnpm run build:js      # Build JavaScript bindings\nnpm run build:docs    # Build documentation\n```\n\n### Building Documentation\n\nThe documentation is generated using TypeDoc and can be built locally:\n\n```bash\ncd dist/javascript\nnpm run docs\n```\n\nThis will generate the documentation website in the `docs/` directory.\n\n### Testing\n\n```bash\n# Run Rust tests\ncargo test\n\n# Run JavaScript tests\ncd dist/javascript\nnpm test\n```\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fa0a7%2Ffastgeotoolkit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fa0a7%2Ffastgeotoolkit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fa0a7%2Ffastgeotoolkit/lists"}