Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
2331cfc
Support NZTM mbtiles creation.
Wentao-Kuang Jun 9, 2025
a34548b
Parse the line into feature first
Wentao-Kuang Jun 9, 2025
0774559
Fix linting
Wentao-Kuang Jun 9, 2025
a42de07
Fix the output path for argo
Wentao-Kuang Jun 9, 2025
e114e56
Support points and lines
Wentao-Kuang Jun 9, 2025
e06f936
Fix the zoom truncates
Wentao-Kuang Jun 10, 2025
deab948
Update the target
Wentao-Kuang Jun 10, 2025
b7b81d9
Fix tippicanoe zooms for nztm
Wentao-Kuang Jun 10, 2025
f0925fd
Remove the style setting in tippecaone, and use the one in feature only
Wentao-Kuang Jun 10, 2025
71668e3
Fix the water line layer and poi layer for zoom levels
Wentao-Kuang Jun 10, 2025
8f7c02e
Fix poi schema
Wentao-Kuang Jun 10, 2025
4f2cd33
Covert building polygons into poi and fix the tagging should after si…
Wentao-Kuang Jun 10, 2025
d42acac
Building is multipolygons
Wentao-Kuang Jun 10, 2025
b858457
Fix the feature been modified by simplify
Wentao-Kuang Jun 11, 2025
b1c8cb2
Find get the _derived_area for large lakes
Wentao-Kuang Jun 11, 2025
24cb42e
Fix the zoom level
Wentao-Kuang Jun 11, 2025
6dcee9d
Merge branch 'master' into feat/nztm-mbtiles
Wentao-Kuang Jun 11, 2025
1dce3a6
Resolve merge conflics
Wentao-Kuang Jun 11, 2025
a698b22
Fix the types
Wentao-Kuang Jun 11, 2025
a644ec4
Revert the paths for extract
Wentao-Kuang Jun 11, 2025
d6d99b6
Fix the major highways tagging
Wentao-Kuang Jun 13, 2025
f2c7574
Fix the road schema
Wentao-Kuang Jun 13, 2025
0544495
Merge branch 'master' into feat/nztm-mbtiles
Wentao-Kuang Jun 13, 2025
7f01ee5
Only update zoom 8 road feature to be major high ways
Wentao-Kuang Jun 15, 2025
616c74b
Fix the river can be overlapping
Wentao-Kuang Jun 15, 2025
0406384
keep the highways below zoom 8
Wentao-Kuang Jun 15, 2025
22ac997
Update includeDerivedArea
Wentao-Kuang Jun 16, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/cli-vector/schema/place_labels.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "place_labels",
"metadata": { "attributes": ["water", "name", "natural", "place"] },
"metadata": { "attributes": ["kind", "water", "name", "natural", "place"] },
"layers": [
{
"id": "51154",
Expand Down
14 changes: 14 additions & 0 deletions packages/cli-vector/schema/pois.json
Original file line number Diff line number Diff line change
Expand Up @@ -792,6 +792,20 @@
"source": "s3://linz-lds-cache/103476/",
"tags": { "man_made": "trig_point" },
"style": { "minZoom": 12, "maxZoom": 15 }
},
{
"id": "50245",
"name": "50245-nz-building-points-topo-150k",
"source": "s3://linz-lds-cache/50245/",
"tags": { "building": "building" },
"style": { "minZoom": 14, "maxZoom": 15 }
},
{
"id": "50246",
"name": "50246-nz-building-polygons-topo-150k",
"source": "s3://linz-lds-cache/50246/",
"tags": { "building": "building" },
"style": { "minZoom": 14, "maxZoom": 15 }
}
]
}
4 changes: 1 addition & 3 deletions packages/cli-vector/schema/street_labels.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,8 @@
"name": "50329-nz-road-centrelines-topo-150k",
"source": "s3://linz-lds-cache/50329/",
"tags": { "kind": "road" },
"style": { "minZoom": 8, "maxZoom": 15 },
"style": { "minZoom": 2, "maxZoom": 15 },
"simplify": [
{ "style": { "minZoom": 0, "maxZoom": 0 }, "tolerance": 0.1 },
{ "style": { "minZoom": 1, "maxZoom": 1 }, "tolerance": 0.01 },
{ "style": { "minZoom": 2, "maxZoom": 2 }, "tolerance": 0.01 },
{ "style": { "minZoom": 3, "maxZoom": 3 }, "tolerance": 0.03 },
{ "style": { "minZoom": 4, "maxZoom": 4 }, "tolerance": 0.008 },
Expand Down
4 changes: 1 addition & 3 deletions packages/cli-vector/schema/streets.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,8 @@
"name": "50329-nz-road-centrelines-topo-150k",
"source": "s3://linz-lds-cache/50329/",
"tags": { "kind": "road" },
"style": { "minZoom": 8, "maxZoom": 15 },
"style": { "minZoom": 2, "maxZoom": 15 },
"simplify": [
{ "style": { "minZoom": 0, "maxZoom": 0 }, "tolerance": 0.1 },
{ "style": { "minZoom": 1, "maxZoom": 1 }, "tolerance": 0.01 },
{ "style": { "minZoom": 2, "maxZoom": 2 }, "tolerance": 0.01 },
{ "style": { "minZoom": 3, "maxZoom": 3 }, "tolerance": 0.03 },
{ "style": { "minZoom": 4, "maxZoom": 4 }, "tolerance": 0.008 },
Expand Down
24 changes: 16 additions & 8 deletions packages/cli-vector/schema/water_polygons.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,56 +34,64 @@
"name": "50293-nz-lake-polygons-topo-150k",
"source": "s3://linz-lds-cache/50293/",
"tags": { "kind": "water", "water": "lake" },
"style": { "minZoom": 1, "maxZoom": 15 }
"style": { "minZoom": 1, "maxZoom": 15 },
"includeDerivedArea": true
},
{
"id": "50088",
"name": "50088-nz-chatham-island-lake-polygons-topo-150k",
"source": "s3://linz-lds-cache/50088/",
"tags": { "kind": "water", "water": "lake" },
"style": { "minZoom": 0, "maxZoom": 15 }
"style": { "minZoom": 0, "maxZoom": 15 },
"includeDerivedArea": true
},
{
"id": "50894",
"name": "50894-nz-snares-island-tini-heke-lake-polygons-topo-125k",
"source": "s3://linz-lds-cache/50894/",
"tags": { "kind": "water", "water": "lake" },
"style": { "minZoom": 0, "maxZoom": 15 }
"style": { "minZoom": 0, "maxZoom": 15 },
"includeDerivedArea": true
},
{
"id": "50909",
"name": "50909-nz-kermadec-is-lake-polygons-topo-125k",
"source": "s3://linz-lds-cache/50909/",
"tags": { "kind": "water", "water": "lake" },
"style": { "minZoom": 0, "maxZoom": 15 }
"style": { "minZoom": 0, "maxZoom": 15 },
"includeDerivedArea": true
},
{
"id": "50933",
"name": "50933-nz-campbell-island-motu-ihupuku-lake-polygons-topo-150k",
"source": "s3://linz-lds-cache/50933/",
"tags": { "kind": "water", "water": "lake" },
"style": { "minZoom": 0, "maxZoom": 15 }
"style": { "minZoom": 0, "maxZoom": 15 },
"includeDerivedArea": true
},
{
"id": "50960",
"name": "50960-nz-auckland-island-lake-polygons-topo-150k",
"source": "s3://linz-lds-cache/50960/",
"tags": { "kind": "water", "water": "lake" },
"style": { "minZoom": 0, "maxZoom": 15 }
"style": { "minZoom": 0, "maxZoom": 15 },
"includeDerivedArea": true
},
{
"id": "52253",
"name": "52253-cook-islands-lake-polygons-topo-125k-zone4",
"source": "s3://linz-lds-cache/52253/",
"tags": { "kind": "water", "water": "lake" },
"style": { "minZoom": 0, "maxZoom": 15 }
"style": { "minZoom": 0, "maxZoom": 15 },
"includeDerivedArea": true
},
{
"id": "52296",
"name": "52296-cook-islands-lake-polygons-topo-125k-zone3",
"source": "s3://linz-lds-cache/52296/",
"tags": { "kind": "water", "water": "lake" },
"style": { "minZoom": 0, "maxZoom": 15 }
"style": { "minZoom": 0, "maxZoom": 15 },
"includeDerivedArea": true
},
{
"id": "50298",
Expand Down
9 changes: 6 additions & 3 deletions packages/cli-vector/src/cli/cli.create.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { TileMatrixSets } from '@basemaps/geo';
import { fsa, LogType, Url, UrlArrayJsonFile } from '@basemaps/shared';
import { CliInfo } from '@basemaps/shared/build/cli/info.js';
import { getLogger, logArguments } from '@basemaps/shared/build/cli/log.js';
Expand Down Expand Up @@ -173,6 +174,8 @@ async function createMbtilesFile(

const layer = options.layer;
const shortbreadLayer = options.name;
const tileMatrix = TileMatrixSets.find(options.tileMatrix);
if (tileMatrix == null) throw new Error(`Tile matrix ${options.tileMatrix} is not supported`);

logger.info({ shortbreadLayer, dataset: layer.name }, 'CreateMbtilesFile: Start');

Expand All @@ -181,7 +184,7 @@ async function createMbtilesFile(
*/
logger.info({ source: tmpPaths.source.path, dataset: layer.name }, '[1/5] Convert source file to ndjson: Start');
if (!(await fsa.exists(tmpPaths.ndjson))) {
await ogr2ogrNDJson(tmpPaths.source.path, tmpPaths.ndjson, logger);
await ogr2ogrNDJson(tmpPaths.source.path, tmpPaths.ndjson, layer, logger);
}
logger.info({ destination: tmpPaths.ndjson, dataset: layer.name }, '[1/5] Convert source file to ndjson: End');

Expand All @@ -191,7 +194,7 @@ async function createMbtilesFile(
logger.info({ source: tmpPaths.ndjson, dataset: layer.name }, '[2/5] Generalise ndjson features: Start');
let metrics: Metrics | null = null;
if (!(await fsa.exists(tmpPaths.genNdjson))) {
metrics = await generalize(tmpPaths.ndjson, tmpPaths.genNdjson, options, logger);
metrics = await generalize(tmpPaths.ndjson, tmpPaths.genNdjson, tileMatrix, options, logger);
if (metrics.output === 0) throw new Error(`Failed to generalize ndjson file ${tmpPaths.ndjson.href}`);
}
logger.info({ destination: tmpPaths.genNdjson, dataset: layer.name }, '[2/5] Generalise ndjson features: End');
Expand All @@ -204,7 +207,7 @@ async function createMbtilesFile(
'[3/5] Transform generalised ndjson into mbtiles: Start',
);
if (!(await fsa.exists(tmpPaths.mbtiles))) {
await tippecanoe(tmpPaths.genNdjson, tmpPaths.mbtiles, layer, logger);
await tippecanoe(tmpPaths.genNdjson, tmpPaths.mbtiles, layer, tileMatrix, logger);
}
logger.info(
{ destination: tmpPaths.mbtiles, dataset: layer.name },
Expand Down
2 changes: 1 addition & 1 deletion packages/cli-vector/src/cli/cli.extract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export const ExtractCommand = command({

// Find all lds layers that need to be process
logger.info({ schema: args.schema }, 'Extract: Start');
const schemaLoader = new SchemaLoader(args.schema, logger, cache);
const schemaLoader = new SchemaLoader(args.schema, tileMatrix, logger, cache);
const schemas = await schemaLoader.load();
const smallLayers = [];
const largeLayers = [];
Expand Down
4 changes: 2 additions & 2 deletions packages/cli-vector/src/cli/cli.join.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { TileMatrixSets } from '@basemaps/geo';
import { fsa, isArgo, LogType, Url, UrlArrayJsonFile } from '@basemaps/shared';
import { fsa, isArgo, LogType, Url, UrlArrayJsonFile, urlToString } from '@basemaps/shared';
import { CliId, CliInfo } from '@basemaps/shared/build/cli/info.js';
import { getLogger, logArguments } from '@basemaps/shared/build/cli/log.js';
import { command, option, optional, string } from 'cmd-ts';
Expand Down Expand Up @@ -145,7 +145,7 @@ export const JoinCommand = command({
// Write output target for argo tasks to create pull request
if (isArgo()) {
const target = new URL(`topographic/${CliId}/${args.filename}.tar.co`, bucketPath);
await fsa.write(fsa.toUrl('/tmp/target'), JSON.stringify([target]));
await fsa.write(fsa.toUrl('/tmp/target'), urlToString(target));
const mbTilesTarget = new URL(`topographic/${CliId}/${args.filename}.mbtiles`, bucketPath);
await fsa.write(fsa.toUrl('/tmp/mbTilesTarget'), mbTilesTarget.toString());
const analyseTarget = new URL(`topographic/${CliId}/`, bucketPath);
Expand Down
58 changes: 35 additions & 23 deletions packages/cli-vector/src/generalization/generalization.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { TileMatrixSet } from '@basemaps/geo';
import { LogType } from '@basemaps/shared';
import { createWriteStream } from 'fs';
import { Geometry, LineString, MultiPolygon, Polygon } from 'geojson';
import { Feature, Geometry, LineString, MultiPolygon, Polygon } from 'geojson';
import readline from 'readline';

import { modifyFeature } from '../modify/modify.js';
import { Metrics, Simplify } from '../schema-loader/schema.js';
import { VectorCreationOptions } from '../stac.js';
import { transformNdJson, transformZoom } from '../transform/nztm.js';
import { VectorGeoFeature } from '../types/VectorGeoFeature.js';
import { createReadStreamSafe } from '../util.js';
import { Point, simplify } from './simplify.js';
Expand All @@ -18,6 +20,7 @@ import { Point, simplify } from './simplify.js';
export async function generalize(
input: URL,
output: URL,
tileMatrix: TileMatrixSet,
options: VectorCreationOptions,
logger: LogType,
): Promise<Metrics> {
Expand All @@ -36,21 +39,23 @@ export async function generalize(
let outputCount = 0;
for await (const line of rl) {
if (line === '') continue;
const feature = JSON.parse(line) as Feature;
if (tileMatrix.identifier === 'NZTM2000Quad') transformNdJson(feature);
inputCount++;
// For simplify, duplicate feature for each zoom level with different tolerance
if (simplify != null) {
for (const s of simplify) {
const feature = tag(options, line, s, logger);
if (feature == null) continue;
const vectorGeofeature = tag(tileMatrix, options, feature, s, logger);
if (vectorGeofeature == null) continue;

writeStream.write(JSON.stringify(feature) + '\n');
writeStream.write(JSON.stringify(vectorGeofeature) + '\n');
outputCount++;
}
} else {
const feature = tag(options, line, null, logger);
if (feature == null) continue;
const vectorGeofeature = tag(tileMatrix, options, feature, null, logger);
if (vectorGeofeature == null) continue;

writeStream.write(JSON.stringify(feature) + '\n');
writeStream.write(JSON.stringify(vectorGeofeature) + '\n');
outputCount++;
}
}
Expand All @@ -72,13 +77,14 @@ export async function generalize(
* Tag feature for layer
*/
function tag(
tileMatrix: TileMatrixSet,
options: VectorCreationOptions,
line: string,
feature: Feature,
simplify: Simplify | null,
logger: LogType,
): VectorGeoFeature | null {
const feature = {
...JSON.parse(line),
const vectorGeofeature = {
...structuredClone(feature),
tippecanoe: {
layer: options.name,
minzoom: options.layer.style.minZoom,
Expand All @@ -87,35 +93,41 @@ function tag(
} as VectorGeoFeature;

// copy the stac json's tags to the feature (i.e. 'kind')
Object.entries(options.layer.tags).forEach(([key, value]) => (feature.properties[key] = value));

// adjust the feature's metadata and properties
const modifiedFeature = modifyFeature(feature, options, logger);
if (modifiedFeature == null) {
return null;
}
Object.entries(options.layer.tags).forEach(([key, value]) => (vectorGeofeature.properties[key] = value));

// Simplify geometry
if (simplify != null) {
// Update the simplified feature zoom level
modifiedFeature['tippecanoe'] = {
vectorGeofeature['tippecanoe'] = {
layer: options.name,
minzoom: simplify.style.minZoom,
maxzoom: simplify.style.maxZoom,
};
if (simplify.tolerance != null) {
const geom = modifiedFeature.geometry;
const geom = vectorGeofeature.geometry;
const type = geom.type;
const coordinates = simplifyFeature(type, geom, simplify.tolerance);
if (coordinates == null) {
const geometry = simplifyFeature(type, geom, simplify.tolerance);
if (geometry == null) {
return null;
}
modifiedFeature.geometry = coordinates;
vectorGeofeature.geometry = geometry;
}
}

// adjust the feature's metadata and properties
const modifiedFeature = modifyFeature(vectorGeofeature, options, logger);
if (modifiedFeature == null) {
return null;
}

// Skip features that maxzoom is less than minzoom, this could happened after simplification and special tags on zoom levels
if (modifiedFeature.tippecanoe.maxzoom < modifiedFeature.tippecanoe.minzoom) return null;

// Transform zoom level for NZTM2000Quad
modifiedFeature.tippecanoe.minzoom = transformZoom(modifiedFeature.tippecanoe.minzoom, tileMatrix);
modifiedFeature.tippecanoe.maxzoom = transformZoom(modifiedFeature.tippecanoe.maxzoom, tileMatrix);

// Remove unused properties
// REVIEW: this function just removes the special tags. something isn't right here
const cleanedFeature = removeAttributes(modifiedFeature, options);
return cleanedFeature;
}
Expand Down
12 changes: 3 additions & 9 deletions packages/cli-vector/src/modify/layers/place_labels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export function handleLayerPlaceLabels(feature: VectorGeoFeature, logger: LogTyp
const zoomLevel = feature.properties['zoom_level'];
if (typeof zoomLevel !== 'number') throw new Error('Zoom level is not a number');

//DATA PROBLEM: We need to store the first feature which have all the propertie values, the duplicate features will only have null values in the properties
const storedFeature = PlaceLabelsFeatures.get(label);
if (storedFeature == null) {
const newFeature = createNewFeature(feature, label, zoomLevel, logger);
Expand All @@ -48,16 +49,9 @@ export function handleLayerPlaceLabels(feature: VectorGeoFeature, logger: LogTyp
}

// update the stored feature's 'minzoom' value
if (zoomLevel < storedFeature.tippecanoe.minzoom) {
storedFeature.tippecanoe.minzoom = zoomLevel;
PlaceLabelsFeatures.set(label, storedFeature);
}

storedFeature.tippecanoe.minzoom = zoomLevel;
// update the stored feature's 'maxzoom' value
if (zoomLevel > storedFeature.tippecanoe.maxzoom) {
storedFeature.tippecanoe.maxzoom = zoomLevel;
PlaceLabelsFeatures.set(label, storedFeature);
}
storedFeature.tippecanoe.maxzoom = zoomLevel;

logger.trace({}, 'HandlePlaceLabels:End');
return storedFeature;
Expand Down
14 changes: 11 additions & 3 deletions packages/cli-vector/src/modify/layers/pois.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { LogType } from '@basemaps/shared';
import { Point } from 'geojson';

import { VectorGeoFeature } from '../../types/VectorGeoFeature.js';
import { getCoordinates, polylabel } from '../shared.js';

/**
* Processes a 'pois' layer feature.
Expand All @@ -14,9 +16,6 @@ export function handleLayerPois(feature: VectorGeoFeature, logger: LogType): Vec
logger.trace({}, 'HandlePois:Start');
feature = structuredClone(feature);

// REVIEW: We don't have any use for this criteria as we don't include the following layers:
// 1. 50245-nz-building-points-topo-150k
// 2. 50246-nz-building-polygons-topo-150k
if (feature.properties['building'] === 'building') {
const bldgUse = feature.properties['bldg_use'];

Expand All @@ -27,6 +26,15 @@ export function handleLayerPois(feature: VectorGeoFeature, logger: LogType): Vec
}

feature.properties['building'] = bldgUse;

// Covert the building polygon to a point for 50246-nz-building-polygons-topo-150k
if (feature.geometry.type === 'Polygon' || feature.geometry.type === 'MultiPolygon') {
const coordinates = getCoordinates(feature.geometry, logger);
const inaccessibilityPole = polylabel(coordinates);

const point: Point = { type: 'Point', coordinates: inaccessibilityPole };
feature.geometry = point;
}
}

logger.trace({}, 'HandlePois:End');
Expand Down
Loading