Skip to content

Behave like a 3857 tile service when google compatible flag found in COG file #1814

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 62 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
010ef99
add get_origin function
sharkAndshark Feb 11, 2025
ef04f93
add get_model_info function
sharkAndshark Feb 11, 2025
72c6e64
add model info verify
sharkAndshark Feb 11, 2025
4654b13
get resolutions in meta
sharkAndshark Feb 11, 2025
77b72aa
add resolutions to meta
sharkAndshark Feb 11, 2025
139337e
add origin to meta
sharkAndshark Feb 11, 2025
887f885
add get_extent method
sharkAndshark Feb 11, 2025
83432bc
get coord transformation info only once
sharkAndshark Feb 11, 2025
6f16f0a
use reference image t o calc resolution
sharkAndshark Feb 12, 2025
78a9a05
update test
sharkAndshark Feb 12, 2025
05d175b
fmt && clippy
sharkAndshark Feb 14, 2025
c9b0554
use approx in test
sharkAndshark Feb 14, 2025
abdd59c
add cusom_tile_grid to tilejson
sharkAndshark Feb 14, 2025
72662e8
get the images_ifd sorted
sharkAndshark Feb 14, 2025
14be39d
fix snapshot for hashmap
sharkAndshark Feb 14, 2025
03c15c0
fix test
sharkAndshark Feb 14, 2025
638efe0
bless
sharkAndshark Feb 14, 2025
f1c7449
bless
sharkAndshark Feb 14, 2025
6490c04
fmt
sharkAndshark Feb 14, 2025
8b7f549
add meta_to_tilejson
sharkAndshark Feb 14, 2025
14eb880
verify whether it's pixel squared
sharkAndshark Feb 14, 2025
d80bd6e
cleanup
sharkAndshark Feb 14, 2025
c8a2cc7
bless
sharkAndshark Feb 14, 2025
4ea348f
fmt
sharkAndshark Feb 14, 2025
ad9ae50
Add tileSize to TileJSON
sharkAndshark Feb 16, 2025
90b8b5e
update test for get_origin
sharkAndshark Feb 17, 2025
71acb2e
update test of car_get_origin
sharkAndshark Feb 17, 2025
d1c1269
cleanup
sharkAndshark Feb 17, 2025
6c7f051
add test for get_extent
sharkAndshark Feb 19, 2025
6803908
verify squared pixel
sharkAndshark Feb 19, 2025
362d240
Merge remote-tracking branch 'maplibre/main' into cog_custom_tile_schema
sharkAndshark Feb 20, 2025
26aa1f0
clippy
sharkAndshark Feb 20, 2025
474ede3
update tilejson
sharkAndshark Feb 20, 2025
6cda582
get resolutions sorted
sharkAndshark Feb 21, 2025
ffa3fa1
bless
sharkAndshark Feb 21, 2025
07a3dd6
bless
sharkAndshark Feb 22, 2025
e524ace
bless
sharkAndshark Feb 25, 2025
79c3a60
Merge remote-tracking branch 'maplibre/main' into cog_custom_tile_schema
sharkAndshark Feb 28, 2025
4872cc4
add draft doc
sharkAndshark Feb 28, 2025
a2018f0
update doc
sharkAndshark Feb 28, 2025
b4a9087
Merge branch 'main' into cog_custom_tile_schema
CommanderStorm Mar 4, 2025
8a0b5a5
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Mar 4, 2025
535e2f1
Update sources-cog-files.md
sharkAndshark Mar 5, 2025
0df310e
add test fixture
sharkAndshark Apr 24, 2025
3f3568d
add dep
sharkAndshark Apr 24, 2025
236ade6
wip
sharkAndshark Apr 24, 2025
8a6bd1e
wip
sharkAndshark Apr 25, 2025
571895b
add sub_region method
sharkAndshark Apr 27, 2025
0092acd
add cog config option:force google
sharkAndshark Apr 27, 2025
09605da
Merge remote-tracking branch 'maplibre/main' into google_warp
sharkAndshark Apr 29, 2025
2d2352e
refactor
sharkAndshark Apr 29, 2025
531f8fd
update test
sharkAndshark Apr 30, 2025
4c24877
make force_google default
sharkAndshark Apr 30, 2025
d55fc6c
update tilejson
sharkAndshark Apr 30, 2025
c61baca
update test
sharkAndshark Apr 30, 2025
d352ec9
fmt
sharkAndshark Apr 30, 2025
3fcfb80
bug fix: fill the gap between tiles
sharkAndshark Apr 30, 2025
7b94dcd
fix the bbox method
sharkAndshark Apr 30, 2025
48b09a6
fix xyz_to_bbox bug
sharkAndshark Apr 30, 2025
c9631eb
set the option correctly
sharkAndshark Apr 30, 2025
b7ed868
just bless
sharkAndshark Apr 30, 2025
3da7830
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Apr 30, 2025
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
832 changes: 695 additions & 137 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ env_logger = "0.11"
flate2 = "1"
flume = "0.11"
futures = "0.3"
image = "0.25.6"
imageproc = "0.25.0"
indoc = "2"
insta = "1"
itertools = "0.14"
Expand Down
90 changes: 90 additions & 0 deletions docs/src/sources-cog-files.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,96 @@ cog:
cog-src2: /path/to/cog2.tif
```

## Tile Grid

Generally `COG` file has a custom tile grid which is not aligned to the google 3857 which is default in almost any map client like MapLibre, OpenLayers, etc..

To display the `COG` file the clients needs to know the custom `tile grid` of COG.

To not break the compatiblity of TileJSON spec, martin choose to add a field in `TileJSON` to tell the custom tile grid.

Lile we have a cog source named `rgb_u8`, we could see the custom filed in our `TileJson` by visit `http://your_host:your_port/rgb_u8`.

