Add centering of layouts.
This commit is contained in:
parent
b79d0dffb6
commit
907691685c
3 changed files with 101 additions and 17 deletions
|
|
@ -1,5 +1,6 @@
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
/// The size field is in block space
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub struct Block {
|
pub struct Block {
|
||||||
pos: Position,
|
pos: Position,
|
||||||
|
|
@ -42,7 +43,7 @@ impl Block {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn world_to_block(&self) -> Transformation {
|
pub fn world_to_block(&self) -> Transformation {
|
||||||
todo!()
|
self.block_to_world().invert()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn block_to_world(&self) -> Transformation {
|
pub fn block_to_world(&self) -> Transformation {
|
||||||
|
|
@ -50,6 +51,12 @@ impl Block {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Transformable for Block {
|
||||||
|
fn transform(&self, t: Transformation) -> Self {
|
||||||
|
Self::new(self.pos.transform(t), self.dir.transform(t), self.size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
@ -64,8 +71,23 @@ mod test {
|
||||||
|
|
||||||
let p = Position::new(3, 2);
|
let p = Position::new(3, 2);
|
||||||
|
|
||||||
dbg!(p.transform(t));
|
let m = p.transform(t);
|
||||||
|
|
||||||
assert!(false);
|
assert_eq!(m, Position::new(8, 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn identity_transformation() {
|
||||||
|
let b = Block::new(Position::new(10, 5), Direction::Right, Position::new(4, 3));
|
||||||
|
|
||||||
|
let t = b.world_to_block();
|
||||||
|
|
||||||
|
let n = b.transform(t);
|
||||||
|
|
||||||
|
dbg!(t, n);
|
||||||
|
|
||||||
|
assert_eq!(n.dir, Direction::Up);
|
||||||
|
assert_eq!(n.pos, Position::new(0, 0));
|
||||||
|
assert_eq!(n.size, Position::new(4, 3));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,18 +15,30 @@ impl Transformation {
|
||||||
Self { rot, pos }
|
Self { rot, pos }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn transform_position(&self, pos: &Position) -> Position {
|
|
||||||
(match self.rot {
|
|
||||||
Direction::Up => *pos,
|
|
||||||
Direction::Right => Position::new(-pos.y, pos.x),
|
|
||||||
Direction::Down => Position::new(-pos.x, -pos.y),
|
|
||||||
Direction::Left => Position::new(pos.y, -pos.x),
|
|
||||||
}) + self.pos
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn rot(&self) -> Direction {
|
pub fn rot(&self) -> Direction {
|
||||||
self.rot
|
self.rot
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn invert(self) -> Self {
|
||||||
|
Self::new(
|
||||||
|
match self.rot {
|
||||||
|
Direction::Up => Direction::Up,
|
||||||
|
Direction::Right => Direction::Left,
|
||||||
|
Direction::Down => Direction::Down,
|
||||||
|
Direction::Left => Direction::Right,
|
||||||
|
},
|
||||||
|
match self.rot {
|
||||||
|
Direction::Up => Position::new(-self.pos.x, -self.pos.y),
|
||||||
|
Direction::Right => Position::new(-self.pos.y, self.pos.x),
|
||||||
|
Direction::Down => self.pos,
|
||||||
|
Direction::Left => Position::new(self.pos.y, -self.pos.x),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn chain(self, other: Self) -> Self {
|
||||||
|
Self::new(self.rot.transform(other), self.pos.transform(other))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Transformable for Position {
|
impl Transformable for Position {
|
||||||
|
|
@ -43,7 +55,7 @@ impl Transformable for Position {
|
||||||
impl Transformable for Direction {
|
impl Transformable for Direction {
|
||||||
fn transform(&self, t: Transformation) -> Self {
|
fn transform(&self, t: Transformation) -> Self {
|
||||||
match (t.rot, self) {
|
match (t.rot, self) {
|
||||||
(Direction::Up, _) => Direction::Up,
|
(Direction::Up, _) => *self,
|
||||||
(Direction::Right, Direction::Up) => Direction::Right,
|
(Direction::Right, Direction::Up) => Direction::Right,
|
||||||
(Direction::Right, Direction::Right) => Direction::Down,
|
(Direction::Right, Direction::Right) => Direction::Down,
|
||||||
(Direction::Right, Direction::Down) => Direction::Left,
|
(Direction::Right, Direction::Down) => Direction::Left,
|
||||||
|
|
@ -69,9 +81,34 @@ mod test {
|
||||||
let p = Position::new(3, 5);
|
let p = Position::new(3, 5);
|
||||||
|
|
||||||
let t = Transformation::new(Direction::Up, Position::new(-3, -5));
|
let t = Transformation::new(Direction::Up, Position::new(-3, -5));
|
||||||
assert_eq!(t.transform_position(&p), Position::new(0, 0));
|
assert_eq!(p.transform(t), Position::new(0, 0));
|
||||||
|
|
||||||
let t = Transformation::new(Direction::Down, Position::new(-3, -5));
|
let t = Transformation::new(Direction::Down, Position::new(-3, -5));
|
||||||
assert_eq!(t.transform_position(&p), Position::new(-6, -10));
|
assert_eq!(p.transform(t), Position::new(-6, -10));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn invert() {
|
||||||
|
let transformations = [
|
||||||
|
Transformation::new(Direction::Up, Position::new(-3, -5)),
|
||||||
|
Transformation::new(Direction::Right, Position::new(-3, -5)),
|
||||||
|
Transformation::new(Direction::Down, Position::new(-3, -5)),
|
||||||
|
Transformation::new(Direction::Left, Position::new(-3, -5)),
|
||||||
|
];
|
||||||
|
|
||||||
|
for o in transformations {
|
||||||
|
let i = o.invert();
|
||||||
|
let c = o.chain(i);
|
||||||
|
|
||||||
|
assert_eq!(c.rot, Direction::Up, "o: {:?}, i: {:?}, c: {:?}", o, i, c);
|
||||||
|
assert_eq!(
|
||||||
|
c.pos,
|
||||||
|
Position::new(0, 0),
|
||||||
|
"o: {:?}, i: {:?}, c: {:?}",
|
||||||
|
o,
|
||||||
|
i,
|
||||||
|
c
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -325,7 +325,9 @@ impl Layout<'_> {
|
||||||
|
|
||||||
assert!(Self::place_block(problem, &mut blocks, rng));
|
assert!(Self::place_block(problem, &mut blocks, rng));
|
||||||
|
|
||||||
Layout { problem, blocks }
|
let mut l = Layout { problem, blocks };
|
||||||
|
l.center();
|
||||||
|
l
|
||||||
}
|
}
|
||||||
|
|
||||||
fn place_block<R: Rng + ?Sized>(
|
fn place_block<R: Rng + ?Sized>(
|
||||||
|
|
@ -381,6 +383,28 @@ impl Layout<'_> {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_aabb(&self) -> AABB {
|
||||||
|
self.blocks
|
||||||
|
.iter()
|
||||||
|
.map(|b| b.get_aabb())
|
||||||
|
.reduce(AABB::combine)
|
||||||
|
.expect("At least one block is required.")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn center(&mut self) {
|
||||||
|
let aabb = self.get_aabb();
|
||||||
|
|
||||||
|
let rest = self.problem.size - aabb.size();
|
||||||
|
|
||||||
|
let new_min = Position::new(rest.x / 2, rest.y / 2);
|
||||||
|
|
||||||
|
let t = Transformation::new(Direction::Up, new_min - aabb.min());
|
||||||
|
|
||||||
|
for b in &mut self.blocks {
|
||||||
|
*b = b.transform(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Mutate existing layout, creating a valid layout
|
/// Mutate existing layout, creating a valid layout
|
||||||
pub fn mutate<R: Rng + ?Sized>(&self, rng: &mut R) -> Self {
|
pub fn mutate<R: Rng + ?Sized>(&self, rng: &mut R) -> Self {
|
||||||
let mut s = self.clone();
|
let mut s = self.clone();
|
||||||
|
|
@ -395,11 +419,12 @@ impl Layout<'_> {
|
||||||
loop {
|
loop {
|
||||||
let p = r.choose_weighted(rng, |i| i.1).unwrap();
|
let p = r.choose_weighted(rng, |i| i.1).unwrap();
|
||||||
|
|
||||||
if p.0(&mut s, rng) && rng.gen_bool(0.05) {
|
if p.0(&mut s, rng) && rng.gen_bool(0.2) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s.center();
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue