@basemaps/cli-raster 8.0.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.
Files changed (73) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +70 -0
  3. package/build/bin.d.ts +1 -0
  4. package/build/bin.js +16 -0
  5. package/build/bin.js.map +1 -0
  6. package/build/cogify/__test__/covering.test.d.ts +1 -0
  7. package/build/cogify/__test__/covering.test.js +64 -0
  8. package/build/cogify/__test__/covering.test.js.map +1 -0
  9. package/build/cogify/__test__/extract.test.d.ts +1 -0
  10. package/build/cogify/__test__/extract.test.js +34 -0
  11. package/build/cogify/__test__/extract.test.js.map +1 -0
  12. package/build/cogify/cli/__test__/cli.cover.test.d.ts +1 -0
  13. package/build/cogify/cli/__test__/cli.cover.test.js +48 -0
  14. package/build/cogify/cli/__test__/cli.cover.test.js.map +1 -0
  15. package/build/cogify/cli/__test__/cli.topo.test.d.ts +1 -0
  16. package/build/cogify/cli/__test__/cli.topo.test.js +53 -0
  17. package/build/cogify/cli/__test__/cli.topo.test.js.map +1 -0
  18. package/build/cogify/cli/cli.cog.d.ts +55 -0
  19. package/build/cogify/cli/cli.cog.js +353 -0
  20. package/build/cogify/cli/cli.cog.js.map +1 -0
  21. package/build/cogify/cli/cli.cover.d.ts +30 -0
  22. package/build/cogify/cli/cli.cover.js +157 -0
  23. package/build/cogify/cli/cli.cover.js.map +1 -0
  24. package/build/cogify/cli/cli.topo.d.ts +50 -0
  25. package/build/cogify/cli/cli.topo.js +169 -0
  26. package/build/cogify/cli/cli.topo.js.map +1 -0
  27. package/build/cogify/cli/cli.validate.d.ts +15 -0
  28. package/build/cogify/cli/cli.validate.js +30 -0
  29. package/build/cogify/cli/cli.validate.js.map +1 -0
  30. package/build/cogify/cli.d.ts +121 -0
  31. package/build/cogify/cli.js +15 -0
  32. package/build/cogify/cli.js.map +1 -0
  33. package/build/cogify/covering/covering.d.ts +28 -0
  34. package/build/cogify/covering/covering.js +126 -0
  35. package/build/cogify/covering/covering.js.map +1 -0
  36. package/build/cogify/covering/cutline.d.ts +29 -0
  37. package/build/cogify/covering/cutline.js +109 -0
  38. package/build/cogify/covering/cutline.js.map +1 -0
  39. package/build/cogify/covering/tile.cover.d.ts +38 -0
  40. package/build/cogify/covering/tile.cover.js +198 -0
  41. package/build/cogify/covering/tile.cover.js.map +1 -0
  42. package/build/cogify/gdal/gdal.command.d.ts +27 -0
  43. package/build/cogify/gdal/gdal.command.js +175 -0
  44. package/build/cogify/gdal/gdal.command.js.map +1 -0
  45. package/build/cogify/gdal/gdal.runner.d.ts +42 -0
  46. package/build/cogify/gdal/gdal.runner.js +194 -0
  47. package/build/cogify/gdal/gdal.runner.js.map +1 -0
  48. package/build/cogify/stac.d.ts +138 -0
  49. package/build/cogify/stac.js +25 -0
  50. package/build/cogify/stac.js.map +1 -0
  51. package/build/cogify/topo/extract.d.ts +82 -0
  52. package/build/cogify/topo/extract.js +195 -0
  53. package/build/cogify/topo/extract.js.map +1 -0
  54. package/build/cogify/topo/slug.d.ts +10 -0
  55. package/build/cogify/topo/slug.js +18 -0
  56. package/build/cogify/topo/slug.js.map +1 -0
  57. package/build/cogify/topo/stac.creation.d.ts +47 -0
  58. package/build/cogify/topo/stac.creation.js +171 -0
  59. package/build/cogify/topo/stac.creation.js.map +1 -0
  60. package/build/download.d.ts +57 -0
  61. package/build/download.js +144 -0
  62. package/build/download.js.map +1 -0
  63. package/build/hash.stream.d.ts +20 -0
  64. package/build/hash.stream.js +62 -0
  65. package/build/hash.stream.js.map +1 -0
  66. package/build/index.d.ts +1 -0
  67. package/build/index.js +2 -0
  68. package/build/index.js.map +1 -0
  69. package/build/preset.d.ts +15 -0
  70. package/build/preset.js +66 -0
  71. package/build/preset.js.map +1 -0
  72. package/dist/index.cjs +85880 -0
  73. package/package.json +61 -0
@@ -0,0 +1,169 @@
1
+ import { loadTiffsFromPaths } from '@basemaps/config-loader/build/json/tiff.config.js';
2
+ import { Bounds } from '@basemaps/geo';
3
+ import { fsa } from '@basemaps/shared';
4
+ import { getLogger, isArgo, logArguments, Url, UrlFolder } from '@basemaps/shared';
5
+ import { CliInfo } from '@basemaps/shared/build/cli/info.js';
6
+ import { boolean, command, flag, option, optional, restPositionals, string } from 'cmd-ts';
7
+ import pLimit from 'p-limit';
8
+ import { brokenTiffs, extractLatestTiffItemsByMapCode, extractTiffItemsByEpsg } from '../topo/extract.js';
9
+ import { mapEpsgToSlug } from '../topo/slug.js';
10
+ import { createStacCollection, createStacItems, writeStacFiles } from '../topo/stac.creation.js';
11
+ const Q = pLimit(10);
12
+ const MapSeriesTitle = {
13
+ topo50: 'Raster Topographic Maps 50k',
14
+ topo250: 'Raster Topographic Maps 250k',
15
+ };
16
+ /**
17
+ * Parses a source path directory topographic maps tiffs and writes out a directory structure
18
+ * of StacItem and StacCollection files to the target path.
19
+ *
20
+ * @param source: Location of the source files
21
+ * @example s3://linz-topographic-upload/topographic/TopoReleaseArchive/NZTopo50_GeoTif_Gridless/
22
+ *
23
+ * @param target: Location of the target path
24
+ */
25
+ export const TopoStacCreationCommand = command({
26
+ name: 'cogify-topo-stac',
27
+ version: CliInfo.version,
28
+ description: 'List input topographic map files, create StacItems, and generate tiles for grouping.',
29
+ args: {
30
+ ...logArguments,
31
+ title: option({
32
+ type: optional(string),
33
+ long: 'title',
34
+ description: 'Imported imagery title, default is created from map series',
35
+ }),
36
+ target: option({
37
+ type: UrlFolder,
38
+ long: 'target',
39
+ description: 'Target location for the output files',
40
+ }),
41
+ mapSeries: option({
42
+ type: string,
43
+ long: 'map-series',
44
+ description: 'Map series name, topo50, or topo250',
45
+ }),
46
+ latestOnly: flag({
47
+ type: boolean,
48
+ defaultValue: () => false,
49
+ long: 'latest-only',
50
+ description: 'Only process the latest version of each map sheet',
51
+ defaultValueIsSerializable: true,
52
+ }),
53
+ output: option({
54
+ type: optional(Url),
55
+ description: 'Output informational assets to specific location',
56
+ long: 'output',
57
+ }),
58
+ paths: restPositionals({
59
+ type: UrlFolder,
60
+ description: 'Location of the source files',
61
+ }),
62
+ },
63
+ async handler(args) {
64
+ const logger = getLogger(this, args, 'cli-raster');
65
+ const startTime = performance.now();
66
+ logger.info('TopoCogify:Start');
67
+ const title = args.title ?? MapSeriesTitle[args.mapSeries];
68
+ if (title == null) {
69
+ throw new Error('--title must be defined if map series is not one of :' + Object.keys(MapSeriesTitle).join(', '));
70
+ }
71
+ const ctx = {
72
+ latestOnly: args.latestOnly,
73
+ paths: args.paths,
74
+ target: args.target,
75
+ title,
76
+ mapSeries: args.mapSeries,
77
+ output: args.output,
78
+ logger,
79
+ };
80
+ const { epsgDirectoryPaths, stacItemPaths } = await loadTiffsToCreateStacs(ctx);
81
+ if (epsgDirectoryPaths.length === 0 || stacItemPaths.length === 0)
82
+ throw new Error('No Stac items created');
83
+ // write stac items into an JSON array
84
+ if (args.output || isArgo()) {
85
+ const targetUrl = args.output ?? fsa.toUrl('/tmp/topo-stac-creation/');
86
+ // for create-config: we need to tell create-config to create a bundled config for each epsg folder (latest only).
87
+ // workflow: will loop 'targets.json' and create a node for each path where each node's job is to create a bundled config.
88
+ await fsa.write(new URL('targets.json', targetUrl), JSON.stringify(epsgDirectoryPaths, null, 2));
89
+ // tiles.json makes the tiff files
90
+ await fsa.write(new URL('tiles.json', targetUrl), JSON.stringify(stacItemPaths.map((m) => ({ path: m })), null, 2));
91
+ await fsa.write(new URL('broken-tiffs.json', targetUrl), JSON.stringify(brokenTiffs, null, 2));
92
+ }
93
+ logger.info({ duration: performance.now() - startTime }, 'TopoCogify:Done');
94
+ },
95
+ });
96
+ /**
97
+ * @param source: Source directory URL from which to load tiff files
98
+ *
99
+ * @param target: Destination directory URL into which to save the STAC collection and item JSON files
100
+ *
101
+ * @param title: The title of the collection
102
+ * @example "New Zealand Topo50 Map Series (Gridless)"
103
+ *
104
+ * @returns an array of StacItem objects
105
+ */
106
+ async function loadTiffsToCreateStacs(ctx) {
107
+ const logger = ctx.logger;
108
+ const source = ctx.paths;
109
+ const target = ctx.target;
110
+ logger?.info({ source }, 'LoadTiffs:Start');
111
+ // extract all file paths from the source directory and convert them into URLs
112
+ const fileUrls = [];
113
+ for (const sourcePath of ctx.paths) {
114
+ for await (const path of fsa.list(sourcePath)) {
115
+ fileUrls.push(path);
116
+ }
117
+ }
118
+ // process all of the URLs into Tiffs
119
+ const tiffs = await loadTiffsFromPaths(fileUrls, Q);
120
+ if (tiffs.length === 0)
121
+ throw new Error('No TIFF files found in locations : ' + source.map((m) => m.href).join(', '));
122
+ logger.info({ count: tiffs.length, hrefs: source.map((m) => m.href) }, 'LoadTiffs:End');
123
+ logger.info('ExtractTiffs:Start');
124
+ const allTiffItems = extractTiffItemsByEpsg(tiffs, logger);
125
+ logger.info({ foundEpsgs: [...allTiffItems.keys()] }, 'ExtractTiffs:End');
126
+ const epsgDirectoryPaths = [];
127
+ const stacItemPaths = [];
128
+ // create and write stac items and collections
129
+ const scale = ctx.mapSeries;
130
+ // TODO: resolution is defined from the GSD over the map scale,
131
+ // and can be extracted in the future if we want to process higher resolution maps
132
+ const resolution = 'gridless_600dpi';
133
+ for (const [epsg, tiffItems] of allTiffItems.entries()) {
134
+ logger?.info({ epsg }, 'CreateStacFiles:Start');
135
+ // identify latest tiff items
136
+ const latestTiffItems = extractLatestTiffItemsByMapCode(tiffItems);
137
+ // create stac items
138
+ const stacItems = createStacItems(scale, resolution, tiffItems, latestTiffItems, logger);
139
+ // convert epsg to slug
140
+ const epsgSlug = mapEpsgToSlug(epsg.code);
141
+ if (epsgSlug == null)
142
+ throw new Error(`Failed to map epsg code '${epsg.code}' to a slug`);
143
+ const linzSlug = `${scale}-${epsgSlug}`;
144
+ // extract bounds
145
+ const allBounds = tiffItems.map((item) => item.bounds);
146
+ const latestBounds = Array.from(latestTiffItems.values()).map((item) => item.bounds);
147
+ // create stac collections
148
+ const title = ctx.title;
149
+ const collection = createStacCollection(title, linzSlug, epsg, Bounds.union(allBounds), stacItems.all, logger);
150
+ const latestCollection = createStacCollection(title, linzSlug, epsg, Bounds.union(latestBounds), stacItems.latest, logger);
151
+ logger?.info({ epsg }, 'CreateStacFiles:End');
152
+ // Write all stac items and collections
153
+ if (!ctx.latestOnly) {
154
+ const allTargetURL = new URL(`${scale}/${resolution}/${epsg.code}/`, target);
155
+ logger?.info({ epsg, target: allTargetURL.href }, 'WriteStacFiles:Start');
156
+ const allPaths = await writeStacFiles(allTargetURL, stacItems.all, collection, logger);
157
+ stacItemPaths.push(...allPaths.items);
158
+ }
159
+ // Write latest stac items and collections
160
+ const latestTargetURL = new URL(`${scale}_latest/${resolution}/${epsg.code}/`, target);
161
+ epsgDirectoryPaths.push({ epsg: epsg.code.toString(), url: latestTargetURL });
162
+ logger?.info({ epsg, target: latestTargetURL.href }, 'WriteStacFiles:Start');
163
+ const latestPaths = await writeStacFiles(latestTargetURL, stacItems.latest, latestCollection, logger);
164
+ stacItemPaths.push(...latestPaths.items);
165
+ logger?.info({ epsg }, 'WriteStacFiles:End');
166
+ }
167
+ return { epsgDirectoryPaths, stacItemPaths };
168
+ }
169
+ //# sourceMappingURL=cli.topo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.topo.js","sourceRoot":"","sources":["../../../src/cogify/cli/cli.topo.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ export declare const BasemapsCogifyValidateCommand: Partial<import("cmd-ts/dist/cjs/argparser.js").Register> & {
2
+ parse(context: import("cmd-ts/dist/cjs/argparser.js").ParseContext): Promise<import("cmd-ts/dist/cjs/argparser.js").ParsingResult<{
3
+ concurrency: number;
4
+ tiffs: URL[];
5
+ verbose: boolean;
6
+ extraVerbose: boolean;
7
+ }>>;
8
+ } & import("cmd-ts/dist/cjs/helpdoc.js").PrintHelp & import("cmd-ts/dist/cjs/helpdoc.js").ProvidesHelp & import("cmd-ts/dist/cjs/helpdoc.js").Named & Partial<import("cmd-ts/dist/cjs/helpdoc.js").Versioned> & import("cmd-ts/dist/cjs/argparser.js").Register & import("cmd-ts/dist/cjs/runner.js").Handling<{
9
+ concurrency: number;
10
+ tiffs: URL[];
11
+ verbose: boolean;
12
+ extraVerbose: boolean;
13
+ }, Promise<void>> & {
14
+ run(context: import("cmd-ts/dist/cjs/argparser.js").ParseContext): Promise<import("cmd-ts/dist/cjs/argparser.js").ParsingResult<Promise<void>>>;
15
+ } & Partial<import("cmd-ts/dist/cjs/helpdoc.js").Versioned & import("cmd-ts/dist/cjs/helpdoc.js").Descriptive & import("cmd-ts/dist/cjs/helpdoc.js").Aliased>;
@@ -0,0 +1,30 @@
1
+ import { getLogger, logArguments, Url } from '@basemaps/shared';
2
+ import { CliInfo } from '@basemaps/shared/build/cli/info.js';
3
+ import { command, number, option, restPositionals } from 'cmd-ts';
4
+ import pLimit from 'p-limit';
5
+ import { validateOutputTiff } from './cli.cog.js';
6
+ export const BasemapsCogifyValidateCommand = command({
7
+ name: 'cogify-validate',
8
+ version: CliInfo.version,
9
+ description: 'Validate a COG is created in a way basemaps likes',
10
+ args: {
11
+ ...logArguments,
12
+ concurrency: option({
13
+ type: number,
14
+ long: 'concurrency',
15
+ description: 'How many COGs to initialise at once',
16
+ defaultValue: () => 25,
17
+ defaultValueIsSerializable: true,
18
+ }),
19
+ tiffs: restPositionals({ type: Url, displayName: 'paths', description: 'COG to validate' }),
20
+ },
21
+ async handler(args) {
22
+ const logger = getLogger(this, args, 'cli-raster');
23
+ const q = pLimit(args.concurrency);
24
+ const promises = args.tiffs.map((tiff) => {
25
+ return q(() => validateOutputTiff(tiff, undefined, logger));
26
+ });
27
+ await Promise.allSettled(promises);
28
+ },
29
+ });
30
+ //# sourceMappingURL=cli.validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.validate.js","sourceRoot":"","sources":["../../../src/cogify/cli/cli.validate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAChE,OAAO,EAAE,OAAO,EAAE,MAAM,oCAAoC,CAAC;AAC7D,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAC;AAClE,OAAO,MAAM,MAAM,SAAS,CAAC;AAE7B,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAElD,MAAM,CAAC,MAAM,6BAA6B,GAAG,OAAO,CAAC;IACnD,IAAI,EAAE,iBAAiB;IACvB,OAAO,EAAE,OAAO,CAAC,OAAO;IACxB,WAAW,EAAE,mDAAmD;IAChE,IAAI,EAAE;QACJ,GAAG,YAAY;QACf,WAAW,EAAE,MAAM,CAAC;YAClB,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,aAAa;YACnB,WAAW,EAAE,qCAAqC;YAClD,YAAY,EAAE,GAAG,EAAE,CAAC,EAAE;YACtB,0BAA0B,EAAE,IAAI;SACjC,CAAC;QACF,KAAK,EAAE,eAAe,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,WAAW,EAAE,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,CAAC;KAC5F;IAED,KAAK,CAAC,OAAO,CAAC,IAAI;QAChB,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC;QACnD,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAEnC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;YACvC,OAAO,CAAC,CAAC,GAAG,EAAE,CAAC,kBAAkB,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;QAC9D,CAAC,CAAC,CAAC;QAEH,MAAM,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IACrC,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,121 @@
1
+ export declare const CogifyCli: Partial<import("cmd-ts/dist/cjs/argparser.js").Register> & {
2
+ parse(context: import("cmd-ts/dist/cjs/argparser.js").ParseContext): Promise<import("cmd-ts/dist/cjs/argparser.js").ParsingResult<{
3
+ command: "cover";
4
+ args: {
5
+ target: URL;
6
+ cutline: URL | undefined;
7
+ cutlineBlend: number;
8
+ paths: URL[];
9
+ preset: string;
10
+ tileMatrix: string;
11
+ baseZoomOffset: number | undefined;
12
+ requireStacCollection: boolean;
13
+ background: import("@basemaps/config").Rgba | undefined;
14
+ verbose: boolean;
15
+ extraVerbose: boolean;
16
+ };
17
+ } | {
18
+ command: "create";
19
+ args: {
20
+ path: URL[];
21
+ force: boolean;
22
+ concurrency: number;
23
+ docker: boolean;
24
+ fromFile: URL[] | undefined;
25
+ verbose: boolean;
26
+ extraVerbose: boolean;
27
+ };
28
+ } | {
29
+ command: "validate";
30
+ args: {
31
+ concurrency: number;
32
+ tiffs: URL[];
33
+ verbose: boolean;
34
+ extraVerbose: boolean;
35
+ };
36
+ } | {
37
+ command: "topo";
38
+ args: {
39
+ title: string | undefined;
40
+ target: URL;
41
+ mapSeries: string;
42
+ latestOnly: boolean;
43
+ output: URL | undefined;
44
+ paths: URL[];
45
+ verbose: boolean;
46
+ extraVerbose: boolean;
47
+ };
48
+ }>>;
49
+ } & import("cmd-ts/dist/cjs/helpdoc.js").Named & Partial<import("cmd-ts/dist/cjs/helpdoc.js").Descriptive & import("cmd-ts/dist/cjs/helpdoc.js").Versioned> & import("cmd-ts/dist/cjs/helpdoc.js").PrintHelp & Partial<import("cmd-ts/dist/cjs/helpdoc.js").Versioned> & import("cmd-ts/dist/cjs/argparser.js").Register & import("cmd-ts/dist/cjs/runner.js").Handling<{
50
+ command: "cover";
51
+ args: {
52
+ target: URL;
53
+ cutline: URL | undefined;
54
+ cutlineBlend: number;
55
+ paths: URL[];
56
+ preset: string;
57
+ tileMatrix: string;
58
+ baseZoomOffset: number | undefined;
59
+ requireStacCollection: boolean;
60
+ background: import("@basemaps/config").Rgba | undefined;
61
+ verbose: boolean;
62
+ extraVerbose: boolean;
63
+ };
64
+ } | {
65
+ command: "create";
66
+ args: {
67
+ path: URL[];
68
+ force: boolean;
69
+ concurrency: number;
70
+ docker: boolean;
71
+ fromFile: URL[] | undefined;
72
+ verbose: boolean;
73
+ extraVerbose: boolean;
74
+ };
75
+ } | {
76
+ command: "validate";
77
+ args: {
78
+ concurrency: number;
79
+ tiffs: URL[];
80
+ verbose: boolean;
81
+ extraVerbose: boolean;
82
+ };
83
+ } | {
84
+ command: "topo";
85
+ args: {
86
+ title: string | undefined;
87
+ target: URL;
88
+ mapSeries: string;
89
+ latestOnly: boolean;
90
+ output: URL | undefined;
91
+ paths: URL[];
92
+ verbose: boolean;
93
+ extraVerbose: boolean;
94
+ };
95
+ }, {
96
+ command: "cover";
97
+ value: Promise<void>;
98
+ } | {
99
+ command: "create";
100
+ value: Promise<void>;
101
+ } | {
102
+ command: "validate";
103
+ value: Promise<void>;
104
+ } | {
105
+ command: "topo";
106
+ value: Promise<void>;
107
+ }> & {
108
+ run(context: import("cmd-ts/dist/cjs/argparser.js").ParseContext): Promise<import("cmd-ts/dist/cjs/argparser.js").ParsingResult<{
109
+ command: "cover";
110
+ value: Promise<void>;
111
+ } | {
112
+ command: "create";
113
+ value: Promise<void>;
114
+ } | {
115
+ command: "validate";
116
+ value: Promise<void>;
117
+ } | {
118
+ command: "topo";
119
+ value: Promise<void>;
120
+ }>>;
121
+ };
@@ -0,0 +1,15 @@
1
+ import { subcommands } from 'cmd-ts';
2
+ import { BasemapsCogifyCreateCommand } from './cli/cli.cog.js';
3
+ import { BasemapsCogifyCoverCommand } from './cli/cli.cover.js';
4
+ import { TopoStacCreationCommand } from './cli/cli.topo.js';
5
+ import { BasemapsCogifyValidateCommand } from './cli/cli.validate.js';
6
+ export const CogifyCli = subcommands({
7
+ name: 'cogify',
8
+ cmds: {
9
+ cover: BasemapsCogifyCoverCommand,
10
+ create: BasemapsCogifyCreateCommand,
11
+ validate: BasemapsCogifyValidateCommand,
12
+ topo: TopoStacCreationCommand,
13
+ },
14
+ });
15
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cogify/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAErC,OAAO,EAAE,2BAA2B,EAAE,MAAM,kBAAkB,CAAC;AAC/D,OAAO,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAChE,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,6BAA6B,EAAE,MAAM,uBAAuB,CAAC;AAEtE,MAAM,CAAC,MAAM,SAAS,GAAG,WAAW,CAAC;IACnC,IAAI,EAAE,QAAQ;IACd,IAAI,EAAE;QACJ,KAAK,EAAE,0BAA0B;QACjC,MAAM,EAAE,2BAA2B;QACnC,QAAQ,EAAE,6BAA6B;QACvC,IAAI,EAAE,uBAAuB;KAC9B;CACF,CAAC,CAAC"}
@@ -0,0 +1,28 @@
1
+ import { Tile, TileMatrixSet } from '@basemaps/geo';
2
+ import { LogType } from '@basemaps/shared';
3
+ import { MultiPolygon } from '@linzjs/geojson';
4
+ import { Metrics } from '@linzjs/metrics';
5
+ import { CutlineOptimizer } from '../covering/cutline.js';
6
+ export declare function addChildren(tile: Tile, todo?: Tile[]): Tile[];
7
+ export declare function addSurrounding(tile: Tile, tileMatrix: TileMatrixSet, todo?: Tile[], seen?: Set<string>): Tile[];
8
+ export interface CoveringContext {
9
+ /** Tile matrix to cover with */
10
+ tileMatrix: TileMatrixSet;
11
+ /** MultiPolygon to cover */
12
+ source: MultiPolygon;
13
+ /** Zoom to start covering at */
14
+ targetZoom: number;
15
+ /** Zoom level the imagery is optimized */
16
+ baseZoom: number;
17
+ /** Min amount of a tile to be covered before using a smaller tiler @default 0.25 (25%) */
18
+ minCoveragePercent?: number;
19
+ /** maximal difference between output tiles and input tiles, @default +2 */
20
+ maxZoomDifference?: number;
21
+ /** Cutline to apply */
22
+ cutline: CutlineOptimizer;
23
+ /** Optional metrics provider to track how long actions take */
24
+ metrics?: Metrics;
25
+ /** Optional logger to trace covering creation */
26
+ logger?: LogType;
27
+ }
28
+ export declare function createCovering(ctx: CoveringContext): Tile[];
@@ -0,0 +1,126 @@
1
+ import { Simplify, TileId } from '@basemaps/geo';
2
+ import { Area, intersection } from '@linzjs/geojson';
3
+ /**
4
+ * Tile offsets for surrounding tiles
5
+ * In the order North, West, South, East
6
+ */
7
+ const SurroundingTiles = [
8
+ { x: 0, y: -1 }, // North
9
+ { x: 1, y: 0 }, // West
10
+ { x: 0, y: 1 }, // South
11
+ { x: -1, y: 0 }, // East
12
+ ];
13
+ export function addChildren(tile, todo = []) {
14
+ const childZ = tile.z + 1;
15
+ const xOffset = tile.x * 2;
16
+ const yOffset = tile.y * 2;
17
+ todo.push({ z: childZ, x: xOffset, y: yOffset }); //top left
18
+ todo.push({ z: childZ, x: xOffset + 1, y: yOffset }); // top right
19
+ todo.push({ z: childZ, x: xOffset, y: yOffset + 1 }); // bottom left
20
+ todo.push({ z: childZ, x: xOffset + 1, y: yOffset + 1 }); // bottom right
21
+ return todo;
22
+ }
23
+ export function addSurrounding(tile, tileMatrix, todo = [], seen) {
24
+ // Zoom should not have surrounding tiles
25
+ if (tile.z === 0)
26
+ return [];
27
+ for (const sr of SurroundingTiles) {
28
+ // TODO this should loop around if it goes outside the bounds of the tile matrix eg crossing the antimeridian
29
+ const nextTile = { z: tile.z, x: sr.x + tile.x, y: sr.y + tile.y };
30
+ const tileZoom = tileMatrix.zooms[tile.z];
31
+ if (nextTile.x >= tileZoom.matrixWidth)
32
+ nextTile.x = nextTile.x - tileZoom.matrixWidth;
33
+ if (nextTile.x < 0)
34
+ nextTile.x = nextTile.x + tileZoom.matrixWidth;
35
+ if (nextTile.y >= tileZoom.matrixHeight)
36
+ nextTile.y = nextTile.y - tileZoom.matrixHeight;
37
+ if (nextTile.y < 0)
38
+ nextTile.y = nextTile.y + tileZoom.matrixHeight;
39
+ if (seen) {
40
+ const tileId = TileId.fromTile(nextTile);
41
+ if (seen?.has(tileId))
42
+ continue;
43
+ }
44
+ todo.push(nextTile);
45
+ }
46
+ return todo;
47
+ }
48
+ export function createCovering(ctx) {
49
+ const minCoveragePercent = ctx.minCoveragePercent ?? 0.25;
50
+ const maxZoomDifference = ctx.maxZoomDifference ?? 2;
51
+ const outputTiles = [];
52
+ const tileMatrix = ctx.tileMatrix;
53
+ // Reduce the complexity of the cutline applied polygon to same as one pixel at the covering resolution
54
+ // this is a approximation and can cause some false positive/negative tiles.
55
+ // but signficiantly improves performance of finding tile covers
56
+ ctx.metrics?.start('cutline:simplify');
57
+ const onePixelAtOverviewResolution = ctx.tileMatrix.pixelScale(ctx.targetZoom);
58
+ const onePixelAtBaseResolution = ctx.tileMatrix.pixelScale(ctx.baseZoom);
59
+ const cutBounds = Simplify.multiPolygon(ctx.cutline.cut(ctx.source), // Cut the source to the cutline
60
+ onePixelAtOverviewResolution, onePixelAtBaseResolution);
61
+ const cutlineDuration = ctx.metrics?.end('cutline:simplify');
62
+ // No imagery was left after the cutline
63
+ if (cutBounds == null)
64
+ throw new Error('Cutline excludes all imagery');
65
+ ctx.logger?.debug({ duration: cutlineDuration }, 'Cutline:Simplified');
66
+ // Tiles that have been seen before
67
+ const visited = new Set();
68
+ const todo = [];
69
+ // Find the tile that intersects with the top left point of each polygon and use that as the starting point
70
+ for (const poly of cutBounds) {
71
+ const topLeftPoint = poly[0][0];
72
+ const targetPx = tileMatrix.sourceToPixels(topLeftPoint[0], topLeftPoint[1], ctx.targetZoom);
73
+ const tile = tileMatrix.pixelsToTile(targetPx.x, targetPx.y, ctx.targetZoom);
74
+ const tileId = TileId.fromTile(tile);
75
+ if (visited.has(tileId))
76
+ continue;
77
+ todo.push(tile);
78
+ visited.add(tileId);
79
+ }
80
+ visited.clear();
81
+ const tilesByZoom = [];
82
+ let zoomDifference = 0;
83
+ while (todo.length > 0) {
84
+ const tile = todo.shift();
85
+ if (tile == null)
86
+ continue;
87
+ const tileId = TileId.fromTile(tile);
88
+ if (visited.has(tileId))
89
+ continue;
90
+ visited.add(tileId);
91
+ const tileSource = tileMatrix.tileToSourceBounds(tile);
92
+ const tileArea = tileSource.width * tileSource.height;
93
+ const tilePolygon = tileSource.toPolygon();
94
+ const tileIntersection = intersection(cutBounds, tilePolygon);
95
+ if (tileIntersection.length === 0)
96
+ continue;
97
+ // Determine how big of a intersection there is
98
+ const area = Area.multiPolygon(tileIntersection);
99
+ const areaPercent = area / tileArea;
100
+ // Is this tile a different zoom level to our target
101
+ const zDiff = tile.z - ctx.targetZoom;
102
+ // Count the number of pixels in the output tiff that would be used
103
+ const tileScale = tileSource.width / ctx.tileMatrix.tileSize;
104
+ const pixelCount = (tileArea * areaPercent) / tileScale;
105
+ if (areaPercent < minCoveragePercent && zDiff < maxZoomDifference) {
106
+ // Not enough coverage was found with this tile, use a more zoomed in tile and try again
107
+ addChildren(tile, todo);
108
+ }
109
+ else if (pixelCount > 1) {
110
+ zoomDifference = Math.max(zDiff, zoomDifference);
111
+ outputTiles.push(tile);
112
+ tilesByZoom[tile.z] = (tilesByZoom[tile.z] ?? 0) + 1;
113
+ ctx.logger?.debug({ tileId, areaPercent: Number((areaPercent * 100).toFixed(2)) }, 'Cover:Tile');
114
+ if (outputTiles.length % 25 === 0) {
115
+ ctx.logger?.info({ tiles: outputTiles.length, tilesByZoom }, 'Cover:Progress');
116
+ }
117
+ }
118
+ else {
119
+ ctx.logger?.debug({ pixelCount, tileId }, 'Cover:SkipTile');
120
+ }
121
+ if (zDiff === 0)
122
+ addSurrounding(tile, ctx.tileMatrix, todo, visited);
123
+ }
124
+ return outputTiles;
125
+ }
126
+ //# sourceMappingURL=covering.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"covering.js","sourceRoot":"","sources":["../../../src/cogify/covering/covering.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import { EpsgCode, Tile, TileMatrixSet } from '@basemaps/geo';
2
+ import { FeatureCollectionWithCrs, MultiPolygon } from '@linzjs/geojson';
3
+ import { CogifyLinkCutline } from '../stac.js';
4
+ export declare function loadCutline(path: URL): Promise<{
5
+ polygon: MultiPolygon;
6
+ projection: EpsgCode;
7
+ }>;
8
+ export declare class CutlineOptimizer {
9
+ /** Pad tiles by 200m when optimizing cutlines so blending will not be affected */
10
+ static TilePixelPadding: number;
11
+ path: URL | null;
12
+ cutline: MultiPolygon | null;
13
+ blend: number;
14
+ tileMatrix: TileMatrixSet;
15
+ constructor(path: URL | null, cutline: MultiPolygon | null, blend: number, tileMatrix: TileMatrixSet);
16
+ /** Cut a polygon to the cutline */
17
+ cut(poly: MultiPolygon): MultiPolygon;
18
+ /** Optimize a cutline for a tile, if it doesn't intersect then ignore the cutline */
19
+ optimize(tile: Tile): FeatureCollectionWithCrs | null;
20
+ /**
21
+ * Convert cutline to geojson FeatureCollection
22
+ *
23
+ * @returns GeoJSON FeatureCollection if cutline exists, null otherwise
24
+ */
25
+ toGeoJson(): FeatureCollectionWithCrs | null;
26
+ static load(path: URL | undefined, blend: number, tileMatrix: TileMatrixSet): Promise<CutlineOptimizer>;
27
+ /** Create a cutline optimizer from a STAC cutline link */
28
+ static loadFromLink(l: CogifyLinkCutline | null, tileMatrix: TileMatrixSet): Promise<CutlineOptimizer>;
29
+ }