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
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
// 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 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/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/raw_maps/ballard.bin,fea0486d3925c7ffce54d0e21139ab75,https://www.dropbox.com/s/dfbtfu6qq7shj9t/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/ballard.bin,4d72687ab860144d19ae3f1328f2b61d,https://www.dropbox.com/s/dkxhkir85rtm906/ballard.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/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_seattle.bin,e7e49c7421e1343371ab06dc9e3dd64b,https://www.dropbox.com/s/dlajjc94bmxf07p/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/montlake.bin,1840e685f91589cf267f146f43878c47,https://www.dropbox.com/s/p5itfq7zioz2b3r/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/udistrict.bin,ae242a89a2b83b2b9fc115dea0c40256,https://www.dropbox.com/s/vefz3ozb7od9xdf/udistrict.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,28ede305a1e45a4298b8d10503324905,https://www.dropbox.com/s/j707o0ka1k4ixgk/lakeslice.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,5eb52175e7fd06da3fc3e93fc2ca88fc,https://www.dropbox.com/s/jfc4ht5ydm05j8y/south_seattle.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/screenshots/downtown.zip,f1cb474323244ef7a31971e3d5b25a12,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/lakeslice.zip,37ad352dbe42ce4aea0ba0a67067d451,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/udistrict.zip,584036034b44708da6ae006b2f40fa3b,https://www.dropbox.com/s/ecnt1tyza48y9o2/udistrict.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,8edcb39fedadb7991ab2959064c98629,https://www.dropbox.com/s/dbzon7k5ukndtza/huge_krakow.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,fbc945c0869c2b85ccfb1fef4340ba2e,https://www.dropbox.com/s/r9vkgwesqklfuq2/montlake.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/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
@ -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/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/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/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/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/downtown.bin,f951b7ca011b91f062334a94585b7083,https://www.dropbox.com/s/ww7jzqlbpxur8l6/downtown.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,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/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_seattle.bin,4086044e523651a631f0745e73238bb8,https://www.dropbox.com/s/aj0h8igtskfths3/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/montlake.bin,032f96ae28a2db2d6b4aa848469e9aea,https://www.dropbox.com/s/rjei8n91qil1bhw/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/udistrict.bin,a9a320f182af78d235af98a78aa0646c,https://www.dropbox.com/s/92joyhk29cqoipk/udistrict.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,ecd6b3b127982eb9b42530da2bb0887b,https://www.dropbox.com/s/dkmf2qaa991uxym/lakeslice.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,174a44c25848f36d82a59644ef56582e,https://www.dropbox.com/s/cu8exdobcdaj6sm/south_seattle.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/prebaked_results/lakeslice/weekday.bin,3bcb09e1d6ddeed75e3baf3b6b476e5c,https://www.dropbox.com/s/5odd5kdxn0caodk/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/weekday.bin,979af6c1db9f5bf31a3cf12301c4c6f9,https://www.dropbox.com/s/0duohjtnbj5y7gc/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/downtown/weekday.bin,2b4506c9aab41a0a12f8d0ef769db492,https://www.dropbox.com/s/swmss3vyrrjnv6n/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/lakeslice/weekday.bin,19812c16dc90945f5c3659b47c1c55e8,https://www.dropbox.com/s/00cjax1g3bcmwvf/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/south_seattle/weekday.bin,9b84537fb47831d6b65f81dcb947600d,https://www.dropbox.com/s/i36o01uv6ud8rj3/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/west_seattle/weekday.bin,48a9b04d69948436c8eb89f943e36b5d,https://www.dropbox.com/s/8jq9rs6dom8t0y9/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,bd7bbdee559245ed5dd85ddd67165cf9,https://www.dropbox.com/s/jefg0ikjy9dsrdd/car%20vs%20bike%20contention.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,b1993a9f154cf88c78884eb96ee28a08,https://www.dropbox.com/s/2sf37gu7nur9o37/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,102b72c09c63042dc7ca3c143bf7508a,https://www.dropbox.com/s/ebvg1zgv2ywnndf/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,3c19364da831e3f81fed81b6edc1a844,https://www.dropbox.com/s/8ypid1mus95ivni/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,25bf5370f905ce57c017028a33612c4e,https://www.dropbox.com/s/msb70poj5dl29q2/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.
- `cargo run --bin game -- --tutorial=12` starts somewhere in the tutorial
- 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)
## Downloading more cities
@ -139,3 +136,24 @@ Common utilities:
- `abstutil`: a grab-bag of IO helpers, timing and logging utilities, etc
- `geom`: types for GPS and map-space points, lines, angles, polylines,
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(
color,
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));

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 draw_bg = g.upload(GeomBatch::from(vec![
(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(
Pt2D::new(0.0, 0.0),

View File

@ -54,7 +54,7 @@ impl CityPicker {
if &name == app.primary.map.get_name() {
batch.push(color.alpha(0.5), polygon.clone());
} 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)));
}

View File

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

View File

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

View File

@ -464,7 +464,7 @@ impl Marker {
} else {
let poly = Polygon::new(&pts);
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);
}
// TODO Refactor
@ -591,9 +591,9 @@ fn simplify(mut raw: Vec<Pt2D>) -> Ring {
downsampled.push(Pt2D::new(pt.x, pt.y));
}
downsampled.push(downsampled[0]);
Ring::new(downsampled)
Ring::must_new(downsampled)
} else {
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)),
) {
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::WHITE, epicenter.clone());
zoomed.push(
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::WHITE.alpha(0.4), epicenter);

