finish up the grand geom stabilization with ring and some docs.

regenerated everything from scratch. one effect is more parking
blockface gets matched onto border roads, but that's fine.
This commit is contained in:
Dustin Carlino 2020-07-11 16:05:26 -07:00
parent 07ed1fec95
commit 0c283d0da7
21 changed files with 99 additions and 95 deletions

View File

@ -9,7 +9,7 @@ pub fn clip_map(map: &mut RawMap, timer: &mut Timer) {
// So we can use retain_btreemap without borrowing issues // So we can use retain_btreemap without borrowing issues
let boundary_polygon = map.boundary_polygon.clone(); let boundary_polygon = map.boundary_polygon.clone();
let boundary_ring = Ring::new(boundary_polygon.points().clone()); let boundary_ring = Ring::must_new(boundary_polygon.points().clone());
// This is kind of indirect and slow, but first pass -- just remove roads that start or end // This is kind of indirect and slow, but first pass -- just remove roads that start or end
// outside the boundary polygon. // outside the boundary polygon.

View File

@ -180,7 +180,7 @@ pub fn extract_osm(
} }
} }
let boundary = Ring::new(map.boundary_polygon.points().clone()); let boundary = Ring::must_new(map.boundary_polygon.points().clone());
let mut simple_turn_restrictions = Vec::new(); let mut simple_turn_restrictions = Vec::new();
let mut complicated_turn_restrictions = Vec::new(); let mut complicated_turn_restrictions = Vec::new();

View File

