mirror of
https://github.com/maplibre/maplibre-rs.git
synced 2025-12-08 19:05:57 +00:00
Fix parsing and add grid handling
This commit is contained in:
parent
742d510ed4
commit
a788c14d7a
@ -12,6 +12,8 @@ log = "0.4"
|
||||
num-traits = "0.2"
|
||||
pointy = "0.3"
|
||||
protobuf = "2.25"
|
||||
tile-grid = "0.3"
|
||||
|
||||
|
||||
[build-dependencies]
|
||||
protobuf-codegen-pure = "2.25"
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::geometry::{
|
||||
Geometry, GeometryLineString, GeometryPoint, GeometryPolygon, MultiPoint, Point,
|
||||
Command, Geometry, GeometryLineString, GeometryPoint, GeometryPolygon, LineTo, MoveTo,
|
||||
MultiPoint, Point,
|
||||
};
|
||||
use crate::protos::vector_tile::{
|
||||
Tile as ProtoTile, Tile_Feature as ProtoFeature, Tile_GeomType as ProtoGeomType, Tile_GeomType,
|
||||
@ -52,19 +53,13 @@ const CMD_LINE_TO_PARAMETERS: usize = 2;
|
||||
const CMD_CLOSE_PATH_PARAMETERS: usize = 0;
|
||||
|
||||
trait ZigZag {
|
||||
/// Encodes a value to zigzag
|
||||
fn zigzag(self) -> i32;
|
||||
/// Decodes a value from zigzag encoding
|
||||
fn zagzig(self) -> i32;
|
||||
}
|
||||
|
||||
impl ZigZag for u32 {
|
||||
fn zigzag(self) -> i32 {
|
||||
((self << 1) ^ (self >> 31)) as i32
|
||||
}
|
||||
|
||||
fn zagzig(self) -> i32 {
|
||||
((self >> 1) as i32 ^ (-((self & 1) as i32)))
|
||||
((self >> 1) as i32) ^ (-((self & 1) as i32))
|
||||
}
|
||||
}
|
||||
|
||||
@ -84,7 +79,10 @@ impl Decode<GeometryPoint> for Vec<u32> {
|
||||
i += 1;
|
||||
|
||||
for parameter in 0..count {
|
||||
points.push(Point::new(self[i + parameter].zagzig(), self[i + parameter + 1].zagzig()));
|
||||
points.push(Point::new(
|
||||
self[i + parameter].zagzig(),
|
||||
self[i + parameter + 1].zagzig(),
|
||||
));
|
||||
}
|
||||
|
||||
i += count * CMD_MOVE_TO_PARAMETERS;
|
||||
@ -95,27 +93,104 @@ impl Decode<GeometryPoint> for Vec<u32> {
|
||||
} else if points.len() > 1 {
|
||||
GeometryPoint::MultiPoint(MultiPoint::new(points))
|
||||
} else {
|
||||
GeometryPoint::Point(Point::new(0, 0)); // point is at the origin
|
||||
GeometryPoint::Point(Point::new(0, 0)) // point is at the origin
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Decode<GeometryLineString> for Vec<u32> {
|
||||
fn decode(self) -> GeometryLineString {
|
||||
let mut commands = vec![];
|
||||
let mut i = 0;
|
||||
|
||||
while i < self.len() - 1 {
|
||||
let command = self[i] & 0x7;
|
||||
|
||||
i += count * match command {
|
||||
CMD_MOVE_TO => CMD_MOVE_TO_PARAMETERS,
|
||||
CMD_LINE_TO => CMD_LINE_TO_PARAMETERS,
|
||||
CMD_CLOSE_PATH => CMD_CLOSE_PATH_PARAMETERS,
|
||||
_ => 0,
|
||||
};
|
||||
let count = (self[i] >> 3) as usize;
|
||||
i += 1;
|
||||
|
||||
for parameter in 0..count {
|
||||
match command {
|
||||
CMD_MOVE_TO => {
|
||||
commands.push(Command::MoveTo(MoveTo {
|
||||
x: self[i + parameter].zagzig(),
|
||||
y: self[i + parameter + 1].zagzig(),
|
||||
}));
|
||||
}
|
||||
CMD_LINE_TO => {
|
||||
commands.push(Command::LineTo(LineTo {
|
||||
x: self[i + parameter].zagzig(),
|
||||
y: self[i + parameter + 1].zagzig(),
|
||||
}));
|
||||
}
|
||||
CMD_CLOSE_PATH => {
|
||||
commands.push(Command::Close);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
i += count
|
||||
* match command {
|
||||
CMD_MOVE_TO => CMD_MOVE_TO_PARAMETERS,
|
||||
CMD_LINE_TO => CMD_LINE_TO_PARAMETERS,
|
||||
CMD_CLOSE_PATH => CMD_CLOSE_PATH_PARAMETERS,
|
||||
_ => 0,
|
||||
};
|
||||
}
|
||||
|
||||
GeometryLineString { commands }
|
||||
}
|
||||
}
|
||||
|
||||
impl Decode<GeometryPolygon> for Vec<u32> {
|
||||
fn decode(self) -> GeometryPolygon {
|
||||
GeometryPolygon::Unknown
|
||||
let mut commands = vec![];
|
||||
let mut i = 0;
|
||||
|
||||
while i < self.len() {
|
||||
let command = self[i] & 0x7;
|
||||
let count = (self[i] >> 3) as usize;
|
||||
|
||||
// parsed command and count => +1
|
||||
i += 1;
|
||||
|
||||
match command {
|
||||
CMD_MOVE_TO => {
|
||||
for parameter in 0..count {
|
||||
let x_index = i;
|
||||
commands.push(Command::MoveTo(MoveTo {
|
||||
x: self[x_index].zagzig(),
|
||||
y: self[x_index + 1].zagzig(),
|
||||
}));
|
||||
i += CMD_MOVE_TO_PARAMETERS;
|
||||
}
|
||||
}
|
||||
CMD_LINE_TO => {
|
||||
for parameter in 0..count {
|
||||
let x_index = i;
|
||||
commands.push(Command::LineTo(LineTo {
|
||||
x: self[x_index].zagzig(),
|
||||
y: self[x_index + 1].zagzig(),
|
||||
}));
|
||||
i += CMD_MOVE_TO_PARAMETERS;
|
||||
}
|
||||
}
|
||||
CMD_CLOSE_PATH => {
|
||||
for _ in 0..count {
|
||||
commands.push(Command::Close);
|
||||
i += CMD_CLOSE_PATH_PARAMETERS;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
panic!("error")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
GeometryPolygon { commands }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -20,38 +20,35 @@ pub struct Point {
|
||||
y: Number,
|
||||
}
|
||||
|
||||
/// Contains relative coordinates to which the cursor is moved
|
||||
#[derive(Debug)]
|
||||
pub enum GeometryLineString {
|
||||
LineString(LineString),
|
||||
MultiLineString(MultiLineString),
|
||||
Unknown,
|
||||
pub struct MoveTo {
|
||||
pub x: Number,
|
||||
pub y: Number,
|
||||
}
|
||||
|
||||
/// Contains relative coordinates to which a line is drawn
|
||||
#[derive(Debug)]
|
||||
pub struct LineTo {
|
||||
pub x: Number,
|
||||
pub y: Number,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct MultiLineString {
|
||||
lines: Vec<LineString>,
|
||||
pub enum Command {
|
||||
MoveTo(MoveTo),
|
||||
LineTo(LineTo),
|
||||
Close,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct LineString {
|
||||
points: Vec<Point>,
|
||||
pub struct GeometryLineString {
|
||||
pub commands: Vec<Command>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum GeometryPolygon {
|
||||
Polygon(Polygon),
|
||||
MultiLineString(MultiPolygon),
|
||||
Unknown,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Polygon {
|
||||
points: Vec<Point>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct MultiPolygon {
|
||||
polygons: Vec<Polygon>,
|
||||
pub struct GeometryPolygon {
|
||||
pub commands: Vec<Command>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -73,27 +70,3 @@ impl MultiPoint {
|
||||
Self { points }
|
||||
}
|
||||
}
|
||||
|
||||
impl LineString {
|
||||
pub(crate) fn new(points: Vec<Point>) -> Self {
|
||||
Self { points }
|
||||
}
|
||||
}
|
||||
|
||||
impl MultiLineString {
|
||||
pub(crate) fn new(lines: Vec<LineString>) -> Self {
|
||||
Self { lines }
|
||||
}
|
||||
}
|
||||
|
||||
impl Polygon {
|
||||
pub(crate) fn new(points: Vec<Point>) -> Self {
|
||||
Self { points }
|
||||
}
|
||||
}
|
||||
|
||||
impl MultiPolygon {
|
||||
pub(crate) fn new(polygons: Vec<Polygon>) -> Self {
|
||||
Self { polygons }
|
||||
}
|
||||
}
|
||||
|
||||
86
libs/vector_tile/src/grid.rs
Normal file
86
libs/vector_tile/src/grid.rs
Normal file
@ -0,0 +1,86 @@
|
||||
use tile_grid::{extent_wgs84_to_merc, Extent, Grid, GridIterator, Origin, Unit};
|
||||
|
||||
fn web_mercator() -> Grid {
|
||||
Grid::new(
|
||||
256,
|
||||
256,
|
||||
Extent {
|
||||
minx: -20037508.3427892480,
|
||||
miny: -20037508.3427892480,
|
||||
maxx: 20037508.3427892480,
|
||||
maxy: 20037508.3427892480,
|
||||
},
|
||||
3857,
|
||||
Unit::Meters,
|
||||
// for calculation see fn test_resolutions
|
||||
vec![
|
||||
156543.0339280410,
|
||||
78271.5169640205,
|
||||
39135.75848201025,
|
||||
19567.879241005125,
|
||||
9783.939620502562,
|
||||
4891.969810251281,
|
||||
2445.9849051256406,
|
||||
1222.9924525628203,
|
||||
611.4962262814101,
|
||||
305.7481131407051,
|
||||
152.87405657035254,
|
||||
76.43702828517627,
|
||||
38.218514142588134,
|
||||
19.109257071294067,
|
||||
9.554628535647034,
|
||||
4.777314267823517,
|
||||
2.3886571339117584,
|
||||
1.1943285669558792,
|
||||
0.5971642834779396,
|
||||
0.2985821417389698,
|
||||
0.1492910708694849,
|
||||
0.07464553543474245,
|
||||
0.037322767717371225,
|
||||
],
|
||||
Origin::TopLeft,
|
||||
)
|
||||
}
|
||||
|
||||
/// z, x, z
|
||||
pub fn get_tile_coordinates_bavaria() -> Vec<(u8, u32, u32)> {
|
||||
let grid = web_mercator();
|
||||
let tile_limits = grid.tile_limits(
|
||||
extent_wgs84_to_merc(&Extent {
|
||||
minx: 10.0,
|
||||
miny: 48.0,
|
||||
maxx: 12.0,
|
||||
maxy: 50.0,
|
||||
}),
|
||||
0,
|
||||
);
|
||||
|
||||
println!("{:?}", grid.tile_extent(0, 0, 0));
|
||||
println!("{:?}", grid.tile_extent(33, 21, 6));
|
||||
println!("{:?}", grid.tile_extent_xyz(0, 0, 0));
|
||||
|
||||
let z = 6;
|
||||
let griditer = GridIterator::new(z, z, tile_limits);
|
||||
griditer.collect()
|
||||
}
|
||||
|
||||
pub fn get_tile_coordinates_tutzing() -> Vec<(u8, u32, u32)> {
|
||||
let grid = web_mercator();
|
||||
let tile_limits = grid.tile_limits(
|
||||
extent_wgs84_to_merc(&Extent {
|
||||
minx: 11.2772666,
|
||||
miny: 47.9125117,
|
||||
maxx: 11.2772666,
|
||||
maxy: 47.9125117,
|
||||
}),
|
||||
1,
|
||||
);
|
||||
|
||||
println!("{:?}", grid.tile_extent(0, 0, 0));
|
||||
println!("{:?}", grid.tile_extent(33, 21, 6));
|
||||
println!("{:?}", grid.tile_extent_xyz(0, 0, 0));
|
||||
|
||||
let z = 12;
|
||||
let griditer = GridIterator::new(z, z, tile_limits);
|
||||
griditer.collect()
|
||||
}
|
||||
@ -1,9 +1,32 @@
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
use std::io::{BufReader, Read};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use protobuf::Message;
|
||||
|
||||
use crate::encoding::Decode;
|
||||
use crate::protos::vector_tile::Tile as TileProto;
|
||||
use crate::tile::Tile;
|
||||
|
||||
mod protos;
|
||||
mod encoding;
|
||||
mod protos;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
pub mod geometry;
|
||||
pub mod tile;
|
||||
pub mod geometry;
|
||||
pub mod grid;
|
||||
|
||||
pub fn parse_tile<P: AsRef<Path>>(path: P) -> io::Result<Tile> {
|
||||
let mut f = File::open(path)?;
|
||||
let mut reader = BufReader::new(f);
|
||||
return Ok(parse_tile_reader(&mut reader));
|
||||
}
|
||||
|
||||
pub fn parse_tile_reader(reader: &mut dyn Read) -> Tile {
|
||||
let proto_tile = TileProto::parse_from_reader(reader).unwrap();
|
||||
return proto_tile.decode();
|
||||
}
|
||||
|
||||
|
||||
@ -1,16 +1,20 @@
|
||||
use std::fs::File;
|
||||
use std::io::BufReader;
|
||||
use crate::encoding::Decode;
|
||||
|
||||
use protobuf::Message;
|
||||
|
||||
use crate::encoding::Decode;
|
||||
use crate::grid::get_tile_coordinates_bavaria;
|
||||
use crate::parse_tile;
|
||||
use crate::protos::vector_tile::Tile;
|
||||
|
||||
#[test]
|
||||
fn it_works() {
|
||||
let mut f = File::open("libs/vector_tile/test_data/europe.pbf").expect("no file found");
|
||||
//let mut f = File::open("test_data/europe.pbf").expect("no file found");
|
||||
let mut reader = BufReader::new(f);
|
||||
let x = Tile::parse_from_reader(&mut reader).unwrap().decode();
|
||||
println!("{:#?}", x);
|
||||
fn test_parsing_europe_pbf() {
|
||||
let tile = parse_tile("libs/vector_tile/test_data/europe.pbf");
|
||||
//println!("{:?}", tile);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tile_coordinates_bavaria() {
|
||||
println!("{:?}", get_tile_coordinates_bavaria());
|
||||
}
|
||||
|
||||
@ -52,6 +52,14 @@ impl Feature {
|
||||
pub fn id(&self) -> u64 {
|
||||
self.internal.get_id()
|
||||
}
|
||||
|
||||
|
||||
pub fn geometry(&self) -> &Geometry {
|
||||
&self.geometry
|
||||
}
|
||||
pub fn properties(&self) -> &HashMap<String, PropertyValue> {
|
||||
&self.properties
|
||||
}
|
||||
}
|
||||
|
||||
impl Layer {
|
||||
@ -70,10 +78,18 @@ impl Layer {
|
||||
pub fn name(&self) -> &str {
|
||||
self.internal.get_name()
|
||||
}
|
||||
|
||||
pub fn features(&self) -> &Vec<Feature> {
|
||||
&self.features
|
||||
}
|
||||
}
|
||||
|
||||
impl Tile {
|
||||
pub(crate) fn new(internal: ProtoTile, layers: Vec<Layer>) -> Self {
|
||||
Tile { internal, layers }
|
||||
}
|
||||
|
||||
pub fn layers(&self) -> &Vec<Layer> {
|
||||
&self.layers
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user