mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-24 23:15:24 +03:00
Speed up the select boundary UI by caching single blocks
This commit is contained in:
parent
c18cc762bb
commit
e2621c40f4
@ -25,7 +25,8 @@ impl widgetry::mapspace::ObjectID for NeighborhoodID {}
|
||||
#[derive(Clone)]
|
||||
pub struct Partitioning {
|
||||
pub neighborhoods: BTreeMap<NeighborhoodID, (Block, Color)>,
|
||||
// TODO Stash the single blocks here -- they never change
|
||||
// The single / unmerged blocks never change
|
||||
pub single_blocks: Vec<Block>,
|
||||
}
|
||||
|
||||
impl Partitioning {
|
||||
@ -33,19 +34,25 @@ impl Partitioning {
|
||||
pub fn empty() -> Partitioning {
|
||||
Partitioning {
|
||||
neighborhoods: BTreeMap::new(),
|
||||
single_blocks: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn seed_using_heuristics(app: &App, timer: &mut Timer) -> Partitioning {
|
||||
let map = &app.primary.map;
|
||||
timer.start("find single blocks");
|
||||
let mut single_blocks = Perimeter::find_all_single_blocks(map);
|
||||
// TODO Ew! Expensive! But the merged neighborhoods differ widely from blockfinder if we don't.
|
||||
single_blocks.retain(|x| x.clone().to_block(map).is_ok());
|
||||
let mut single_blocks = Vec::new();
|
||||
let mut single_block_perims = Vec::new();
|
||||
for perim in Perimeter::find_all_single_blocks(map) {
|
||||
if let Ok(block) = perim.to_block(map) {
|
||||
single_block_perims.push(block.perimeter.clone());
|
||||
single_blocks.push(block);
|
||||
}
|
||||
}
|
||||
timer.stop("find single blocks");
|
||||
|
||||
timer.start("partition");
|
||||
let partitions = Perimeter::partition_by_predicate(single_blocks, |r| {
|
||||
let partitions = Perimeter::partition_by_predicate(single_block_perims, |r| {
|
||||
// "Interior" roads of a neighborhood aren't classified as arterial
|
||||
map.get_r(r).get_rank() == RoadRank::Local
|
||||
});
|
||||
@ -81,7 +88,10 @@ impl Partitioning {
|
||||
let color = COLORS[color_idx % COLORS.len()];
|
||||
neighborhoods.insert(NeighborhoodID(neighborhoods.len()), (block, color));
|
||||
}
|
||||
Partitioning { neighborhoods }
|
||||
Partitioning {
|
||||
neighborhoods,
|
||||
single_blocks,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn neighborhood_containing(&self, find_block: &Block) -> Option<NeighborhoodID> {
|
||||
|
@ -55,49 +55,28 @@ impl SelectBoundary {
|
||||
orig_partitioning: app.session.partitioning.clone(),
|
||||
};
|
||||
|
||||
ctx.loading_screen("calculate all blocks", |ctx, timer| {
|
||||
timer.start("find single blocks");
|
||||
let perimeters = Perimeter::find_all_single_blocks(&app.primary.map);
|
||||
timer.stop("find single blocks");
|
||||
|
||||
let mut blocks = Vec::new();
|
||||
timer.start_iter("blockify", perimeters.len());
|
||||
for perimeter in perimeters {
|
||||
timer.next();
|
||||
match perimeter.to_block(&app.primary.map) {
|
||||
Ok(block) => {
|
||||
blocks.push(block);
|
||||
}
|
||||
Err(err) => {
|
||||
warn!("Failed to make a block from a perimeter: {}", err);
|
||||
}
|
||||
}
|
||||
for (idx, block) in app.session.partitioning.single_blocks.iter().enumerate() {
|
||||
let id = BlockID(idx);
|
||||
if let Some(neighborhood) = app.session.partitioning.neighborhood_containing(block) {
|
||||
state.block_to_neighborhood.insert(id, neighborhood);
|
||||
} else {
|
||||
// TODO What happened?
|
||||
error!(
|
||||
"Block doesn't belong to any neighborhood?! {:?}",
|
||||
block.perimeter
|
||||
);
|
||||
}
|
||||
|
||||
for (idx, block) in blocks.into_iter().enumerate() {
|
||||
let id = BlockID(idx);
|
||||
if let Some(neighborhood) = app.session.partitioning.neighborhood_containing(&block)
|
||||
{
|
||||
state.block_to_neighborhood.insert(id, neighborhood);
|
||||
} else {
|
||||
// TODO What happened?
|
||||
error!(
|
||||
"Block doesn't belong to any neighborhood?! {:?}",
|
||||
block.perimeter
|
||||
);
|
||||
}
|
||||
if initial_boundary.contains(&block.perimeter) {
|
||||
state.selected.insert(id);
|
||||
}
|
||||
state.blocks.insert(id, block);
|
||||
if initial_boundary.contains(&block.perimeter) {
|
||||
state.selected.insert(id);
|
||||
}
|
||||
state.frontier = calculate_frontier(&initial_boundary, &state.blocks);
|
||||
state.blocks.insert(id, block.clone());
|
||||
}
|
||||
state.frontier = calculate_frontier(&initial_boundary, &state.blocks);
|
||||
|
||||
// Fill out the world initially
|
||||
for id in state.blocks.keys().cloned().collect::<Vec<_>>() {
|
||||
state.add_block(ctx, app, id);
|
||||
}
|
||||
});
|
||||
// Fill out the world initially
|
||||
for id in state.blocks.keys().cloned().collect::<Vec<_>>() {
|
||||
state.add_block(ctx, app, id);
|
||||
}
|
||||
|
||||
state.redraw_outline(ctx, app, initial_boundary);
|
||||
state.world.initialize_hover(ctx);
|
||||
|
Loading…
Reference in New Issue
Block a user