Skip to content

Commit ea7dbbb

Browse files
committed
update LineStringCurve occurrences in PlanarLineStringCurve
1 parent 66c052d commit ea7dbbb

File tree

2 files changed

+95
-46
lines changed

2 files changed

+95
-46
lines changed

src/curves.rs

+91-42
Original file line numberDiff line numberDiff line change
@@ -185,13 +185,15 @@ impl Curve for PlanarLineStringCurve {
185185
fn intersect_segment(&self, segment: Line) -> Option<Point> {
186186
self.geom
187187
.lines()
188-
.flat_map(|curve_line| match geo::line_intersection::line_intersection(segment, curve_line) {
189-
Some(LineIntersection::SinglePoint {
190-
intersection,
191-
is_proper: _,
192-
}) => Some(intersection.into()),
193-
Some(LineIntersection::Collinear { intersection: _ }) => None,
194-
None => None,
188+
.flat_map(|curve_line| {
189+
match geo::line_intersection::line_intersection(segment, curve_line) {
190+
Some(LineIntersection::SinglePoint {
191+
intersection,
192+
is_proper: _,
193+
}) => Some(intersection.into()),
194+
Some(LineIntersection::Collinear { intersection: _ }) => None,
195+
None => None,
196+
}
195197
})
196198
.next()
197199
}
@@ -210,7 +212,10 @@ impl Curve for PlanarLineStringCurve {
210212
.ok_or(CurveError::NotFiniteCoordinates)?;
211213

212214
// translate to (0, 0) and normalize by the length of the curve to get unit vector of tangent
213-
let tangent = ((line.end.x - line.start.x) / self.length, (line.end.y - line.start.y) / self.length);
215+
let tangent = (
216+
(line.end.x - line.start.x) / self.length,
217+
(line.end.y - line.start.y) / self.length,
218+
);
214219

215220
// 90° clockwise rotation
216221
let normal = (-tangent.1, tangent.0);
@@ -293,7 +298,9 @@ impl Curve for SphericalLineStringCurve {
293298
}
294299

295300
fn is_valid(&self) -> bool {
296-
if !(self.geom.coords_count() >= 2 && (self.geom.coords_count() > 2 || !self.geom.is_closed())) {
301+
if !(self.geom.coords_count() >= 2
302+
&& (self.geom.coords_count() > 2 || !self.geom.is_closed()))
303+
{
297304
return false;
298305
}
299306
for coord in self.geom.coords() {
@@ -311,7 +318,9 @@ impl Curve for SphericalLineStringCurve {
311318

312319
match self.geom.haversine_closest_point(&point) {
313320
geo::Closest::SinglePoint(closest_point) => {
314-
let distance_along_curve = closest_point.haversine_distance(&self.geom.points().next().unwrap()) + self.start_offset;
321+
let distance_along_curve = closest_point
322+
.haversine_distance(&self.geom.points().next().unwrap())
323+
+ self.start_offset;
315324

316325
let begin = self.geom.coords().next().unwrap();
317326
let end = self.geom.coords().next_back().unwrap();
@@ -324,11 +333,11 @@ impl Curve for SphericalLineStringCurve {
324333

325334
Ok(CurveProjection {
326335
distance_along_curve,
327-
offset
336+
offset,
328337
})
329338
}
330339
geo::Closest::Intersection(_) => Err(CurveError::InvalidGeometry),
331-
geo::Closest::Indeterminate => Err(CurveError::NotFiniteCoordinates)
340+
geo::Closest::Indeterminate => Err(CurveError::NotFiniteCoordinates),
332341
}
333342
}
334343

@@ -381,17 +390,15 @@ impl Curve for SphericalLineStringCurve {
381390
self.geom
382391
.densify_haversine(self.densify_by)
383392
.lines()
384-
.flat_map(|curve_line| match geo::line_intersection::line_intersection(segment, curve_line) {
385-
Some(LineIntersection::SinglePoint {
386-
intersection,
387-
is_proper: _,
388-
}) => {
389-
Some(intersection.into())
390-
},
391-
Some(LineIntersection::Collinear { intersection: _ }) => {
392-
None
393-
},
394-
None => None,
393+
.flat_map(|curve_line| {
394+
match geo::line_intersection::line_intersection(segment, curve_line) {
395+
Some(LineIntersection::SinglePoint {
396+
intersection,
397+
is_proper: _,
398+
}) => Some(intersection.into()),
399+
Some(LineIntersection::Collinear { intersection: _ }) => None,
400+
None => None,
401+
}
395402
})
396403
.next()
397404
}
@@ -467,7 +474,11 @@ mod tests {
467474
#[test]
468475
fn planar_fragmented() {
469476
let framentation_max_length = 1.;
470-
let c = PlanarLineStringCurve::new_fragmented(line_string![(x: 0., y: 0.), (x: 2., y: 0.)], framentation_max_length, 1.);
477+
let c = PlanarLineStringCurve::new_fragmented(
478+
line_string![(x: 0., y: 0.), (x: 2., y: 0.)],
479+
framentation_max_length,
480+
1.,
481+
);
471482
assert_eq!(2, c.len());
472483
assert_eq!(framentation_max_length, c[0].length());
473484
}
@@ -571,22 +582,39 @@ mod tests {
571582
#[test]
572583
fn spherical_fragmented() {
573584
let framentation_max_length = 1.;
574-
let paris_to_new_york = SphericalLineStringCurve::new_fragmented(line_string![(x: PARIS_LON, y: PARIS_LAT), (x: NEW_YORK_LON, y: NEW_YORK_LAT)], framentation_max_length, 1.);
585+
let paris_to_new_york = SphericalLineStringCurve::new_fragmented(
586+
line_string![(x: PARIS_LON, y: PARIS_LAT), (x: NEW_YORK_LON, y: NEW_YORK_LAT)],
587+
framentation_max_length,
588+
1.,
589+
);
575590

576591
assert_eq!(5837284, paris_to_new_york.len());
577-
assert_relative_eq!(framentation_max_length, paris_to_new_york[0].length(), epsilon = 1e-7);
592+
assert_relative_eq!(
593+
framentation_max_length,
594+
paris_to_new_york[0].length(),
595+
epsilon = 1e-7
596+
);
578597
// 1e-7 means we lose 0.1 micrometer per segment
579598
}
580599

581600
#[test]
582601
fn spherical_length() {
583-
let paris_to_new_york = SphericalLineStringCurve::new(line_string![(x: PARIS_LON, y: PARIS_LAT), (x: NEW_YORK_LON, y: NEW_YORK_LAT)], 1.);
602+
let paris_to_new_york = SphericalLineStringCurve::new(
603+
line_string![(x: PARIS_LON, y: PARIS_LAT), (x: NEW_YORK_LON, y: NEW_YORK_LAT)],
604+
1.,
605+
);
584606
assert_relative_eq!(5837283.441678336, paris_to_new_york.length()); // 5837283.441678336 using [`HaversineLength`] and 5852969.839293494 using [`GeodesicLength`]
585607

586-
let lille_to_perpignan = SphericalLineStringCurve::new(line_string![(x: LILLE_LON, y: LILLE_LAT), (x: PERPIGNAN_LON, y: PERPIGNAN_LAT)], 1.);
608+
let lille_to_perpignan = SphericalLineStringCurve::new(
609+
line_string![(x: LILLE_LON, y: LILLE_LAT), (x: PERPIGNAN_LON, y: PERPIGNAN_LAT)],
610+
1.,
611+
);
587612
assert_relative_eq!(883505.2931188548, lille_to_perpignan.length()); // 883505.2931188548 using [`HaversineLength`] and 883260.051153502 using [`GeodesicLength`]
588613

589-
let brest_to_nancy = SphericalLineStringCurve::new(line_string![(x: BREST_LON, y: BREST_LAT), (x: NANCY_LON, y: NANCY_LAT)], 1.);
614+
let brest_to_nancy = SphericalLineStringCurve::new(
615+
line_string![(x: BREST_LON, y: BREST_LAT), (x: NANCY_LON, y: NANCY_LAT)],
616+
1.,
617+
);
590618
assert_relative_eq!(785636.8730262491, brest_to_nancy.length()); // 785636.8730262491 using [`HaversineLength`] and 787994.4363866252 using [`GeodesicLength`]
591619
}
592620

@@ -597,7 +625,8 @@ mod tests {
597625
assert!(curve.is_valid());
598626

599627
// Invalid curve: too few coordinates
600-
let curve = SphericalLineStringCurve::new(line_string![(x: 0., y: 0.)], 1.);
628+
let curve =
629+
SphericalLineStringCurve::new(line_string![(x: 0., y: 0.)], 1.);
601630
assert!(!curve.is_valid());
602631

603632
// Invalid curve: closed LineString with only 2 coordinates
@@ -613,51 +642,71 @@ mod tests {
613642
assert!(!curve.is_valid());
614643

615644
// Invalid curve: latitude > 90.
616-
let curve = SphericalLineStringCurve::new(line_string![(x: 0., y: 90.1), (x: 0., y: 0.)], 1.);
645+
let curve =
646+
SphericalLineStringCurve::new(line_string![(x: 0., y: 90.1), (x: 0., y: 0.)], 1.);
617647
assert!(!curve.is_valid());
618648

619649
// Invalid curve: latitude > 180.
620-
let curve = SphericalLineStringCurve::new(line_string![(x: 0., y: -90.1), (x: 0., y: 0.)], 1.);
650+
let curve =
651+
SphericalLineStringCurve::new(line_string![(x: 0., y: -90.1), (x: 0., y: 0.)], 1.);
621652
assert!(!curve.is_valid());
622653
}
623654

624655
#[test]
625656
fn spherical_projection() {
626-
let mut paris_to_new_york = SphericalLineStringCurve::new(line_string![(x: PARIS_LON, y: PARIS_LAT), (x: NEW_YORK_LON, y: NEW_YORK_LAT)], 1.);
657+
let mut paris_to_new_york = SphericalLineStringCurve::new(
658+
line_string![(x: PARIS_LON, y: PARIS_LAT), (x: NEW_YORK_LON, y: NEW_YORK_LAT)],
659+
1.,
660+
);
627661

628662
// Point is located on the right (north) of the curve
629-
let projected = paris_to_new_york.project(point! {x: -6.705403880820967, y: 51.42135181702875}).unwrap();
663+
let projected = paris_to_new_york
664+
.project(point! {x: -6.705403880820967, y: 51.42135181702875})
665+
.unwrap();
630666
assert_eq!(701924.3809693493, projected.distance_along_curve);
631667
assert_eq!(-67157.93913531031, projected.offset);
632668

633669
// Point is located on the left (south) of the curve
634-
let projected = paris_to_new_york.project(point! {x: -12.250890759346419, y: 45.857650969554356}).unwrap();
670+
let projected = paris_to_new_york
671+
.project(point! {x: -12.250890759346419, y: 45.857650969554356})
672+
.unwrap();
635673
assert_eq!(963365.3768036617, projected.distance_along_curve);
636674
assert_eq!(625592.3211438804, projected.offset);
637675

638676
// Same point, but with an offset from the curve
639677
paris_to_new_york.start_offset = 1000000.;
640-
let projected = paris_to_new_york.project(point! {x: -12.250890759346419, y: 45.857650969554356}).unwrap();
678+
let projected = paris_to_new_york
679+
.project(point! {x: -12.250890759346419, y: 45.857650969554356})
680+
.unwrap();
641681
assert_eq!(1963365.3768036617, projected.distance_along_curve);
642682
assert_eq!(625592.3211438804, projected.offset);
643683

644684
// ################################################################################
645-
let mut new_york_to_paris = SphericalLineStringCurve::new(line_string![(x: NEW_YORK_LON, y: NEW_YORK_LAT), (x: PARIS_LON, y: PARIS_LAT)], 1.);
685+
let mut new_york_to_paris = SphericalLineStringCurve::new(
686+
line_string![(x: NEW_YORK_LON, y: NEW_YORK_LAT), (x: PARIS_LON, y: PARIS_LAT)],
687+
1.,
688+
);
646689

647690
// Point is located on the left (north) of the curve
648-
let projected = new_york_to_paris.project(point! {x: -6.705403880820967, y: 51.42135181702875}).unwrap();
691+
let projected = new_york_to_paris
692+
.project(point! {x: -6.705403880820967, y: 51.42135181702875})
693+
.unwrap();
649694
assert_eq!(5135359.060708988, projected.distance_along_curve);
650695
assert_eq!(67157.93913531031, projected.offset);
651696

652697
// Point is located on the right (south) of the curve
653-
let projected = new_york_to_paris.project(point! {x: -12.250890759346419, y: 45.857650969554356}).unwrap();
698+
let projected = new_york_to_paris
699+
.project(point! {x: -12.250890759346419, y: 45.857650969554356})
700+
.unwrap();
654701
assert_eq!(4873918.064874676, projected.distance_along_curve);
655702
assert_eq!(-625592.3211438811, projected.offset); // Note: result is weird -> distance should remain the same than the other way curve, difference is 0.7mm
656703

657704

658705
// Same point, but with an offset from the curve
659706
new_york_to_paris.start_offset = 1000000.;
660-
let projected = new_york_to_paris.project(point! {x: -12.250890759346419, y: 45.857650969554356}).unwrap();
707+
let projected = new_york_to_paris
708+
.project(point! {x: -12.250890759346419, y: 45.857650969554356})
709+
.unwrap();
661710
assert_eq!(5873918.064874676, projected.distance_along_curve);
662711
assert_eq!(-625592.3211438811, projected.offset); // Note: same, difference is 0.7mm
663712
}
@@ -717,7 +766,7 @@ mod tests {
717766
#[test]
718767
fn spherical_intersect_segment() {
719768
// Note: following tests have been computed with a maximum length of curve of 100m, otherwise the curve is densified.
720-
769+
721770
// Intersection
722771
let paris_to_new_york = SphericalLineStringCurve::new(line_string![(x: PARIS_LON, y: PARIS_LAT), (x: NEW_YORK_LON, y: NEW_YORK_LAT)], 1.);
723772
let segment = Line::new(coord! {x: -36.76627263796084, y: 69.72980545457074}, coord! {x: -53.52127629098692, y: 15.34337895024332});
@@ -728,7 +777,7 @@ mod tests {
728777
assert!(paris_to_new_york.intersect_segment(segment).is_none());
729778

730779
// TODO: Collinear
731-
// Notes:
780+
// Notes:
732781
// - because of the haversine densification, the geometry is slightly different and includes more points
733782
// than before, thus creating intersection(s) point(s).
734783
// - is very rare in reality

src/lrs.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -563,19 +563,19 @@ impl<CurveImpl: Curve> Lrs<CurveImpl> {
563563
mod tests {
564564
use geo::line_string;
565565

566-
use crate::curves::LineStringCurve;
566+
use crate::curves::PlanarLineStringCurve;
567567

568568
use super::*;
569569

570-
fn lrs() -> Lrs<LineStringCurve> {
570+
fn lrs() -> Lrs<PlanarLineStringCurve> {
571571
let traversal = Traversal {
572-
curve: LineStringCurve::new(line_string![(x: 0., y:0.), (x: 200., y:0.)], 1.),
572+
curve: PlanarLineStringCurve::new(line_string![(x: 0., y:0.), (x: 200., y:0.)], 1.),
573573
id: "curve".to_owned(),
574574
lrms: vec![LrmHandle(0), LrmHandle(1)],
575575
};
576576

577577
let traversal2 = Traversal {
578-
curve: LineStringCurve::new(line_string![(x: 0., y:-1.), (x: 200., y:-1.)], 1.),
578+
curve: PlanarLineStringCurve::new(line_string![(x: 0., y:-1.), (x: 200., y:-1.)], 1.),
579579
id: "curve".to_owned(),
580580
lrms: vec![LrmHandle(1)],
581581
};

0 commit comments

Comments
 (0)