commit 35734a7e6a83926aa03312cfb66a9f62c2937e6a
Author: Marcel <mtrnord1@gmail.com>
Date: Sun, 29 Dec 2019 16:12:03 +0100
Initial Commit
Took 7 hours 8 minutes
Diffstat:
11 files changed, 566 insertions(+), 0 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -0,0 +1,3 @@
+/target
+/data
+/out
diff --git a/.idea/.gitignore b/.idea/.gitignore
@@ -0,0 +1,2 @@
+# Default ignored files
+/workspace.xml
+\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ProjectRootManager">
+ <output url="file://$PROJECT_DIR$/out" />
+ </component>
+</project>
+\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ProjectModuleManager">
+ <modules>
+ <module fileurl="file://$PROJECT_DIR$/OSM_to_Euroscope.iml" filepath="$PROJECT_DIR$/OSM_to_Euroscope.iml" />
+ </modules>
+ </component>
+</project>
+\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="VcsDirectoryMappings">
+ <mapping directory="" vcs="Git" />
+ </component>
+</project>
+\ No newline at end of file
diff --git a/Cargo.lock b/Cargo.lock
@@ -0,0 +1,275 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "OSM_to_Euroscope"
+version = "0.1.0"
+dependencies = [
+ "fnv",
+ "osmpbf",
+]
+
+[[package]]
+name = "adler32"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2"
+
+[[package]]
+name = "autocfg"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2"
+
+[[package]]
+name = "byteorder"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
+
+[[package]]
+name = "cfg-if"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
+
+[[package]]
+name = "crc32fast"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "crossbeam-deque"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3aa945d63861bfe624b55d153a39684da1e8c0bc8fba932f7ee3a3c16cea3ca"
+dependencies = [
+ "crossbeam-epoch",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-epoch"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5064ebdbf05ce3cb95e45c8b086f72263f4166b29b97f6baff7ef7fe047b55ac"
+dependencies = [
+ "autocfg",
+ "cfg-if",
+ "crossbeam-utils",
+ "lazy_static",
+ "memoffset",
+ "scopeguard",
+]
+
+[[package]]
+name = "crossbeam-queue"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c695eeca1e7173472a32221542ae469b3e9aac3a4fc81f7696bcad82029493db"
+dependencies = [
+ "cfg-if",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-utils"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4"
+dependencies = [
+ "autocfg",
+ "cfg-if",
+ "lazy_static",
+]
+
+[[package]]
+name = "either"
+version = "1.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3"
+
+[[package]]
+name = "flate2"
+version = "1.0.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6bd6d6f4752952feb71363cffc9ebac9411b75b87c6ab6058c40c8900cf43c0f"
+dependencies = [
+ "cfg-if",
+ "crc32fast",
+ "libc",
+ "miniz_oxide",
+]
+
+[[package]]
+name = "fnv"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
+
+[[package]]
+name = "hermit-abi"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f629dc602392d3ec14bfc8a09b5e644d7ffd725102b48b81e59f90f2633621d7"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "inflate"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1cdb29978cc5797bd8dcc8e5bf7de604891df2a8dc576973d71a281e916db2ff"
+dependencies = [
+ "adler32",
+]
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
+[[package]]
+name = "libc"
+version = "0.2.66"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558"
+
+[[package]]
+name = "memmap"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b"
+dependencies = [
+ "libc",
+ "winapi",
+]
+
+[[package]]
+name = "memoffset"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9"
+dependencies = [
+ "rustc_version",
+]
+
+[[package]]
+name = "miniz_oxide"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f3f74f726ae935c3f514300cc6773a0c9492abc5e972d42ba0c0ebb88757625"
+dependencies = [
+ "adler32",
+]
+
+[[package]]
+name = "num_cpus"
+version = "1.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "76dac5ed2a876980778b8b85f75a71b6cbf0db0b1232ee12f826bccb00d09d72"
+dependencies = [
+ "hermit-abi",
+ "libc",
+]
+
+[[package]]
+name = "osmpbf"
+version = "0.1.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "52f8eed4edc2f1c5e720ff5cea4d872c88cfb81115096c3999f4a75e2d3c272a"
+dependencies = [
+ "byteorder",
+ "flate2",
+ "inflate",
+ "memmap",
+ "protobuf",
+ "rayon",
+]
+
+[[package]]
+name = "protobuf"
+version = "2.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "40361836defdd5871ff7e84096c6f6444af7fc157f8ef1789f54f147687caa20"
+
+[[package]]
+name = "rayon"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "db6ce3297f9c85e16621bb8cca38a06779ffc31bb8184e1be4bed2be4678a098"
+dependencies = [
+ "crossbeam-deque",
+ "either",
+ "rayon-core",
+]
+
+[[package]]
+name = "rayon-core"
+version = "1.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08a89b46efaf957e52b18062fb2f4660f8b8a4dde1807ca002690868ef2c85a9"
+dependencies = [
+ "crossbeam-deque",
+ "crossbeam-queue",
+ "crossbeam-utils",
+ "lazy_static",
+ "num_cpus",
+]
+
+[[package]]
+name = "rustc_version"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
+dependencies = [
+ "semver",
+]
+
+[[package]]
+name = "scopeguard"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d"
+
+[[package]]
+name = "semver"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
+dependencies = [
+ "semver-parser",
+]
+
+[[package]]
+name = "semver-parser"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
+
+[[package]]
+name = "winapi"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
diff --git a/Cargo.toml b/Cargo.toml
@@ -0,0 +1,11 @@
+[package]
+name = "OSM_to_Euroscope"
+version = "0.1.0"
+authors = ["Marcel <mtrnord1@gmail.com>"]
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+osmpbf = "0.1"
+fnv = "1.0.6"
diff --git a/OSM_to_Euroscope.iml b/OSM_to_Euroscope.iml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="RUST_MODULE" version="4">
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/examples" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" />
+ <sourceFolder url="file://$MODULE_DIR$/benches" isTestSource="true" />
+ <excludeFolder url="file://$MODULE_DIR$/target" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ </component>
+</module>
+\ No newline at end of file
diff --git a/src/main.rs b/src/main.rs
@@ -0,0 +1,169 @@
+//#![feature(test)]
+#![allow(non_snake_case)]
+
+use std::fs;
+use std::fs::File;
+use std::io::Write;
+use std::path::Path;
+
+use fnv::FnvHashMap;
+use osmpbf::*;
+
+#[derive(Copy, Clone, Debug, PartialOrd, PartialEq)]
+struct LatLon {
+ lat: f64,
+ lon: f64,
+}
+
+type Coords = Vec<LatLon>;
+type Refs = Vec<i64>;
+
+fn main() {
+ generate_ese_ground_taxiway("./data/EDDH_cleaned.osm.pbf", "EDDH")
+}
+
+fn generate_ese_ground_taxiway<P: AsRef<Path> + Copy>(source_path: P, airport_name: &str) {
+ let out_path_string = format!("./out/{}.ese", airport_name);
+ let out_path = Path::new(&out_path_string);
+ if !out_path.parent().unwrap().exists() {
+ fs::create_dir_all(out_path.parent().unwrap()).expect("unable to generate dir");
+ }
+ let out_file = &mut File::create(out_path).expect("unable to open file");
+
+ out_file
+ .write_all(b"[GROUND]\n")
+ .expect("failed to write file");
+ let taxiways = get_taxiways(source_path);
+
+ let coords = get_taxiways_coords(source_path, taxiways);
+ write_taxiways(out_file, airport_name, coords);
+
+ out_file.sync_all().expect("unable to sync to file");
+}
+
+fn to_2_digits(n: i32) -> i32 {
+ let n = n as f32;
+ let digit_offset = std::cmp::max((n.abs().log10() - 2.0).ceil() as i32, 0);
+ let rounded = n / 10f32.powi(digit_offset);
+ rounded as i32
+}
+
+fn format_coordinate(coordinate_raw: f64) -> String {
+ let coordinate = coordinate_raw;
+ let degree = coordinate.trunc() as i64;
+ let minute = ((coordinate - degree as f64).abs() * 60.0).trunc() as i64;
+ let seconds = 3600.0 * (coordinate - degree as f64).abs() - 60.0 * (minute as f64);
+ let decimal_part_string = format!("{:.2}", seconds - (seconds.trunc() as f64) as f64);
+ let decimal_part_split = decimal_part_string.split('.').collect::<Vec<&str>>();
+ let decimal_part = decimal_part_split.last().unwrap();
+
+ format!(
+ "{:03}.{:02}.{:02}.{:02}",
+ degree,
+ minute,
+ to_2_digits(seconds as i32),
+ decimal_part
+ )
+}
+
+fn write_taxiways(out_file: &mut File, airport_name: &str, taxiways: FnvHashMap<String, Coords>) {
+ taxiways.iter().for_each(|(name, coordinates)| {
+ let type_string = format!("TAXI:{} {}:20:1\n", airport_name, name);
+ out_file
+ .write_all(type_string.as_bytes())
+ .expect("failed to write file");
+
+ let local_coords: Vec<&LatLon> = coordinates.iter().clone().collect();
+ local_coords.iter().for_each(|latlon| {
+ let lat_str = format_coordinate(latlon.lat);
+
+ let lon_str = format_coordinate(latlon.lon);
+
+ let coordinate_string: String;
+
+ coordinate_string = format!("COORD:N{}:E{}\n", lat_str, lon_str);
+ out_file
+ .write_all(coordinate_string.as_bytes())
+ .expect("failed to write file");
+ });
+ });
+}
+
+struct Node {
+ id: i64,
+ lat: f64,
+ lon: f64,
+}
+
+fn get_taxiways_coords<P: AsRef<Path> + Copy>(
+ path: P,
+ refs: FnvHashMap<String, Refs>,
+) -> FnvHashMap<String, Coords> {
+ let mut taxiways: FnvHashMap<String, Coords> = FnvHashMap::default();
+ let mut nodes: Vec<Node> = Vec::new();
+
+ let reader = ElementReader::from_path(path).unwrap();
+ reader
+ .for_each(|element| {
+ if let Element::DenseNode(node) = element {
+ let new_node = Node {
+ id: node.id,
+ lat: node.lat(),
+ lon: node.lon(),
+ };
+ nodes.push(new_node);
+ }
+ })
+ .unwrap();
+
+ for (key, val) in refs.iter() {
+ val.iter().for_each(|refval| {
+ if let Some(node) = nodes.iter().find(|x| x.id == *refval) {
+ let lat_lon = LatLon {
+ lat: node.lat,
+ lon: node.lon,
+ };
+
+ if taxiways.contains_key(key.as_str()) {
+ (*(taxiways.get_mut(key.as_str()).unwrap())).push(lat_lon);
+ } else {
+ let mut coords: Coords = Vec::new();
+ coords.push(lat_lon);
+ taxiways.insert(key.clone(), coords);
+ }
+ }
+ })
+ }
+
+ taxiways
+}
+
+fn get_taxiways<P: AsRef<Path> + Copy>(path: P) -> FnvHashMap<String, Refs> {
+ let mut taxiways: FnvHashMap<String, Refs> = FnvHashMap::default();
+
+ let reader = ElementReader::from_path(path).unwrap();
+ reader
+ .for_each(|element| {
+ if let Element::Way(way) = element {
+ if way
+ .tags()
+ .any(|(key, value)| key == "aeroway" && value == "taxiway")
+ {
+ if let Some((_, value)) = way.tags().find(|(key, _)| *key == "ref") {
+ let mut new_vals = way.refs().collect::<Vec<i64>>();
+
+ if taxiways.contains_key(value) {
+ taxiways.get_mut(value).unwrap().append(&mut new_vals);
+ } else {
+ taxiways.insert(value.to_string(), new_vals);
+ }
+ }
+ }
+ }
+ })
+ .unwrap();
+ taxiways
+}
+
+#[cfg(test)]
+mod tests;
diff --git a/src/main_lahm.rs b/src/main_lahm.rs
@@ -0,0 +1,46 @@
+use std::fs::File;
+
+use osm_xml::{Reference, Tag, OSM, Way};
+
+fn main() {
+ let f = File::open("./data/EDDH.osm").unwrap();
+ let doc = OSM::parse(f).unwrap();
+
+ let way_info = way_reference_statistics(&doc);
+
+ println!(
+ "Way count {}",
+ doc.ways
+ .values()
+ .filter(|way| {
+ way.tags.contains(&Tag {
+ key: "aeroway".to_string(),
+ val: "taxiway".to_string(),
+ })
+ })
+ .collect::<Vec<&Way>>()
+ .len()
+ );
+ println!(
+ "Way reference count: {}, invalid references: {}",
+ way_info.0, way_info.1
+ );
+}
+
+fn way_reference_statistics(doc: &OSM) -> (usize, usize) {
+ doc.ways
+ .values()
+ .filter(|way| {
+ way.tags.contains(&Tag {
+ key: "aeroway".to_string(),
+ val: "taxiway".to_string(),
+ })
+ })
+ .flat_map(|way| way.nodes.iter())
+ .fold((0, 0), |acc, node| match doc.resolve_reference(&node) {
+ Reference::Node(_) => (acc.0 + 1, acc.1),
+ Reference::Unresolved | Reference::Way(_) | Reference::Relation(_) => {
+ (acc.0, acc.1 + 1)
+ }
+ })
+}
diff --git a/src/tests.rs b/src/tests.rs
@@ -0,0 +1,20 @@
+extern crate test;
+
+use test::Bencher;
+
+use super::*;
+
+#[bench]
+fn bench_eddh(b: &mut Bencher) {
+ b.iter(|| generate_ese_ground_taxiway("./data/EDDH.osm.pbf", "EDDH1"));
+}
+
+#[bench]
+fn bench_eddh_cleaned(b: &mut Bencher) {
+ b.iter(|| generate_ese_ground_taxiway("./data/EDDH_cleaned.osm.pbf", "EDDH2"));
+}
+
+#[bench]
+fn bench_hamburg(b: &mut Bencher) {
+ b.iter(|| generate_ese_ground_taxiway("./data/hamburg-latest.osm.pbf", "EDDH3"));
+}