diff --git a/README.md b/README.md index 1ff7720..1c80343 100644 --- a/README.md +++ b/README.md @@ -19,8 +19,8 @@ Options: --version Show version number [boolean] -i, --input GeoPackage file [string] -o, --output Output quads file [string] - --bounding-box Limit features to bounding box [string] - --bounding-box-crs Coordinate Reference System code [string] + --bbox Limit features to bounding box [string] + --bbox-crs Coordinate Reference System code [string] --only-layers Only output named feature layers and attribute ta bles [array] --base-iri Base IRI [string] @@ -32,9 +32,9 @@ Options: ## Options -Limit **large GeoPackages** with `--bounding-box`. +Limit **large GeoPackages** with `--bbox`. Supply a space separated list of coordinates as a string to limit the Features returned. -Provide the bounding box as WGS84 (GeoJSON default) or supply a CRS code (lookup via EPSG.io) or Projection WKT with `--bounding-box-crs`. +Provide the bounding box as WGS84 (GeoJSON default) or supply a CRS code (lookup via EPSG.io) or Projection WKT with `--bbox-crs`. You can also **limit** which feature **layers** (or attribute tables) are output with `--only-layers`. **NULL values** are never output and **binary values** are skipped, unless `--include-binary-values` is provided. @@ -60,7 +60,7 @@ That Geometry in turn has a `geo:asGeoJSON` and `geo:asWKT` representations of t Column metadata is very limited and most values are not typed properly. Example data abridged [from NGA][example.gpkg]: -the table `media`is a feature table, `nga_properties` is an attribute table. +the table `media` is a feature table, `nga_properties` is an attribute table. ```trig xyz:media { diff --git a/src/bounding-box.ts b/src/bounding-box.ts index 462d7b1..89f500b 100644 --- a/src/bounding-box.ts +++ b/src/bounding-box.ts @@ -42,20 +42,61 @@ export async function getWGS84Converter( } } -export function suppliedBoundingBox( +function spaceSepBbox( + bbstring: string, + srs: proj4.Converter | string, +): BoundingBox { + const [west, east, south, north] = bbstring + .split(" ", 4) + .map((c) => Number(c)); + const bb = new BoundingBox(west, east, south, north); + return bb.projectBoundingBox(srs, WGS84_CODE); +} + +function commaSepBbox( bbstring: string, - inCRS: proj4.Converter | string, -) { + srs: proj4.Converter | string, +): BoundingBox { + const parts = bbstring.split(","); + let west: string, + east: string, + __1: string, + south: string, + north: string, + __2: string; + if (parts.length == 4) [west, east, south, north] = parts; + else [west, east, __1, south, north, __2] = parts; + + const bb = new BoundingBox( + Number(west), + Number(east), + Number(south), + Number(north), + ); + return bb.projectBoundingBox(srs, WGS84_CODE); +} + +/** + * Convert a supplied bbox definition string to a {BoundingBox}. + * + * There are two types of bbox definition strings: + * 1. Four parts, space separated (deprecated) + * 2. Four or six parts, comma separated. (3rd axis ignored) + * + * @param bboxString Bouding box provided string + * @param srs The SRS in which to interpret this bboxstring + */ +export function suppliedBoundingBox( + bboxString: string, + srs: proj4.Converter | string, +): BoundingBox { try { - const [west, east, south, north] = bbstring - .split(" ", 4) - .map((c) => Number(c)); - const bb = new BoundingBox(west, east, south, north); - return bb.projectBoundingBox(inCRS, WGS84_CODE); + if (bboxString.includes(" ")) return spaceSepBbox(bboxString, srs); + return commaSepBbox(bboxString, srs); } catch (e) { Bye( - `Bounding box could not be parsed. Provide as a single space-separated string:`, - `"{min long (west)} {max long (east)} {min lat (south)} {max lat (north)}".`, + `Bounding box could not be parsed. Provide a single comma-separated string:`, + `"{min long (west)},{max long (east)},{min lat (south)},{max lat (north)}".`, ); } } diff --git a/src/cli.ts b/src/cli.ts index 5b52f89..51b868d 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -41,11 +41,11 @@ async function cli() { }) .option("output", { alias: "o", type: "string", desc: "Output quads file" }) .normalize(["input", "output"]) - .option("bounding-box", { + .option("bbox", { type: "string", desc: "Limit features to bounding box", }) - .option("bounding-box-crs", { + .option("bbox-crs", { type: "string", desc: `Coordinate Reference System code`, }) @@ -87,11 +87,11 @@ async function cli() { // If there's a bounding box CRS defined, first check if we can parse it. // This is less expensive than converting quads etc. // TODO: Can we remove this reference to WGS84? - const bboxConverter = argv.boundingBoxCrs - ? await getWGS84Converter(argv.boundingBoxCrs) + const bboxConverter = argv.bboxCrs + ? await getWGS84Converter(argv.bboxCrs) : await getWGS84Converter(WGS84_CODE); - const boundingBox = argv.boundingBox - ? suppliedBoundingBox(argv.boundingBox, bboxConverter) + const boundingBox = argv.bbox + ? suppliedBoundingBox(argv.bbox, bboxConverter) : undefined; // If there's a target file, open a write stream and determine the mimetype off of it.