Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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 CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
- _...Add new stuff here..._

### 🐞 Bug fixes
- Fix image sources being clipped at -180 and 180 longitude when terrain is enabled ([#4088](https://github.com/maplibre/maplibre-gl-js/issues/4088))
- Fix use of `textureSize` call in color relief shader ([#5980](https://github.com/maplibre/maplibre-gl-js/pull/5980))
- Fix Y axis transformation in projectFromLabelPlaneToClipSpace ([#6021](https://github.com/maplibre/maplibre-gl-js/pull/6021))
- Alpha-sort all examples ([#6049](https://github.com/maplibre/maplibre-gl-js/pull/6049))
- Ensure opacity is reset for popups when `locationOccludedOpacity` no longer applicable ([#6088](https://github.com/maplibre/maplibre-gl-js/pull/6088))

- _...Add new stuff here..._

## 5.6.0
Expand Down
84 changes: 80 additions & 4 deletions src/source/image_source.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -241,10 +241,86 @@ describe('ImageSource', () => {
source.onAdd(map);
server.respond();
source.setCoordinates([[11.39585,47.30074],[11.46585,47.30074],[11.46585,47.25074],[11.39585,47.25074]]);
expect(source.terrainTileRanges[9]).toEqual({minTileX: 272, minTileY: 179, maxTileX: 272, maxTileY: 179});
expect(source.terrainTileRanges[10]).toEqual({minTileX: 544, minTileY: 358, maxTileX: 544, maxTileY: 359});
expect(source.terrainTileRanges[11]).toEqual({minTileX: 1088, minTileY: 717, maxTileX: 1089, maxTileY: 718});
expect(source.terrainTileRanges[12]).toEqual({minTileX: 2177, minTileY: 1435, maxTileX: 2178, maxTileY: 1436});
expect(source.terrainTileRanges[9]).toEqual({
minWrap: 0,
maxWrap: 0,
minTileXWrapped: 272,
maxTileXWrapped: 272,
minTileY: 179,
maxTileY: 179
});
expect(source.terrainTileRanges[10]).toEqual({
minWrap: 0,
maxWrap: 0,
minTileXWrapped: 544,
maxTileXWrapped: 544,
minTileY: 358,
maxTileY: 359
});
expect(source.terrainTileRanges[11]).toEqual({
minWrap: 0,
maxWrap: 0,
minTileXWrapped: 1088,
maxTileXWrapped: 1089,
minTileY: 717,
maxTileY: 718
});
expect(source.terrainTileRanges[12]).toEqual({
minWrap: 0,
maxWrap: 0,
minTileXWrapped: 2177,
maxTileXWrapped: 2178,
minTileY: 1435,
maxTileY: 1436
});
});

test('calculates tile ranges for an image exceeds the world bounds - east', () => {
const source = createSource({url: '/image.png'});
const map = new StubMap() as any;
source.onAdd(map);
server.respond();
source.setCoordinates([[-180, 60], [270, 60], [270, -60], [-180, -60]]);
expect(source.terrainTileRanges[0]).toEqual({
minWrap: 0,
maxWrap: 1,
minTileXWrapped: 0,
maxTileXWrapped: 0,
minTileY: 0,
maxTileY: 0
});
expect(source.terrainTileRanges[1]).toEqual({
minWrap: 0,
maxWrap: 1,
minTileXWrapped: 0,
maxTileXWrapped: 0,
minTileY: 0,
maxTileY: 1
});
});

test('calculates tile ranges for an image exceeds the world bounds - west', () => {
const source = createSource({url: '/image.png'});
const map = new StubMap() as any;
source.onAdd(map);
server.respond();
source.setCoordinates([[120, 60], [-270, 60], [-270, -60], [120, -60]]);
expect(source.terrainTileRanges[0]).toEqual({
minWrap: -1,
maxWrap: 0,
minTileXWrapped: 0,
maxTileXWrapped: 0,
minTileY: 0,
maxTileY: 0
});
expect(source.terrainTileRanges[1]).toEqual({
minWrap: -1,
maxWrap: 0,
minTileXWrapped: 1,
maxTileXWrapped: 1,
minTileY: 0,
maxTileY: 1
});
});
});
});
22 changes: 18 additions & 4 deletions src/source/image_source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,17 @@ export type UpdateImageOptions = {
};

export type CanonicalTileRange = {
minTileX: number;
minTileY: number;
maxTileX: number;
maxTileY: number;

/**
* Image can exceed the boundary of a single "world" (tile 0/0/0),
* so we need to know the tile range for wrapping.
*/
minTileXWrapped: number;
maxTileXWrapped: number;
minWrap: number;
maxWrap: number;
};

/**
Expand Down Expand Up @@ -320,10 +327,17 @@ export class ImageSource extends Evented implements Source {
const maxTileX = Math.floor(maxX * tilesAtZoom);
const maxTileY = Math.floor(maxY * tilesAtZoom);

const minTileXWrapped = ((minTileX % tilesAtZoom) + tilesAtZoom) % tilesAtZoom;
const maxTileXWrapped = maxTileX % tilesAtZoom;
const minWrap = Math.floor(minTileX / tilesAtZoom);
const maxWrap = Math.floor(maxTileX / tilesAtZoom);

ranges[z] = {
minTileX,
minWrap,
maxWrap,
minTileXWrapped,
maxTileXWrapped,
minTileY,
maxTileX,
maxTileY
};
}
Expand Down
18 changes: 15 additions & 3 deletions src/source/terrain_source_cache.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,11 @@ describe('TerrainSourceCache', () => {
minTileX: 2,
maxTileX: 4,
minTileY: 1,
maxTileY: 3
maxTileY: 3,
minTileXWrapped: 2,
maxTileXWrapped: 4,
minWrap: 0,
maxWrap: 0
}
};
const resultOverlapping = tsc.getTerrainCoords(testTileOverlapping, terrainTileRanges);
Expand All @@ -159,7 +163,11 @@ describe('TerrainSourceCache', () => {
minTileX: 4,
maxTileX: 6,
minTileY: 1,
maxTileY: 3
maxTileY: 3,
minTileXWrapped: 4,
maxTileXWrapped: 6,
minWrap: 0,
maxWrap: 0
}
};
const resultOverlapping = tsc.getTerrainCoords(testTileOverlapping, terrainTileRanges);
Expand All @@ -182,7 +190,11 @@ describe('TerrainSourceCache', () => {
minTileX: 2,
maxTileX: 4,
minTileY: 1,
maxTileY: 3
maxTileY: 3,
minTileXWrapped: 2,
maxTileXWrapped: 4,
minWrap: 0,
maxWrap: 0
}
};
const result = tsc.getTerrainCoords(testTile, terrainTileRanges);
Expand Down
23 changes: 15 additions & 8 deletions src/source/terrain_source_cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,14 +218,16 @@ export class TerrainSourceCache extends Evented {
const coord = tileID.clone();
const mat = createMat4f64();
if (terrainTileID.canonical.z === tileID.canonical.z) {
const dx = tileID.canonical.x - terrainTileID.canonical.x;
const dx = tileID.canonical.x - terrainTileID.canonical.x
+ tileID.wrap * (1 << tileID.canonical.z); // include wrap shift
const dy = tileID.canonical.y - terrainTileID.canonical.y;
mat4.ortho(mat, 0, EXTENT, EXTENT, 0, 0, 1);
mat4.translate(mat, mat, [dx * EXTENT, dy * EXTENT, 0]);
} else if (terrainTileID.canonical.z > tileID.canonical.z) {
const dz = terrainTileID.canonical.z - tileID.canonical.z;
// this translation is needed to project tileID to terrainTileID zoom level
const dx = terrainTileID.canonical.x - (terrainTileID.canonical.x >> dz << dz);
const dx = terrainTileID.canonical.x - (terrainTileID.canonical.x >> dz << dz)
+ tileID.wrap * (1 << terrainTileID.canonical.z); // include wrap shift
const dy = terrainTileID.canonical.y - (terrainTileID.canonical.y >> dz << dz);
// this translation is needed if terrainTileID is not a parent of tileID
const dx2 = tileID.canonical.x - (terrainTileID.canonical.x >> dz);
Expand All @@ -237,7 +239,8 @@ export class TerrainSourceCache extends Evented {
} else { // terrainTileID.canonical.z < tileID.canonical.z
const dz = tileID.canonical.z - terrainTileID.canonical.z;
// this translation is needed to project tileID to terrainTileID zoom level
const dx = tileID.canonical.x - (tileID.canonical.x >> dz << dz);
const dx = tileID.canonical.x - (tileID.canonical.x >> dz << dz)
+ tileID.wrap * (1 << tileID.canonical.z); // include wrap shift
const dy = tileID.canonical.y - (tileID.canonical.y >> dz << dz);
// this translation is needed if terrainTileID is not a parent of tileID
const dx2 = (tileID.canonical.x >> dz) - terrainTileID.canonical.x;
Expand Down Expand Up @@ -294,10 +297,14 @@ export class TerrainSourceCache extends Evented {
tileID: OverscaledTileID,
canonicalTileRanges: {[zoom: string]: CanonicalTileRange}
): boolean {
return canonicalTileRanges[tileID.canonical.z] &&
tileID.canonical.x >= canonicalTileRanges[tileID.canonical.z].minTileX &&
tileID.canonical.x <= canonicalTileRanges[tileID.canonical.z].maxTileX &&
tileID.canonical.y >= canonicalTileRanges[tileID.canonical.z].minTileY &&
tileID.canonical.y <= canonicalTileRanges[tileID.canonical.z].maxTileY;
const range = canonicalTileRanges[tileID.canonical.z];

return !!range && (
tileID.wrap > range.minWrap || tileID.wrap < range.maxWrap ||
tileID.canonical.x >= range.minTileXWrapped &&
tileID.canonical.x <= range.maxTileXWrapped &&
tileID.canonical.y >= range.minTileY &&
tileID.canonical.y <= range.maxTileY
);
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"version": 8,
"metadata": {
"test": {
"height": 512,
"width": 512
}
},
"center": [90, 0],
"zoom": 0,
"pitch": 0,
"bearing": 0,
"sources": {
"repeat": {
"type": "raster",
"tiles": ["local://tiles/white-with-x.png"],
"tileSize": 256
},
"terrain": {
"type": "raster-dem",
"tiles": ["local://tiles/terrain/{z}-{x}-{y}.terrain.png"],
"minzoom": 7,
"maxzoom": 12,
"tileSize": 256
},
"image": {
"type": "image",
"coordinates": [
[0, 40],
[210, 40],
[210, -40],
[0, -40]
],
"url": "local://image/1.png"
}
},
"layers": [
{"id": "osm", "type": "raster", "source": "repeat"},
{
"id": "image",
"type": "raster",
"source": "image",
"paint": {
"raster-fade-duration": 0
}
}
],
"terrain": {
"source": "terrain",
"exaggeration": 1
}
}