```json
{
"maxzoom": 3,
"minzoom": 0,
"tilejson": "3.0.0",
"tiles": [
"http://localhost:3111/rgb_u8/{z}/{x}/{y}"
],
"custom_grid": { // the custom tile grid added here
"extent": [
1620750.2508,
4271892.7153,
1625870.2508,
4277012.7153
],
"maxZoom": 3,
"minZoom": 0,
"origin": [
1620750.2508,
4277012.7153
],
"resolutions": [
80,
40,
20,
10
],
"tileSize": [
256,
256
]
},
}
```

A demo about how to load it with `openlayers`.

```js
import './style.css';
import { Map, View } from 'ol';
import TileLayer from 'ol/layer/Tile';
import OSM from 'ol/source/OSM';
import XYZ from 'ol/source/XYZ.js';


import TileGrid from 'ol/tilegrid/TileGrid.js';

var custom_grid = new TileGrid({
extent: [
1620750.2508,
4271892.7153,
1625870.2508,
4277012.7153],
resolutions: [
80,
40,
20,
10],
tileSize: [256, 256],
origin: [1620750.2508, 4277012.7153]
});

var source = new XYZ({
url: "http://10.1.155.35:3000/rgb_u8/{z}/{x}/{y}", tileGrid: custom_grid
});

const map = new Map({
target: 'map',
layers: [
new TileLayer({
source: source
}),
],
view: new View({
center: [(1620750.2508 + 1625870.2508) / 2, (4271892.7153 + 4277012.7153) / 2],
zoom: 14
})
});
```

## About COG

[COG](https://cogeo.org/) is just Cloud Optimized GeoTIFF file.
Expand Down
29 changes: 29 additions & 0 deletions martin-tile-utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,35 @@ pub fn xyz_to_bbox(zoom: u8, min_x: u32, min_y: u32, max_x: u32, max_y: u32) ->
[min_lng, min_lat, max_lng, max_lat]
}