@ -3,22 +3,22 @@ data/input/austin/osm/downtown_atx.osm,a30b0f460a481598e494f16a9d07a822,https://
data/input/austin/osm/huge_austin.osm,fb166029fc8006bd20dc959fbbbde3b6,https://www.dropbox.com/s/4x421o9o8px0m6o/huge_austin.osm.zip?dl=0 data/input/austin/osm/huge_austin.osm,fb166029fc8006bd20dc959fbbbde3b6,https://www.dropbox.com/s/4x421o9o8px0m6o/huge_austin.osm.zip?dl=0
data/input/krakow/osm/huge_krakow.osm,0b098456c8ae844ff240ca9fe3b617d1,https://www.dropbox.com/s/fe2e8qzd4g5tkoy/huge_krakow.osm.zip?dl=0 data/input/krakow/osm/huge_krakow.osm,0b098456c8ae844ff240ca9fe3b617d1,https://www.dropbox.com/s/fe2e8qzd4g5tkoy/huge_krakow.osm.zip?dl=0
data/input/krakow/osm/malopolskie-latest.osm.pbf,d848a278092001aaab3ced09de4d98ff,https://www.dropbox.com/s/ia2uwy3z52r6hpe/malopolskie-latest.osm.pbf.zip?dl=0 data/input/krakow/osm/malopolskie-latest.osm.pbf,d848a278092001aaab3ced09de4d98ff,https://www.dropbox.com/s/ia2uwy3z52r6hpe/malopolskie-latest.osm.pbf.zip?dl=0
data/input/raw_maps/ballard.bin,fea0486d3925c7ffce54d0e21139ab75,https://www.dropbox.com/s/dfbtfu6qq7shj9t/ballard.bin.zip?dl=0 data/input/raw_maps/ballard.bin,4d72687ab860144d19ae3f1328f2b61d,https://www.dropbox.com/s/dkxhkir85rtm906/ballard.bin.zip?dl=0
data/input/raw_maps/downtown.bin,5da76c12b035bcde09d0735c6673d4ae,https://www.dropbox.com/s/f3jz7qk6xiij5po/downtown.bin.zip?dl=0 data/input/raw_maps/downtown.bin,48886494c43fd7b9db12a53f990dcb4f,https://www.dropbox.com/s/87rpndh1yudrlxb/downtown.bin.zip?dl=0
data/input/raw_maps/downtown_atx.bin,2995df6f32feb8135fbb1126b52402ba,https://www.dropbox.com/s/csuzjqhhbtw657x/downtown_atx.bin.zip?dl=0 data/input/raw_maps/downtown_atx.bin,2995df6f32feb8135fbb1126b52402ba,https://www.dropbox.com/s/csuzjqhhbtw657x/downtown_atx.bin.zip?dl=0
data/input/raw_maps/huge_austin.bin,fb671ea39ea254207c334b5662763433,https://www.dropbox.com/s/91i763larrbmx7z/huge_austin.bin.zip?dl=0 data/input/raw_maps/huge_austin.bin,fb671ea39ea254207c334b5662763433,https://www.dropbox.com/s/91i763larrbmx7z/huge_austin.bin.zip?dl=0
data/input/raw_maps/huge_krakow.bin,978426f967f122675ba530edc94b43e3,https://www.dropbox.com/s/5l9ojm1lfq32otz/huge_krakow.bin.zip?dl=0 data/input/raw_maps/huge_krakow.bin,978426f967f122675ba530edc94b43e3,https://www.dropbox.com/s/5l9ojm1lfq32otz/huge_krakow.bin.zip?dl=0
data/input/raw_maps/huge_seattle.bin,e7e49c7421e1343371ab06dc9e3dd64b,https://www.dropbox.com/s/dlajjc94bmxf07p/huge_seattle.bin.zip?dl=0 data/input/raw_maps/huge_seattle.bin,95798750903b3a7c35f165aaf3e39c91,https://www.dropbox.com/s/5pumdup46zmhb34/huge_seattle.bin.zip?dl=0
data/input/raw_maps/lakeslice.bin,95ed0a848ed098c068ada54db04c9495,https://www.dropbox.com/s/g1y26xudv7rkmko/lakeslice.bin.zip?dl=0 data/input/raw_maps/lakeslice.bin,28ede305a1e45a4298b8d10503324905,https://www.dropbox.com/s/j707o0ka1k4ixgk/lakeslice.bin.zip?dl=0
data/input/raw_maps/montlake.bin,1840e685f91589cf267f146f43878c47,https://www.dropbox.com/s/p5itfq7zioz2b3r/montlake.bin.zip?dl=0 data/input/raw_maps/montlake.bin,712532a30baa5225aca621fd1f1f7f0a,https://www.dropbox.com/s/evwmldb5872nf0u/montlake.bin.zip?dl=0
data/input/raw_maps/south_seattle.bin,bb870ffa8bd159a7ce9dca83216ac0b0,https://www.dropbox.com/s/v405rk7wm7luc0o/south_seattle.bin.zip?dl=0 data/input/raw_maps/south_seattle.bin,5eb52175e7fd06da3fc3e93fc2ca88fc,https://www.dropbox.com/s/jfc4ht5ydm05j8y/south_seattle.bin.zip?dl=0
data/input/raw_maps/udistrict.bin,ae242a89a2b83b2b9fc115dea0c40256,https://www.dropbox.com/s/vefz3ozb7od9xdf/udistrict.bin.zip?dl=0 data/input/raw_maps/udistrict.bin,a45f45140c03da4abf8d698cda580133,https://www.dropbox.com/s/plspsqay9c77fwz/udistrict.bin.zip?dl=0
data/input/raw_maps/west_seattle.bin,4784c2eeebd11c6c180d11eda73cf1e1,https://www.dropbox.com/s/6lp4foo4l7g487n/west_seattle.bin.zip?dl=0 data/input/raw_maps/west_seattle.bin,4784c2eeebd11c6c180d11eda73cf1e1,https://www.dropbox.com/s/6lp4foo4l7g487n/west_seattle.bin.zip?dl=0
data/input/screenshots/downtown.zip,f1cb474323244ef7a31971e3d5b25a12,https://www.dropbox.com/s/qawd35wz62m2acl/downtown.zip.zip?dl=0 data/input/screenshots/downtown.zip,bdad536ddb7f0e5aab912433b3c28e69,https://www.dropbox.com/s/qawd35wz62m2acl/downtown.zip.zip?dl=0
data/input/screenshots/huge_krakow.zip,cfc8fe595097fed224d369f2c647443c,https://www.dropbox.com/s/dbzon7k5ukndtza/huge_krakow.zip.zip?dl=0 data/input/screenshots/huge_krakow.zip,8edcb39fedadb7991ab2959064c98629,https://www.dropbox.com/s/dbzon7k5ukndtza/huge_krakow.zip.zip?dl=0
data/input/screenshots/lakeslice.zip,37ad352dbe42ce4aea0ba0a67067d451,https://www.dropbox.com/s/z0z96lsn7bunqfy/lakeslice.zip.zip?dl=0 data/input/screenshots/lakeslice.zip,73c0ed5add17f8c49218b1c22ee464cc,https://www.dropbox.com/s/z0z96lsn7bunqfy/lakeslice.zip.zip?dl=0
data/input/screenshots/montlake.zip,c8b016f00792ef23b9fae44956d2d86c,https://www.dropbox.com/s/r9vkgwesqklfuq2/montlake.zip.zip?dl=0 data/input/screenshots/montlake.zip,fbc945c0869c2b85ccfb1fef4340ba2e,https://www.dropbox.com/s/r9vkgwesqklfuq2/montlake.zip.zip?dl=0
data/input/screenshots/udistrict.zip,584036034b44708da6ae006b2f40fa3b,https://www.dropbox.com/s/ecnt1tyza48y9o2/udistrict.zip.zip?dl=0 data/input/screenshots/udistrict.zip,c7a7a258e3d0a417ada55f70c897d4d3,https://www.dropbox.com/s/ecnt1tyza48y9o2/udistrict.zip.zip?dl=0
data/input/seattle/N47W122.hgt,0db4e23e51f7680538b0bbbc72208e07,https://www.dropbox.com/s/mmb4mgutwotijdw/N47W122.hgt.zip?dl=0 data/input/seattle/N47W122.hgt,0db4e23e51f7680538b0bbbc72208e07,https://www.dropbox.com/s/mmb4mgutwotijdw/N47W122.hgt.zip?dl=0
data/input/seattle/blockface.bin,add872bab9040ae911366328a230f8b5,https://www.dropbox.com/s/rxd2care60tbe75/blockface.bin.zip?dl=0 data/input/seattle/blockface.bin,add872bab9040ae911366328a230f8b5,https://www.dropbox.com/s/rxd2care60tbe75/blockface.bin.zip?dl=0
data/input/seattle/blockface.kml,350bd9e59bf2af4e885a7c0741e6ee6b,https://www.dropbox.com/s/ukknmpjdvilncq9/blockface.kml.zip?dl=0 data/input/seattle/blockface.kml,350bd9e59bf2af4e885a7c0741e6ee6b,https://www.dropbox.com/s/ukknmpjdvilncq9/blockface.kml.zip?dl=0
@ -33,30 +33,30 @@ data/input/seattle/osm/south_seattle.osm,2a20b3549004a3d37ef962baf07fbf93,https:
data/input/seattle/osm/udistrict.osm,769388ffc0d73c6a149ed79698e2b8f3,https://www.dropbox.com/s/3v6axtyuofqatit/udistrict.osm.zip?dl=0 data/input/seattle/osm/udistrict.osm,769388ffc0d73c6a149ed79698e2b8f3,https://www.dropbox.com/s/3v6axtyuofqatit/udistrict.osm.zip?dl=0
data/input/seattle/osm/washington-latest.osm.pbf,ac31d2a9d3a109f4467e5f64b5922509,https://www.dropbox.com/s/eilk9soyod3war6/washington-latest.osm.pbf.zip?dl=0 data/input/seattle/osm/washington-latest.osm.pbf,ac31d2a9d3a109f4467e5f64b5922509,https://www.dropbox.com/s/eilk9soyod3war6/washington-latest.osm.pbf.zip?dl=0
data/input/seattle/osm/west_seattle.osm,b87c760bd512c4302846519ed052ad5a,https://www.dropbox.com/s/qhtkotrtp7ilmy1/west_seattle.osm.zip?dl=0 data/input/seattle/osm/west_seattle.osm,b87c760bd512c4302846519ed052ad5a,https://www.dropbox.com/s/qhtkotrtp7ilmy1/west_seattle.osm.zip?dl=0
data/input/seattle/parcels.bin,1cfdc485a35df9edce7b24e5c17b2977,https://www.dropbox.com/s/s977yzbcds355nv/parcels.bin.zip?dl=0 data/input/seattle/parcels.bin,fbaa5480e614e7f59a9e958f92a12526,https://www.dropbox.com/s/cy88qmctgya2g76/parcels.bin.zip?dl=0
data/input/seattle/parcels_urbansim.txt,db63d7d606e8702d12f9399e87e6a00f,https://www.dropbox.com/s/6g8rbsf200dssj3/parcels_urbansim.txt.zip?dl=0 data/input/seattle/parcels_urbansim.txt,db63d7d606e8702d12f9399e87e6a00f,https://www.dropbox.com/s/6g8rbsf200dssj3/parcels_urbansim.txt.zip?dl=0
data/input/seattle/popdat.bin,ad38e1f20ce71f488112fe81e32798d2,https://www.dropbox.com/s/ajqii1qpfke8063/popdat.bin.zip?dl=0 data/input/seattle/popdat.bin,ad38e1f20ce71f488112fe81e32798d2,https://www.dropbox.com/s/ajqii1qpfke8063/popdat.bin.zip?dl=0
data/input/seattle/trips_2014.csv,d4a8e733045b28c0385fb81359d6df03,https://www.dropbox.com/s/5ppravwmk6bf20d/trips_2014.csv.zip?dl=0 data/input/seattle/trips_2014.csv,d4a8e733045b28c0385fb81359d6df03,https://www.dropbox.com/s/5ppravwmk6bf20d/trips_2014.csv.zip?dl=0
data/system/cities/seattle.bin,9ed9ff25b3f3941fecf530b3815a1b05,https://www.dropbox.com/s/nwb29tt4koqk6um/seattle.bin.zip?dl=0 data/system/cities/seattle.bin,9ed9ff25b3f3941fecf530b3815a1b05,https://www.dropbox.com/s/nwb29tt4koqk6um/seattle.bin.zip?dl=0
data/system/maps/ballard.bin,b98c9b698d876ebadd34bbcb541630d3,https://www.dropbox.com/s/ocv4p7dzrxcogyq/ballard.bin.zip?dl=0 data/system/maps/ballard.bin,d4ab6ceb6905dfa14b2aaac99c495eff,https://www.dropbox.com/s/too29h0nr6s64wm/ballard.bin.zip?dl=0
data/system/maps/downtown.bin,f951b7ca011b91f062334a94585b7083,https://www.dropbox.com/s/ww7jzqlbpxur8l6/downtown.bin.zip?dl=0 data/system/maps/downtown.bin,6b7735033169acdb4c1429b084632de5,https://www.dropbox.com/s/8s6pjo91spchkfx/downtown.bin.zip?dl=0
data/system/maps/downtown_atx.bin,700a4a78af42e37ef1245e4fc63ce0c4,https://www.dropbox.com/s/ixijn46f07zizzi/downtown_atx.bin.zip?dl=0 data/system/maps/downtown_atx.bin,700a4a78af42e37ef1245e4fc63ce0c4,https://www.dropbox.com/s/ixijn46f07zizzi/downtown_atx.bin.zip?dl=0
data/system/maps/huge_austin.bin,f7ea14d6b616a6ca9a63ac4460b0a2a0,https://www.dropbox.com/s/5jlbbinjp4132rp/huge_austin.bin.zip?dl=0 data/system/maps/huge_austin.bin,f7ea14d6b616a6ca9a63ac4460b0a2a0,https://www.dropbox.com/s/5jlbbinjp4132rp/huge_austin.bin.zip?dl=0
data/system/maps/huge_krakow.bin,f87b77708170bafa72331cccc6df57b6,https://www.dropbox.com/s/friayproln1gtig/huge_krakow.bin.zip?dl=0 data/system/maps/huge_krakow.bin,f87b77708170bafa72331cccc6df57b6,https://www.dropbox.com/s/friayproln1gtig/huge_krakow.bin.zip?dl=0
data/system/maps/huge_seattle.bin,4086044e523651a631f0745e73238bb8,https://www.dropbox.com/s/aj0h8igtskfths3/huge_seattle.bin.zip?dl=0 data/system/maps/huge_seattle.bin,05214611240c878306f351b76d07db3b,https://www.dropbox.com/s/xakfwfqbcyeznuy/huge_seattle.bin.zip?dl=0
data/system/maps/lakeslice.bin,ea5e918b7b70db2c8e484f8666c4737b,https://www.dropbox.com/s/p6r64ujz81vx7vd/lakeslice.bin.zip?dl=0 data/system/maps/lakeslice.bin,ecd6b3b127982eb9b42530da2bb0887b,https://www.dropbox.com/s/dkmf2qaa991uxym/lakeslice.bin.zip?dl=0
data/system/maps/montlake.bin,032f96ae28a2db2d6b4aa848469e9aea,https://www.dropbox.com/s/rjei8n91qil1bhw/montlake.bin.zip?dl=0 data/system/maps/montlake.bin,cb2246cb15edc0553f5b03af4886471c,https://www.dropbox.com/s/0dnysbp2h7wdaf4/montlake.bin.zip?dl=0
data/system/maps/south_seattle.bin,c967a5d372ef7298a711fc213244ccd8,https://www.dropbox.com/s/nynh73cxqggeuj3/south_seattle.bin.zip?dl=0 data/system/maps/south_seattle.bin,174a44c25848f36d82a59644ef56582e,https://www.dropbox.com/s/cu8exdobcdaj6sm/south_seattle.bin.zip?dl=0
data/system/maps/udistrict.bin,a9a320f182af78d235af98a78aa0646c,https://www.dropbox.com/s/92joyhk29cqoipk/udistrict.bin.zip?dl=0 data/system/maps/udistrict.bin,c0cf3f4758ebd9faef843cf587b32a99,https://www.dropbox.com/s/z38hxojx3x8qpvl/udistrict.bin.zip?dl=0
data/system/maps/west_seattle.bin,ccfb1547ffceaa8a635b12252951ce8f,https://www.dropbox.com/s/x9o4lg7fgvy5kr2/west_seattle.bin.zip?dl=0 data/system/maps/west_seattle.bin,ccfb1547ffceaa8a635b12252951ce8f,https://www.dropbox.com/s/x9o4lg7fgvy5kr2/west_seattle.bin.zip?dl=0
data/system/prebaked_results/lakeslice/weekday.bin,3bcb09e1d6ddeed75e3baf3b6b476e5c,https://www.dropbox.com/s/5odd5kdxn0caodk/weekday.bin.zip?dl=0 data/system/prebaked_results/lakeslice/weekday.bin,6cb89d0581ad0d78cd7644a882ab0528,https://www.dropbox.com/s/frg14z9f90qrk8v/weekday.bin.zip?dl=0
data/system/prebaked_results/montlake/car vs bike contention.bin,d3e42a758ba4e10e6143c8f8370a638f,https://www.dropbox.com/s/jefg0ikjy9dsrdd/car%20vs%20bike%20contention.bin.zip?dl=0 data/system/prebaked_results/montlake/car vs bike contention.bin,bd7bbdee559245ed5dd85ddd67165cf9,https://www.dropbox.com/s/jefg0ikjy9dsrdd/car%20vs%20bike%20contention.bin.zip?dl=0
data/system/prebaked_results/montlake/weekday.bin,979af6c1db9f5bf31a3cf12301c4c6f9,https://www.dropbox.com/s/0duohjtnbj5y7gc/weekday.bin.zip?dl=0 data/system/prebaked_results/montlake/weekday.bin,be76cdebe55527b2e19e1c09f9540426,https://www.dropbox.com/s/gzxg2orfu8z9s6x/weekday.bin.zip?dl=0
data/system/scenarios/ballard/weekday.bin,f6d7dac5af0f35a6ae5589d3943be789,https://www.dropbox.com/s/klvs4wkauh00xud/weekday.bin.zip?dl=0 data/system/scenarios/ballard/weekday.bin,b1993a9f154cf88c78884eb96ee28a08,https://www.dropbox.com/s/2sf37gu7nur9o37/weekday.bin.zip?dl=0
data/system/scenarios/downtown/weekday.bin,2b4506c9aab41a0a12f8d0ef769db492,https://www.dropbox.com/s/swmss3vyrrjnv6n/weekday.bin.zip?dl=0 data/system/scenarios/downtown/weekday.bin,67c8345c4340cbd0a69d3c079c1c6b6c,https://www.dropbox.com/s/kasxsyett83oo03/weekday.bin.zip?dl=0
data/system/scenarios/huge_seattle/weekday.bin,30cf8491099a33c758aa76c31267bd13,https://www.dropbox.com/s/a20dujaxnwhe2aj/weekday.bin.zip?dl=0 data/system/scenarios/huge_seattle/weekday.bin,102b72c09c63042dc7ca3c143bf7508a,https://www.dropbox.com/s/ebvg1zgv2ywnndf/weekday.bin.zip?dl=0
data/system/scenarios/lakeslice/weekday.bin,19812c16dc90945f5c3659b47c1c55e8,https://www.dropbox.com/s/00cjax1g3bcmwvf/weekday.bin.zip?dl=0 data/system/scenarios/lakeslice/weekday.bin,0d86fa1518f5e06942c0b2b8869b9000,https://www.dropbox.com/s/0cuc7urc0fsgqi5/weekday.bin.zip?dl=0
data/system/scenarios/montlake/weekday.bin,ee5359d37d1d9446578d34c3b97b9266,https://www.dropbox.com/s/bx6sv6rogt2alyq/weekday.bin.zip?dl=0 data/system/scenarios/montlake/weekday.bin,3c19364da831e3f81fed81b6edc1a844,https://www.dropbox.com/s/8ypid1mus95ivni/weekday.bin.zip?dl=0
data/system/scenarios/south_seattle/weekday.bin,9b84537fb47831d6b65f81dcb947600d,https://www.dropbox.com/s/i36o01uv6ud8rj3/weekday.bin.zip?dl=0 data/system/scenarios/south_seattle/weekday.bin,16f5512c24bc140b6d333a44819936d2,https://www.dropbox.com/s/rvyypxoc0awubn1/weekday.bin.zip?dl=0
data/system/scenarios/udistrict/weekday.bin,6c08853e72f8fc65b25b69639cb59464,https://www.dropbox.com/s/3c0tlq9k8niz0pr/weekday.bin.zip?dl=0 data/system/scenarios/udistrict/weekday.bin,25bf5370f905ce57c017028a33612c4e,https://www.dropbox.com/s/msb70poj5dl29q2/weekday.bin.zip?dl=0
data/system/scenarios/west_seattle/weekday.bin,48a9b04d69948436c8eb89f943e36b5d,https://www.dropbox.com/s/8jq9rs6dom8t0y9/weekday.bin.zip?dl=0 data/system/scenarios/west_seattle/weekday.bin,089ee9b267bafc860f8c6952a69f3efe,https://www.dropbox.com/s/l3lfj8gk232cyrl/weekday.bin.zip?dl=0

