fn apply_edits(&mut self, mut new_edits: MapEdits, enforce_valid: bool) -> EditEffects {
        let mut effects = EditEffects {
            changed_roads: BTreeSet::new(),
            deleted_lanes: BTreeSet::new(),
            changed_intersections: BTreeSet::new(),
            added_turns: BTreeSet::new(),
            deleted_turns: BTreeSet::new(),
            changed_parking_lots: BTreeSet::new(),
        };

        // Short-circuit to avoid marking pathfinder_dirty
        if self.edits == new_edits {
            return effects;
        }

        // We need to undo() all of the current commands in reverse order, then apply() all of the
        // new commands. But in many cases, new_edits is just the current edits with a few commands
        // at the end. So a simple optimization with equivalent behavior is to skip the common
        // prefix of commands.
        let mut start_at_idx = 0;
        for (cmd1, cmd2) in self.edits.commands.iter().zip(new_edits.commands.iter()) {
            if cmd1 == cmd2 {
                start_at_idx += 1;
            } else {
                break;
            }
        }

        // Undo existing edits
        for _ in start_at_idx..self.edits.commands.len() {
            self.edits
                .commands
                .pop()
                .unwrap()
                .undo()
                .apply(&mut effects, self);
        }

        // Apply new edits.
        for cmd in &new_edits.commands[start_at_idx..] {
            cmd.apply(&mut effects, self);
        }

        // Might need to update bus stops.
        if enforce_valid {
            for id in &effects.changed_roads {
                let stops = self.get_r(*id).all_bus_stops(self);
                for s in stops {
                    let sidewalk_pos = self.get_bs(s).sidewalk_pos;
                    // Must exist, because we aren't allowed to orphan a bus stop.
                    let driving_lane = self
                        .get_r(*id)
                        .find_closest_lane(
                            sidewalk_pos.lane(),
                            |l| PathConstraints::Bus.can_use(l, self),
                            self,
                        )
                        .unwrap();
                    let driving_pos = sidewalk_pos.equiv_pos(driving_lane, self);
                    self.bus_stops.get_mut(&s).unwrap().driving_pos = driving_pos;
                }
            }
        }

        let merge_zones_changed = self.edits.merge_zones != new_edits.merge_zones;

        new_edits.update_derived(self);
        self.edits = new_edits;
        self.pathfinder_dirty = true;

        // Update zones after setting the new edits, since it'll pull merge_zones from there
        if !effects.changed_roads.is_empty() || merge_zones_changed {
            self.zones = Zone::make_all(self);
        }

        // Some of these might've been added, then later deleted.
        effects
            .added_turns
            .retain(|t| self.maybe_get_t(*t).is_some());

        let mut more_changed_intersections = Vec::new();
        for t in effects
            .deleted_turns
            .iter()
            .chain(effects.added_turns.iter())
        {
            more_changed_intersections.push(t.parent);
        }
        effects
            .changed_intersections
            .extend(more_changed_intersections);

        self.recalculate_road_to_buildings();

        effects
    }
// new_edits don't necessarily have to be valid; this could be used for speculatively testing
// edits. Doesn't update pathfinding yet.
new_edits don't necessarily have to be valid; this could be used for speculatively testing
edits. Doesn't update pathfinding yet.
new_edits don ' t necessarily have to be valid ; this could be used for speculatively testing edits . Doesn ' t update pathfinding yet .
fn apply_edits(&mut self, mut new_edits: MapEdits, enforce_valid: bool) -> EditEffects {
        let mut effects = EditEffects {
            changed_roads: BTreeSet::new(),
            deleted_lanes: BTreeSet::new(),
            changed_intersections: BTreeSet::new(),
            added_turns: BTreeSet::new(),
            deleted_turns: BTreeSet::new(),
            changed_parking_lots: BTreeSet::new(),
        };
        // Short-circuit to avoid marking pathfinder_dirty
        if self.edits == new_edits {
            return effects;
        }
        // We need to undo() all of the current commands in reverse order, then apply() all of the
        // new commands. But in many cases, new_edits is just the current edits with a few commands
        // at the end. So a simple optimization with equivalent behavior is to skip the common
        // prefix of commands.
        let mut start_at_idx = 0;
        for (cmd1, cmd2) in self.edits.commands.iter().zip(new_edits.commands.iter()) {
            if cmd1 == cmd2 {
                start_at_idx += 1;
            } else {
                break;
            }
        }
        // Undo existing edits
        for _ in start_at_idx..self.edits.commands.len() {
            self.edits
                .commands
                .pop()
                .unwrap()
                .undo()
                .apply(&mut effects, self);
        }
        // Apply new edits.
        for cmd in &new_edits.commands[start_at_idx..] {
            cmd.apply(&mut effects, self);
        }
        // Might need to update bus stops.
        if enforce_valid {
            for id in &effects.changed_roads {
                let stops = self.get_r(*id).all_bus_stops(self);
                for s in stops {
                    let sidewalk_pos = self.get_bs(s).sidewalk_pos;
                    // Must exist, because we aren't allowed to orphan a bus stop.
                    let driving_lane = self
                        .get_r(*id)
                        .find_closest_lane(
                            sidewalk_pos.lane(),
                            |l| PathConstraints::Bus.can_use(l, self),
                            self,
                        )
                        .unwrap();
                    let driving_pos = sidewalk_pos.equiv_pos(driving_lane, self);
                    self.bus_stops.get_mut(&s).unwrap().driving_pos = driving_pos;
                }
            }
        }
        let merge_zones_changed = self.edits.merge_zones != new_edits.merge_zones;
        new_edits.update_derived(self);
        self.edits = new_edits;
        self.pathfinder_dirty = true;
        // Update zones after setting the new edits, since it'll pull merge_zones from there
        if !effects.changed_roads.is_empty() || merge_zones_changed {
            self.zones = Zone::make_all(self);
        }
        // Some of these might've been added, then later deleted.
        effects
            .added_turns
            .retain(|t| self.maybe_get_t(*t).is_some());
        let mut more_changed_intersections = Vec::new();
        for t in effects
            .deleted_turns
            .iter()
            .chain(effects.added_turns.iter())
        {
            more_changed_intersections.push(t.parent);
        }
        effects
            .changed_intersections
            .extend(more_changed_intersections);
        self.recalculate_road_to_buildings();
        effects
    }
