Skip to content

Commit b867ffd

Browse files
authored
Merge pull request #2 from hove-io/improve_github_actions
chore: Improve GitHub-Actions, bump Geo and fix Clippy
2 parents dacc66c + 62f04cf commit b867ffd

File tree

6 files changed

+113
-93
lines changed

6 files changed

+113
-93
lines changed

.github/workflows/auto-tagging.yml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
name: Auto-tagging major/minor version
2+
3+
on:
4+
release:
5+
types: [published]
6+
7+
jobs:
8+
tag-major-minor:
9+
runs-on: ubuntu-latest
10+
permissions: write-all
11+
steps:
12+
- uses: actions/checkout@v6
13+
- name: Fetch existing tags
14+
run: git fetch --tags
15+
- name: Generate tag
16+
run: |
17+
export MAJOR_VERSION=$( echo "${GITHUB_REF_NAME}" | cut --delimiter '.' --fields=1 )
18+
export MINOR_VERSION=$( echo "${GITHUB_REF_NAME}" | cut --delimiter '.' --fields=2 )
19+
20+
export MAJOR_TAG="${MAJOR_VERSION}"
21+
echo "Creating tag '${MAJOR_TAG}' from '${GITHUB_REF_NAME}'"
22+
git tag --force ${MAJOR_TAG} ${GITHUB_REF_NAME}
23+
echo "Pushing new tag '${MAJOR_TAG}'"
24+
25+
export MINOR_TAG="${MAJOR_VERSION}.${MINOR_VERSION}"
26+
echo "Creating tag '${MINOR_TAG}' from '${GITHUB_REF_NAME}'"
27+
git tag --force ${MINOR_TAG} ${GITHUB_REF_NAME}
28+
echo "Pushing new tag '${MINOR_TAG}'"
29+
30+
git push origin --force ${MAJOR_TAG} ${MINOR_TAG}

.github/workflows/ci.yml

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,26 @@
1-
on: [push, pull_request]
1+
name: Continuous Integration
2+
on:
3+
push:
4+
branches: [main]
5+
pull_request:
6+
7+
permissions:
8+
contents: read
9+
pull-requests: write
210

311
jobs:
4-
build:
12+
ci:
13+
name: CI
514
runs-on: ubuntu-latest
6-
container:
7-
image: rust:1
815
steps:
9-
- name: Checkout repository
10-
uses: actions/checkout@v2
11-
12-
- run: rustup component add rustfmt
13-
- run: cargo test
14-
- run: cargo fmt --all -- --check
15-
16-
- name: Publish crate
17-
if: github.ref == 'refs/heads/master'
18-
run: cargo publish
19-
env:
20-
CARGO_REGISTRY_TOKEN: ${{ secrets.CRATESIO_TOKEN }}
16+
- uses: actions/checkout@v4
17+
- name: Install Rust stable
18+
uses: dtolnay/rust-toolchain@stable
19+
with:
20+
components: rustfmt, clippy
21+
- name: Run cargo fmt
22+
run: cargo fmt --all -- --check
23+
- name: Run cargo clippy
24+
run: cargo clippy -- -D warnings
25+
- name: Run tests with all features
26+
run: cargo test

Cargo.toml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
[package]
22
name = "osm_boundaries_utils"
3-
version = "0.11.0"
3+
version = "0.12.1"
44
authors = ["dt.ro <dt.ro@canaltp.fr>", "Antoine Desbordes <antoine.desbordes@gmail.com>"]
55
description = "utilities to help reading OpenStreetMap boundaries in rust."
66
repository = "https://github.com/hove-io/osm_boundaries_utils"
77
keywords = ["openstreetmap", "osm", "boundaries"]
88
license = "WTFPL"
99
readme = "README.md"
10+
edition = "2024"
1011

1112
[dependencies]
12-
log = "0.4"
13-
osmpbfreader = "0.16"
14-
geo-types = "^0.7"
15-
geo = "0.18"
13+
geo = "0.32"
14+
tracing = "0.1"
15+
osmpbfreader = "0.19"

src/boundaries.rs

Lines changed: 46 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
extern crate osmpbfreader;
1+
use tracing::{debug, warn};
22

3-
use geo_types::{Coordinate, LineString, MultiPolygon, Point, Polygon};
3+
use geo::{Coord, LineString, MultiPolygon, Point, Polygon};
44
use std::borrow::Borrow;
55
use std::collections::BTreeMap;
66

