diff --git a/packages/geo/src/__tests__/bounds.test.ts b/packages/geo/src/__tests__/bounds.test.ts index 04da86d5a..5ff53eabf 100644 --- a/packages/geo/src/__tests__/bounds.test.ts +++ b/packages/geo/src/__tests__/bounds.test.ts @@ -15,6 +15,9 @@ o.spec('Bounds', () => { o(new Bounds(1.1, 10.1, 12.2, 11.2).round().toJson()).deepEquals({ x: 1, y: 10, width: 12, height: 11 }); o(new Bounds(1.4, 10.6, 12.2, 11.4).round().toJson()).deepEquals({ x: 1, y: 11, width: 13, height: 11 }); o(new Bounds(0.4, 0.6, 2.4, 1.6).round().toJson()).deepEquals({ x: 0, y: 1, width: 3, height: 1 }); + + o(new Bounds(1.6, 10.6, 12.5, 11.5).round().toJson()).deepEquals({ x: 2, y: 11, width: 12, height: 11 }); + o(new Bounds(1.6, 10.6, 12.5, 11.5).round(0.2).toJson()).deepEquals({ x: 1, y: 10, width: 13, height: 12 }); }); o('toBbox', () => { diff --git a/packages/geo/src/bounds.ts b/packages/geo/src/bounds.ts index b3f732cbc..2bd412ac2 100644 --- a/packages/geo/src/bounds.ts +++ b/packages/geo/src/bounds.ts @@ -158,11 +158,14 @@ export class Bounds implements BoundingBox { /** * Round dimensions to integers keeping the error a low as possible + + * @param bias influence the rounding in favour of a larger area (+ve bias) or smaller area (-ve + * bias). Example: bias = 0.2 would round left and top down when < 0.7 and round right and bottom up when >= 0.3 */ - public round(): Bounds { - const x = Math.round(this.x); - const y = Math.round(this.y); - return new Bounds(x, y, Math.round(this.right) - x, Math.round(this.bottom) - y); + public round(bias = 0): Bounds { + const x = Math.round(this.x - bias); + const y = Math.round(this.y - bias); + return new Bounds(x, y, Math.round(this.right + bias) - x, Math.round(this.bottom + bias) - y); } public add(bounds: Point): Bounds { diff --git a/packages/tiler/src/tiler.ts b/packages/tiler/src/tiler.ts index f59c69c52..cef01906f 100644 --- a/packages/tiler/src/tiler.ts +++ b/packages/tiler/src/tiler.ts @@ -13,6 +13,9 @@ export interface RasterPixelBounds { tiff: Bounds; } +/** The amount to bias the Bounds.round function to cover a larger, rather than smaller, area. */ +const ROUND_BIAS = 0.2; + export class Tiler { /** Tile size for the tiler and sub objects */ public readonly tms: TileMatrixSet; @@ -78,7 +81,7 @@ export class Tiler { ): Composition | null { const source = Bounds.fromJson(img.getTileBounds(x, y)); - const target = source.scale(scaleFactor, scaleFactor).add(raster.tiff).round(); + const target = source.scale(scaleFactor, scaleFactor).add(raster.tiff).round(ROUND_BIAS); // Validate that the requested COG tile actually intersects with the output raster const tileIntersection = target.intersection(raster.tile);