From 98bdaa92aa562d8eb18da420fd260736a67b12d5 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Tue, 21 Jan 2025 16:07:39 -0800 Subject: [PATCH] no need to reverse line --- .../src/geo_helpers/slice_nearest_boundary.rs | 38 +++--- backend/src/neighbourhood.rs | 127 +++++++++--------- 2 files changed, 88 insertions(+), 77 deletions(-) diff --git a/backend/src/geo_helpers/slice_nearest_boundary.rs b/backend/src/geo_helpers/slice_nearest_boundary.rs index 0964ba7..8064067 100644 --- a/backend/src/geo_helpers/slice_nearest_boundary.rs +++ b/backend/src/geo_helpers/slice_nearest_boundary.rs @@ -4,14 +4,22 @@ use geo::{ use std::cmp::Ordering; pub trait SliceNearestFrechetBoundary { - /// Returns the subset of self closest to `closest_to`. + /// Splits `self.exterior` at the two points nearest to `closest_to.start` and `closest_to.end` + /// + /// In the likely event that the closest points on the exterior are not pre-existing vertices, + /// new coords will be interpolated into the existing segments. + fn split_boundary_nearest_endpoints(&self, closest_to: &LineString) + -> (LineString, LineString); + + /// Returns the subset of self.exterior() closest to `closest_to` and its frechet distance. + /// + /// i.e. returns one of the LineStrings from `split_boundary_nearest_endpoints`, whichever + /// one has the smallest frechet distance. /// /// All points in the output will be *topologically* within `self`, however the first and /// final points of the output may not appear explicitly in `self`, in which case they /// represent splitting the existing segments at the point nearest `closest_to`. fn slice_nearest_frechet_boundary(&self, closest_to: &LineString) -> (LineString, f64); - fn split_boundary_nearest_endpoints(&self, closest_to: &LineString) - -> (LineString, LineString); } impl SliceNearestFrechetBoundary for Polygon { @@ -21,10 +29,11 @@ impl SliceNearestFrechetBoundary for Polygon { // // Of the two parts, the one with the lowest frechet_distance represents the best // candidate for it's corresponding boundary. - let (forwards_half, mut backwards_half) = self.split_boundary_nearest_endpoints(closest_to); - + let (forwards_half, backwards_half) = self.split_boundary_nearest_endpoints(closest_to); let forwards_frechet = forwards_half.frechet_distance(closest_to); + // The second half of the polygon begins where the first half ends, so we + // need to reverse `closest_to` to get an accurate (minimal) distance measure let mut backwards_closest_to = closest_to.clone(); backwards_closest_to.0.reverse(); let backwards_frechet = backwards_half.frechet_distance(&backwards_closest_to); @@ -32,7 +41,6 @@ impl SliceNearestFrechetBoundary for Polygon { if forwards_frechet < backwards_frechet { (forwards_half, forwards_frechet) } else { - backwards_half.0.reverse(); (backwards_half, backwards_frechet) } } @@ -123,19 +131,19 @@ impl SliceNearestFrechetBoundary for Polygon { LineString::new(coords) }; - let forward_half = assemble( + let front_half = assemble( segment_idx_closest_to_first, segment_idx_closest_to_final, coord_closest_to_first, coord_closest_to_final, ); - let backwards_half = assemble( + let back_half = assemble( segment_idx_closest_to_final, segment_idx_closest_to_first, coord_closest_to_final, coord_closest_to_first, ); - (forward_half, backwards_half) + (front_half, back_half) } } @@ -150,7 +158,7 @@ mod tests { let boundary = wkt!(POLYGON((0. 0.,0. 10.,10. 10.,10. 0.,0. 0.))); let (closest, _) = boundary.slice_nearest_frechet_boundary(&wkt!(LINESTRING(0.1 0.2,0.1 9.8))); - assert_relative_eq!(wkt!(LINESTRING(0. 0.2,0. 9.8)), closest); + assert_relative_eq!(wkt!(LINESTRING(0.0 9.8,0.0 0.2)), closest); } #[test] @@ -158,7 +166,7 @@ mod tests { let boundary = wkt!(POLYGON((0. 0.,0. 10.,10. 10.,10. 0.,0. 0.))); let (closest, _) = boundary.slice_nearest_frechet_boundary(&wkt!(LINESTRING(0.1 9.8,0.1 0.2))); - assert_relative_eq!(wkt!(LINESTRING(0. 9.8,0. 0.2)), closest); + assert_relative_eq!(wkt!(LINESTRING(0. 0.2,0. 9.8)), closest); } #[test] @@ -167,7 +175,7 @@ mod tests { let (closest, _) = boundary.slice_nearest_frechet_boundary(&wkt!(LINESTRING(0.1 0.2,0.1 9.8))); assert_relative_eq!( - wkt!(LINESTRING(0. 0.2,0. 9.8)), + wkt!(LINESTRING(0. 9.8, 0. 0.2)), closest, max_relative = 1e-14 ); @@ -179,7 +187,7 @@ mod tests { let (closest, _) = boundary.slice_nearest_frechet_boundary(&wkt!(LINESTRING(0.1 9.8,0.1 0.2))); assert_relative_eq!( - wkt!(LINESTRING(0. 9.8,0. 0.2)), + wkt!(LINESTRING(0. 0.2, 0. 9.8)), closest, max_relative = 1e-14 ); @@ -235,10 +243,8 @@ mod tests { let line_string = wkt!(LINESTRING(1495.3224949514188 1205.7438525123148,1495.1276851599255 1178.667850475072)); let (closest, _) = boundary.slice_nearest_frechet_boundary(&line_string); - // dbg!(line_string.length::()); - // dbg!(closest.length::()); assert_relative_eq!( - wkt!(LINESTRING(1495.3224949514188 1205.7438525123148,1495.1276851599255 1178.667850475072)), + wkt!(LINESTRING(1495.1276851599255 1178.667850475072,1495.3224949514188 1205.7438525123148)), closest, max_relative = 1e-14 ); diff --git a/backend/src/neighbourhood.rs b/backend/src/neighbourhood.rs index e3d2186..2eccbb0 100644 --- a/backend/src/neighbourhood.rs +++ b/backend/src/neighbourhood.rs @@ -469,83 +469,88 @@ mod tests { assert_eq!(result, LineInPolygon::Inside); } - // A neighborhood in Seattle - fn portage_bay_neighborhood() -> Polygon { - wkt!(POLYGON((1494.8879192632764 1156.4065954129007,1495.030280264711 1166.3140770613454,1495.1276851599255 1178.667850475072,1495.3224949514188 1205.7438525123148,1496.109226801229 1253.1574347241208,1496.2965439078196 1305.5414370219842,1496.5812659106891 1334.163050674363,1496.7386122808641 1343.8815006865716,1496.78356838602 1350.3864128804018,1496.761090333442 1354.5117503570798,1496.858495229721 1361.7505500795464,1497.420446550558 1456.043978118121,1497.6826905008495 1491.0593088835872,1497.6377343946288 1499.8214812056735,1497.5703002358305 1507.5384197739918,1495.8619682196775 1624.7602733560345,1495.8544755358398 1671.918106883475,1495.7570706395607 1688.4083372820328,1495.6671584281842 1719.4428841752342,1495.794534060879 1749.8102605871381,1497.278085549123 1769.2805191360155,1511.9637467430978 1769.3805947078151,1542.901040145765 1769.6029848685107,1553.6605347755903 1769.6474629003337,1567.90412759652 1769.725299456617,1581.1437007235688 1769.7920165047467,1590.4870780239487 1769.8364945373598,1599.583196742777 1769.8809725691826,1604.0713146277628 1769.9032115854895,1614.561072623459 1769.958809125466,1632.0789684763247 1770.0366456817487,1648.48045437029 1770.1144822372416,1657.9062511982088 1770.0255261735956,1681.8303921124464 1769.8253750292065,1711.096816920279 1769.2916386441689,1719.391218420557 1769.4250727404283,1724.0891314657758 1770.3479919060906,1730.8999814788747 1772.6163715425002,1739.4116708232234 1778.665383907576,1751.4748925185404 1788.6173435886337,1765.815890235749 1802.1275458368718,1781.8502346003709 1817.261196256529,1822.0110223545612 1811.034271763371,1906.8656718541479 1798.15788147276,1939.294009428897 1792.8761151615709,1917.0632151631369 1766.7452713062971,1900.661729268107 1747.0748616130306,1883.7207701058826 1726.6038473422077,1880.9859403422056 1723.379190015676,1878.3934715810285 1719.365047618951,1874.6396367547297 1711.5035554462202,1873.463285322998 1706.0438770069486,1873.1935486888685 1700.4730034869342,1873.485763375576 1633.5891627270407,1873.4333145855173 1624.6046002442586,1873.4932560594139 1617.2657249484123,1873.2385047940243 1553.417509878815,1873.0661730561737 1507.2493125651663,1873.0287096348557 1500.4330541469942,1873.0362023186935 1492.938505739372,1872.9687681598953 1370.9019051830478,1872.9687681598953 1362.640110721539,1872.9612754760572 1361.6727135240535,1871.1630312485281 1355.8349718115203,1869.3647870199336 1350.9535077891094,1867.1919085781583 1345.071288044753,1853.068198706085 1322.0094284042352,1844.661406940788 1308.2323579634783,1844.0994556199514 1307.309438797816,1842.9305968709923 1305.3968834175714,1837.2136787642164 1296.0342576615276,1814.1437038575227 1258.1945718583077,1812.7425718968175 1255.9150727137448,1808.2919174331498 1248.6762729904879,1804.118492287449 1241.8155365397026,1791.028772845673 1220.399364086911,1790.1970848907072 1219.031664599857,1783.2438738761737 1207.6564078925592,1782.487112763844 1206.4110229936116,1770.0117934340276 1185.8732916746592,1768.8279493173934 1184.0385728506974,1768.4608077869848 1183.349163353094,1751.9769023654808 1156.8736147498087,1748.230560224085 1150.946916972839,1743.8698179717937 1143.6302806940894,1677.0350741720133 1032.3573639045326,1674.974585994192 1028.9770334654347,1673.9331028789925 1029.3106187060832,1672.8466636575724 1029.2883796897768,1671.820165911113 1028.9325554328216,1670.9585072186667 1028.2765044596779,1670.3441071077716 1027.3758243095322,1670.0518924199994 1026.3305905557634,1670.1043412100576 1025.2408787693819,1670.493960793044 1024.2290035392832,1671.1832877465754 1023.3839209291136,1671.6703122247757 1023.0948137210783,1667.9089847157045 1016.8122916871537,1663.7355595700037 1009.9626747453119,1623.2001376015673 942.7452487439798,1617.8203902866546 933.849642325634,1612.717872289709 937.8415457052624,1608.4020861436386 941.1551590962304,1560.6062531052212 1030.9451863848656,1559.5048285161258 1032.9355783213932,1556.425335275683 1038.8845151138794,1518.6696991760793 1110.927807596856,1506.2243505826789 1134.8236303393896,1499.638281098554 1147.4442719456351,1494.8879192632764 1156.4065954129007))) - } + // These represent bugs witnessed in real world OSM data + mod real_world { + use super::*; - // See https://github.com/a-b-street/ltn/issues/67 - gwinn should be editable, but it's not considered - #[test] - fn missing_east_gwinn_in_portage_bay() { - // https://www.openstreetmap.org/way/6475490 - let line_string = wkt!(LINESTRING(1496.109226801229 1253.1574347241208,1505.2428089413754 1253.1685542322741,1798.2891839156541 1253.3687053766632,1800.4021208835336 1252.3901886702342,1808.2919174331498 1248.6762729904879)); + // A neighborhood in Seattle + fn portage_bay_neighborhood() -> Polygon { + wkt!(POLYGON((1494.8879192632764 1156.4065954129007,1495.030280264711 1166.3140770613454,1495.1276851599255 1178.667850475072,1495.3224949514188 1205.7438525123148,1496.109226801229 1253.1574347241208,1496.2965439078196 1305.5414370219842,1496.5812659106891 1334.163050674363,1496.7386122808641 1343.8815006865716,1496.78356838602 1350.3864128804018,1496.761090333442 1354.5117503570798,1496.858495229721 1361.7505500795464,1497.420446550558 1456.043978118121,1497.6826905008495 1491.0593088835872,1497.6377343946288 1499.8214812056735,1497.5703002358305 1507.5384197739918,1495.8619682196775 1624.7602733560345,1495.8544755358398 1671.918106883475,1495.7570706395607 1688.4083372820328,1495.6671584281842 1719.4428841752342,1495.794534060879 1749.8102605871381,1497.278085549123 1769.2805191360155,1511.9637467430978 1769.3805947078151,1542.901040145765 1769.6029848685107,1553.6605347755903 1769.6474629003337,1567.90412759652 1769.725299456617,1581.1437007235688 1769.7920165047467,1590.4870780239487 1769.8364945373598,1599.583196742777 1769.8809725691826,1604.0713146277628 1769.9032115854895,1614.561072623459 1769.958809125466,1632.0789684763247 1770.0366456817487,1648.48045437029 1770.1144822372416,1657.9062511982088 1770.0255261735956,1681.8303921124464 1769.8253750292065,1711.096816920279 1769.2916386441689,1719.391218420557 1769.4250727404283,1724.0891314657758 1770.3479919060906,1730.8999814788747 1772.6163715425002,1739.4116708232234 1778.665383907576,1751.4748925185404 1788.6173435886337,1765.815890235749 1802.1275458368718,1781.8502346003709 1817.261196256529,1822.0110223545612 1811.034271763371,1906.8656718541479 1798.15788147276,1939.294009428897 1792.8761151615709,1917.0632151631369 1766.7452713062971,1900.661729268107 1747.0748616130306,1883.7207701058826 1726.6038473422077,1880.9859403422056 1723.379190015676,1878.3934715810285 1719.365047618951,1874.6396367547297 1711.5035554462202,1873.463285322998 1706.0438770069486,1873.1935486888685 1700.4730034869342,1873.485763375576 1633.5891627270407,1873.4333145855173 1624.6046002442586,1873.4932560594139 1617.2657249484123,1873.2385047940243 1553.417509878815,1873.0661730561737 1507.2493125651663,1873.0287096348557 1500.4330541469942,1873.0362023186935 1492.938505739372,1872.9687681598953 1370.9019051830478,1872.9687681598953 1362.640110721539,1872.9612754760572 1361.6727135240535,1871.1630312485281 1355.8349718115203,1869.3647870199336 1350.9535077891094,1867.1919085781583 1345.071288044753,1853.068198706085 1322.0094284042352,1844.661406940788 1308.2323579634783,1844.0994556199514 1307.309438797816,1842.9305968709923 1305.3968834175714,1837.2136787642164 1296.0342576615276,1814.1437038575227 1258.1945718583077,1812.7425718968175 1255.9150727137448,1808.2919174331498 1248.6762729904879,1804.118492287449 1241.8155365397026,1791.028772845673 1220.399364086911,1790.1970848907072 1219.031664599857,1783.2438738761737 1207.6564078925592,1782.487112763844 1206.4110229936116,1770.0117934340276 1185.8732916746592,1768.8279493173934 1184.0385728506974,1768.4608077869848 1183.349163353094,1751.9769023654808 1156.8736147498087,1748.230560224085 1150.946916972839,1743.8698179717937 1143.6302806940894,1677.0350741720133 1032.3573639045326,1674.974585994192 1028.9770334654347,1673.9331028789925 1029.3106187060832,1672.8466636575724 1029.2883796897768,1671.820165911113 1028.9325554328216,1670.9585072186667 1028.2765044596779,1670.3441071077716 1027.3758243095322,1670.0518924199994 1026.3305905557634,1670.1043412100576 1025.2408787693819,1670.493960793044 1024.2290035392832,1671.1832877465754 1023.3839209291136,1671.6703122247757 1023.0948137210783,1667.9089847157045 1016.8122916871537,1663.7355595700037 1009.9626747453119,1623.2001376015673 942.7452487439798,1617.8203902866546 933.849642325634,1612.717872289709 937.8415457052624,1608.4020861436386 941.1551590962304,1560.6062531052212 1030.9451863848656,1559.5048285161258 1032.9355783213932,1556.425335275683 1038.8845151138794,1518.6696991760793 1110.927807596856,1506.2243505826789 1134.8236303393896,1499.638281098554 1147.4442719456351,1494.8879192632764 1156.4065954129007))) + } - let boundary = portage_bay_neighborhood(); - let prepared_polygon = PreparedGeometry::from(&boundary); - let result = line_in_polygon(&line_string, &boundary, &prepared_polygon); + // See https://github.com/a-b-street/ltn/issues/67 - gwinn should be editable, but it's not considered + #[test] + fn missing_east_gwinn_in_portage_bay() { + // https://www.openstreetmap.org/way/6475490 + let line_string = wkt!(LINESTRING(1496.109226801229 1253.1574347241208,1505.2428089413754 1253.1685542322741,1798.2891839156541 1253.3687053766632,1800.4021208835336 1252.3901886702342,1808.2919174331498 1248.6762729904879)); - // This is considered *crossing* not Inside, which is why it's not showing up as editable. - assert_eq!(result, LineInPolygon::Inside); - } + let boundary = portage_bay_neighborhood(); + let prepared_polygon = PreparedGeometry::from(&boundary); + let result = line_in_polygon(&line_string, &boundary, &prepared_polygon); - #[test] - fn part_of_harvard() { - // way: https://www.openstreetmap.org/way/256916775 - let line_string = wkt!(LINESTRING(1495.3224949514188 1205.7438525123148,1495.1276851599255 1178.667850475072)); + // This is considered *crossing* not Inside, which is why it's not showing up as editable. + assert_eq!(result, LineInPolygon::Inside); + } - let boundary = wkt!(POLYGON ((1495.030280264711 1166.3140770613454, 1495.1276851599255 1178.667850475072, 1495.3224949514188 1205.7438525123148, 1495.6671584281842 1719.4428841752342, 1878.3934715810285 1719.365047618951, 1872.9612754760572 1361.6727135240535, 1495.030280264711 1166.3140770613454))); + #[test] + fn part_of_harvard() { + // way: https://www.openstreetmap.org/way/256916775 + let line_string = wkt!(LINESTRING(1495.3224949514188 1205.7438525123148,1495.1276851599255 1178.667850475072)); - let prepared_polygon = PreparedGeometry::from(&boundary); - let result = line_in_polygon(&line_string, &boundary, &prepared_polygon); + let boundary = wkt!(POLYGON ((1495.030280264711 1166.3140770613454, 1495.1276851599255 1178.667850475072, 1495.3224949514188 1205.7438525123148, 1495.6671584281842 1719.4428841752342, 1878.3934715810285 1719.365047618951, 1872.9612754760572 1361.6727135240535, 1495.030280264711 1166.3140770613454))); - assert_eq!(result, LineInPolygon::Perimeter); - } + let prepared_polygon = PreparedGeometry::from(&boundary); + let result = line_in_polygon(&line_string, &boundary, &prepared_polygon); - fn invalid_columbus_neighborhood() -> Polygon { - wkt!(POLYGON((555.3645758729823 964.2614967693613,556.7283122085399 973.6018835090985,558.1772820648426 983.6094407301326,562.524191633751 1013.7433074731879,563.8026944485632 1022.4165237316282,566.1039995147408 1037.4278595631795,569.5985738737743 1060.8900214924752,575.6501538624323 1101.9210060985572,577.0138901979898 1111.4837829982,578.4628600542925 1121.2689500593285,588.0090144007727 1185.984486754612,597.6404022704206 1251.478389012725,599.7712402938965 1265.8225543621893,625.3412965816635 1262.153116715056,663.0145128467466 1256.593362703195,698.6421246078877 1251.3671939319825,700.9434296740653 1251.1448037720768,712.705655565978 1249.4768775680443,738.6166459379372 1246.0298300808167,750.1231712676139 1244.4730989575273,752.5097098545369 1260.9299708324152,754.8962484414598 1276.6084771452634,762.0558642022282 1323.3104108431594,770.6644498192995 1380.6870722441763,772.1134196756022 1390.472239304515,773.3919224904147 1399.5902358835565,764.9538039148338 1416.9366683996468,763.3343670170407 1420.161325726969,756.5156853404642 1426.4994453000797,748.2480338063738 1429.7241026266115,743.6454236752297 1430.168882948003,748.2480338063738 1429.7241026266115,756.5156853404642 1426.4994453000797,763.3343670170407 1420.161325726969,764.9538039148338 1416.9366683996468,773.3919224904147 1399.5902358835565,772.1134196756022 1390.472239304515,770.6644498192995 1380.6870722441763,762.0558642022282 1323.3104108431594,754.8962484414598 1276.6084771452634,752.5097098545369 1260.9299708324152,750.1231712676139 1244.4730989575273,761.0330619508629 1242.805172754285,824.1058674622226 1232.686420453298,887.5196070565631 1223.0124484729122,898.0885636556199 1221.4557173496228,907.890418565547 1220.010181306286,971.6450922440796 1210.558599486596,960.0533333936577 1131.054117119667,964.4854764833111 1130.38694663837,995.1695440291161 1125.8279483484544,993.7205741728133 1115.8203911274202,987.9246947476023 1075.1229917619867,987.9246947476023 1070.452798392118,988.0951617890927 1069.5632377501256,989.7145986880973 1064.5594591396084,990.0555327710782 1060.1116559304355,990.2259998137799 1057.887754325849,989.5441316453954 1053.99592651802,1006.5908358380477 1051.4384396719952,1019.6315645447726 1049.5481233080573,1025.5979110126852 1044.6555397782831,1033.2689278991365 1043.321198814899,1031.9904250843242 1034.425592396553,1026.5354797433054 997.953606080387,1073.0729821876955 990.7259258644933,1113.8146052056632 984.3878062913824,1120.1218857577683 983.387050569437,1126.173465745215 982.4974899274443,1127.5372020807724 982.2750997667487,1134.6115843207958 981.1631489648506,1213.7935252929763 968.820495058487,1207.060077137145 923.6752924838806,1200.1561619386123 877.0845538659374,1198.7924256042659 867.7441671262003,1206.122508406525 866.5210212443492,1240.5568508748104 859.5157311891513,1239.278348059998 850.5089296900626,1230.073127796499 787.9060995186228,1227.1751880838933 768.224570317203,1224.106781328586 747.0975050732366,1278.6562347436195 738.7578740554447,1277.633432492254 731.4189987603884,1276.354929677442 721.8562218599554,1287.4352874021813 719.521125175416,1324.1709349366442 710.0695433557262,1366.4467613328713 699.6172058133006,1377.1009514526734 696.8373288073701,1383.2377649620767 695.2805976840807,1391.9315840998931 692.7231108388457,1447.6743068077826 679.7132864519751,1471.6249261977562 673.59755703877,1503.8431971206094 665.369121101721,1507.7639390857912 664.3683653797757,1514.92355484656 662.4780490150474,1609.7884636746237 638.1263264445492,1603.9925842494129 614.7753595952063,1601.3503451002541 606.9917039787586,1597.6000701777737 599.4304385230064,1592.0598913147985 591.9803681472074,1582.5989704890635 584.1967125307594,1577.3997257102803 580.6384699635792,1549.5283643563355 561.1793309228551,1498.558718821081 527.820806852478,1486.455558844976 546.0568000105611,1481.1710805454475 554.6188211890485,1478.3583743535871 559.956185040214,1468.215585359468 575.7458864330149,1402.6710077416515 572.1876438658346,1396.8751283152294 571.8540586251861,1383.7491660877592 570.7421078224979,1382.129729189966 597.6513172390214,1380.595525812918 626.3396479395299,1379.1465559566152 653.3600524360058,1371.0493714652266 654.5831983186472,1326.216539439375 661.0325129725009,1317.096552696621 662.3668539350947,1268.5986792702454 669.4833390702456,1267.8315775811159 664.5907555396811,1161.0339758184377 680.4916520132251,1122.6788913861815 686.1626011050391,1108.530126906135 688.2753076296726,1104.9503190263563 688.8312830310169,1056.1967450365337 696.0589632461204,1038.63863971941 698.6164500913553,961.1613691657683 710.0695433557262,948.9729756689181 711.8486646389213,941.7281263874044 712.9606154416097,934.0571095009532 714.0725662435077,894.0825881696925 720.0771005767601,883.2579310084 721.6338317000498,866.0407597742574 724.191318545285,848.3974209351773 726.7488053905199,834.5895905393228 728.8615119151534,825.2139032343331 730.1958528777473,820.1851254970405 696.3925484867689,809.4457018564932 697.9492796100585,746.3728963463449 707.2896663497957,741.8555197347349 707.9568368310925,683.1296237934947 716.6300530895328,672.2197331102458 718.2979792927752,661.7360100319344 719.8547104160646,652.1898556842428 721.1890513786586,660.6279742598238 785.4598077533406,662.3326446783622 795.9121452957662,646.5644433005223 798.2472419803054,618.2669143428515 802.4726550295727,619.8863512406448 813.2585778118565,621.3353210969475 823.0437448729851,616.8179444853374 823.7109153542821,619.7158841991543 843.281249474959,622.1024227848659 859.7381213498469,624.3184943302982 877.3069440266331,591.5035887610173 882.1995275571974,569.7690409152648 885.5353799636821,558.7739167112705 887.0921110869716,544.2842181482429 889.3160126915581,553.7451389751891 953.141988745639,555.3645758729823 964.2614967693613))) - } + assert_eq!(result, LineInPolygon::Perimeter); + } - #[test] - fn missing_segment_in_invalid_columbus() { - // https://www.openstreetmap.org/way/1312473650 should be Perimeter but was Outside due to the invalid neighborhood boundary messing - // up our perimeter metric. - let line_string = wkt!(LINESTRING(750.1572646763966 1244.5286964975037,738.6251692907384 1246.0631886052765,712.705655565978 1249.5213556006574)); - let boundary = invalid_columbus_neighborhood(); + fn invalid_columbus_neighborhood() -> Polygon { + wkt!(POLYGON((555.3645758729823 964.2614967693613,556.7283122085399 973.6018835090985,558.1772820648426 983.6094407301326,562.524191633751 1013.7433074731879,563.8026944485632 1022.4165237316282,566.1039995147408 1037.4278595631795,569.5985738737743 1060.8900214924752,575.6501538624323 1101.9210060985572,577.0138901979898 1111.4837829982,578.4628600542925 1121.2689500593285,588.0090144007727 1185.984486754612,597.6404022704206 1251.478389012725,599.7712402938965 1265.8225543621893,625.3412965816635 1262.153116715056,663.0145128467466 1256.593362703195,698.6421246078877 1251.3671939319825,700.9434296740653 1251.1448037720768,712.705655565978 1249.4768775680443,738.6166459379372 1246.0298300808167,750.1231712676139 1244.4730989575273,752.5097098545369 1260.9299708324152,754.8962484414598 1276.6084771452634,762.0558642022282 1323.3104108431594,770.6644498192995 1380.6870722441763,772.1134196756022 1390.472239304515,773.3919224904147 1399.5902358835565,764.9538039148338 1416.9366683996468,763.3343670170407 1420.161325726969,756.5156853404642 1426.4994453000797,748.2480338063738 1429.7241026266115,743.6454236752297 1430.168882948003,748.2480338063738 1429.7241026266115,756.5156853404642 1426.4994453000797,763.3343670170407 1420.161325726969,764.9538039148338 1416.9366683996468,773.3919224904147 1399.5902358835565,772.1134196756022 1390.472239304515,770.6644498192995 1380.6870722441763,762.0558642022282 1323.3104108431594,754.8962484414598 1276.6084771452634,752.5097098545369 1260.9299708324152,750.1231712676139 1244.4730989575273,761.0330619508629 1242.805172754285,824.1058674622226 1232.686420453298,887.5196070565631 1223.0124484729122,898.0885636556199 1221.4557173496228,907.890418565547 1220.010181306286,971.6450922440796 1210.558599486596,960.0533333936577 1131.054117119667,964.4854764833111 1130.38694663837,995.1695440291161 1125.8279483484544,993.7205741728133 1115.8203911274202,987.9246947476023 1075.1229917619867,987.9246947476023 1070.452798392118,988.0951617890927 1069.5632377501256,989.7145986880973 1064.5594591396084,990.0555327710782 1060.1116559304355,990.2259998137799 1057.887754325849,989.5441316453954 1053.99592651802,1006.5908358380477 1051.4384396719952,1019.6315645447726 1049.5481233080573,1025.5979110126852 1044.6555397782831,1033.2689278991365 1043.321198814899,1031.9904250843242 1034.425592396553,1026.5354797433054 997.953606080387,1073.0729821876955 990.7259258644933,1113.8146052056632 984.3878062913824,1120.1218857577683 983.387050569437,1126.173465745215 982.4974899274443,1127.5372020807724 982.2750997667487,1134.6115843207958 981.1631489648506,1213.7935252929763 968.820495058487,1207.060077137145 923.6752924838806,1200.1561619386123 877.0845538659374,1198.7924256042659 867.7441671262003,1206.122508406525 866.5210212443492,1240.5568508748104 859.5157311891513,1239.278348059998 850.5089296900626,1230.073127796499 787.9060995186228,1227.1751880838933 768.224570317203,1224.106781328586 747.0975050732366,1278.6562347436195 738.7578740554447,1277.633432492254 731.4189987603884,1276.354929677442 721.8562218599554,1287.4352874021813 719.521125175416,1324.1709349366442 710.0695433557262,1366.4467613328713 699.6172058133006,1377.1009514526734 696.8373288073701,1383.2377649620767 695.2805976840807,1391.9315840998931 692.7231108388457,1447.6743068077826 679.7132864519751,1471.6249261977562 673.59755703877,1503.8431971206094 665.369121101721,1507.7639390857912 664.3683653797757,1514.92355484656 662.4780490150474,1609.7884636746237 638.1263264445492,1603.9925842494129 614.7753595952063,1601.3503451002541 606.9917039787586,1597.6000701777737 599.4304385230064,1592.0598913147985 591.9803681472074,1582.5989704890635 584.1967125307594,1577.3997257102803 580.6384699635792,1549.5283643563355 561.1793309228551,1498.558718821081 527.820806852478,1486.455558844976 546.0568000105611,1481.1710805454475 554.6188211890485,1478.3583743535871 559.956185040214,1468.215585359468 575.7458864330149,1402.6710077416515 572.1876438658346,1396.8751283152294 571.8540586251861,1383.7491660877592 570.7421078224979,1382.129729189966 597.6513172390214,1380.595525812918 626.3396479395299,1379.1465559566152 653.3600524360058,1371.0493714652266 654.5831983186472,1326.216539439375 661.0325129725009,1317.096552696621 662.3668539350947,1268.5986792702454 669.4833390702456,1267.8315775811159 664.5907555396811,1161.0339758184377 680.4916520132251,1122.6788913861815 686.1626011050391,1108.530126906135 688.2753076296726,1104.9503190263563 688.8312830310169,1056.1967450365337 696.0589632461204,1038.63863971941 698.6164500913553,961.1613691657683 710.0695433557262,948.9729756689181 711.8486646389213,941.7281263874044 712.9606154416097,934.0571095009532 714.0725662435077,894.0825881696925 720.0771005767601,883.2579310084 721.6338317000498,866.0407597742574 724.191318545285,848.3974209351773 726.7488053905199,834.5895905393228 728.8615119151534,825.2139032343331 730.1958528777473,820.1851254970405 696.3925484867689,809.4457018564932 697.9492796100585,746.3728963463449 707.2896663497957,741.8555197347349 707.9568368310925,683.1296237934947 716.6300530895328,672.2197331102458 718.2979792927752,661.7360100319344 719.8547104160646,652.1898556842428 721.1890513786586,660.6279742598238 785.4598077533406,662.3326446783622 795.9121452957662,646.5644433005223 798.2472419803054,618.2669143428515 802.4726550295727,619.8863512406448 813.2585778118565,621.3353210969475 823.0437448729851,616.8179444853374 823.7109153542821,619.7158841991543 843.281249474959,622.1024227848659 859.7381213498469,624.3184943302982 877.3069440266331,591.5035887610173 882.1995275571974,569.7690409152648 885.5353799636821,558.7739167112705 887.0921110869716,544.2842181482429 889.3160126915581,553.7451389751891 953.141988745639,555.3645758729823 964.2614967693613))) + } - { - let prepared_boundary = PreparedGeometry::from(&boundary); - let result = line_in_polygon(&line_string, &boundary, &prepared_boundary); + #[test] + fn missing_segment_in_invalid_columbus() { + // https://www.openstreetmap.org/way/1312473650 should be Perimeter but was Outside due to the invalid neighborhood boundary messing + // up our perimeter metric. + let line_string = wkt!(LINESTRING(750.1572646763966 1244.5286964975037,738.6251692907384 1246.0631886052765,712.705655565978 1249.5213556006574)); + let boundary = invalid_columbus_neighborhood(); - // NOTE: This isn't *desirable* but documents how giving an invalid polygon can produce - // invalid results. Specifically, an invalid "spike" near the line_string can break our "perimeter" check. - assert_eq!(result, LineInPolygon::Outside); - } + { + let prepared_boundary = PreparedGeometry::from(&boundary); + let result = line_in_polygon(&line_string, &boundary, &prepared_boundary); - { - use geo::BooleanOps; - let mut valid_boundary = boundary.union(&boundary); - let prepared_valid_boundary = PreparedGeometry::from(&boundary); - assert_eq!(valid_boundary.0.len(), 1); - let valid_boundary = valid_boundary.0.pop().unwrap(); - let result = - line_in_polygon(&line_string, &valid_boundary, &prepared_valid_boundary); - // With a valid boundary polygon, we get the result we expect - assert_eq!(result, LineInPolygon::Perimeter); + // NOTE: This isn't *desirable* but documents how giving an invalid polygon can produce + // invalid results. Specifically, an invalid "spike" near the line_string can break our "perimeter" check. + assert_eq!(result, LineInPolygon::Outside); + } + + { + use geo::BooleanOps; + let mut valid_boundary = boundary.union(&boundary); + let prepared_valid_boundary = PreparedGeometry::from(&boundary); + assert_eq!(valid_boundary.0.len(), 1); + let valid_boundary = valid_boundary.0.pop().unwrap(); + let result = + line_in_polygon(&line_string, &valid_boundary, &prepared_valid_boundary); + // With a valid boundary polygon, we get the result we expect + assert_eq!(result, LineInPolygon::Perimeter); + } } - } - #[test] - fn missing_segment_protruding_past_boundary_in_columbus() { - // This way *crosses* the boundary - currently we can either include or ignore it. - // For now, we consider most crossings as Perimeter + #[test] + fn missing_segment_protruding_past_boundary_in_columbus() { + // This way *crosses* the boundary - currently we can either include or ignore it. + // For now, we consider most crossings as Perimeter - // https://www.openstreetmap.org/way/850023685, Crosses { percent: 0.6833 } - let line_string = wkt!(LINESTRING(555.3645758729823 964.2392577530547,553.7280922707979 953.1197497301224,544.3268349086155 889.2937736760415)); - let boundary = invalid_columbus_neighborhood(); - let prepared_boundary = PreparedGeometry::from(&boundary); - let result = line_in_polygon(&line_string, &boundary, &prepared_boundary); + // https://www.openstreetmap.org/way/850023685, Crosses { percent: 0.6833 } + let line_string = wkt!(LINESTRING(555.3645758729823 964.2392577530547,553.7280922707979 953.1197497301224,544.3268349086155 889.2937736760415)); + let boundary = invalid_columbus_neighborhood(); + let prepared_boundary = PreparedGeometry::from(&boundary); + let result = line_in_polygon(&line_string, &boundary, &prepared_boundary); - assert_eq!(result, LineInPolygon::Perimeter); + assert_eq!(result, LineInPolygon::Perimeter); + } } } }