mapcachetools 1.0.7 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,16 @@
1
+ ISC License
2
+
3
+ Copyright (c) 2025 Mohammad Said Hefny
4
+
5
+ Permission to use, copy, modify, and/or distribute this software for any
6
+ purpose with or without fee is hereby granted, provided that the above
7
+ copyright notice and this permission notice appear in all copies.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
+
package/README.md CHANGED
@@ -1,46 +1,122 @@
1
- # MAP Cache Tools
1
+ # Map Cache Tools
2
2
 
3
- This tool download any area from map provider and store it as images in a folder.
4
- You can use these images with a library like [Leafet](https://leafletjs.com/ "Leafet") to make your own map server easily without the need to download a local OpenStreetMap server.
3
+ A robust Node.js tool to download map tiles (satellite or terrain RGB) for a specified geographic area and zoom range, storing them as PNG images in a folder. Ideal for offline map applications, such as integration with [Leaflet](https://leafletjs.com/) or 3D rendering projects like WebGL-based terrain visualization. Features include parallel downloads, retry handling, progress tracking, and support for multiple map providers.
5
4
 
6
- [![Downloaded Images of Map](https://github.com/HefnySco/mapcache/blob/master/images/Screenshot%20from%202022-09-03%2002-19-12.png?raw=true "Downloaded Images of Map")](https://github.com/HefnySco/mapcache/blob/master/images/Screenshot%20from%202022-09-03%2002-19-12.png?raw=true "Downloaded Images of Map")
7
5
 
8
- ## Usage
6
+ Watch a demo video showcasing the tool:
7
+ [![Watch the video](https://github.com/HefnySco/mapcache/blob/master/images/youtube.png?raw=true)](https://youtu.be/aSb6xNOQqok)
9
8
 
10
- Download area from 58.5500977,-4.5231876 to 58.5501,-4.5231976 with maximum zoom in of 20 and minimum zoom in of 0 i.e. whole world zoom, and store images in folder called image_folder
11
9
 
10
+ ## Features
12
11
 
13
- mapcache_download --lat1=58.5500977 --lng1=-4.5231876 --lat2=58.5501 --lng2=-4.5231976 --zin=20 --zout=0 --folder=./image_folder
12
+ - **Supported Providers**: OpenStreetMap (OSM), Mapbox Satellite, and Mapbox Terrain RGB (for elevation data).
13
+ - **Unified PNG Format**: All tiles are saved as PNG, with Mapbox Satellite tiles converted from JPG for consistency.
14
+ - **Parallel Downloads**: Configurable concurrency to optimize speed while respecting provider rate limits.
15
+ - **Retry Mechanism**: Automatically retries failed downloads (default: 3 attempts) with exponential backoff.
16
+ - **Progress Tracking**: Displays real-time progress with percentage completion.
17
+ - **File Management**: Skips existing files unless `--force` is used, with automatic output folder creation.
18
+ - **Flexible Zoom**: Download tiles for a range of zoom levels (min `--zout` to max `--zin`).
19
+ - **Integration**: Outputs tiles compatible with 3D mapping projects (e.g., Three.js terrain rendering) and Leaflet-based map servers.
14
20
 
15
- ## Map Providers
21
+ ## Installation
22
+
23
+ 1. Clone the repository:
24
+ ```bash
25
+ git clone https://github.com/HefnySco/mapcache.git
26
+ cd mapcache
27
+ ```
28
+
29
+ 2. Install dependencies:
30
+ ```bash
31
+ npm install
32
+ ```
33
+ Note: The `sharp` library is required for JPG-to-PNG conversion. Ensure system dependencies are installed:
34
+ - Ubuntu/Debian: `sudo apt-get install libvips-dev`
35
+ - macOS: `brew install libvips`
36
+
37
+ ## Usage
38
+
39
+ Download map tiles for a geographic area defined by two coordinates (`lat1,lng1` to `lat2,lng2`), a zoom range, and an output folder. Run the script with:
40
+
41
+ ```bash
42
+ node mapcache_download.js --lat1=<lat> --lng1=<lng> --lat2=<lat> --lng2=<lng> --zin=<max_zoom> --folder=<output_folder> [options]
43
+ ```
16
44
 
17
- The application supports [openstreetmap.org](https://www.openstreetmap.org/#map=7/26.805/30.246 "openstreetmap.org")
45
+ ### Example: Download OSM Tiles
46
+ Download OpenStreetMap tiles for a small area with zoom levels 0 to 14:
47
+ ```bash
48
+ node mapcache_download.js --lat1=40.7128 --lng1=-74.0060 --lat2=40.7228 --lng2=-73.9960 --zin=14 --zout=0 --folder=./site/cachedMaps
49
+ ```
18
50
 
51
+ ### Example: Download Mapbox Satellite Tiles
52
+ Download Mapbox satellite tiles (saved as PNG, requires a Mapbox access token):
19
53
  ```bash
20
- mapcache_download --lat1=58.5500977 --lng1=-4.5231876 --lat2=58.5501 --lng2=-4.5231976 --zin=20 --folder=./out
54
+ node mapcache_download.js --lat1=40.7128 --lng1=-74.0060 --lat2=40.7228 --lng2=-73.9960 --zin=14 --folder=./site/cachedMaps --provider=1 --token=pk.eyJ1IjoibWhlZm55IiwiYSI6ImNrZW84Nm9rYTA2ZWgycm9mdmNscmFxYzcifQ.c-zxDjXCthXmRsErPzKhbQ
55
+ ```
21
56
 
57
+ ### Example: Download Mapbox Terrain RGB Tiles
58
+ Download Mapbox terrain RGB tiles for elevation data:
59
+ ```bash
60
+ node mapcache_download.js --lat1=40.7128 --lng1=-74.0060 --lat2=40.7228 --lng2=-73.9960 --zin=14 --folder=./site/cachedMaps --provider=2 --token=pk.eyJ1IjoibWhlZm55IiwiYSI6ImNrZW84Nm9rYTA2ZWgycm9mdmNscmFxYzcifQ.c-zxDjXCthXmRsErPzKhbQ
22
61
  ```
23
62
 
24
- and [api.mapbox.com](https://api.mapbox.com "api.mapbox.com"). You need to have a **TOKEN** for using [api.mapbox.com](https://api.mapbox.com "api.mapbox.com").
63
+ ### Options
64
+ - `--lat1, --lng1`: Starting coordinates (required).
65
+ - `--lat2, --lng2`: Ending coordinates (required).
66
+ - `--zin`: Maximum zoom level (required, e.g., 18).
67
+ - `--zout`: Minimum zoom level (default: 0).
68
+ - `--folder`: Output folder for tiles (required, e.g., `./site/cachedMaps`).
69
+ - `--provider`: Map provider (0=OSM, 1=Mapbox Satellite, 2=Mapbox Terrain RGB; default: 0).
70
+ - `--token`: Mapbox access token (required for provider 1 or 2).
71
+ - `--concurrency`: Number of parallel downloads (default: 5).
72
+ - `--retries`: Retry attempts for failed downloads (default: 3).
73
+ - `--force`: Redownload existing files (default: false).
74
+ - `--help, -h`: Display help message.
75
+ - `--version, -v`: Display script version.
76
+
77
+ ## Serving Tiles Locally
78
+
79
+ Use a local HTTP server to serve downloaded tiles for testing with Leaflet or other map libraries:
25
80
 
26
81
  ```bash
27
- mapcache_download --lat1=58.5500977 --lng1=-4.5231876 --lat2=58.5501 --lng2=-4.5231976 --zin=20 --folder=./out --provider=1 --token=pk.eyJ1IjoibSahlZm59IiwiYSI6ImNrZW84Nm9rYTA2ZWgycv9mdmNscmFxYzcifQ.c-z43FdasErPzKhbQ
82
+ cd site
83
+ npm install -g http-server
84
+ http-server
28
85
  ```
29
86
 
30
- ## Sample
87
+ Access the tiles at `http://localhost:8080/cachedMaps`. The folder `./site/cachedMaps` contains tiles named as:
88
+ - OSM: `osm_<x>_<y>_<zoom>.png`
89
+ - Mapbox Satellite: `sat_<x>_<y>_<zoom>.png`
90
+ - Mapbox Terrain RGB: `terrain_<x>_<y>_<zoom>.png`
91
+
92
+ ## Integration with 3D Mapping Projects
31
93
 
32
- folder ./site contains a folder called **cachedMaps** you can put your maps into it and browse them.
94
+ The downloaded tiles are saved as PNG, compatible with 3D mapping applications like Three.js for terrain rendering. For example, Mapbox terrain RGB tiles can be used to generate heightmaps:
33
95
 
96
+ ```javascript
97
+ const terrainData = await textureLoader.loadAsync('terrain_<x>_<y>_<zoom>.png');
98
+ const data = getPixelData(terrainData); // Extract RGB values
99
+ const height = -10000 + ((r * 65536 + g * 256 + b) * 0.1); // Mapbox terrain RGB formula
100
+ ```
34
101
 
102
+ Ensure the output folder matches your project's tile cache directory, and use the same zoom levels (e.g., 14) for consistency with your rendering logic.
103
+
104
+ ## Map Providers
35
105
 
36
- cd ./site
37
- http-server .
38
-
106
+ - **OpenStreetMap (OSM)**: Free, no token required. Tiles are natively PNG. [Website](https://www.openstreetmap.org/).
107
+ - **Mapbox Satellite**: High-quality satellite imagery, converted from JPG to PNG for consistency. Requires a Mapbox access token. [Website](https://api.mapbox.com/).
108
+ - **Mapbox Terrain RGB**: Elevation data encoded in RGB PNG tiles. Requires a Mapbox access token. [Website](https://docs.mapbox.com/data/tilesets/reference/mapbox-terrain-rgb-v1/).
39
109
 
110
+ Obtain a Mapbox token from [Mapbox Account](https://account.mapbox.com/).
40
111
 
112
+ ## Notes
41
113
 
114
+ - **Rate Limits**: Mapbox enforces rate limits (e.g., 750 requests/min for satellite, 200 for terrain RGB on free tiers). Adjust `--concurrency` to avoid being throttled.
115
+ - **File Overwrites**: Use `--force=true` to redownload tiles if they are outdated or corrupted.
116
+ - **File Size**: Mapbox Satellite tiles are converted to PNG, which may increase file size compared to JPG. Consider disk space for large areas.
117
+ - **Tile Validation**: For critical applications, validate PNG tiles post-download to ensure integrity (e.g., using `sharp` metadata).
42
118
 
43
- ### Disclaimer
44
- Please make sure to review any terms and conditions of map providers you want to use. Author assumes no liability for any incidental, consequential or other liability from the use of this product.
45
119
 
120
+ ## Disclaimer
46
121
 
122
+ Please review the terms and conditions of your chosen map provider (e.g., [OpenStreetMap](https://www.openstreetmap.org/copyright), [Mapbox](https://www.mapbox.com/tos)). The author assumes no liability for any incidental, consequential, or other damages arising from the use of this tool.
@@ -0,0 +1,325 @@
1
+ /*
2
+ Enhanced Map Tile Downloader with Terrain Support and Single Extension
3
+ - Downloads map tiles (satellite or terrain RGB) for a given geographic bounding box and zoom range.
4
+ - Saves all tiles as PNG for consistency, converting Mapbox Satellite tiles from JPG to PNG.
5
+ - Supports OpenStreetMap (default) and Mapbox (with token) for satellite and terrain RGB tiles.
6
+ - Parallel downloads with configurable concurrency to respect rate limits.
7
+ - Retry mechanism for failed downloads.
8
+ - Creates output folder if it doesn't exist.
9
+ - Progress reporting with total count and completion percentage.
10
+ - Better input validation and default values.
11
+ - Force redownload option.
12
+ - Improved error handling and logging.
13
+
14
+ Usage: node mapcache_download.js --lat1=<lat> --lng1=<lng> --lat2=<lat> --lng2=<lng> --zin=<max_zoom> [options]
15
+
16
+ Run with --help for full options.
17
+ */
18
+ "use strict";
19
+
20
+ const fs = require("fs");
21
+ const path = require("path");
22
+ const axios = require("axios");
23
+ const sharp = require("sharp"); // Added for JPG-to-PNG conversion
24
+ const v_pjson = require("../package.json"); // Assuming this exists; otherwise, hardcode version.
25
+ const c_args = require("../helpers/hlp_args.js"); // Assuming this provides getArgs().
26
+ const c_colors = require("../helpers/js_colors.js").Colors; // Assuming this provides color codes.
27
+
28
+ const EARTH_RADIUS = 6378137;
29
+ const MAX_LATITUDE = 85.0511287798;
30
+ const R_MINOR = 6356752.314245179; // Not used, but kept for completeness.
31
+
32
+ // Default values
33
+ const DEFAULT_PROVIDER = 0; // 0: OSM, 1: Mapbox Satellite, 2: Mapbox Terrain RGB
34
+ const DEFAULT_CONCURRENCY = 5; // Safe default to avoid rate limits
35
+ const DEFAULT_RETRIES = 3;
36
+ const DEFAULT_ZOUT = 0;
37
+ const DEFAULT_FORCE = false;
38
+
39
+ // Global variables
40
+ let map_provider = DEFAULT_PROVIDER;
41
+ let TOKEN = ""; // Required for Mapbox
42
+ let myArgs = c_args.getArgs();
43
+ let totalTiles = 0;
44
+ let downloadedTiles = 0;
45
+
46
+ /*
47
+ * Projection functions (unchanged)
48
+ */
49
+ function project(p_lat, p_lng) {
50
+ const d = Math.PI / 180,
51
+ max = MAX_LATITUDE,
52
+ lat = Math.max(Math.min(max, p_lat), -max),
53
+ sin = Math.sin(lat * d);
54
+
55
+ return {
56
+ x: EARTH_RADIUS * p_lng * d,
57
+ y: (EARTH_RADIUS * Math.log((1 + sin) / (1 - sin))) / 2,
58
+ };
59
+ }
60
+
61
+ function unproject(point) {
62
+ const d = 180 / Math.PI;
63
+
64
+ return {
65
+ lat: (2 * Math.atan(Math.exp(point.y / EARTH_RADIUS)) - Math.PI / 2) * d,
66
+ lng: (point.x * d) / EARTH_RADIUS,
67
+ };
68
+ }
69
+
70
+ function zoomScale(zoom) {
71
+ return 256 * Math.pow(2, zoom);
72
+ }
73
+
74
+ function transform(point, scale) {
75
+ scale = scale || 1;
76
+ point.x = scale * (2.495320233665337e-8 * point.x + 0.5);
77
+ point.y = scale * (-2.495320233665337e-8 * point.y + 0.5);
78
+ return point;
79
+ }
80
+
81
+ function fn_convertFromLngLatToPoints(lat1, lng1, lat2, lng2, zoom) {
82
+ // Normalize bounds
83
+ if (lng1 > lng2) [lng1, lng2] = [lng2, lng1];
84
+ if (lat1 > lat2) [lat1, lat2] = [lat2, lat1];
85
+
86
+ let point1 = project(lat1, lng1);
87
+ let point2 = project(lat2, lng2);
88
+
89
+ let scaledZoom = zoomScale(zoom);
90
+ point1 = transform(point1, scaledZoom);
91
+ point2 = transform(point2, scaledZoom);
92
+
93
+ // Floor to tile indices
94
+ point1.x = Math.floor(point1.x / 256);
95
+ point1.y = Math.floor(point1.y / 256);
96
+ point2.x = Math.floor(point2.x / 256);
97
+ point2.y = Math.floor(point2.y / 256);
98
+
99
+ // Ensure point1 is top-left, point2 bottom-right
100
+ if (point1.y > point2.y) [point1.y, point2.y] = [point2.y, point1.y];
101
+
102
+ return [point1, point2];
103
+ }
104
+
105
+ /* ============================================================
106
+ Enhanced Download Function with Retry
107
+ ============================================================ */
108
+
109
+ const download_image = async (url, image_path, isMapboxSatellite = false, retries = myArgs.retries || DEFAULT_RETRIES) => {
110
+ for (let attempt = 1; attempt <= retries; attempt++) {
111
+ try {
112
+ const response = await axios({
113
+ url,
114
+ responseType: "arraybuffer", // Changed to arraybuffer for sharp compatibility
115
+ timeout: 10000, // 10s timeout
116
+ });
117
+
118
+ // Convert to PNG if Mapbox Satellite (JPG), otherwise save directly
119
+ const buffer = isMapboxSatellite
120
+ ? await sharp(response.data).png().toBuffer()
121
+ : response.data;
122
+
123
+ await fs.promises.writeFile(image_path, buffer);
124
+ return; // Success
125
+ } catch (error) {
126
+ console.log(c_colors.BError + `Attempt ${attempt} failed for ${url}: ${error.message}` + c_colors.Reset);
127
+ if (attempt === retries) {
128
+ throw error; // Final failure
129
+ }
130
+ await new Promise(resolve => setTimeout(resolve, 1000 * attempt)); // Exponential backoff
131
+ }
132
+ }
133
+ };
134
+
135
+ /* ============================================================
136
+ Generate Tile URL and Filename
137
+ ============================================================ */
138
+
139
+ function getTileUrlAndFilename(i, j, zoom) {
140
+ let url, typePrefix, isMapboxSatellite = false;
141
+ if (map_provider === 1) {
142
+ // Mapbox Satellite
143
+ url = `https://api.mapbox.com/styles/v1/mapbox/satellite-v9/tiles/${zoom}/${i}/${j}?access_token=${TOKEN}`;
144
+ typePrefix = "sat";
145
+ isMapboxSatellite = true;
146
+ } else if (map_provider === 2) {
147
+ // Mapbox Terrain RGB
148
+ url = `https://api.mapbox.com/v4/mapbox.terrain-rgb/${zoom}/${i}/${j}.png?access_token=${TOKEN}`;
149
+ typePrefix = "terrain";
150
+ } else {
151
+ // OpenStreetMap
152
+ url = `https://tile.openstreetmap.org/${zoom}/${i}/${j}.png`;
153
+ typePrefix = "osm";
154
+ }
155
+ const filename = `${typePrefix}_${i}_${j}_${zoom}.png`; // Always PNG
156
+ return { url, filename, isMapboxSatellite };
157
+ }
158
+
159
+ /* ============================================================
160
+ Download Tiles for a Zoom Level (Parallel with Concurrency)
161
+ ============================================================ */
162
+
163
+ async function fn_download_tiles_for_zoom(point1, point2, zoom, folder, force) {
164
+ const tiles = [];
165
+ for (let i = point1.x; i <= point2.x; i++) {
166
+ for (let j = point1.y; j <= point2.y; j++) {
167
+ tiles.push({ i, j });
168
+ }
169
+ }
170
+
171
+ totalTiles += tiles.length;
172
+ console.log(c_colors.BSuccess + `Queueing ${tiles.length} tiles for zoom ${zoom}...` + c_colors.Reset);
173
+
174
+ // Process in batches to limit concurrency
175
+ const concurrency = myArgs.concurrency || DEFAULT_CONCURRENCY;
176
+ for (let batchStart = 0; batchStart < tiles.length; batchStart += concurrency) {
177
+ const batch = tiles.slice(batchStart, batchStart + concurrency);
178
+ await Promise.all(
179
+ batch.map(async ({ i, j }) => {
180
+ const { url, filename, isMapboxSatellite } = getTileUrlAndFilename(i, j, zoom);
181
+ const image_path = path.join(folder, filename);
182
+
183
+ if (!force && fs.existsSync(image_path)) {
184
+ console.log(c_colors.FgCyan + `Skipping existing: ${filename}` + c_colors.Reset);
185
+ downloadedTiles++;
186
+ updateProgress();
187
+ return;
188
+ }
189
+
190
+ try {
191
+ await download_image(url, image_path, isMapboxSatellite);
192
+ console.log(c_colors.BSuccess + `Downloaded: ${filename}` + c_colors.Reset);
193
+ } catch (error) {
194
+ console.error(c_colors.BError + `Failed to download ${filename} after retries.` + c_colors.Reset);
195
+ } finally {
196
+ downloadedTiles++;
197
+ updateProgress();
198
+ }
199
+ })
200
+ );
201
+ }
202
+ }
203
+
204
+ /* ============================================================
205
+ Progress Updater
206
+ ============================================================ */
207
+
208
+ function updateProgress() {
209
+ const progress = ((downloadedTiles / totalTiles) * 100).toFixed(2);
210
+ console.log(c_colors.FgYellow + `Progress: ${downloadedTiles}/${totalTiles} (${progress}%)` + c_colors.Reset);
211
+ }
212
+
213
+ /* ============================================================
214
+ Input Validation and Argument Handling
215
+ ============================================================ */
216
+
217
+ function fn_handle_arguments() {
218
+ myArgs = c_args.getArgs();
219
+ let error = false;
220
+
221
+ if (myArgs.help || myArgs.h || myArgs.version || myArgs.v) {
222
+ console.log(
223
+ c_colors.BSuccess +
224
+ "MAP Tile Downloader v" +
225
+ c_colors.FgYellow +
226
+ (v_pjson.version || "1.0.0") +
227
+ c_colors.Reset
228
+ );
229
+ console.log(c_colors.BSuccess + "Usage: node mapcache_download.js --lat1=<lat> --lng1=<lng> --lat2=<lat> --lng2=<lng> --zin=<max_zoom> [options]" + c_colors.Reset);
230
+ console.log(c_colors.BSuccess + "--lat1, --lng1: Start coordinates (required)" + c_colors.Reset);
231
+ console.log(c_colors.BSuccess + "--lat2, --lng2: End coordinates (required)" + c_colors.Reset);
232
+ console.log(c_colors.BSuccess + "--zout: Min zoom (default: 0)" + c_colors.Reset);
233
+ console.log(c_colors.BSuccess + "--zin: Max zoom (required, e.g., 18)" + c_colors.Reset);
234
+ console.log(c_colors.BSuccess + "--folder: Output folder (required, e.g., ./out)" + c_colors.Reset);
235
+ console.log(c_colors.BSuccess + "--provider: 0=OSM (default), 1=Mapbox Satellite, 2=Mapbox Terrain RGB" + c_colors.Reset);
236
+ console.log(c_colors.BSuccess + "--token: Mapbox access token (required if provider=1 or 2)" + c_colors.Reset);
237
+ console.log(c_colors.BSuccess + "--concurrency: Parallel downloads (default: 5)" + c_colors.Reset);
238
+ console.log(c_colors.BSuccess + "--retries: Retry attempts per tile (default: 3)" + c_colors.Reset);
239
+ console.log(c_colors.BSuccess + "--force: Redownload existing files (default: false)" + c_colors.Reset);
240
+ process.exit(0);
241
+ }
242
+
243
+ // Required args
244
+ ["lat1", "lng1", "lat2", "lng2", "zin", "folder"].forEach(arg => {
245
+ if (!myArgs[arg]) {
246
+ error = true;
247
+ console.log(c_colors.BError + `Missing required argument: --${arg}` + c_colors.Reset);
248
+ }
249
+ });
250
+
251
+ // Validate lat/lng
252
+ ["lat1", "lat2"].forEach(arg => {
253
+ if (myArgs[arg] && (myArgs[arg] < -90 || myArgs[arg] > 90)) {
254
+ error = true;
255
+ console.log(c_colors.BError + `Invalid latitude ${arg}: ${myArgs[arg]} (must be -90 to 90)` + c_colors.Reset);
256
+ }
257
+ });
258
+ ["lng1", "lng2"].forEach(arg => {
259
+ if (myArgs[arg] && (myArgs[arg] < -180 || myArgs[arg] > 180)) {
260
+ error = true;
261
+ console.log(c_colors.BError + `Invalid longitude ${arg}: ${myArgs[arg]} (must be -180 to 180)` + c_colors.Reset);
262
+ }
263
+ });
264
+
265
+ // Provider and token
266
+ map_provider = myArgs.provider ? parseInt(myArgs.provider) : DEFAULT_PROVIDER;
267
+ if (map_provider === 1 || map_provider === 2) {
268
+ TOKEN = myArgs.token;
269
+ if (!TOKEN) {
270
+ error = true;
271
+ console.log(c_colors.BError + "Missing --token for Mapbox provider (satellite or terrain)." + c_colors.Reset);
272
+ }
273
+ }
274
+
275
+ // Zooms
276
+ myArgs.zout = myArgs.zout ? parseInt(myArgs.zout) : DEFAULT_ZOUT;
277
+ myArgs.zin = parseInt(myArgs.zin);
278
+ if (myArgs.zout > myArgs.zin || myArgs.zout < 0 || myArgs.zin > 22) {
279
+ error = true;
280
+ console.log(c_colors.BError + "Invalid zoom range: zout <= zin, 0-22." + c_colors.Reset);
281
+ }
282
+
283
+ // Force
284
+ myArgs.force = myArgs.force === "true" || myArgs.force === true ? true : DEFAULT_FORCE;
285
+
286
+ if (error) process.exit(1);
287
+
288
+ // Create folder if needed
289
+ const folder = myArgs.folder;
290
+ if (!fs.existsSync(folder)) {
291
+ fs.mkdirSync(folder, { recursive: true });
292
+ console.log(c_colors.BSuccess + `Created output folder: ${folder}` + c_colors.Reset);
293
+ }
294
+ }
295
+
296
+ /* ============================================================
297
+ Main Execution
298
+ ============================================================ */
299
+
300
+ async function main() {
301
+ fn_handle_arguments();
302
+ const folder = myArgs.folder;
303
+ const force = myArgs.force;
304
+
305
+ // Calculate total tiles across all zooms for progress
306
+ for (let zoom = myArgs.zout; zoom <= myArgs.zin; zoom++) {
307
+ const [point1, point2] = fn_convertFromLngLatToPoints(myArgs.lat1, myArgs.lng1, myArgs.lat2, myArgs.lng2, zoom);
308
+ totalTiles += (point2.x - point1.x + 1) * (point2.y - point1.y + 1);
309
+ }
310
+
311
+ console.log(c_colors.BSuccess + `Total tiles to process: ${totalTiles}` + c_colors.Reset);
312
+
313
+ // Download per zoom
314
+ for (let zoom = myArgs.zout; zoom <= myArgs.zin; zoom++) {
315
+ const [point1, point2] = fn_convertFromLngLatToPoints(myArgs.lat1, myArgs.lng1, myArgs.lat2, myArgs.lng2, zoom);
316
+ await fn_download_tiles_for_zoom(point1, point2, zoom, folder, force);
317
+ }
318
+
319
+ console.log(c_colors.BSuccess + "Download complete!" + c_colors.Reset);
320
+ }
321
+
322
+ main().catch(error => {
323
+ console.error(c_colors.BError + `Unexpected error: ${error.message}` + c_colors.Reset);
324
+ process.exit(1);
325
+ });
package/package.json CHANGED
@@ -1,24 +1,52 @@
1
1
  {
2
2
  "name": "mapcachetools",
3
- "version": "1.0.7",
4
- "description": "This tool downloads images from a map provider and cache it locally on your device. Please check terms and condition of your map provider. The tool is provided as is with no responsibility from author. Please Use IT AT YOUR OWN RISK.",
5
- "main": "downloadmaps.js",
6
- "scripts": {
7
- "start": "node ./bin/downloadmaps.js"
8
- },
3
+ "version": "2.2.0",
4
+ "description": "A Node.js tool to download and cache map tiles (OSM, Mapbox Satellite, Mapbox Terrain RGB) as PNG images for offline use in mapping applications. Use at your own risk and comply with provider terms.",
5
+ "main": "bin/mapcache_download.js",
9
6
  "bin": {
10
- "mapcache_download": "mapcache_download.js"
7
+ "mapcache-download": "./bin/mapcache_download.js"
8
+ },
9
+ "scripts": {
10
+ "start": "node ./bin/mapcache_download.js",
11
+ "test": "jest",
12
+ "prepublishOnly": "npm test"
11
13
  },
12
14
  "keywords": [
13
15
  "map",
14
- "local server",
15
- "cache"
16
+ "tile",
17
+ "cache",
18
+ "openstreetmap",
19
+ "mapbox",
20
+ "terrain",
21
+ "offline",
22
+ "leaflet",
23
+ "threejs"
16
24
  ],
17
25
  "homepage": "https://github.com/HefnySco/mapcache",
18
- "author": "Mohammad Said Hefny - rcmobilestuff <rcmobilestuff@gmail.com> (http://www.andruav.com)",
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "git+https://github.com/HefnySco/mapcache.git"
29
+ },
30
+ "bugs": {
31
+ "url": "https://github.com/HefnySco/mapcache/issues"
32
+ },
33
+ "author": "Mohammad Said Hefny <rcmobilestuff@gmail.com> (http://www.andruav.com)",
19
34
  "license": "ISC",
20
35
  "dependencies": {
21
- "axios": "^0.21.1",
22
- "request": "^2.88.2"
23
- }
36
+ "axios": "^1.7.7",
37
+ "sharp": "^0.34.0"
38
+ },
39
+ "devDependencies": {
40
+ "eslint": "^8.57.0",
41
+ "jest": "^30.2.0"
42
+ },
43
+ "engines": {
44
+ "node": ">=14.0.0"
45
+ },
46
+ "files": [
47
+ "bin",
48
+ "helpers",
49
+ "README.md",
50
+ "LICENSE"
51
+ ]
24
52
  }
package/REALKEY.txt DELETED
@@ -1 +0,0 @@
1
- const TOKEN = "pk.eyJ1IjoiaHNhYWQiLCJhIjoiY2tqZnIwNXRuMndvdTJ4cnV0ODQ4djZ3NiJ9.LKojA3YMrG34L93jRThEGQ"