diff --git a/__fixtures__/biomes-test-large.png b/__fixtures__/biomes-test-large.png new file mode 100644 index 0000000..6f6545a Binary files /dev/null and b/__fixtures__/biomes-test-large.png differ diff --git a/__fixtures__/mercator.png b/__fixtures__/mercator.png new file mode 100644 index 0000000..13c0d20 Binary files /dev/null and b/__fixtures__/mercator.png differ diff --git a/__fixtures__/ph.png b/__fixtures__/ph.png new file mode 100644 index 0000000..e4b8ce0 Binary files /dev/null and b/__fixtures__/ph.png differ diff --git a/__fixtures__/robinson.png b/__fixtures__/robinson.png new file mode 100644 index 0000000..b508ea6 Binary files /dev/null and b/__fixtures__/robinson.png differ diff --git a/__fixtures__/sinusoidal.png b/__fixtures__/sinusoidal.png new file mode 100644 index 0000000..7b68006 Binary files /dev/null and b/__fixtures__/sinusoidal.png differ diff --git a/__fixtures__/world.png b/__fixtures__/world.png new file mode 100644 index 0000000..2aaef8c Binary files /dev/null and b/__fixtures__/world.png differ diff --git a/src/index.ts b/src/index.ts index 0535fee..62e847d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,10 +1,57 @@ import yargs from 'yargs'; import { hideBin } from 'yargs/helpers'; -import { project } from '@theoryofnekomata/orbis-core'; +import { project, Bounds } from '@theoryofnekomata/orbis-core'; import { writeFile } from 'fs/promises'; import { basename, dirname, resolve } from 'path'; -type ProjectArgs = { input: string, projection: string, output?: string }; +type ProjectArgs = { + input: string, + projection: string, + output?: string, + bounds: Bounds, + width?: number, + height?: number, + padding: [number, number], +}; + +const coerceNumber = (n?: string) => { + if (typeof n === 'undefined') { + return undefined; + } + const tryWidth = Number(n); + if (Number.isFinite(tryWidth)) { + return tryWidth; + } + return undefined; +}; + +const coercePadding = (n?: string) => { + if (typeof n !== 'string') { + return [0, 0]; + } + const [paddingXString = '0', paddingYString = paddingXString] = n.split(';'); + return [ + Number(paddingXString), + Number(paddingYString), + ]; +}; + +const coerceBounds = (n?: string): Bounds => { + if (typeof n !== 'string') { + return [ + [-180, 90], + [180, -90], + ] as Bounds; + } + + return n + .split(';') + .map((p) => ( + p + .split(',') + .map((c: string) => Number(c)) + )) as Bounds; +}; const main = async (argv: string | readonly string[]) => { await yargs @@ -19,9 +66,6 @@ const main = async (argv: string | readonly string[]) => { .option('output', { alias: 'o', }) - .option('width', { - alias: 'w', - }) .coerce('output', (output) => { if (!output) { return null; @@ -31,17 +75,46 @@ const main = async (argv: string | readonly string[]) => { } return output; }) + .option('width', { + alias: 'w', + }) + .coerce('width', coerceNumber) + .option('height', { + alias: 'h', + }) + .coerce('height', coerceNumber) + .option('padding', { + alias: 'p', + default: [0, 0], + }) + .coerce('padding', coercePadding) .option('bounds', { alias: 'b', - default: '-180,90;180,-90', - }), + default: [[-180, 90], [180, -90]], + }) + .coerce('bounds', coerceBounds), handler: async (projectArgvRaw) => { const projectArgv = projectArgvRaw as unknown as ProjectArgs; - const outputPng = await project(projectArgv.input, [projectArgv.projection]); + const outputPng = await project(projectArgv.input, [projectArgv.projection], { + bounds: projectArgv.bounds, + wrapAround: false, + outputSize: { + width: projectArgv.width, + height: projectArgv.height, + }, + outputPadding: { + x: projectArgv.padding[0], + y: projectArgv.padding[1], + }, + }); + if (!outputPng) { + process.stdout.write('No output created.\n'); + return; + } const outputFilename = projectArgv.output ?? `${basename(projectArgv.input, '.png')}.out.png`; const outputPath = resolve( dirname(projectArgv.input), - outputFilename.endsWith('.png') ? outputFilename : `${outputFilename}.png` + outputFilename.endsWith('.png') ? outputFilename : `${outputFilename}.png`, ); await writeFile(outputPath, outputPng); process.stdout.write(`Created output file: ${outputPath}\n`);