View File

@ -40,7 +40,7 @@ impl DrawBuilding {
cs.sidewalk,
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);
}
@ -102,7 +102,7 @@ impl Renderable for DrawBuilding {
fn get_outline(&self, map: &Map) -> Polygon {
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
} else {
b.polygon.clone()

View File

@ -163,7 +163,9 @@ impl Renderable for DrawIntersection {
}
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 {

View File

@ -100,7 +100,7 @@ impl Renderable for DrawParkingLot {
fn get_outline(&self, map: &Map) -> Polygon {
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
} else {
pl.polygon.clone()

View File

@ -368,7 +368,7 @@ pub fn make_signal_diagram(
let mut hovered = GeomBatch::new();
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(
ctx,

View File

@ -266,7 +266,7 @@ fn contingency_table(ctx: &mut EventCtx, app: &App, filter: &Filter) -> Widget {
if num_savings > 0 {
let height = (total_savings / max_y) * max_bar_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);
}
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 rect =
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);
}
batch.push(Color::RED, rect.clone());

View File

@ -74,7 +74,7 @@ impl Circle {
if false {
let mut pts = Circle::new(center, radius).to_polygon().points().clone();
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.

View File

@ -3,6 +3,7 @@ use geo::algorithm::area::Area;
use geo::algorithm::convexhull::ConvexHull;
use geo_booleanop::boolean::BooleanOp;
use serde::{Deserialize, Serialize};
use std::error::Error;
use std::fmt;
#[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
// example.
pub fn to_outline(&self, thickness: Distance) -> Polygon {
Ring::new(self.points.clone()).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))
pub fn to_outline(&self, thickness: Distance) -> Result<Polygon, Box<dyn Error>> {
Ring::new(self.points.clone()).map(|r| r.make_polygons(thickness))
}
// Usually m^2, unless the polygon is in screen-space
@ -301,7 +298,7 @@ impl Polygon {
// Doesn't handle multiple crossings in and out.
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);
if hits.len() == 0 {

View File

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

View File

@ -12,39 +12,16 @@ pub struct Ring {
}
impl Ring {
pub fn new(pts: Vec<Pt2D>) -> Ring {
assert!(pts.len() >= 3);
assert_eq!(pts[0], *pts.last().unwrap());
// 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);
pub fn new(pts: Vec<Pt2D>) -> Result<Ring, Box<dyn Error>> {
if pts.len() < 3 {
return Err(format!("Can't make a ring with < 3 points").into());
}
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() {
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]) {
return None;
return Err(format!("Ring has ~dupe adjacent pts").into());
}
let result = Ring { pts };
@ -54,10 +31,13 @@ impl Ring {
seen_pts.insert(pt.to_hashable());
}
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 {
@ -137,7 +117,7 @@ impl Ring {
current.push(pt);
if intersections.contains(&pt.to_hashable()) && current.len() > 1 {
if current[0] == pt {
rings.push(Ring::new(current.drain(..).collect()));
rings.push(Ring::must_new(current.drain(..).collect()));
} else {
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.
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