View File

@ -46,9 +46,6 @@ One-time setup:
experience, so they're hidden for now. experience, so they're hidden for now.
- `cargo run --bin game -- --tutorial=12` starts somewhere in the tutorial - `cargo run --bin game -- --tutorial=12` starts somewhere in the tutorial
- Adding `--edits='name of edits'` starts with edits applied to the map. - Adding `--edits='name of edits'` starts with edits applied to the map.
- All code is automatically formatted using
https://github.com/rust-lang/rustfmt; please run `cargo +nightly fmt` before
sending a PR. (You have to install the nightly toolchain just for fmt)
- More random notes [here](/docs/misc_dev_tricks.md) - More random notes [here](/docs/misc_dev_tricks.md)
## Downloading more cities ## Downloading more cities
@ -139,3 +136,24 @@ Common utilities:
- `abstutil`: a grab-bag of IO helpers, timing and logging utilities, etc - `abstutil`: a grab-bag of IO helpers, timing and logging utilities, etc
- `geom`: types for GPS and map-space points, lines, angles, polylines, - `geom`: types for GPS and map-space points, lines, angles, polylines,
polygons, circles, durations, speeds polygons, circles, durations, speeds
## Code conventions
All code is automatically formatted using https://github.com/rust-lang/rustfmt;
please run `cargo +nightly fmt` before sending a PR. (You have to install the
nightly toolchain just for fmt)
The error handling is unfortunately inconsistent. The goal is to gracefully
degrade instead of crashing the game. If a crash does happen, make sure the logs
will have enough context to reproduce and debug. For example, giving up when
some geometry problem happens isn't ideal, but at least make sure to print the
road / agent IDs or whatever will help find the problem. It's fine to crash
during map importing, since the player won't deal with this, and loudly stopping
problems is useful. It's also fine to crash when initially constructing all of
the renderable map objects, because this crash will consistently happen at
startup-time and be noticed by somebody developing before a player gets to it.
I have lots of thoughts about testing that I haven't written anywhere yet.
You'll surely note the lack of unit tests. If it bothers you, let's talk about
what tests should exist. In the meantime, note lots of validation does happen
via importing maps, running the prebaked scenarios, and screenshot diffing.

