Skip to content

Commit

Permalink
fix(cli): refactor projection logic to allow chathams to be built (#854)
Browse files Browse the repository at this point in the history
Source projection does not need to have a TileMatrixSet. This commit removes that constraint.
  • Loading branch information
Geoff Jacobsen committed Jul 3, 2020
1 parent 7e11d4a commit f799006
Show file tree
Hide file tree
Showing 19 changed files with 286 additions and 219 deletions.
2 changes: 1 addition & 1 deletion packages/cli/src/cli/cogify/__test__/action.batch.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import o from 'ospec';
import { CogJob } from '../../../cog/types';
import { extractResolutionFromName, extractYearFromName, createImageryRecordFromJob } from '../action.batch';
import { qkToNamedBounds } from '@basemaps/shared/build/tms/__test__/test.util';
import { qkToNamedBounds } from '@basemaps/shared/build/proj/__test__/test.util';
import { Bounds } from '@basemaps/geo';
import { round } from '@basemaps/test/build/rounding';

Expand Down
4 changes: 2 additions & 2 deletions packages/cli/src/cli/cogify/action.batch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,9 @@ export class ActionBatchJob extends CommandLineAction {
isCommit: boolean,
): Promise<{ jobName: string; jobId: string; memory: number }> {
const jobName = ActionBatchJob.id(job, name);
const targetProj = ProjectionTileMatrixSet.get(job.projection);
const targetPtms = ProjectionTileMatrixSet.get(job.projection);
const tile = TileMatrixSet.nameToTile(name);
const alignmentLevels = targetProj.findAlignmentLevels(tile, job.source.pixelScale);
const alignmentLevels = targetPtms.findAlignmentLevels(tile, job.source.pixelScale);
// Give 25% more memory to larger jobs
const resDiff = 1 + Math.max(alignmentLevels - MagicAlignmentLevel, 0) * 0.25;
const memory = 3900 * resDiff;
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/cog/__test__/cog.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { buildCogForName } from '../cog';
import { SourceTiffTestHelper } from './source.tiff.testhelper';
import { TilingScheme } from '../../gdal/gdal.config';
import { round } from '@basemaps/test/build/rounding';
import { qkToName } from '@basemaps/shared/build/tms/__test__/test.util';
import { qkToName } from '@basemaps/shared/build/proj/__test__/test.util';

LogConfig.disable();

Expand Down
20 changes: 10 additions & 10 deletions packages/cli/src/cog/__test__/cog.vrt.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { EpsgCode } from '@basemaps/geo';
import { FileOperatorSimple, LogConfig, ProjectionTileMatrixSet } from '@basemaps/shared';
import { qkToName } from '@basemaps/shared/build/tms/__test__/test.util';
import { qkToName } from '@basemaps/shared/build/proj/__test__/test.util';
import { round } from '@basemaps/test/build/rounding';
import o from 'ospec';
import { GdalCogBuilder } from '../../gdal/gdal';
Expand All @@ -18,7 +18,7 @@ o.spec('cog.vrt', () => {

const testDir = `${__dirname}/../../../__test.assets__`;

const googleProj = ProjectionTileMatrixSet.get(EpsgCode.Google);
const googlePtms = ProjectionTileMatrixSet.get(EpsgCode.Google);

const sourceBounds = SourceTiffTestHelper.tiffNztmBounds(testDir);
const [tif1, tif2] = sourceBounds;
Expand Down Expand Up @@ -56,8 +56,8 @@ o.spec('cog.vrt', () => {
});

o('1 crosses, 1 outside', async () => {
const cutline = new Cutline(googleProj, await Cutline.loadCutline(testDir + '/kapiti.geojson'));
const cl2 = new Cutline(googleProj, await Cutline.loadCutline(testDir + '/mana.geojson'));
const cutline = new Cutline(googlePtms, await Cutline.loadCutline(testDir + '/kapiti.geojson'));
const cl2 = new Cutline(googlePtms, await Cutline.loadCutline(testDir + '/mana.geojson'));
cutline.clipPoly.push(...cl2.clipPoly);

job.source.resZoom = 17;
Expand All @@ -70,7 +70,7 @@ o.spec('cog.vrt', () => {
});

o('not within tile', async () => {
const cutline = new Cutline(googleProj, await Cutline.loadCutline(testDir + '/kapiti.geojson'));
const cutline = new Cutline(googlePtms, await Cutline.loadCutline(testDir + '/kapiti.geojson'));

const vrt = await CogVrt.buildVrt(tmpFolder, job, cutline, qkToName('3131110001'), logger);

Expand All @@ -80,7 +80,7 @@ o.spec('cog.vrt', () => {
});

o('no cutline same projection', async () => {
const vrt = await CogVrt.buildVrt(tmpFolder, job, new Cutline(googleProj), qkToName('31'), logger);
const vrt = await CogVrt.buildVrt(tmpFolder, job, new Cutline(googlePtms), qkToName('31'), logger);

o(job.source.files).deepEquals([tif1, tif2]);
o(cutTiffArgs.length).equals(0);
Expand All @@ -91,7 +91,7 @@ o.spec('cog.vrt', () => {

o('no cutline diff projection', async () => {
job.projection = EpsgCode.Nztm2000;
const vrt = await CogVrt.buildVrt(tmpFolder, job, new Cutline(googleProj), qkToName('31'), logger);
const vrt = await CogVrt.buildVrt(tmpFolder, job, new Cutline(googlePtms), qkToName('31'), logger);

o(job.source.files).deepEquals([tif1, tif2]);
o(cutTiffArgs.length).equals(0);
Expand All @@ -101,7 +101,7 @@ o.spec('cog.vrt', () => {
});

o('fully within same projection', async () => {
const cutline = new Cutline(googleProj, await Cutline.loadCutline(testDir + '/kapiti.geojson'), -100);
const cutline = new Cutline(googlePtms, await Cutline.loadCutline(testDir + '/kapiti.geojson'), -100);

const name = qkToName('311333222321113310');

Expand All @@ -115,7 +115,7 @@ o.spec('cog.vrt', () => {
});

o('intersected cutline', async () => {
const cutline = new Cutline(googleProj, await Cutline.loadCutline(testDir + '/kapiti.geojson'), 20);
const cutline = new Cutline(googlePtms, await Cutline.loadCutline(testDir + '/kapiti.geojson'), 20);
job.output.cutline = { blend: 20, source: 'cutline.json' };

const name = qkToName('311333222321113');
Expand Down Expand Up @@ -177,7 +177,7 @@ o.spec('cog.vrt', () => {
return o;
});
job.output.cutline = { blend: 10, source: 'cutline.json' };
const cutline = new Cutline(googleProj, await Cutline.loadCutline(testDir + '/mana.geojson'));
const cutline = new Cutline(googlePtms, await Cutline.loadCutline(testDir + '/mana.geojson'));

const vrt = await CogVrt.buildVrt(tmpFolder, job, cutline, qkToName('3131110001'), logger);

Expand Down
22 changes: 11 additions & 11 deletions packages/cli/src/cog/__test__/cutline.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@ import o from 'ospec';
import { Cutline } from '../cutline';
import { SourceMetadata } from '../types';
import { SourceTiffTestHelper } from './source.tiff.testhelper';
import { qkToName } from '@basemaps/shared/build/tms/__test__/test.util';
import { qkToName } from '@basemaps/shared/build/proj/__test__/test.util';

o.spec('cutline', () => {
const testDir = `${__dirname}/../../../__test.assets__`;
const googleProj = ProjectionTileMatrixSet.get(EpsgCode.Google);
const nztmProj = ProjectionTileMatrixSet.get(EpsgCode.Nztm2000);
const googlePtms = ProjectionTileMatrixSet.get(EpsgCode.Google);
const nztmPtms = ProjectionTileMatrixSet.get(EpsgCode.Nztm2000);

o.spec('filterSourcesForName', () => {
o('fully within same projection', async () => {
const cutline = new Cutline(googleProj, await Cutline.loadCutline(testDir + '/kapiti.geojson'), -100);
const cutline = new Cutline(googlePtms, await Cutline.loadCutline(testDir + '/kapiti.geojson'), -100);

const name = qkToName('311333222321113310');

Expand All @@ -34,7 +34,7 @@ o.spec('cutline', () => {
});

o('loadCutline', async () => {
const cutline = new Cutline(googleProj, await Cutline.loadCutline(testDir + '/mana.geojson'));
const cutline = new Cutline(googlePtms, await Cutline.loadCutline(testDir + '/mana.geojson'));
const geojson = cutline.toGeoJson();
const mp = geojson.features[0].geometry as MultiPolygon;
const { coordinates } = mp;
Expand All @@ -58,7 +58,7 @@ o.spec('cutline', () => {
});

o('findCovering', async () => {
const cutline = new Cutline(googleProj, await Cutline.loadCutline(testDir + '/mana.geojson'));
const cutline = new Cutline(googlePtms, await Cutline.loadCutline(testDir + '/mana.geojson'));
const bounds = SourceTiffTestHelper.tiffNztmBounds();

o(cutline.clipPoly.length).equals(2);
Expand All @@ -72,7 +72,7 @@ o.spec('cutline', () => {
const bounds = SourceTiffTestHelper.tiffNztmBounds();

o('nztm', () => {
const cutline = new Cutline(nztmProj);
const cutline = new Cutline(nztmPtms);

const covering = cutline.optimizeCovering({
projection: EpsgCode.Nztm2000,
Expand Down Expand Up @@ -122,7 +122,7 @@ o.spec('cutline', () => {
};

const bounds = [tiff1, tiff2];
const cutline = new Cutline(googleProj, await Cutline.loadCutline(testDir + '/kapiti.geojson'), 500);
const cutline = new Cutline(googlePtms, await Cutline.loadCutline(testDir + '/kapiti.geojson'), 500);

const covering = cutline.optimizeCovering({
projection: EpsgCode.Nztm2000,
Expand Down Expand Up @@ -158,7 +158,7 @@ o.spec('cutline', () => {
});

o('boundary part inland, part coastal', async () => {
const cutline = new Cutline(googleProj, await Cutline.loadCutline(testDir + '/kapiti.geojson'), 500);
const cutline = new Cutline(googlePtms, await Cutline.loadCutline(testDir + '/kapiti.geojson'), 500);
const bounds = [
{
name: 'tiff1',
Expand Down Expand Up @@ -197,7 +197,7 @@ o.spec('cutline', () => {
});

o('low res', () => {
const cutline = new Cutline(googleProj);
const cutline = new Cutline(googlePtms);

const covering = cutline.optimizeCovering({
projection: EpsgCode.Nztm2000,
Expand All @@ -210,7 +210,7 @@ o.spec('cutline', () => {
});

o('hi res', () => {
const covering2 = new Cutline(googleProj).optimizeCovering({
const covering2 = new Cutline(googlePtms).optimizeCovering({
projection: EpsgCode.Nztm2000,
bounds,
resZoom: 18,
Expand Down
12 changes: 6 additions & 6 deletions packages/cli/src/cog/builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export function guessProjection(wkt: string): Epsg | null {
export class CogBuilder {
q: pLimit.Limit;
logger: LogType;
targetProj: ProjectionTileMatrixSet;
targetPtms: ProjectionTileMatrixSet;
srcProj?: Epsg;

// Prevent guessing spamming the logs
Expand All @@ -52,8 +52,8 @@ export class CogBuilder {
/**
* @param concurrency number of requests to run at a time
*/
constructor(targetProj: ProjectionTileMatrixSet, concurrency: number, logger: LogType, srcProj?: Epsg) {
this.targetProj = targetProj;
constructor(targetPtms: ProjectionTileMatrixSet, concurrency: number, logger: LogType, srcProj?: Epsg) {
this.targetPtms = targetPtms;
this.logger = logger;
this.q = pLimit(concurrency);
this.srcProj = srcProj;
Expand Down Expand Up @@ -136,7 +136,7 @@ export class CogBuilder {
bands,
bounds,
pixelScale: resX,
resZoom: this.targetProj.getTiffResZoom(resX),
resZoom: this.targetPtms.getTiffResZoom(resX),
};
}

Expand Down Expand Up @@ -196,15 +196,15 @@ export class CogBuilder {
CacheFolder,
CacheVersion +
createHash('sha256')
.update(this.targetProj.tms.projection.toString())
.update(this.targetPtms.tms.projection.toString())
.update(tiffs.map((c) => c.name).join('\n'))
.digest('hex'),
) + '.json';

if (existsSync(cacheKey)) {
this.logger.debug({ path: cacheKey }, 'MetadataCacheHit');
const metadata = (await FileOperatorSimple.readJson(cacheKey)) as SourceMetadata;
metadata.resZoom = this.targetProj.getTiffResZoom(metadata.pixelScale);
metadata.resZoom = this.targetPtms.getTiffResZoom(metadata.pixelScale);
return metadata;
}

Expand Down
12 changes: 6 additions & 6 deletions packages/cli/src/cog/cog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,20 +49,20 @@ export async function buildCogForName(
const startTime = Date.now();

const { resZoom } = job.source;
const targetProj = ProjectionTileMatrixSet.get(job.projection);
const { tms } = targetProj;
const targetPtms = ProjectionTileMatrixSet.get(job.projection);
const { tms } = targetPtms;

const tile = TileMatrixSet.nameToTile(name);

const ul = tms.tileToSource(tile);
const lr = tms.tileToSource({ x: tile.x + 1, y: tile.y + 1, z: tile.z });

const blockSize = tms.tileSize * targetProj.blockFactor;
const alignmentLevels = targetProj.findAlignmentLevels(tile, job.source.pixelScale);
const blockSize = tms.tileSize * targetPtms.blockFactor;
const alignmentLevels = targetPtms.findAlignmentLevels(tile, job.source.pixelScale);

const cogBuild = new GdalCogBuilder(vrtLocation, outputTiffPath, {
bbox: [ul.x, ul.y, lr.x, lr.y],
projection: targetProj.tms.projection,
projection: targetPtms.tms.projection,
tilingScheme: tilingScheme(job.projection),
blockSize,
targetRes: tms.pixelScale(resZoom),
Expand All @@ -75,7 +75,7 @@ export async function buildCogForName(

logger.info(
{
imageSize: targetProj.getImagePixelWidth(tile, resZoom),
imageSize: targetPtms.getImagePixelWidth(tile, resZoom),
name,
tile,
alignmentLevels,
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/cog/cog.vrt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ export const CogVrt = {
gdalCommand.mount(tmpFolder);
}

const tr = cutline.targetProj.tms.pixelScale(job.source.resZoom).toString();
const tr = cutline.tms.pixelScale(job.source.resZoom).toString();

const defaultOps = ['-tr', tr, tr, '-tap'];

Expand Down
Loading

0 comments on commit f799006

Please sign in to comment.