/// Convert min/max XYZ tile coordinates to a bounding box values.
///
/// The result is `[min_lng, min_lat, max_lng, max_lat]`
///
/// # Panics
/// Panics if `zoom` is greater than [`MAX_ZOOM`].
#[must_use]
pub fn xyz_to_bbox_webmercator(
zoom: u8,
min_x: u32,
min_y: u32,
max_x: u32,
max_y: u32,
) -> [f64; 4] {
assert!(zoom <= MAX_ZOOM, "zoom {zoom} must be <= {MAX_ZOOM}");

let tile_length = EARTH_CIRCUMFERENCE / f64::from(1_u32 << zoom);

let left_down_bbox = tile_bbox(min_x, max_y, tile_length);
let right_top_bbox = tile_bbox(max_x, min_y, tile_length);

[
left_down_bbox[0],
left_down_bbox[1],
right_top_bbox[2],
right_top_bbox[3],
]
}

#[allow(clippy::cast_lossless)]
fn tile_bbox(x: u32, y: u32, tile_length: f64) -> [f64; 4] {
let min_x = EARTH_CIRCUMFERENCE * -0.5 + x as f64 * tile_length;
Expand Down
5 changes: 4 additions & 1 deletion martin/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ fonts = ["dep:bit-set", "dep:pbf_font_tools"]
lambda = ["dep:lambda-web"]
mbtiles = ["dep:mbtiles"]
pmtiles = ["dep:pmtiles"]
cog = ["dep:tiff", "dep:png"]
cog = ["dep:tiff", "dep:png", "dep:image", "dep:imageproc"]
styles = ["dep:walkdir", "tokio/fs"]
postgres = ["dep:deadpool-postgres", "dep:json-patch", "dep:postgis", "dep:postgres", "dep:postgres-protocol", "dep:semver", "dep:tokio-postgres-rustls"]
sprites = ["dep:spreet", "tokio/fs"]
Expand All @@ -79,6 +79,8 @@ enum-display.workspace = true
env_logger.workspace = true
futures.workspace = true
itertools.workspace = true
image = { workspace = true, optional = true }
imageproc = { workspace = true, optional = true }
json-patch = { workspace = true, optional = true }
lambda-web = { workspace = true, optional = true }
log.workspace = true
Expand Down Expand Up @@ -118,6 +120,7 @@ static-files = { workspace = true, optional = true }

[dev-dependencies]
anyhow.workspace = true
approx.workspace = true
criterion.workspace = true
ctor.workspace = true
indoc.workspace = true
Expand Down
4 changes: 3 additions & 1 deletion martin/src/cog/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ use crate::file_config::{ConfigExtras, FileResult, SourceConfigExtras};
pub struct CogConfig {
#[serde(flatten)]
pub unrecognized: UnrecognizedValues,

pub force_google: Option<bool>,
}

impl ConfigExtras for CogConfig {
Expand All @@ -23,7 +25,7 @@ impl ConfigExtras for CogConfig {

impl SourceConfigExtras for CogConfig {
async fn new_sources(&self, id: String, path: PathBuf) -> FileResult<Box<dyn Source>> {
let cog = CogSource::new(id, path)?;
let cog = CogSource::new(id, path, self.force_google.unwrap_or(true))?;
Ok(Box::new(cog))
}

Expand Down
17 changes: 17 additions & 0 deletions martin/src/cog/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,21 @@ pub enum CogError {

#[error("Striped tiff file is not supported, the tiff file is {0}")]
NotSupportedChunkType(PathBuf),

#[error("Get origin failed for {0}")]
GetOriginFailed(PathBuf),

#[error("Coord transformation in {0} is invalid")]
InvalidGeoInformation(PathBuf, String),

#[error("Get full resolution failed from file: {0}")]
GetFullResolutionFailed(PathBuf),

#[error("Get extent failed from file: {0}")]
GetExtentFailed(PathBuf),

#[error(
"The pixel size of the image {0} is not squared, the x_scale is {1}, the y_scale is {2}"
)]
NonSquaredImage(PathBuf, f64, f64),
}
Loading
Loading