@@ -180,19 +180,19 @@ impl Partitioning {
180180 p
181181 }
182182
183- // TODO Explain return value
184- pub fn transfer_block (
183+ /// Add all specified blocks to new_owner. `Ok(None)` is success. `Ok(Some(x))` is also
184+ /// success, but means the old neighbourhood of SOME block in `add_all` is now gone and
185+ /// replaced with something new. (This call shouldn't be used to remove multiple blocks at
186+ /// once, since interpreting the result is confusing!)
187+ pub fn transfer_blocks (
185188 & mut self ,
186189 map : & Map ,
187- add_block : BlockID ,
190+ add_all : Vec < BlockID > ,
188191 new_owner : NeighbourhoodID ,
189192 ) -> Result < Option < NeighbourhoodID > > {
190- let old_owner = self . block_to_neighbourhood ( add_block) ;
191- assert_ne ! ( old_owner, new_owner) ;
192-
193193 // Is the newly expanded neighbourhood a valid perimeter?
194194 let mut new_owner_blocks = self . neighbourhood_to_blocks ( new_owner) ;
195- new_owner_blocks. insert ( add_block ) ;
195+ new_owner_blocks. extend ( add_all . clone ( ) ) ;
196196 let mut new_neighbourhood_blocks = self . make_merged_blocks ( map, new_owner_blocks) ?;
197197 if new_neighbourhood_blocks. len ( ) != 1 {
198198 // This happens when a hole would be created by adding this block. There are probably
@@ -201,46 +201,53 @@ impl Partitioning {
201201 }
202202 let new_neighbourhood_block = new_neighbourhood_blocks. pop ( ) . unwrap ( ) ;
203203
204- // Is the old neighbourhood, minus this block, still valid?
205- // TODO refactor Neighbourhood to BlockIDs?
206- let mut old_owner_blocks = self . neighbourhood_to_blocks ( old_owner) ;
207- old_owner_blocks. remove ( & add_block) ;
208- if old_owner_blocks. is_empty ( ) {
209- // We're deleting the old neighbourhood!
210- self . neighbourhoods . get_mut ( & new_owner) . unwrap ( ) . block = new_neighbourhood_block;
211- self . neighbourhoods . remove ( & old_owner) . unwrap ( ) ;
212- self . block_to_neighbourhood . insert ( add_block, new_owner) ;
213- // Tell the caller to recreate this SelectBoundary state, switching to the neighbourhood
214- // we just donated to, since the old is now gone
215- return Ok ( Some ( new_owner) ) ;
216- }
204+ let old_owners: BTreeSet < NeighbourhoodID > = add_all
205+ . iter ( )
206+ . map ( |block| self . block_to_neighbourhood [ block] )
207+ . collect ( ) ;
208+ // Are each of the old neighbourhoods, minus any new blocks, still valid?
209+ let mut return_value = None ;
210+ for old_owner in old_owners {
211+ let mut old_owner_blocks = self . neighbourhood_to_blocks ( old_owner) ;
212+ for x in & add_all {
213+ old_owner_blocks. remove ( x) ;
214+ }
215+ if old_owner_blocks. is_empty ( ) {
216+ self . neighbourhoods . remove ( & old_owner) . unwrap ( ) ;
217+ return_value = Some ( new_owner) ;
218+ continue ;
219+ }
217220
218- let mut old_neighbourhood_blocks =
219- self . make_merged_blocks ( map, old_owner_blocks. clone ( ) ) ?;
220- // We might be splitting the old neighbourhood into multiple pieces! Pick the largest piece
221- // as the old_owner (so the UI for trimming a neighbourhood is less jarring), and create new
222- // neighbourhoods for the others.
223- old_neighbourhood_blocks. sort_by_key ( |block| block. perimeter . interior . len ( ) ) ;
224- self . neighbourhoods . get_mut ( & old_owner) . unwrap ( ) . block =
225- old_neighbourhood_blocks. pop ( ) . unwrap ( ) ;
226- let new_splits = !old_neighbourhood_blocks. is_empty ( ) ;
227- for split_piece in old_neighbourhood_blocks {
228- let new_neighbourhood = NeighbourhoodID ( self . neighbourhood_id_counter ) ;
229- self . neighbourhood_id_counter += 1 ;
230- self . neighbourhoods
231- . insert ( new_neighbourhood, NeighbourhoodInfo :: new ( split_piece) ) ;
232- }
233- if new_splits {
234- // We need to update the owner of all single blocks in these new pieces
235- for id in old_owner_blocks {
236- self . block_to_neighbourhood
237- . insert ( id, self . neighbourhood_containing ( id) . unwrap ( ) ) ;
221+ let mut old_neighbourhood_blocks =
222+ self . make_merged_blocks ( map, old_owner_blocks. clone ( ) ) ?;
223+ // We might be splitting the old neighbourhood into multiple pieces! Pick the largest piece
224+ // as the old_owner (so the UI for trimming a neighbourhood is less jarring), and create new
225+ // neighbourhoods for the others.
226+ old_neighbourhood_blocks. sort_by_key ( |block| block. perimeter . interior . len ( ) ) ;
227+ self . neighbourhoods . get_mut ( & old_owner) . unwrap ( ) . block =
228+ old_neighbourhood_blocks. pop ( ) . unwrap ( ) ;
229+ let new_splits = !old_neighbourhood_blocks. is_empty ( ) ;
230+ for split_piece in old_neighbourhood_blocks {
231+ let new_neighbourhood = NeighbourhoodID ( self . neighbourhood_id_counter ) ;
232+ self . neighbourhood_id_counter += 1 ;
233+ self . neighbourhoods
234+ . insert ( new_neighbourhood, NeighbourhoodInfo :: new ( split_piece) ) ;
235+ }
236+ if new_splits {
237+ // We need to update the owner of all single blocks in these new pieces
238+ for id in old_owner_blocks {
239+ self . block_to_neighbourhood
240+ . insert ( id, self . neighbourhood_containing ( id) . unwrap ( ) ) ;
241+ }
238242 }
239243 }
240244
245+ // Set up the newly expanded neighbourhood
241246 self . neighbourhoods . get_mut ( & new_owner) . unwrap ( ) . block = new_neighbourhood_block;
242- self . block_to_neighbourhood . insert ( add_block, new_owner) ;
243- Ok ( None )
247+ for id in add_all {
248+ self . block_to_neighbourhood . insert ( id, new_owner) ;
249+ }
250+ Ok ( return_value)
244251 }
245252
246253 /// Needs to find an existing neighbourhood to take the block, or make a new one
@@ -273,7 +280,7 @@ impl Partitioning {
273280 . iter ( )
274281 . find ( |( _, info) | info. block . perimeter . roads . contains ( & other_side) )
275282 {
276- return self . transfer_block ( map, id , * new_owner) ;
283+ return self . transfer_blocks ( map, vec ! [ id ] , * new_owner) ;
277284 }
278285 }
279286
@@ -285,7 +292,7 @@ impl Partitioning {
285292 new_owner,
286293 NeighbourhoodInfo :: new ( self . get_block ( id) . clone ( ) ) ,
287294 ) ;
288- let result = self . transfer_block ( map, id , new_owner) ;
295+ let result = self . transfer_blocks ( map, vec ! [ id ] , new_owner) ;
289296 if result. is_err ( ) {
290297 // Revert the change above!
291298 self . neighbourhoods . remove ( & new_owner) . unwrap ( ) ;
0 commit comments