fn apply_edits ( & mut self , mut new_edits : MapEdits , enforce_valid : bool ) -> EditEffects { let mut effects = EditEffects { changed_roads : BTreeSet :: new ( ) , deleted_lanes : BTreeSet :: new ( ) , changed_intersections : BTreeSet :: new ( ) , added_turns : BTreeSet :: new ( ) , deleted_turns : BTreeSet :: new ( ) , changed_parking_lots : BTreeSet :: new ( ) , } ; // Short-circuit to avoid marking pathfinder_dirty if self . edits == new_edits { return effects ; } // We need to undo() all of the current commands in reverse order, then apply() all of the // new commands. But in many cases, new_edits is just the current edits with a few commands // at the end. So a simple optimization with equivalent behavior is to skip the common // prefix of commands. let mut start_at_idx = 0 ; for ( cmd1 , cmd2 ) in self . edits . commands . iter ( ) . zip ( new_edits . commands . iter ( ) ) { if cmd1 == cmd2 { start_at_idx += 1 ; } else { break ; } } // Undo existing edits for _ in start_at_idx .. self . edits . commands . len ( ) { self . edits . commands . pop ( ) . unwrap ( ) . undo ( ) . apply ( & mut effects , self ) ; } // Apply new edits. for cmd in & new_edits . commands [ start_at_idx .. ] { cmd . apply ( & mut effects , self ) ; } // Might need to update bus stops. if enforce_valid { for id in & effects . changed_roads { let stops = self . get_r ( * id ) . all_bus_stops ( self ) ; for s in stops { let sidewalk_pos = self . get_bs ( s ) . sidewalk_pos ; // Must exist, because we aren't allowed to orphan a bus stop. let driving_lane = self . get_r ( * id ) . find_closest_lane ( sidewalk_pos . lane ( ) , | l | PathConstraints :: Bus . can_use ( l , self ) , self , ) . unwrap ( ) ; let driving_pos = sidewalk_pos . equiv_pos ( driving_lane , self ) ; self . bus_stops . get_mut ( & s ) . unwrap ( ) . driving_pos = driving_pos ; } } } let merge_zones_changed = self . edits . merge_zones != new_edits . merge_zones ; new_edits . update_derived ( self ) ; self . edits = new_edits ; self . pathfinder_dirty = true ; // Update zones after setting the new edits, since it'll pull merge_zones from there if ! effects . changed_roads . is_empty ( ) || merge_zones_changed { self . zones = Zone :: make_all ( self ) ; } // Some of these might've been added, then later deleted. effects . added_turns . retain ( | t | self . maybe_get_t ( * t ) . is_some ( ) ) ; let mut more_changed_intersections = Vec :: new ( ) ; for t in effects . deleted_turns . iter ( ) . chain ( effects . added_turns . iter ( ) ) { more_changed_intersections . push ( t . parent ) ; } effects . changed_intersections . extend ( more_changed_intersections ) ; self . recalculate_road_to_buildings ( ) ; effects }
new_edits don't necessarily have to be valid; this could be used for speculatively testing
edits.
new_edits don ' t necessarily have to be valid ; this could be used for speculatively testing edits .
&mut self
new_edits
MapEdits
enforce_valid
bool