@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.
- package/LICENSE +21 -0
- package/README.md +70 -0
- package/build/bin.d.ts +1 -0
- package/build/bin.js +16 -0
- package/build/bin.js.map +1 -0
- package/build/cogify/__test__/covering.test.d.ts +1 -0
- package/build/cogify/__test__/covering.test.js +64 -0
- package/build/cogify/__test__/covering.test.js.map +1 -0
- package/build/cogify/__test__/extract.test.d.ts +1 -0
- package/build/cogify/__test__/extract.test.js +34 -0
- package/build/cogify/__test__/extract.test.js.map +1 -0
- package/build/cogify/cli/__test__/cli.cover.test.d.ts +1 -0
- package/build/cogify/cli/__test__/cli.cover.test.js +48 -0
- package/build/cogify/cli/__test__/cli.cover.test.js.map +1 -0
- package/build/cogify/cli/__test__/cli.topo.test.d.ts +1 -0
- package/build/cogify/cli/__test__/cli.topo.test.js +53 -0
- package/build/cogify/cli/__test__/cli.topo.test.js.map +1 -0
- package/build/cogify/cli/cli.cog.d.ts +55 -0
- package/build/cogify/cli/cli.cog.js +353 -0
- package/build/cogify/cli/cli.cog.js.map +1 -0
- package/build/cogify/cli/cli.cover.d.ts +30 -0
- package/build/cogify/cli/cli.cover.js +157 -0
- package/build/cogify/cli/cli.cover.js.map +1 -0
- package/build/cogify/cli/cli.topo.d.ts +50 -0
- package/build/cogify/cli/cli.topo.js +169 -0
- package/build/cogify/cli/cli.topo.js.map +1 -0
- package/build/cogify/cli/cli.validate.d.ts +15 -0
- package/build/cogify/cli/cli.validate.js +30 -0
- package/build/cogify/cli/cli.validate.js.map +1 -0
- package/build/cogify/cli.d.ts +121 -0
- package/build/cogify/cli.js +15 -0
- package/build/cogify/cli.js.map +1 -0
- package/build/cogify/covering/covering.d.ts +28 -0
- package/build/cogify/covering/covering.js +126 -0
- package/build/cogify/covering/covering.js.map +1 -0
- package/build/cogify/covering/cutline.d.ts +29 -0
- package/build/cogify/covering/cutline.js +109 -0
- package/build/cogify/covering/cutline.js.map +1 -0
- package/build/cogify/covering/tile.cover.d.ts +38 -0
- package/build/cogify/covering/tile.cover.js +198 -0
- package/build/cogify/covering/tile.cover.js.map +1 -0
- package/build/cogify/gdal/gdal.command.d.ts +27 -0
- package/build/cogify/gdal/gdal.command.js +175 -0
- package/build/cogify/gdal/gdal.command.js.map +1 -0
- package/build/cogify/gdal/gdal.runner.d.ts +42 -0
- package/build/cogify/gdal/gdal.runner.js +194 -0
- package/build/cogify/gdal/gdal.runner.js.map +1 -0
- package/build/cogify/stac.d.ts +138 -0
- package/build/cogify/stac.js +25 -0
- package/build/cogify/stac.js.map +1 -0
- package/build/cogify/topo/extract.d.ts +82 -0
- package/build/cogify/topo/extract.js +195 -0
- package/build/cogify/topo/extract.js.map +1 -0
- package/build/cogify/topo/slug.d.ts +10 -0
- package/build/cogify/topo/slug.js +18 -0
- package/build/cogify/topo/slug.js.map +1 -0
- package/build/cogify/topo/stac.creation.d.ts +47 -0
- package/build/cogify/topo/stac.creation.js +171 -0
- package/build/cogify/topo/stac.creation.js.map +1 -0
- package/build/download.d.ts +57 -0
- package/build/download.js +144 -0
- package/build/download.js.map +1 -0
- package/build/hash.stream.d.ts +20 -0
- package/build/hash.stream.js +62 -0
- package/build/hash.stream.js.map +1 -0
- package/build/index.d.ts +1 -0
- package/build/index.js +2 -0
- package/build/index.js.map +1 -0
- package/build/preset.d.ts +15 -0
- package/build/preset.js +66 -0
- package/build/preset.js.map +1 -0
- package/dist/index.cjs +85880 -0
- package/package.json +61 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { Epsg, EpsgCode, Projection } from '@basemaps/geo';
|
|
2
|
+
import { fsa } from '@basemaps/shared';
|
|
3
|
+
import { Area, featuresToMultiPolygon, intersection, toFeatureCollection, toFeatureMultiPolygon, } from '@linzjs/geojson';
|
|
4
|
+
export async function loadCutline(path) {
|
|
5
|
+
const buf = await fsa.read(path);
|
|
6
|
+
if (path.pathname.endsWith('.geojson') || path.pathname.endsWith('.json')) {
|
|
7
|
+
const data = JSON.parse(buf.toString());
|
|
8
|
+
const projection = Epsg.parseCode(data.crs?.properties?.name ?? '') ?? EpsgCode.Wgs84;
|
|
9
|
+
const polygon = featuresToMultiPolygon(data.features, true).coordinates;
|
|
10
|
+
return { polygon, projection };
|
|
11
|
+
}
|
|
12
|
+
throw new Error('Unknown cutline type: ' + path.href);
|
|
13
|
+
}
|
|
14
|
+
export class CutlineOptimizer {
|
|
15
|
+
constructor(path, cutline, blend, tileMatrix) {
|
|
16
|
+
Object.defineProperty(this, "path", {
|
|
17
|
+
enumerable: true,
|
|
18
|
+
configurable: true,
|
|
19
|
+
writable: true,
|
|
20
|
+
value: void 0
|
|
21
|
+
});
|
|
22
|
+
Object.defineProperty(this, "cutline", {
|
|
23
|
+
enumerable: true,
|
|
24
|
+
configurable: true,
|
|
25
|
+
writable: true,
|
|
26
|
+
value: void 0
|
|
27
|
+
});
|
|
28
|
+
Object.defineProperty(this, "blend", {
|
|
29
|
+
enumerable: true,
|
|
30
|
+
configurable: true,
|
|
31
|
+
writable: true,
|
|
32
|
+
value: void 0
|
|
33
|
+
});
|
|
34
|
+
Object.defineProperty(this, "tileMatrix", {
|
|
35
|
+
enumerable: true,
|
|
36
|
+
configurable: true,
|
|
37
|
+
writable: true,
|
|
38
|
+
value: void 0
|
|
39
|
+
});
|
|
40
|
+
this.path = path;
|
|
41
|
+
this.cutline = cutline;
|
|
42
|
+
this.blend = blend;
|
|
43
|
+
this.tileMatrix = tileMatrix;
|
|
44
|
+
}
|
|
45
|
+
/** Cut a polygon to the cutline */
|
|
46
|
+
cut(poly) {
|
|
47
|
+
if (this.cutline == null)
|
|
48
|
+
return poly;
|
|
49
|
+
// TODO buffer the cutline by this.blend so blended tiles will be included
|
|
50
|
+
// although it is somewhat wasteful to make a cog just for a blended cut
|
|
51
|
+
return intersection(poly, this.cutline);
|
|
52
|
+
}
|
|
53
|
+
/** Optimize a cutline for a tile, if it doesn't intersect then ignore the cutline */
|
|
54
|
+
optimize(tile) {
|
|
55
|
+
if (this.cutline == null)
|
|
56
|
+
return null;
|
|
57
|
+
const tileBounds = this.tileMatrix.tileToSourceBounds(tile);
|
|
58
|
+
const tileScale = this.tileMatrix.pixelScale(tile.z);
|
|
59
|
+
// Expand the tile bounds to ensure optimized bounds are not clipping and blended.
|
|
60
|
+
const scaleAmount = (tileBounds.width + tileScale * (CutlineOptimizer.TilePixelPadding + this.blend) * 2) / tileBounds.width;
|
|
61
|
+
const scaledBounds = tileBounds.scaleFromCenter(scaleAmount);
|
|
62
|
+
const optimized = intersection(this.cutline, scaledBounds.toPolygon());
|
|
63
|
+
// Check how much of a change was the optimized cutline
|
|
64
|
+
const optimizedArea = Area.multiPolygon(optimized);
|
|
65
|
+
const scaledArea = scaledBounds.width * scaledBounds.height;
|
|
66
|
+
const areaPercent = 1 - optimizedArea / scaledArea;
|
|
67
|
+
// if area is bigger than 0.0001% then assume the cutline was applied
|
|
68
|
+
if (areaPercent < 1e-4)
|
|
69
|
+
return null;
|
|
70
|
+
const feature = toFeatureCollection([toFeatureMultiPolygon(optimized)]);
|
|
71
|
+
feature.crs = { type: 'name', properties: { name: this.tileMatrix.projection.toUrn() } };
|
|
72
|
+
return feature;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Convert cutline to geojson FeatureCollection
|
|
76
|
+
*
|
|
77
|
+
* @returns GeoJSON FeatureCollection if cutline exists, null otherwise
|
|
78
|
+
*/
|
|
79
|
+
toGeoJson() {
|
|
80
|
+
if (this.cutline == null)
|
|
81
|
+
return null;
|
|
82
|
+
const feature = toFeatureCollection([toFeatureMultiPolygon(this.cutline)]);
|
|
83
|
+
feature.crs = { type: 'name', properties: { name: this.tileMatrix.projection.toUrn() } };
|
|
84
|
+
return feature;
|
|
85
|
+
}
|
|
86
|
+
static async load(path, blend, tileMatrix) {
|
|
87
|
+
if (path == null)
|
|
88
|
+
return new CutlineOptimizer(null, null, blend, tileMatrix);
|
|
89
|
+
const cut = await loadCutline(path);
|
|
90
|
+
if (cut.projection === tileMatrix.projection.code)
|
|
91
|
+
return new CutlineOptimizer(path, cut.polygon, blend, tileMatrix);
|
|
92
|
+
const projected = Projection.get(cut.projection).projectMultipolygon(cut.polygon, Projection.get(tileMatrix.projection));
|
|
93
|
+
return new CutlineOptimizer(path, projected, blend, tileMatrix);
|
|
94
|
+
}
|
|
95
|
+
/** Create a cutline optimizer from a STAC cutline link */
|
|
96
|
+
static async loadFromLink(l, tileMatrix) {
|
|
97
|
+
if (l == null)
|
|
98
|
+
return new CutlineOptimizer(null, null, 0, tileMatrix);
|
|
99
|
+
return this.load(new URL(l.href), l.blend, tileMatrix);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/** Pad tiles by 200m when optimizing cutlines so blending will not be affected */
|
|
103
|
+
Object.defineProperty(CutlineOptimizer, "TilePixelPadding", {
|
|
104
|
+
enumerable: true,
|
|
105
|
+
configurable: true,
|
|
106
|
+
writable: true,
|
|
107
|
+
value: 200
|
|
108
|
+
});
|
|
109
|
+
//# sourceMappingURL=cutline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cutline.js","sourceRoot":"","sources":["../../../src/cogify/covering/cutline.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Rgba } from '@basemaps/config';
|
|
2
|
+
import { ConfigImageryTiff } from '@basemaps/config-loader';
|
|
3
|
+
import { TileMatrixSet } from '@basemaps/geo';
|
|
4
|
+
import { LogType } from '@basemaps/shared';
|
|
5
|
+
import { Metrics } from '@linzjs/metrics';
|
|
6
|
+
import { CogifyStacCollection, CogifyStacItem } from '../stac.js';
|
|
7
|
+
import { CutlineOptimizer } from './cutline.js';
|
|
8
|
+
export interface TileCoverContext {
|
|
9
|
+
/** Unique id for the covering */
|
|
10
|
+
id: string;
|
|
11
|
+
/** List of imagery to cover */
|
|
12
|
+
imagery: ConfigImageryTiff;
|
|
13
|
+
/** Cutline to apply */
|
|
14
|
+
cutline: CutlineOptimizer;
|
|
15
|
+
/** Output tile matrix */
|
|
16
|
+
tileMatrix: TileMatrixSet;
|
|
17
|
+
/** Optional metrics provider to track how long actions take */
|
|
18
|
+
metrics?: Metrics;
|
|
19
|
+
/** Optional logger to trace covering creation */
|
|
20
|
+
logger?: LogType;
|
|
21
|
+
/** GDAL configuration preset */
|
|
22
|
+
preset: string;
|
|
23
|
+
/** Optional color with which to replace all transparent COG pixels */
|
|
24
|
+
background?: Rgba;
|
|
25
|
+
/**
|
|
26
|
+
* Override the base zoom to store the output COGS as
|
|
27
|
+
*/
|
|
28
|
+
targetZoomOffset?: number;
|
|
29
|
+
}
|
|
30
|
+
export interface TileCoverResult {
|
|
31
|
+
/** Stac collection for the imagery */
|
|
32
|
+
collection: CogifyStacCollection;
|
|
33
|
+
/** tiles to create */
|
|
34
|
+
items: CogifyStacItem[];
|
|
35
|
+
/** GeoJSON features of all the source imagery */
|
|
36
|
+
source: GeoJSON.FeatureCollection;
|
|
37
|
+
}
|
|
38
|
+
export declare function createTileCover(ctx: TileCoverContext): Promise<TileCoverResult>;
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { Bounds, Projection, ProjectionLoader, TileId } from '@basemaps/geo';
|
|
2
|
+
import { fsa, urlToString } from '@basemaps/shared';
|
|
3
|
+
import { CliDate, CliInfo } from '@basemaps/shared/build/cli/info.js';
|
|
4
|
+
import { intersection, toFeatureCollection, union } from '@linzjs/geojson';
|
|
5
|
+
import { Presets } from '../../preset.js';
|
|
6
|
+
import { createFileStats } from '../stac.js';
|
|
7
|
+
import { createCovering } from './covering.js';
|
|
8
|
+
function getDateTime(ctx) {
|
|
9
|
+
const interval = ctx.imagery.collection?.extent?.temporal?.interval?.[0];
|
|
10
|
+
if (interval)
|
|
11
|
+
return { start: interval[0], end: interval[1] };
|
|
12
|
+
// TODO should we guess datetime
|
|
13
|
+
return { start: null, end: null };
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Find a zoom level in the target tile matrix that is at least as good as resolution as `resolution`
|
|
17
|
+
*
|
|
18
|
+
* for some imagery sets this can mean a large difference in the source to target for example 1M resolution source imagery
|
|
19
|
+
* is resampled to 0.59m (z18) rather than the closer 1.19m (z17) `targetZoomOffset` can adjust the resolution
|
|
20
|
+
* to a nearer value using `-1` will convert a 1M target from 0.59m (z18) to 1.19m (z17)
|
|
21
|
+
*
|
|
22
|
+
* This can greatly reduce the size of output tiles
|
|
23
|
+
*
|
|
24
|
+
* @param tileMatrix target tile tile matrix to use
|
|
25
|
+
* @param resolution target resolution
|
|
26
|
+
* @param targetZoomOffset override the target base zoom, for instance -1 turns a z18 into z17
|
|
27
|
+
* @returns
|
|
28
|
+
*/
|
|
29
|
+
function getTargetBaseZoom(tileMatrix, resolution, targetZoomOffset) {
|
|
30
|
+
if (targetZoomOffset == null)
|
|
31
|
+
return Projection.getTiffResZoom(tileMatrix, resolution);
|
|
32
|
+
return Projection.getTiffResZoom(tileMatrix, resolution) + targetZoomOffset;
|
|
33
|
+
}
|
|
34
|
+
export async function createTileCover(ctx) {
|
|
35
|
+
// Ensure we have the projection loaded for the source imagery
|
|
36
|
+
await ProjectionLoader.load(ctx.imagery.projection);
|
|
37
|
+
// Find the zoom level that is at least as good as the source imagery
|
|
38
|
+
const targetBaseZoom = getTargetBaseZoom(ctx.tileMatrix, ctx.imagery.gsd, ctx.targetZoomOffset);
|
|
39
|
+
// The base zoom is 256x256 pixels at its resolution, we are trying to find a image that is <32k pixels wide/high
|
|
40
|
+
// zooming out 7 levels converts a 256x256 image into 32k x 32k image
|
|
41
|
+
// 256 * 2 ** 7 = 32,768 - 256x256 tile
|
|
42
|
+
// 512 * 2 ** 6 = 32,768 - 512x512 tile
|
|
43
|
+
const optimalCoveringZoom = Math.max(1, targetBaseZoom - 7); // z12 from z19
|
|
44
|
+
ctx.logger?.debug({ targetBaseZoom, cogOverZoom: optimalCoveringZoom }, 'Imagery:ZoomLevel');
|
|
45
|
+
const sourceBounds = projectPolygon(polygonFromBounds(ctx.imagery.files), ctx.imagery.projection, ctx.tileMatrix.projection.code);
|
|
46
|
+
ctx.logger?.debug('Cutline:Apply');
|
|
47
|
+
ctx.metrics?.start('cutline:apply');
|
|
48
|
+
const dateTime = getDateTime(ctx);
|
|
49
|
+
// Convert the source imagery to a geojson
|
|
50
|
+
const sourceGeoJson = ctx.imagery.files.map((file) => {
|
|
51
|
+
return Projection.get(ctx.imagery.projection).boundsToGeoJsonFeature(file, { url: file.name });
|
|
52
|
+
});
|
|
53
|
+
ctx.logger?.info({ zoom: optimalCoveringZoom }, 'Imagery:Covering:Start');
|
|
54
|
+
// Cover the source imagery in tiles
|
|
55
|
+
ctx.metrics?.start('covering:create');
|
|
56
|
+
const covering = createCovering({
|
|
57
|
+
tileMatrix: ctx.tileMatrix,
|
|
58
|
+
source: sourceBounds,
|
|
59
|
+
targetZoom: optimalCoveringZoom,
|
|
60
|
+
baseZoom: targetBaseZoom,
|
|
61
|
+
cutline: ctx.cutline,
|
|
62
|
+
metrics: ctx.metrics,
|
|
63
|
+
logger: ctx.logger,
|
|
64
|
+
});
|
|
65
|
+
ctx.metrics?.end('covering:create');
|
|
66
|
+
if (covering.length === 0)
|
|
67
|
+
throw new Error('Unable to create tile covering, no tiles created.');
|
|
68
|
+
ctx.logger?.info({ tiles: covering.length, zoom: optimalCoveringZoom }, 'Imagery:Covering:Created');
|
|
69
|
+
const imageryBounds = ctx.imagery.files.map((f) => {
|
|
70
|
+
const polygon = Bounds.fromJson(f).toPolygon();
|
|
71
|
+
return { ...f, polygon };
|
|
72
|
+
});
|
|
73
|
+
ctx.metrics?.start('covering:polygon');
|
|
74
|
+
const items = [];
|
|
75
|
+
for (const tile of covering) {
|
|
76
|
+
const bounds = ctx.tileMatrix.tileToSourceBounds(tile);
|
|
77
|
+
// Scale the tile bounds slightly to ensure we get all relevant imagery
|
|
78
|
+
const scaledBounds = bounds.scaleFromCenter(1.05);
|
|
79
|
+
const tileBounds = Projection.get(ctx.tileMatrix).projectMultipolygon([scaledBounds.toPolygon()], Projection.get(ctx.imagery.projection));
|
|
80
|
+
const source = imageryBounds.filter((f) => intersection(tileBounds, f.polygon).length > 0);
|
|
81
|
+
const feature = Projection.get(ctx.tileMatrix).boundsToGeoJsonFeature(bounds);
|
|
82
|
+
const tileId = TileId.fromTile(tile);
|
|
83
|
+
const item = {
|
|
84
|
+
id: `${ctx.id}/${tileId}`,
|
|
85
|
+
type: 'Feature',
|
|
86
|
+
collection: ctx.id,
|
|
87
|
+
stac_version: '1.0.0',
|
|
88
|
+
stac_extensions: [],
|
|
89
|
+
geometry: feature.geometry,
|
|
90
|
+
bbox: Projection.get(ctx.tileMatrix).boundsToWgs84BoundingBox(bounds),
|
|
91
|
+
links: [
|
|
92
|
+
{ href: `./${tileId}.json`, rel: 'self' },
|
|
93
|
+
{ href: './collection.json', rel: 'collection' },
|
|
94
|
+
{ href: './collection.json', rel: 'parent' },
|
|
95
|
+
],
|
|
96
|
+
properties: {
|
|
97
|
+
datetime: dateTime.start ? null : CliDate,
|
|
98
|
+
start_datetime: dateTime.start ?? undefined,
|
|
99
|
+
end_datetime: dateTime.end ?? undefined,
|
|
100
|
+
'proj:epsg': ctx.tileMatrix.projection.code,
|
|
101
|
+
'linz_basemaps:options': {
|
|
102
|
+
preset: ctx.preset,
|
|
103
|
+
...Presets[ctx.preset].options,
|
|
104
|
+
tile,
|
|
105
|
+
tileMatrix: ctx.tileMatrix.identifier,
|
|
106
|
+
sourceEpsg: ctx.imagery.projection,
|
|
107
|
+
zoomLevel: targetBaseZoom,
|
|
108
|
+
},
|
|
109
|
+
'linz_basemaps:generated': {
|
|
110
|
+
package: CliInfo.package,
|
|
111
|
+
hash: CliInfo.hash,
|
|
112
|
+
version: CliInfo.version,
|
|
113
|
+
datetime: CliDate,
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
assets: {},
|
|
117
|
+
};
|
|
118
|
+
// Add the background color if it exists
|
|
119
|
+
if (ctx.background)
|
|
120
|
+
item.properties['linz_basemaps:options'].background = ctx.background;
|
|
121
|
+
// Add the source imagery as a STAC Link
|
|
122
|
+
for (const src of source) {
|
|
123
|
+
const srcLink = {
|
|
124
|
+
href: new URL(src.name, ctx.imagery.url).href,
|
|
125
|
+
rel: 'linz_basemaps:source',
|
|
126
|
+
type: 'image/tiff; application=geotiff;',
|
|
127
|
+
'linz_basemaps:source_height': src.height,
|
|
128
|
+
'linz_basemaps:source_width': src.width,
|
|
129
|
+
};
|
|
130
|
+
item.links.push(srcLink);
|
|
131
|
+
}
|
|
132
|
+
// Add the cutline as a STAC Link if it exists
|
|
133
|
+
if (ctx.cutline.path) {
|
|
134
|
+
const cutLink = {
|
|
135
|
+
href: urlToString(ctx.cutline.path),
|
|
136
|
+
rel: 'linz_basemaps:cutline',
|
|
137
|
+
blend: ctx.cutline.blend,
|
|
138
|
+
};
|
|
139
|
+
item.links.push(cutLink);
|
|
140
|
+
}
|
|
141
|
+
items.push(item);
|
|
142
|
+
}
|
|
143
|
+
ctx.metrics?.end('covering:polygon');
|
|
144
|
+
const collection = {
|
|
145
|
+
id: ctx.id,
|
|
146
|
+
type: 'Collection',
|
|
147
|
+
stac_version: '1.0.0',
|
|
148
|
+
stac_extensions: [],
|
|
149
|
+
license: ctx.imagery.collection?.license ?? 'CC-BY-4.0',
|
|
150
|
+
title: ctx.imagery.title,
|
|
151
|
+
description: ctx.imagery.collection?.description ?? 'Missing source STAC',
|
|
152
|
+
providers: ctx.imagery.collection?.providers,
|
|
153
|
+
extent: {
|
|
154
|
+
spatial: { bbox: [Projection.get(ctx.imagery.projection).boundsToWgs84BoundingBox(ctx.imagery.bounds)] },
|
|
155
|
+
// Default the temporal time today if no times were found as it is required for STAC
|
|
156
|
+
temporal: { interval: dateTime.start ? [[dateTime.start, dateTime.end]] : [[CliDate, null]] },
|
|
157
|
+
},
|
|
158
|
+
links: items.map((item) => {
|
|
159
|
+
const tile = item.properties['linz_basemaps:options'].tile;
|
|
160
|
+
if (tile == null)
|
|
161
|
+
throw new Error('Tile missing from item');
|
|
162
|
+
const tileId = TileId.fromTile(tile);
|
|
163
|
+
return { href: `./${tileId}.json`, rel: 'item', type: 'application/json' };
|
|
164
|
+
}),
|
|
165
|
+
};
|
|
166
|
+
// Add a self link to the links
|
|
167
|
+
collection.links.unshift({ rel: 'self', href: './collection.json', type: 'application/json' });
|
|
168
|
+
// Include a link back to the source collection
|
|
169
|
+
if (ctx.imagery.collection) {
|
|
170
|
+
const target = new URL('collection.json', ctx.imagery.url);
|
|
171
|
+
const stac = await fsa.read(target);
|
|
172
|
+
collection.links.push({
|
|
173
|
+
rel: 'linz_basemaps:source_collection',
|
|
174
|
+
href: target.href,
|
|
175
|
+
type: 'application/json',
|
|
176
|
+
...createFileStats(stac),
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
return { collection, items, source: toFeatureCollection(sourceGeoJson) };
|
|
180
|
+
}
|
|
181
|
+
/** Convert a list of bounding boxes into a multipolygon */
|
|
182
|
+
function polygonFromBounds(bounds, scale = 1 + 1e-8) {
|
|
183
|
+
const srcPoly = [];
|
|
184
|
+
// merge imagery bounds
|
|
185
|
+
for (const image of bounds) {
|
|
186
|
+
srcPoly.push(Bounds.fromJson(image).scaleFromCenter(scale).toPolygon());
|
|
187
|
+
}
|
|
188
|
+
return union(srcPoly);
|
|
189
|
+
}
|
|
190
|
+
/** project a polygon from the source projection to a target projection */
|
|
191
|
+
function projectPolygon(p, sourceProjection, targetProjection) {
|
|
192
|
+
if (sourceProjection === targetProjection)
|
|
193
|
+
return p;
|
|
194
|
+
const sourceProj = Projection.get(sourceProjection);
|
|
195
|
+
const targetProj = Projection.get(targetProjection);
|
|
196
|
+
return sourceProj.projectMultipolygon(p, targetProj);
|
|
197
|
+
}
|
|
198
|
+
//# sourceMappingURL=tile.cover.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tile.cover.js","sourceRoot":"","sources":["../../../src/cogify/covering/tile.cover.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Rgba } from '@basemaps/config';
|
|
2
|
+
import { EpsgCode } from '@basemaps/geo';
|
|
3
|
+
import { CogifyCreationOptions } from '../stac.js';
|
|
4
|
+
import { GdalCommand } from './gdal.runner.js';
|
|
5
|
+
export declare function gdalBuildVrt(targetVrt: URL, source: URL[], addalpha?: boolean): GdalCommand;
|
|
6
|
+
export declare function gdalBuildVrtWarp(targetVrt: URL, sourceVrt: URL, sourceProjection: EpsgCode, cutline: {
|
|
7
|
+
url: URL | null;
|
|
8
|
+
blend: number;
|
|
9
|
+
}, opt: CogifyCreationOptions): GdalCommand;
|
|
10
|
+
export declare function gdalBuildCog(targetTiff: URL, sourceVrt: URL, opt: CogifyCreationOptions): GdalCommand;
|
|
11
|
+
/**
|
|
12
|
+
* Creates an empty tiff where all pixel values are set to the given color.
|
|
13
|
+
* Used to force a background so that there are no empty pixels in the final COG.
|
|
14
|
+
*
|
|
15
|
+
* @param targetTiff the file path and name for the created tiff
|
|
16
|
+
* @param color the color to set all pixel values
|
|
17
|
+
* @param opt a CogifyCreationOptions object
|
|
18
|
+
*
|
|
19
|
+
* @returns a 'gdal_create' GdalCommand object
|
|
20
|
+
*/
|
|
21
|
+
export declare function gdalCreate(targetTiff: URL, color: Rgba, opt: CogifyCreationOptions): GdalCommand;
|
|
22
|
+
/**
|
|
23
|
+
* Build a topographic mapsheet cog
|
|
24
|
+
*
|
|
25
|
+
* This is specific configuration to LINZ's topo50 and 250 mapsheets
|
|
26
|
+
*/
|
|
27
|
+
export declare function gdalBuildTopoRasterCommands(targetTiff: URL, sourceVrt: URL, opt: CogifyCreationOptions, width: number, height: number): GdalCommand;
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { Epsg, TileMatrixSets } from '@basemaps/geo';
|
|
2
|
+
import { urlToString } from '@basemaps/shared';
|
|
3
|
+
import { Presets } from '../../preset.js';
|
|
4
|
+
const isPowerOfTwo = (x) => (x & (x - 1)) === 0;
|
|
5
|
+
/**
|
|
6
|
+
* Topographic mapsheets are rendered generally at 1:600 dpi,
|
|
7
|
+
*
|
|
8
|
+
* A topo50 mapsheet 1:600dpi does not perfectly align to full pixels and approximatly 1.7 pixels
|
|
9
|
+
* of empty space is rendered at the edge of every mapsheet.
|
|
10
|
+
*
|
|
11
|
+
*/
|
|
12
|
+
const DefaultTrimPixelRight = 1.7; // 1.7 pixels to trim from the right side of the topo raster imagery
|
|
13
|
+
export function gdalBuildVrt(targetVrt, source, addalpha) {
|
|
14
|
+
if (source.length === 0)
|
|
15
|
+
throw new Error('No source files given for :' + targetVrt.href);
|
|
16
|
+
return {
|
|
17
|
+
output: targetVrt,
|
|
18
|
+
command: 'gdalbuildvrt',
|
|
19
|
+
args: [addalpha ? ['-addalpha'] : undefined, urlToString(targetVrt), ...source.map(urlToString)]
|
|
20
|
+
.filter((f) => f != null)
|
|
21
|
+
.flat()
|
|
22
|
+
.map(String),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
export function gdalBuildVrtWarp(targetVrt, sourceVrt, sourceProjection, cutline, opt) {
|
|
26
|
+
const tileMatrix = TileMatrixSets.find(opt.tileMatrix);
|
|
27
|
+
if (tileMatrix == null)
|
|
28
|
+
throw new Error('Unable to find tileMatrix: ' + opt.tileMatrix);
|
|
29
|
+
const targetResolution = tileMatrix.pixelScale(opt.zoomLevel);
|
|
30
|
+
return {
|
|
31
|
+
output: targetVrt,
|
|
32
|
+
command: 'gdalwarp',
|
|
33
|
+
args: [
|
|
34
|
+
['-of', 'vrt'], // Output as a VRT
|
|
35
|
+
// ['-co', 'compress=lzw'],
|
|
36
|
+
// ['-co', 'bigtiff=yes'],
|
|
37
|
+
'-multi', // Mutithread IO
|
|
38
|
+
['-wo', 'NUM_THREADS=ALL_CPUS'], // Multithread the warp
|
|
39
|
+
['-s_srs', Epsg.get(sourceProjection).toEpsgString()], // Source EPSG
|
|
40
|
+
['-t_srs', tileMatrix.projection.toEpsgString()], // Target EPSG
|
|
41
|
+
['-tr', targetResolution, targetResolution],
|
|
42
|
+
opt.warpResampling ? ['-r', opt.warpResampling] : undefined,
|
|
43
|
+
cutline.url ? ['-cutline', urlToString(cutline.url), '-cblend', cutline.blend] : undefined,
|
|
44
|
+
urlToString(sourceVrt),
|
|
45
|
+
urlToString(targetVrt),
|
|
46
|
+
]
|
|
47
|
+
.filter((f) => f != null)
|
|
48
|
+
.flat()
|
|
49
|
+
.map(String),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
export function gdalBuildCog(targetTiff, sourceVrt, opt) {
|
|
53
|
+
const cfg = { ...Presets[opt.preset], ...opt };
|
|
54
|
+
const tileMatrix = TileMatrixSets.find(cfg.tileMatrix);
|
|
55
|
+
if (tileMatrix == null)
|
|
56
|
+
throw new Error('Unable to find tileMatrix: ' + cfg.tileMatrix);
|
|
57
|
+
const bounds = tileMatrix.tileToSourceBounds(cfg.tile);
|
|
58
|
+
const tileExtent = [
|
|
59
|
+
Math.min(bounds.x, bounds.right),
|
|
60
|
+
Math.min(bounds.y, bounds.bottom),
|
|
61
|
+
Math.max(bounds.x, bounds.right),
|
|
62
|
+
Math.max(bounds.y, bounds.bottom),
|
|
63
|
+
];
|
|
64
|
+
const targetResolution = tileMatrix.pixelScale(cfg.zoomLevel);
|
|
65
|
+
return {
|
|
66
|
+
command: 'gdal_translate',
|
|
67
|
+
output: targetTiff,
|
|
68
|
+
args: [
|
|
69
|
+
['-of', 'COG'],
|
|
70
|
+
['-co', 'NUM_THREADS=ALL_CPUS'], // Use all CPUS
|
|
71
|
+
['--config', 'GDAL_NUM_THREADS', 'all_cpus'], // Also required to NUM_THREADS till gdal 3.7.x
|
|
72
|
+
['-co', 'BIGTIFF=IF_NEEDED'], // BigTiff is somewhat slower and most (All?) of the COGS should be well below 4GB
|
|
73
|
+
['-co', 'ADD_ALPHA=YES'],
|
|
74
|
+
/**
|
|
75
|
+
* GDAL will recompress existing overviews if they exist which will compound
|
|
76
|
+
* any lossly compression on the overview, so compute new overviews instead
|
|
77
|
+
*/
|
|
78
|
+
['-co', 'OVERVIEWS=IGNORE_EXISTING'],
|
|
79
|
+
['-co', `BLOCKSIZE=${cfg.blockSize}`],
|
|
80
|
+
// ['-co', 'RESAMPLING=cubic'],
|
|
81
|
+
['-co', `WARP_RESAMPLING=${cfg.warpResampling}`],
|
|
82
|
+
['-co', `OVERVIEW_RESAMPLING=${cfg.overviewResampling}`],
|
|
83
|
+
['-co', `COMPRESS=${cfg.compression}`],
|
|
84
|
+
cfg.quality ? ['-co', `QUALITY=${cfg.quality}`] : undefined,
|
|
85
|
+
cfg.maxZError ? ['-co', `MAX_Z_ERROR=${cfg.maxZError}`] : undefined,
|
|
86
|
+
cfg.maxZErrorOverview ? ['-co', `MAX_Z_ERROR_OVERVIEW=${cfg.maxZErrorOverview}`] : undefined,
|
|
87
|
+
['-co', 'SPARSE_OK=YES'],
|
|
88
|
+
['-co', `TARGET_SRS=${tileMatrix.projection.toEpsgString()}`],
|
|
89
|
+
['-co', `EXTENT=${tileExtent.join(',')},`],
|
|
90
|
+
['-tr', targetResolution, targetResolution],
|
|
91
|
+
urlToString(sourceVrt),
|
|
92
|
+
urlToString(targetTiff),
|
|
93
|
+
]
|
|
94
|
+
.filter((f) => f != null)
|
|
95
|
+
.flat()
|
|
96
|
+
.map(String),
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Creates an empty tiff where all pixel values are set to the given color.
|
|
101
|
+
* Used to force a background so that there are no empty pixels in the final COG.
|
|
102
|
+
*
|
|
103
|
+
* @param targetTiff the file path and name for the created tiff
|
|
104
|
+
* @param color the color to set all pixel values
|
|
105
|
+
* @param opt a CogifyCreationOptions object
|
|
106
|
+
*
|
|
107
|
+
* @returns a 'gdal_create' GdalCommand object
|
|
108
|
+
*/
|
|
109
|
+
export function gdalCreate(targetTiff, color, opt) {
|
|
110
|
+
const cfg = { ...Presets[opt.preset], ...opt };
|
|
111
|
+
const tileMatrix = TileMatrixSets.find(cfg.tileMatrix);
|
|
112
|
+
if (tileMatrix == null)
|
|
113
|
+
throw new Error('Unable to find tileMatrix: ' + cfg.tileMatrix);
|
|
114
|
+
const bounds = tileMatrix.tileToSourceBounds(cfg.tile);
|
|
115
|
+
const pixelScale = tileMatrix.pixelScale(cfg.zoomLevel);
|
|
116
|
+
const size = Math.round(bounds.width / pixelScale);
|
|
117
|
+
// if the value of 'size' is not a power of 2
|
|
118
|
+
if (!isPowerOfTwo(size))
|
|
119
|
+
throw new Error('Size did not compute to a power of 2');
|
|
120
|
+
return {
|
|
121
|
+
command: 'gdal_create',
|
|
122
|
+
output: targetTiff,
|
|
123
|
+
args: [
|
|
124
|
+
['-of', 'GTiff'],
|
|
125
|
+
['-outsize', size, size], // set the size to match that of the final COG
|
|
126
|
+
['-bands', '4'],
|
|
127
|
+
['-burn', `${color.r} ${color.g} ${color.b} ${color.alpha}`], // set all pixel values to the given color
|
|
128
|
+
['-a_srs', tileMatrix.projection.toEpsgString()],
|
|
129
|
+
['-a_ullr', bounds.x, bounds.bottom, bounds.right, bounds.y],
|
|
130
|
+
['-co', 'COMPRESS=LZW'],
|
|
131
|
+
urlToString(targetTiff),
|
|
132
|
+
]
|
|
133
|
+
.filter((f) => f != null)
|
|
134
|
+
.flat()
|
|
135
|
+
.map(String),
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Build a topographic mapsheet cog
|
|
140
|
+
*
|
|
141
|
+
* This is specific configuration to LINZ's topo50 and 250 mapsheets
|
|
142
|
+
*/
|
|
143
|
+
export function gdalBuildTopoRasterCommands(targetTiff, sourceVrt, opt, width, height) {
|
|
144
|
+
const command = {
|
|
145
|
+
command: 'gdal_translate',
|
|
146
|
+
output: targetTiff,
|
|
147
|
+
args: [
|
|
148
|
+
['-q'], // Supress non-error output
|
|
149
|
+
['-stats'], // Force stats (re)computation
|
|
150
|
+
['-of', 'COG'], // Output format
|
|
151
|
+
['-srcwin', '0', '0', `${width - DefaultTrimPixelRight}`, `${height}`],
|
|
152
|
+
['-a_srs', `EPSG:${opt.sourceEpsg}`],
|
|
153
|
+
// https://gdal.org/en/latest/drivers/raster/cog.html#creation-options
|
|
154
|
+
['-co', 'BIGTIFF=NO'],
|
|
155
|
+
['-co', 'BLOCKSIZE=512'],
|
|
156
|
+
['-co', 'COMPRESS=WEBP'],
|
|
157
|
+
['-co', 'NUM_THREADS=ALL_CPUS'], // Use all CPUS
|
|
158
|
+
['-co', 'OVERVIEW_COMPRESS=WEBP'],
|
|
159
|
+
['-co', 'OVERVIEWS=IGNORE_EXISTING'],
|
|
160
|
+
['-co', 'OVERVIEW_QUALITY=90'],
|
|
161
|
+
['-co', 'OVERVIEW_RESAMPLING=LANCZOS'],
|
|
162
|
+
['-co', 'QUALITY=100'],
|
|
163
|
+
['-co', 'SPARSE_OK=TRUE'], // Allow for sparse writes
|
|
164
|
+
// https://gdal.org/en/latest/drivers/raster/cog.html#reprojection-related-creation-options
|
|
165
|
+
['-co', 'ADD_ALPHA=YES'],
|
|
166
|
+
urlToString(sourceVrt),
|
|
167
|
+
urlToString(targetTiff),
|
|
168
|
+
]
|
|
169
|
+
.filter((f) => f != null)
|
|
170
|
+
.flat()
|
|
171
|
+
.map(String),
|
|
172
|
+
};
|
|
173
|
+
return command;
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=gdal.command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gdal.command.js","sourceRoot":"","sources":["../../../src/cogify/gdal/gdal.command.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { LogType } from '@basemaps/shared';
|
|
2
|
+
import { EventEmitter } from 'events';
|
|
3
|
+
export interface GdalCommand {
|
|
4
|
+
/** Output file location */
|
|
5
|
+
output: URL;
|
|
6
|
+
/** GDAL command to use */
|
|
7
|
+
command: 'gdal_create' | 'gdalwarp' | 'gdalbuildvrt' | 'gdal_translate';
|
|
8
|
+
/** GDAL arguments to use */
|
|
9
|
+
args: string[];
|
|
10
|
+
}
|
|
11
|
+
export declare class GdalRunner {
|
|
12
|
+
parser: GdalProgressParser;
|
|
13
|
+
startTime: number;
|
|
14
|
+
cmd: GdalCommand;
|
|
15
|
+
constructor(cmd: GdalCommand);
|
|
16
|
+
/**
|
|
17
|
+
* Run a GDAL command
|
|
18
|
+
*
|
|
19
|
+
* @param logger logger to use
|
|
20
|
+
*/
|
|
21
|
+
run(logger?: LogType): Promise<{
|
|
22
|
+
stdout: string;
|
|
23
|
+
stderr: string;
|
|
24
|
+
duration: number;
|
|
25
|
+
}>;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Emit a "progress" event every time a "." is recorded in the output
|
|
29
|
+
*/
|
|
30
|
+
export declare class GdalProgressParser extends EventEmitter<{
|
|
31
|
+
progress: [number];
|
|
32
|
+
}> {
|
|
33
|
+
waitNewLine: boolean;
|
|
34
|
+
dotCount: number;
|
|
35
|
+
byteCount: number;
|
|
36
|
+
lastEmit: number;
|
|
37
|
+
debounceMs: number;
|
|
38
|
+
/** Reset the progress counter */
|
|
39
|
+
reset(): void;
|
|
40
|
+
get progress(): number;
|
|
41
|
+
data(data: Buffer): void;
|
|
42
|
+
}
|