View File

@ -421,7 +421,8 @@ impl Widget {
batch.push( batch.push(
color, color,
Polygon::rounded_rectangle(width, height, self.layout.rounded_radius) Polygon::rounded_rectangle(width, height, self.layout.rounded_radius)
.to_outline(Distance::meters(thickness)), .to_outline(Distance::meters(thickness))
.unwrap(),
); );
} }
self.bg = Some(ctx.upload(batch)); self.bg = Some(ctx.upload(batch));

View File

@ -130,7 +130,10 @@ impl<T: 'static + Clone> WidgetImpl for Dropdown<T> {
let rect = Polygon::rounded_rectangle(width, height, Some(5.0)); let rect = Polygon::rounded_rectangle(width, height, Some(5.0));
let draw_bg = g.upload(GeomBatch::from(vec![ let draw_bg = g.upload(GeomBatch::from(vec![
(Color::grey(0.3), rect.clone()), (Color::grey(0.3), rect.clone()),
(Color::WHITE, rect.to_outline(Distance::meters(3.0))), (
Color::WHITE,
rect.to_outline(Distance::meters(3.0)).unwrap(),
),
])); ]));
g.fork( g.fork(
Pt2D::new(0.0, 0.0), Pt2D::new(0.0, 0.0),

View File

@ -54,7 +54,7 @@ impl CityPicker {
if &name == app.primary.map.get_name() { if &name == app.primary.map.get_name() {
batch.push(color.alpha(0.5), polygon.clone()); batch.push(color.alpha(0.5), polygon.clone());
} else { } else {
batch.push(color, polygon.to_outline(Distance::meters(200.0))); batch.push(color, polygon.to_outline(Distance::meters(200.0)).unwrap());
} }
regions.push((name, color, polygon.scale(zoom_no_scale_factor))); regions.push((name, color, polygon.scale(zoom_no_scale_factor)));
} }

View File

@ -300,7 +300,7 @@ impl Minimap {
}; };
g.draw_polygon( g.draw_polygon(
Color::BLACK, Color::BLACK,
&Ring::new(vec![ &Ring::must_new(vec![
Pt2D::new(x1, y1), Pt2D::new(x1, y1),
Pt2D::new(x2, y1), Pt2D::new(x2, y1),
Pt2D::new(x2, y2), Pt2D::new(x2, y2),

View File

@ -204,7 +204,7 @@ fn make_object(
} else if pts[0] == *pts.last().unwrap() { } else if pts[0] == *pts.last().unwrap() {
// TODO Toggle between these better // TODO Toggle between these better
//Polygon::new(&pts) //Polygon::new(&pts)
Ring::new(pts).make_polygons(THICKNESS) Ring::must_new(pts).make_polygons(THICKNESS)
} else { } else {
let backup = pts[0]; let backup = pts[0];
match PolyLine::new(pts) { match PolyLine::new(pts) {

View File

@ -464,7 +464,7 @@ impl Marker {
} else { } else {
let poly = Polygon::new(&pts); let poly = Polygon::new(&pts);
batch.push(Color::RED.alpha(0.8), poly.clone()); batch.push(Color::RED.alpha(0.8), poly.clone());
if let Some(o) = poly.maybe_to_outline(Distance::meters(1.0)) { if let Ok(o) = poly.to_outline(Distance::meters(1.0)) {
batch.push(Color::RED, o); batch.push(Color::RED, o);
} }
// TODO Refactor // TODO Refactor
@ -591,9 +591,9 @@ fn simplify(mut raw: Vec<Pt2D>) -> Ring {
downsampled.push(Pt2D::new(pt.x, pt.y)); downsampled.push(Pt2D::new(pt.x, pt.y));
} }
downsampled.push(downsampled[0]); downsampled.push(downsampled[0]);
Ring::new(downsampled) Ring::must_new(downsampled)
} else { } else {
raw.push(raw[0]); raw.push(raw[0]);
Ring::new(raw) Ring::must_new(raw)
} }
} }

View File

@ -498,13 +498,16 @@ impl TrafficJams {
app.primary.sim.delayed_intersections(Duration::minutes(5)), app.primary.sim.delayed_intersections(Duration::minutes(5)),
) { ) {
cnt += 1; cnt += 1;
unzoomed.push(Color::RED, boundary.to_outline(Distance::meters(5.0))); unzoomed.push(
Color::RED,
boundary.to_outline(Distance::meters(5.0)).unwrap(),
);
unzoomed.push(Color::RED.alpha(0.5), boundary.clone()); unzoomed.push(Color::RED.alpha(0.5), boundary.clone());
unzoomed.push(Color::WHITE, epicenter.clone()); unzoomed.push(Color::WHITE, epicenter.clone());
zoomed.push( zoomed.push(
Color::RED.alpha(0.4), Color::RED.alpha(0.4),
boundary.to_outline(Distance::meters(5.0)), boundary.to_outline(Distance::meters(5.0)).unwrap(),
); );
zoomed.push(Color::RED.alpha(0.3), boundary); zoomed.push(Color::RED.alpha(0.3), boundary);
zoomed.push(Color::WHITE.alpha(0.4), epicenter); zoomed.push(Color::WHITE.alpha(0.4), epicenter);

View File

@ -40,7 +40,7 @@ impl DrawBuilding {
cs.sidewalk, cs.sidewalk,
front_path_line.make_polygons(NORMAL_LANE_THICKNESS), front_path_line.make_polygons(NORMAL_LANE_THICKNESS),
); );
if let Some(p) = bldg.polygon.maybe_to_outline(Distance::meters(0.1)) { if let Ok(p) = bldg.polygon.to_outline(Distance::meters(0.1)) {
outlines_batch.push(cs.building_outline, p); outlines_batch.push(cs.building_outline, p);
} }
@ -102,7 +102,7 @@ impl Renderable for DrawBuilding {
fn get_outline(&self, map: &Map) -> Polygon { fn get_outline(&self, map: &Map) -> Polygon {
let b = map.get_b(self.id); let b = map.get_b(self.id);
if let Some(p) = b.polygon.maybe_to_outline(OUTLINE_THICKNESS) { if let Ok(p) = b.polygon.to_outline(OUTLINE_THICKNESS) {
p p
} else { } else {
b.polygon.clone() b.polygon.clone()

View File

@ -163,7 +163,9 @@ impl Renderable for DrawIntersection {
} }
fn get_outline(&self, map: &Map) -> Polygon { fn get_outline(&self, map: &Map) -> Polygon {
map.get_i(self.id).polygon.to_outline(OUTLINE_THICKNESS) let poly = &map.get_i(self.id).polygon;
poly.to_outline(OUTLINE_THICKNESS)
.unwrap_or_else(|_| poly.clone())
} }
fn contains_pt(&self, pt: Pt2D, map: &Map) -> bool { fn contains_pt(&self, pt: Pt2D, map: &Map) -> bool {

View File

@ -100,7 +100,7 @@ impl Renderable for DrawParkingLot {
fn get_outline(&self, map: &Map) -> Polygon { fn get_outline(&self, map: &Map) -> Polygon {
let pl = map.get_pl(self.id); let pl = map.get_pl(self.id);
if let Some(p) = pl.polygon.maybe_to_outline(OUTLINE_THICKNESS) { if let Ok(p) = pl.polygon.to_outline(OUTLINE_THICKNESS) {
p p
} else { } else {
pl.polygon.clone() pl.polygon.clone()

View File

@ -368,7 +368,7 @@ pub fn make_signal_diagram(
let mut hovered = GeomBatch::new(); let mut hovered = GeomBatch::new();
hovered.append(normal.clone()); hovered.append(normal.clone());
hovered.push(Color::RED, bbox.to_outline(Distance::meters(5.0))); hovered.push(Color::RED, bbox.to_outline(Distance::meters(5.0)).unwrap());
Btn::custom(normal, hovered, bbox.clone()).build( Btn::custom(normal, hovered, bbox.clone()).build(
ctx, ctx,

View File

@ -266,7 +266,7 @@ fn contingency_table(ctx: &mut EventCtx, app: &App, filter: &Filter) -> Widget {
if num_savings > 0 { if num_savings > 0 {
let height = (total_savings / max_y) * max_bar_height; let height = (total_savings / max_y) * max_bar_height;
let rect = Polygon::rectangle(bar_width, height).translate(x1, max_bar_height - height); let rect = Polygon::rectangle(bar_width, height).translate(x1, max_bar_height - height);
if let Some(o) = rect.maybe_to_outline(Distance::meters(1.5)) { if let Ok(o) = rect.to_outline(Distance::meters(1.5)) {
outlines.push(o); outlines.push(o);
} }
batch.push(Color::GREEN, rect.clone()); batch.push(Color::GREEN, rect.clone());
@ -287,7 +287,7 @@ fn contingency_table(ctx: &mut EventCtx, app: &App, filter: &Filter) -> Widget {
let height = (total_loss / max_y) * max_bar_height; let height = (total_loss / max_y) * max_bar_height;
let rect = let rect =
Polygon::rectangle(bar_width, height).translate(x1, total_height - max_bar_height); Polygon::rectangle(bar_width, height).translate(x1, total_height - max_bar_height);
if let Some(o) = rect.maybe_to_outline(Distance::meters(1.5)) { if let Ok(o) = rect.to_outline(Distance::meters(1.5)) {
outlines.push(o); outlines.push(o);
} }
batch.push(Color::RED, rect.clone()); batch.push(Color::RED, rect.clone());

View File

@ -74,7 +74,7 @@ impl Circle {
if false { if false {
let mut pts = Circle::new(center, radius).to_polygon().points().clone(); let mut pts = Circle::new(center, radius).to_polygon().points().clone();
pts.push(pts[0]); pts.push(pts[0]);
return Ok(Ring::new(pts).make_polygons(thickness)); return Ok(Ring::must_new(pts).make_polygons(thickness));
} }
// TODO Argh this one also leaves a little piece missing, but it looks less bad. Fine. // TODO Argh this one also leaves a little piece missing, but it looks less bad. Fine.

View File

@ -3,6 +3,7 @@ use geo::algorithm::area::Area;
use geo::algorithm::convexhull::ConvexHull; use geo::algorithm::convexhull::ConvexHull;
use geo_booleanop::boolean::BooleanOp; use geo_booleanop::boolean::BooleanOp;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::error::Error;
use std::fmt; use std::fmt;
#[derive(Serialize, Deserialize, Clone, Debug)] #[derive(Serialize, Deserialize, Clone, Debug)]
@ -286,12 +287,8 @@ impl Polygon {
// Only works for polygons that're formed from rings. Those made from PolyLines won't work, for // Only works for polygons that're formed from rings. Those made from PolyLines won't work, for
// example. // example.
pub fn to_outline(&self, thickness: Distance) -> Polygon { pub fn to_outline(&self, thickness: Distance) -> Result<Polygon, Box<dyn Error>> {
Ring::new(self.points.clone()).make_polygons(thickness) Ring::new(self.points.clone()).map(|r| r.make_polygons(thickness))
}
pub fn maybe_to_outline(&self, thickness: Distance) -> Option<Polygon> {
Ring::maybe_new(self.points.clone()).map(|r| r.make_polygons(thickness))
} }
// Usually m^2, unless the polygon is in screen-space // Usually m^2, unless the polygon is in screen-space
@ -301,7 +298,7 @@ impl Polygon {
// Doesn't handle multiple crossings in and out. // Doesn't handle multiple crossings in and out.
pub fn clip_polyline(&self, input: &PolyLine) -> Option<Vec<Pt2D>> { pub fn clip_polyline(&self, input: &PolyLine) -> Option<Vec<Pt2D>> {
let ring = Ring::new(self.points.clone()); let ring = Ring::must_new(self.points.clone());
let hits = ring.all_intersections(input); let hits = ring.all_intersections(input);
if hits.len() == 0 { if hits.len() == 0 {

View File

@ -93,7 +93,7 @@ impl PolyLine {
side1.extend(side2); side1.extend(side2);
side1.push(side1[0]); side1.push(side1[0]);
side1.dedup(); side1.dedup();
Some(Ring::new(side1).make_polygons(boundary_width)) Some(Ring::must_new(side1).make_polygons(boundary_width))
} }
pub fn reversed(&self) -> PolyLine { pub fn reversed(&self) -> PolyLine {
@ -556,7 +556,7 @@ impl PolyLine {
let angle = slice.last_pt().angle_to(self.last_pt()); let angle = slice.last_pt().angle_to(self.last_pt());
vec![ vec![
p, p,
Ring::new(vec![ Ring::must_new(vec![
self.last_pt(), self.last_pt(),
self.last_pt() self.last_pt()
.project_away(head_size, angle.rotate_degs(-135.0)), .project_away(head_size, angle.rotate_degs(-135.0)),

View File

@ -12,39 +12,16 @@ pub struct Ring {
} }
impl Ring { impl Ring {
pub fn new(pts: Vec<Pt2D>) -> Ring { pub fn new(pts: Vec<Pt2D>) -> Result<Ring, Box<dyn Error>> {
assert!(pts.len() >= 3); if pts.len() < 3 {
assert_eq!(pts[0], *pts.last().unwrap()); return Err(format!("Can't make a ring with < 3 points").into());
// This checks no lines are too small. Could take the other approach and automatically
// squish down points here and make sure the final result is at least EPSILON_DIST.
// But probably better for the callers to do this -- they have better understanding of what
// needs to be squished down, why, and how.
if pts.windows(2).any(|pair| pair[0] == pair[1]) {
panic!("Ring has ~dupe adjacent pts: {:?}", pts);
} }
let result = Ring { pts };
let mut seen_pts = HashSet::new();
for pt in result.pts.iter().skip(1) {
seen_pts.insert(pt.to_hashable());
}
if seen_pts.len() != result.pts.len() - 1 {
panic!("Ring has repeat points: {}", result);
}
result
}
pub fn maybe_new(pts: Vec<Pt2D>) -> Option<Ring> {
assert!(pts.len() >= 3);
if pts[0] != *pts.last().unwrap() { if pts[0] != *pts.last().unwrap() {
return None; return Err(format!("Can't make a ring with mismatching first/last points").into());
} }
if pts.windows(2).any(|pair| pair[0] == pair[1]) { if pts.windows(2).any(|pair| pair[0] == pair[1]) {
return None; return Err(format!("Ring has ~dupe adjacent pts").into());
} }
let result = Ring { pts }; let result = Ring { pts };
@ -54,10 +31,13 @@ impl Ring {
seen_pts.insert(pt.to_hashable()); seen_pts.insert(pt.to_hashable());
} }
if seen_pts.len() != result.pts.len() - 1 { if seen_pts.len() != result.pts.len() - 1 {
return None; return Err(format!("Ring has repeat non-adjacent points").into());
} }
Some(result) Ok(result)
}
pub fn must_new(pts: Vec<Pt2D>) -> Ring {
Ring::new(pts).unwrap()
} }
pub fn make_polygons(&self, thickness: Distance) -> Polygon { pub fn make_polygons(&self, thickness: Distance) -> Polygon {
@ -137,7 +117,7 @@ impl Ring {
current.push(pt); current.push(pt);
if intersections.contains(&pt.to_hashable()) && current.len() > 1 { if intersections.contains(&pt.to_hashable()) && current.len() > 1 {
if current[0] == pt { if current[0] == pt {
rings.push(Ring::new(current.drain(..).collect())); rings.push(Ring::must_new(current.drain(..).collect()));
} else { } else {
polylines.push(PolyLine::new(current.drain(..).collect())?); polylines.push(PolyLine::new(current.drain(..).collect())?);
} }

View File

@ -549,7 +549,7 @@ fn make_shared_sidewalk_corner(
// TODO Something like this will be MUCH simpler and avoid going around the long way sometimes. // TODO Something like this will be MUCH simpler and avoid going around the long way sometimes.
if false { if false {
return Ring::new(i.polygon.points().clone()).get_shorter_slice_btwn(corner1, corner2); return Ring::must_new(i.polygon.points().clone()).get_shorter_slice_btwn(corner1, corner2);
} }
// The order of the points here seems backwards, but it's because we scan from corner2 // The order of the points here seems backwards, but it's because we scan from corner2