@@ -129,29 +129,29 @@ pub fn build_boundary<T: Borrow<osmpbfreader::OsmObj>>(
129129
let mut outer_polys = build_boundary_parts(relation, objects, vec!["outer", "enclave", ""]);
130130
let inner_polys = build_boundary_parts(relation, objects, vec!["inner"]);
131131

132-
if let Some(ref mut outers) = outer_polys {
133-
if let Some(inners) = inner_polys {
134-
inners.into_iter().for_each(|inner| {
135-
/*
136-
It's assumed here that the 'inner' ring is contained into
137-
exactly ONE outer ring. To find it among all 'outers', all
138-
we need is to find a candidate 'outer' area that shares a point
139-
point with (i.e 'intersects') all 'inner' segments.
140-
Using 'contains' is not suitable here, as 'inner' may touch its outer
141-
ring at a single point.
142-
143-
NB: this algorithm cannot handle "donut inside donut" boundaries
144-
(where 'inner' would be contained into multiple concentric outer rings).
145-
*/
146-
let (exterior, _) = inner.into_inner();
147-
for ref mut outer in outers.0.iter_mut() {
148-
if exterior.lines().all(|line| outer.intersects(&line)) {
149-
outer.interiors_push(exterior);
150-
break;
151-
}
132+
if let Some(ref mut outers) = outer_polys
133+
&& let Some(inners) = inner_polys
134+
{
135+
inners.into_iter().for_each(|inner| {
136+
/*
137+
It's assumed here that the 'inner' ring is contained into
138+
exactly ONE outer ring. To find it among all 'outers', all
139+
we need is to find a candidate 'outer' area that shares a point
140+
point with (i.e 'intersects') all 'inner' segments.
141+
Using 'contains' is not suitable here, as 'inner' may touch its outer
142+
ring at a single point.
143+
144+
NB: this algorithm cannot handle "donut inside donut" boundaries
145+
(where 'inner' would be contained into multiple concentric outer rings).
146+
*/
147+
let (exterior, _) = inner.into_inner();
148+
for ref mut outer in outers.0.iter_mut() {
149+
if exterior.lines().all(|line| outer.intersects(&line)) {
150+
outer.interiors_push(exterior);
151+
break;
152152
}
153-
})
154-
}
153+
}
154+
})
155155
}
156156
outer_polys
157157
}
@@ -185,7 +185,7 @@ pub fn build_boundary_parts<T: Borrow<osmpbfreader::OsmObj>>(
185185
let mut append_ring = |nodes: &[osmpbfreader::Node]| {
186186
let poly_geom = nodes
187187
.iter()
188-
.map(|n| Coordinate {
188+
.map(|n| Coord {
189189
x: n.lon(),
190190
y: n.lat(),
191191
})
@@ -257,22 +257,24 @@ pub fn build_boundary_parts<T: Borrow<osmpbfreader::OsmObj>>(
257257
}
258258
}
259259
if !added_part {
260-
use geo::haversine_distance::HaversineDistance;
260+
use geo::{Distance, Haversine};
261261
let p = |n: &osmpbfreader::Node| {
262-
Point(Coordinate {
262+
Point(Coord {
263263
x: n.lon(),
264264
y: n.lat(),
265265
})
266266
};
267267

268268
if added_nodes.len() > 1 {
269-
let distance = p(added_nodes.first().unwrap())
270-
.haversine_distance(&p(added_nodes.last().unwrap()));
269+
let distance = Haversine.distance(
270+
p(added_nodes.first().unwrap()),
271+
p(added_nodes.last().unwrap()),
272+
);
271273
if distance < WARN_UNCLOSED_RING_MAX_DISTANCE {
272274
warn!(
273275
"boundary: relation/{} ({}): unclosed polygon, dist({:?}, {:?}) = {}",
274276
relation.id.0,
275-
relation.tags.get("name").map_or("", |s| &s),
277+
relation.tags.get("name").map_or("", |s| s),
276278
added_nodes.first().unwrap().id,
277279
added_nodes.last().unwrap().id,
278280
distance
@@ -327,7 +329,7 @@ fn test_build_boundary_not_closed() {
327329
.relation_id
328330
.into();
329331
if let osmpbfreader::OsmObj::Relation(ref relation) = builder.objects[&rel_id] {
330-
assert!(build_boundary(&relation, &builder.objects).is_none());
332+
assert!(build_boundary(relation, &builder.objects).is_none());
331333
} else {
332334
unreachable!()
333335
}
@@ -350,7 +352,7 @@ fn test_build_boundary_closed() {
350352
.relation_id
351353
.into();
352354
if let osmpbfreader::OsmObj::Relation(ref relation) = builder.objects[&rel_id] {
353-
let multipolygon = build_boundary(&relation, &builder.objects);
355+
let multipolygon = build_boundary(relation, &builder.objects);
354356
assert!(multipolygon.is_some());
355357
let multipolygon = multipolygon.unwrap();
356358
assert_eq!(multipolygon.0.len(), 1);
@@ -376,7 +378,7 @@ fn test_build_boundary_closed_reverse() {
376378
.relation_id
377379
.into();
378380
if let osmpbfreader::OsmObj::Relation(ref relation) = builder.objects[&rel_id] {
379-
let multipolygon = build_boundary(&relation, &builder.objects);
381+
let multipolygon = build_boundary(relation, &builder.objects);
380382
assert!(multipolygon.is_some());
381383
let multipolygon = multipolygon.unwrap();
382384
assert_eq!(multipolygon.0.len(), 1);
@@ -399,7 +401,7 @@ fn test_build_one_boundary_closed() {
399401
.relation_id
400402
.into();
401403
if let osmpbfreader::OsmObj::Relation(ref relation) = builder.objects[&rel_id] {
402-
let multipolygon = build_boundary(&relation, &builder.objects);
404+
let multipolygon = build_boundary(relation, &builder.objects);
403405
assert!(multipolygon.is_some());
404406
let multipolygon = multipolygon.unwrap();
405407
assert_eq!(multipolygon.0.len(), 1);
@@ -431,14 +433,14 @@ fn test_build_two_opposite_clockwise_boundaries() {
431433
.relation_id
432434
.into();
433435
if let osmpbfreader::OsmObj::Relation(ref relation) = builder.objects[&rel_id] {
434-
let multipolygon = build_boundary(&relation, &builder.objects);
436+
let multipolygon = build_boundary(relation, &builder.objects);
435437
assert!(multipolygon.is_some());
436438
let multipolygon = multipolygon.unwrap();
437439
assert_eq!(multipolygon.0.len(), 2);
438440
let centroid = multipolygon.centroid();
439441
let centroid = centroid.unwrap();
440-
assert!(centroid.lng().abs() < f64::EPSILON);
441-
assert!(centroid.lat().abs() < f64::EPSILON);
442+
assert!(centroid.x().abs() < f64::EPSILON);
443+
assert!(centroid.y().abs() < f64::EPSILON);
442444
} else {
443445
unreachable!()
444446
}
@@ -464,7 +466,7 @@ fn test_build_two_boundaries_closed() {
464466
.relation_id
465467
.into();
466468
if let osmpbfreader::OsmObj::Relation(ref relation) = builder.objects[&rel_id] {
467-
let multipolygon = build_boundary(&relation, &builder.objects);
469+
let multipolygon = build_boundary(relation, &builder.objects);
468470
assert!(multipolygon.is_some());
469471
let multipolygon = multipolygon.unwrap();
470472
assert_eq!(multipolygon.0.len(), 2);
@@ -496,7 +498,7 @@ fn test_build_one_donut_boundary() {
496498
.relation_id
497499
.into();
498500
if let osmpbfreader::OsmObj::Relation(ref relation) = builder.objects[&rel_id] {
499-
let multipolygon = build_boundary(&relation, &builder.objects);
501+
let multipolygon = build_boundary(relation, &builder.objects);
500502
assert!(multipolygon.is_some());
501503
let multipolygon = multipolygon.unwrap();
502504
assert_eq!(multipolygon.0.len(), 1);
@@ -536,7 +538,7 @@ fn test_build_two_boundaries_with_one_hole() {
536538
.relation_id
537539
.into();
538540
if let osmpbfreader::OsmObj::Relation(ref relation) = builder.objects[&rel_id] {
539-
let multipolygon = build_boundary(&relation, &builder.objects);
541+
let multipolygon = build_boundary(relation, &builder.objects);
540542
assert!(multipolygon.is_some());
541543
let multipolygon = multipolygon.unwrap();
542544
assert_eq!(multipolygon.0.len(), 2);
@@ -576,7 +578,7 @@ fn test_build_one_boundary_with_two_holes() {
576578
.relation_id
577579
.into();
578580
if let osmpbfreader::OsmObj::Relation(ref relation) = builder.objects[&rel_id] {
579-
let multipolygon = build_boundary(&relation, &builder.objects);
581+
let multipolygon = build_boundary(relation, &builder.objects);
580582
assert!(multipolygon.is_some());
581583
let multipolygon = multipolygon.unwrap();
582584
assert_eq!(multipolygon.0.len(), 1);
@@ -624,7 +626,7 @@ fn test_build_two_boundaries_with_two_holes() {
624626
.relation_id
625627
.into();
626628
if let osmpbfreader::OsmObj::Relation(ref relation) = builder.objects[&rel_id] {
627-
let multipolygon = build_boundary(&relation, &builder.objects);
629+
let multipolygon = build_boundary(relation, &builder.objects);
628630
assert!(multipolygon.is_some());
629631
let multipolygon = multipolygon.unwrap();
630632
assert_eq!(multipolygon.0.len(), 2);
@@ -663,7 +665,7 @@ fn test_build_inner_touching_outer_at_one_point() {
663665
.relation_id
664666
.into();
665667
if let osmpbfreader::OsmObj::Relation(ref relation) = builder.objects[&rel_id] {
666-
let multipolygon = build_boundary(&relation, &builder.objects);
668+
let multipolygon = build_boundary(relation, &builder.objects);
667669
assert!(multipolygon.is_some());
668670
let multipolygon = multipolygon.unwrap();
669671
assert_eq!(multipolygon.0.len(), 1);
@@ -705,7 +707,7 @@ fn test_build_two_touching_rings() {
705707
.relation_id
706708
.into();
707709
if let osmpbfreader::OsmObj::Relation(ref relation) = builder.objects[&rel_id] {
708-
let multipolygon = build_boundary(&relation, &builder.objects);
710+
let multipolygon = build_boundary(relation, &builder.objects);
709711
assert!(multipolygon.is_some());
710712
let multipolygon = multipolygon.unwrap();
711713
assert_eq!(multipolygon.0.len(), 2);

src/lib.rs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,4 @@
1-
extern crate geo_types;
2-
#[macro_use]
3-
extern crate log;
4-
extern crate geo;
5-
extern crate osmpbfreader;
6-
71
mod boundaries;
82
pub mod osm_builder;
93

10-
pub use crate::boundaries::build_boundary;
4+
pub use boundaries::build_boundary;

src/osm_builder.rs

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
extern crate osmpbfreader;
2-
use geo_types::Point;
1+
use geo::Point;
32
use std::collections::BTreeMap;
43

54
pub fn named_node(lon: f64, lat: f64, name: &'static str) -> (Point<f64>, Option<String>) {
@@ -12,9 +11,9 @@ pub struct Relation<'a> {
1211
}
1312

1413
impl<'a> Relation<'a> {
15-
pub fn outer(&mut self, coords: Vec<(Point<f64>, Option<String>)>) -> &'a mut Relation {
14+
pub fn outer(&mut self, coords: Vec<(Point<f64>, Option<String>)>) -> &'a mut Relation<'_> {
1615
let id = self.builder.way(coords);
17-
if let osmpbfreader::OsmObj::Relation(ref mut rel) = self
16+
if let osmpbfreader::OsmObj::Relation(rel) = self
1817
.builder
1918
.objects
2019
.get_mut(&self.relation_id.into())
@@ -30,9 +29,9 @@ impl<'a> Relation<'a> {
3029
}
3130

3231
impl<'a> Relation<'a> {
33-
pub fn inner(&mut self, coords: Vec<(Point<f64>, Option<String>)>) -> &'a mut Relation {
32+
pub fn inner(&mut self, coords: Vec<(Point<f64>, Option<String>)>) -> &'a mut Relation<'_> {
3433
let id = self.builder.way(coords);
35-
if let osmpbfreader::OsmObj::Relation(ref mut rel) = self
34+
if let osmpbfreader::OsmObj::Relation(rel) = self
3635
.builder
3736
.objects
3837
.get_mut(&self.relation_id.into())
@@ -47,6 +46,7 @@ impl<'a> Relation<'a> {
4746
}
4847
}
4948

49+
#[derive(Default)]
5050
pub struct OsmBuilder {
5151
node_id: i64,
5252
way_id: i64,
@@ -55,24 +55,12 @@ pub struct OsmBuilder {
5555
named_nodes: BTreeMap<String, osmpbfreader::NodeId>,
5656
}
5757

58-
impl Default for OsmBuilder {
59-
fn default() -> Self {
60-
Self {
61-
node_id: 0,
62-
way_id: 0,
63-
relation_id: 0,
64-
objects: BTreeMap::new(),
65-
named_nodes: BTreeMap::new(),
66-
}
67-
}
68-
}
69-
7058
impl OsmBuilder {
7159
pub fn new() -> OsmBuilder {
7260
Self::default()
7361
}
7462

75-
pub fn relation(&mut self) -> Relation {
63+
pub fn relation(&mut self) -> Relation<'_> {
7664
let id = osmpbfreader::RelationId(self.relation_id);
7765
let r = osmpbfreader::Relation {
7866
id,
@@ -110,8 +98,8 @@ impl OsmBuilder {
11098
let id = osmpbfreader::NodeId(self.node_id);
11199
let n = osmpbfreader::Node {
112100
id,
113-
decimicro_lat: (coord.lat() * 1e7) as i32,
114-
decimicro_lon: (coord.lng() * 1e7) as i32,
101+
decimicro_lat: (coord.y() * 1e7) as i32,
102+
decimicro_lon: (coord.x() * 1e7) as i32,
115103
tags: osmpbfreader::Tags::new(),
116104
};
117105
self.node_id += 1;

0 commit comments

Comments
 (0)