Choose swap lanes by motion direction
This commit is contained in:
parent
b109cdf6f2
commit
a712786ecf
2 changed files with 69 additions and 3 deletions
|
|
@ -217,6 +217,9 @@ Preferred approach:
|
||||||
Current pure planner status:
|
Current pure planner status:
|
||||||
|
|
||||||
- Two-window same-axis swaps use shrink lanes, move, then grow.
|
- Two-window same-axis swaps use shrink lanes, move, then grow.
|
||||||
|
- Swap lane choice follows motion direction, not node identity: right/down
|
||||||
|
moving windows take the first lane, and left/up moving windows take the second
|
||||||
|
lane.
|
||||||
- Stack extraction/return patterns are covered in both horizontal and vertical
|
- Stack extraction/return patterns are covered in both horizontal and vertical
|
||||||
orientations: peer/container space scales first, the extracted child moves
|
orientations: peer/container space scales first, the extracted child moves
|
||||||
only after space exists, and orthogonal growth happens in the final phase.
|
only after space exists, and orthogonal growth happens in the final phase.
|
||||||
|
|
|
||||||
|
|
@ -173,7 +173,12 @@ fn plan_axis_crossing_lanes(
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut windows = request.windows.clone();
|
let mut windows = request.windows.clone();
|
||||||
windows.sort_by_key(|window| window.node_id.0);
|
windows.sort_by_key(|window| lane_index_for_direction(*window, axis));
|
||||||
|
if windows.windows(2).any(|pair| {
|
||||||
|
lane_index_for_direction(pair[0], axis) == lane_index_for_direction(pair[1], axis)
|
||||||
|
}) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
let mut phase1 = vec![];
|
let mut phase1 = vec![];
|
||||||
let mut phase2 = vec![];
|
let mut phase2 = vec![];
|
||||||
let mut phase3 = vec![];
|
let mut phase3 = vec![];
|
||||||
|
|
@ -205,6 +210,15 @@ fn plan_axis_crossing_lanes(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn lane_index_for_direction(window: MultiphaseWindow, axis: PhaseAxis) -> Option<usize> {
|
||||||
|
let delta = main_start(window.to, axis) - main_start(window.from, axis);
|
||||||
|
match delta.cmp(&0) {
|
||||||
|
std::cmp::Ordering::Greater => Some(0),
|
||||||
|
std::cmp::Ordering::Less => Some(1),
|
||||||
|
std::cmp::Ordering::Equal => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn plan_space_then_orthogonal_growth(
|
fn plan_space_then_orthogonal_growth(
|
||||||
request: &MultiphaseRequest,
|
request: &MultiphaseRequest,
|
||||||
axis: PhaseAxis,
|
axis: PhaseAxis,
|
||||||
|
|
@ -627,6 +641,15 @@ mod tests {
|
||||||
plan.phases.iter().map(|phase| phase.action).collect()
|
plan.phases.iter().map(|phase| phase.action).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn step_to(plan: &MultiphasePlan, phase: usize, node_id: NodeId) -> Rect {
|
||||||
|
plan.phases[phase]
|
||||||
|
.steps
|
||||||
|
.iter()
|
||||||
|
.find(|step| step.node_id == node_id)
|
||||||
|
.unwrap()
|
||||||
|
.to
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn horizontal_swap_shrinks_moves_then_grows_without_overlap() {
|
fn horizontal_swap_shrinks_moves_then_grows_without_overlap() {
|
||||||
let req = request(vec![
|
let req = request(vec![
|
||||||
|
|
@ -679,8 +702,48 @@ mod tests {
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
let plan = plan_no_overlap(&req).unwrap();
|
let plan = plan_no_overlap(&req).unwrap();
|
||||||
assert_eq!(plan.phases[0].steps[0].to, rect(100, 0, 200, 50));
|
assert_eq!(step_to(&plan, 0, id(2)), rect(0, 0, 100, 50));
|
||||||
assert_eq!(plan.phases[0].steps[1].to, rect(0, 50, 100, 100));
|
assert_eq!(step_to(&plan, 0, id(1)), rect(100, 50, 200, 100));
|
||||||
|
assert!(validate_plan_continuous(&req, &plan));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn horizontal_swap_lanes_follow_motion_direction_not_node_id() {
|
||||||
|
let req = request(vec![
|
||||||
|
MultiphaseWindow {
|
||||||
|
node_id: id(1),
|
||||||
|
from: rect(100, 0, 200, 100),
|
||||||
|
to: rect(0, 0, 100, 100),
|
||||||
|
},
|
||||||
|
MultiphaseWindow {
|
||||||
|
node_id: id(2),
|
||||||
|
from: rect(0, 0, 100, 100),
|
||||||
|
to: rect(100, 0, 200, 100),
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
let plan = plan_no_overlap(&req).unwrap();
|
||||||
|
assert_eq!(step_to(&plan, 0, id(2)), rect(0, 0, 100, 50));
|
||||||
|
assert_eq!(step_to(&plan, 0, id(1)), rect(100, 50, 200, 100));
|
||||||
|
assert!(validate_plan_continuous(&req, &plan));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn vertical_swap_lanes_follow_motion_direction_not_node_id() {
|
||||||
|
let req = request(vec![
|
||||||
|
MultiphaseWindow {
|
||||||
|
node_id: id(1),
|
||||||
|
from: rect(0, 100, 100, 200),
|
||||||
|
to: rect(0, 0, 100, 100),
|
||||||
|
},
|
||||||
|
MultiphaseWindow {
|
||||||
|
node_id: id(2),
|
||||||
|
from: rect(0, 0, 100, 100),
|
||||||
|
to: rect(0, 100, 100, 200),
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
let plan = plan_no_overlap(&req).unwrap();
|
||||||
|
assert_eq!(step_to(&plan, 0, id(2)), rect(0, 0, 50, 100));
|
||||||
|
assert_eq!(step_to(&plan, 0, id(1)), rect(50, 100, 100, 200));
|
||||||
assert!(validate_plan_continuous(&req, &plan));
|
assert!(validate_plan_continuous(&req, &plan));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue