-
Notifications
You must be signed in to change notification settings - Fork 43
Description
I'm trying to use polygonize to take a set of LineStrings and turn them into a Polygon. However, this is frequently failing, with the output being just an empty geometry collection. This is likely not a bug in the Rust GEOS bindings, and may not even be a bug in GEOS. However, I'm looking for some help to understand why it's working for some sets of lines and not others. None of the lines overlap, however I'm not certain that every one of the endpoints line up exactly to the 14th decimal place with the starting points of the next line. Is this required for polygonize? The lines may also not be wound appropriately. Is that important?
I have tried doing a unary union on the MultiLineString as suggested here, but that doesn't change the fact that polygonize is giving me an empty result in the failure case below.
MRE code
use anyhow::{anyhow, Result};
use geo::{Geometry, LineString, MultiLineString};
use geojson::GeoJson;
use geos::{Geometry as GeosGeometry, WKTWriter};
fn main() -> Result<()> {
for geoj in [GEOJSON_STRING_WORKS, GEOJSON_STRING_FAILS] {
let geojson = geoj.parse::<GeoJson>()?;
let geos_multi_linestring = process_geojson(geojson)?;
print_geom("before", &geos_multi_linestring);
let mut unioned = geos_multi_linestring
.unary_union()
.expect("ERROR: failed union");
unioned.normalize().expect("ERROR: failed normalization");
let geos_poly = GeosGeometry::polygonize(&[unioned]).expect("ERROR: Polygonize failed");
print_geom("after", &geos_poly);
}
Ok(())
}
fn print_geom(tag: &str, geom: &GeosGeometry) {
let mut writer = WKTWriter::new().expect("Failed to create WKTWriter");
match writer.write(geom) {
Ok(wkt) => println!("\n\n\n==WKT string {}==\n\n{}", tag, wkt),
_ => println!("••• WKT conversion failed"),
}
}
// Processes a GeoJSON object and returns the processed GeoJSON as a String
fn process_geojson(geojson: GeoJson) -> Result<GeosGeometry> {
match geojson {
GeoJson::FeatureCollection(collection) => {
let lines: Vec<LineString> = collection
.features
.into_iter()
.flat_map(|f| TryInto::<Geometry>::try_into(f))
.flat_map(|g| TryInto::<LineString>::try_into(g))
.collect();
let multi_line = MultiLineString(lines.clone());
let g_geom = GeosGeometry::try_from(&multi_line).expect("Failed conversion to GEOS");
Ok(g_geom)
}
_ => Err(anyhow!("Input GeoJSON must be a FeatureCollection")),
}
}
const GEOJSON_STRING_FAILS: &str = r#"{"features":[{"geometry":{"coordinates":[[-73.1678200000696,41.19344600032452],[-73.16775299977584,41.19344300022071],[-73.16765799986257,41.19343900008236],[-73.1675530002779,41.193450999822936],[-73.1674870000187,41.19346000013419]],"type":"LineString"},"properties":{"index":0},"type":"Feature"},{"geometry":{"coordinates":[[-73.16842600011974,41.19342899973656],[-73.1683039999472,41.19342699966739],[-73.16812299975751,41.19342500027269],[-73.16794100020769,41.19343700001327],[-73.1678200000696,41.19344600032452]],"type":"LineString"},"properties":{"index":1},"type":"Feature"},{"geometry":{"coordinates":[[-73.16878799982472,41.193411999823084],[-73.16871499999782,41.19341299985772],[-73.16860600027496,41.19341499992681],[-73.168497999912,41.193423000203516],[-73.16842600011974,41.19342899973656]],"type":"LineString"},"properties":{"index":2},"type":"Feature"},{"geometry":{"coordinates":[[-73.16933799996153,41.19339099977125],[-73.16922800020396,41.19339499990961],[-73.16889700022222,41.193407000324584],[-73.16878799982472,41.193411999823084]],"type":"LineString"},"properties":{"index":3},"type":"Feature"},{"geometry":{"coordinates":[[-73.16972299978741,41.19335599990967],[-73.16964599982225,41.19336500022101],[-73.16952899982252,41.19338000006531],[-73.16941499992669,41.19338600027284],[-73.16933799996153,41.19339099977125]],"type":"LineString"},"properties":{"index":4},"type":"Feature"},{"geometry":{"coordinates":[[-73.17021900007998,41.1933470002729],[-73.17011899999382,41.193354999875126],[-73.1699749997348,41.19336899968479],[-73.16982199983903,41.19336100008265],[-73.16972299978741,41.19335599990967]],"type":"LineString"},"properties":{"index":5},"type":"Feature"},{"geometry":{"coordinates":[[-73.1718577789133,41.193395526882114],[-73.17176109549814,41.19339059859732],[-73.17136199975647,41.19338500031756],[-73.17133999964125,41.193381000133115],[-73.17113299998795,41.193369999625816],[-73.1708709995969,41.19335699992564],[-73.17044699982915,41.193349999602844],[-73.17021900010673,41.193347000363815]],"type":"LineString"},"properties":{"index":6},"type":"Feature"},{"geometry":{"coordinates":[[-73.17185326335287,41.18892700605986],[-73.17193445157719,41.18909258832794],[-73.17199155855562,41.18938764149979],[-73.17199155855562,41.189749319254915],[-73.17196300506644,41.19009196180036],[-73.17193445157719,41.19050122892908],[-73.17188686287817,41.19079628210093],[-73.17188686287817,41.19119603162481],[-73.17190589808793,41.19161481703294],[-73.17187734459876,41.19198601306756],[-73.1718487911095,41.19217636988729],[-73.17185830871433,41.19249997654832],[-73.17183927350456,41.19313767226553],[-73.17185777893332,41.19339552683957]],"type":"LineString"},"properties":{"index":7},"type":"Feature"},{"geometry":{"coordinates":[[-73.17185326341735,41.18892700607654],[-73.1716280003319,41.18894999994262],[-73.17158400010146,41.18895400012707],[-73.1714809998482,41.18896499973499],[-73.17122199959556,41.18899600026526],[-73.17104300033418,41.18902199966561],[-73.17089799994272,41.18904499982693],[-73.17077599971259,41.18906399980381],[-73.17074800021999,41.189061999711555],[-73.17029500001422,41.189040999642486],[-73.17014500029148,41.18903500026511]],"type":"LineString"},"properties":{"index":8},"type":"Feature"},{"geometry":{"coordinates":[[-73.17014500021854,41.18903500019883],[-73.17002200001146,41.18902699992221],[-73.16965400009896,41.18900599987038],[-73.16953199992632,41.1889990003027]],"type":"LineString"},"properties":{"index":9},"type":"Feature"},{"geometry":{"coordinates":[[-73.16953199990184,41.18899900040361],[-73.16944200024807,41.18899100003466],[-73.16930999955679,41.188980999573516],[-73.16917399958038,41.188983999711866],[-73.16908499997271,41.18898599980412],[-73.1687639995589,41.18896499973499],[-73.16828399990663,41.1889340001041],[-73.16780000006992,41.18891700021942],[-73.16747899965605,41.188906999758274]],"type":"LineString"},"properties":{"index":10},"type":"Feature"},{"geometry":{"coordinates":[[-73.16747899965605,41.188906999758274],[-73.1674809997483,41.18913200024167],[-73.16748599997885,41.18945199971006],[-73.16747500037093,41.18980799993932],[-73.16747000014038,41.18999999980019],[-73.16746900009423,41.19003399956949]],"type":"LineString"},"properties":{"index":11},"type":"Feature"},{"geometry":{"coordinates":[[-73.16746900007058,41.19003399967717],[-73.16747000010521,41.19026300017804],[-73.16747200017439,41.19062599991756],[-73.16747899974207,41.19095299976102],[-73.16748499994951,41.19118300029644]],"type":"LineString"},"properties":{"index":12},"type":"Feature"},{"geometry":{"coordinates":[[-73.16748499994951,41.19118300029644],[-73.1674950002954,41.191637999845504],[-73.16750099982845,41.191882000190674],[-73.1674870000187,41.19257499987738],[-73.16748996411894,41.192786918879456],[-73.16749300022622,41.193003999876105],[-73.1674870000187,41.19346000013419]],"type":"LineString"},"properties":{"index":13},"type":"Feature"}],"type":"FeatureCollection"}"#;
const GEOJSON_STRING_WORKS: &str = r#"{"features":[{"geometry":{"coordinates":[[-73.17734200024968,41.19073100017662],[-73.17731800009412,41.19086500008983],[-73.17724799969656,41.191269999933006],[-73.17722600028458,41.191405999915304]],"type":"LineString"},"properties":{"index":0},"type":"Feature"},{"geometry":{"coordinates":[[-73.17744799986889,41.19006800017852],[-73.17742000024947,41.190198999988006],[-73.17741400004202,41.190230999745786],[-73.17736100023232,41.19059800029813],[-73.17734200024968,41.19073100017662]],"type":"LineString"},"properties":{"index":1},"type":"Feature"},{"geometry":{"coordinates":[[-73.17759800033542,41.18911899973167],[-73.17756599990325,41.18930800019806],[-73.17751900030109,41.189592999937865],[-73.17747600016288,41.18987700031752],[-73.17744799986889,41.19006800017852]],"type":"LineString"},"properties":{"index":2},"type":"Feature"},{"geometry":{"coordinates":[[-73.1795329998111,41.18919100019841],[-73.17914599991595,41.189175999679634],[-73.17798500023058,41.18913300021582],[-73.17759800033542,41.18911899973167]],"type":"LineString"},"properties":{"index":3},"type":"Feature"},{"geometry":{"coordinates":[[-73.18063900029208,41.18924299997339],[-73.18041700003327,41.18923200026753],[-73.17975400003517,41.189200999869726],[-73.1795329998111,41.18919100019841]],"type":"LineString"},"properties":{"index":4},"type":"Feature"},{"geometry":{"coordinates":[[-73.18063900029208,41.18924299997339],[-73.18062899994628,41.18943399983456],[-73.18060000029223,41.19000800012684],[-73.18059099998098,41.19020000002255]],"type":"LineString"},"properties":{"index":5},"type":"Feature"},{"geometry":{"coordinates":[[-73.18059099998098,41.19020000002255],[-73.18058499977344,41.190334999970304],[-73.18057800020586,41.190548999952306],[-73.18056299968698,41.19073999981348],[-73.18055300001566,41.19087599979578]],"type":"LineString"},"properties":{"index":6},"type":"Feature"},{"geometry":{"coordinates":[[-73.18055300001566,41.19087599979578],[-73.18054799984267,41.191012999812706],[-73.18053299999838,41.19142399986341],[-73.18052799982549,41.19156099988025]],"type":"LineString"},"properties":{"index":7},"type":"Feature"},{"geometry":{"coordinates":[[-73.18052799982549,41.19156099988025],[-73.18030600024116,41.19154800010513],[-73.1796440002776,41.19151100017446],[-73.17942300005353,41.191498999759396]],"type":"LineString"},"properties":{"index":8},"type":"Feature"},{"geometry":{"coordinates":[[-73.17942300005353,41.191498999759396],[-73.17920299986382,41.19148900008799],[-73.17854500003871,41.19146199982872],[-73.17832599988371,41.19145300019186]],"type":"LineString"},"properties":{"index":9},"type":"Feature"},{"geometry":{"coordinates":[[-73.17832599988371,41.19145300019186],[-73.1781059996941,41.19144299984607],[-73.17744599979972,41.191415000226556],[-73.17722600028458,41.191405999915304]],"type":"LineString"},"properties":{"index":10},"type":"Feature"}],"type":"FeatureCollection"}"#;