Turn area functions into methods
This commit is contained in:
parent
98cec33c81
commit
6db7c73ff0
@ -1,8 +1,7 @@
|
||||
use super::{Command, BLOCK_CACHE_SIZE};
|
||||
|
||||
use crate::{unwrap_or, opt_unwrap_or};
|
||||
use crate::spatial::{Vec3, area_rel_block_overlap,
|
||||
area_abs_block_overlap};
|
||||
use crate::spatial::Vec3;
|
||||
use crate::map_database::MapDatabase;
|
||||
use crate::map_block::{MapBlock, MapBlockError, is_valid_generated,
|
||||
NodeMetadataList, NodeMetadataListExt};
|
||||
@ -68,8 +67,7 @@ fn clone(inst: &mut InstBundle) {
|
||||
);
|
||||
|
||||
let dst_pos = Vec3::from_block_key(dst_key);
|
||||
let dst_part_abs = area_abs_block_overlap(&dst_area, dst_pos)
|
||||
.unwrap();
|
||||
let dst_part_abs = dst_area.abs_block_overlap(dst_pos).unwrap();
|
||||
let src_part_abs = dst_part_abs - offset;
|
||||
let src_blocks_needed = src_part_abs.to_touching_block_area();
|
||||
|
||||
@ -89,11 +87,11 @@ fn clone(inst: &mut InstBundle) {
|
||||
continue
|
||||
);
|
||||
|
||||
let src_frag_abs = area_abs_block_overlap(&src_part_abs, src_pos)
|
||||
let src_frag_abs = src_part_abs.abs_block_overlap(src_pos)
|
||||
.unwrap();
|
||||
let src_frag_rel = src_frag_abs - src_pos * 16;
|
||||
let dst_frag_rel = area_rel_block_overlap(
|
||||
&(src_frag_abs + offset), dst_pos).unwrap();
|
||||
let dst_frag_rel = (src_frag_abs + offset)
|
||||
.rel_block_overlap(dst_pos).unwrap();
|
||||
|
||||
{
|
||||
let _t = tk.get_timer("merge");
|
||||
|
@ -1,7 +1,7 @@
|
||||
use super::Command;
|
||||
|
||||
use crate::unwrap_or;
|
||||
use crate::spatial::{Vec3, Area, area_rel_block_overlap, area_contains_block};
|
||||
use crate::spatial::{Vec3, Area};
|
||||
use crate::instance::{ArgType, InstBundle};
|
||||
use crate::map_block::MapBlock;
|
||||
use crate::block_utils::clean_name_id_map;
|
||||
@ -42,7 +42,7 @@ fn fill(inst: &mut InstBundle) {
|
||||
continue;
|
||||
});
|
||||
|
||||
if area_contains_block(&area, pos) {
|
||||
if area.contains_block(pos) {
|
||||
let nd = block.node_data.get_mut();
|
||||
for x in &mut nd.nodes {
|
||||
*x = 0;
|
||||
@ -51,7 +51,7 @@ fn fill(inst: &mut InstBundle) {
|
||||
block.nimap.0.insert(0, node.to_vec());
|
||||
count += nd.nodes.len() as u64;
|
||||
} else {
|
||||
let slice = area_rel_block_overlap(&area, pos).unwrap();
|
||||
let slice = area.rel_block_overlap(pos).unwrap();
|
||||
let fill_id = block.nimap.get_id(&node).unwrap_or_else(|| {
|
||||
let next = block.nimap.get_max_id().unwrap() + 1;
|
||||
block.nimap.0.insert(next, node.to_vec());
|
||||
|
@ -1,8 +1,7 @@
|
||||
use super::{Command, BLOCK_CACHE_SIZE};
|
||||
|
||||
use crate::{unwrap_or, opt_unwrap_or};
|
||||
use crate::spatial::{Vec3, Area, area_rel_block_overlap,
|
||||
area_abs_block_overlap, area_contains_block, area_touches_block};
|
||||
use crate::spatial::{Vec3, Area};
|
||||
use crate::instance::{ArgType, InstArgs, InstBundle};
|
||||
use crate::map_database::MapDatabase;
|
||||
use crate::map_block::{MapBlock, MapBlockError, is_valid_generated,
|
||||
@ -44,8 +43,8 @@ fn overlay_no_offset(inst: &mut InstBundle) {
|
||||
if let Some(area) = inst.args.area {
|
||||
let pos = Vec3::from_block_key(key);
|
||||
|
||||
if (!invert && area_contains_block(&area, pos))
|
||||
|| (invert && !area_touches_block(&area, pos))
|
||||
if (!invert && area.contains_block(pos))
|
||||
|| (invert && !area.touches_block(pos))
|
||||
{ // If possible, copy whole map block.
|
||||
let data = idb.get_block(key).unwrap();
|
||||
if is_valid_generated(&data) {
|
||||
@ -66,8 +65,7 @@ fn overlay_no_offset(inst: &mut InstBundle) {
|
||||
let mut dst_meta = NodeMetadataList::deserialize(
|
||||
&dst_block.metadata.get_ref())?;
|
||||
|
||||
let block_part = area_rel_block_overlap(&area, pos)
|
||||
.unwrap();
|
||||
let block_part = area.rel_block_overlap(pos).unwrap();
|
||||
if invert {
|
||||
// For inverted selections, reverse the order of the
|
||||
// overlay operations.
|
||||
@ -157,7 +155,7 @@ fn overlay_with_offset(inst: &mut InstBundle) {
|
||||
|
||||
let dst_part_abs = dst_area.map_or(
|
||||
Area::new(dst_pos * 16, dst_pos * 16 + 15),
|
||||
|ref a| area_abs_block_overlap(a, dst_pos).unwrap()
|
||||
|ref a| a.abs_block_overlap(dst_pos).unwrap()
|
||||
);
|
||||
let src_part_abs = dst_part_abs - offset;
|
||||
let src_blocks_needed = src_part_abs.to_touching_block_area();
|
||||
@ -177,11 +175,11 @@ fn overlay_with_offset(inst: &mut InstBundle) {
|
||||
continue
|
||||
);
|
||||
|
||||
let src_frag_abs = area_abs_block_overlap(&src_part_abs, src_pos)
|
||||
let src_frag_abs = src_part_abs.abs_block_overlap(src_pos)
|
||||
.unwrap();
|
||||
let src_frag_rel = src_frag_abs - src_pos * 16;
|
||||
let dst_frag_rel = area_rel_block_overlap(
|
||||
&(src_frag_abs + offset), dst_pos).unwrap();
|
||||
let dst_frag_rel = (src_frag_abs + offset)
|
||||
.rel_block_overlap(dst_pos).unwrap();
|
||||
|
||||
merge_blocks(&src_block, &mut dst_block,
|
||||
src_frag_rel, dst_frag_rel);
|
||||
|
@ -1,7 +1,6 @@
|
||||
use super::Command;
|
||||
|
||||
use crate::spatial::{Vec3, Area, area_contains_block, area_touches_block,
|
||||
area_rel_block_overlap};
|
||||
use crate::spatial::{Vec3, Area};
|
||||
use crate::instance::{ArgType, InstArgs, InstBundle};
|
||||
use crate::map_block::MapBlock;
|
||||
use crate::time_keeper::TimeKeeper;
|
||||
@ -22,12 +21,11 @@ fn do_replace(
|
||||
let mut count = 0;
|
||||
|
||||
// Replace nodes in a portion of a map block.
|
||||
if area.is_some() && area_contains_block(&area.unwrap(), block_pos) !=
|
||||
area_touches_block(&area.unwrap(), block_pos)
|
||||
if area.is_some() && area.unwrap().contains_block(block_pos) !=
|
||||
area.unwrap().touches_block(block_pos)
|
||||
{
|
||||
let _t = tk.get_timer("replace (partial block)");
|
||||
let node_area = area_rel_block_overlap(&area.unwrap(), block_pos)
|
||||
.unwrap();
|
||||
let node_area = area.unwrap().rel_block_overlap(block_pos).unwrap();
|
||||
|
||||
let mut new_replace_id = false;
|
||||
let replace_id = block.nimap.get_id(new_node)
|
||||
|
@ -1,6 +1,6 @@
|
||||
use super::Command;
|
||||
|
||||
use crate::spatial::{Vec3, Area, area_rel_block_overlap, area_contains_block};
|
||||
use crate::spatial::{Vec3, Area};
|
||||
use crate::instance::{ArgType, InstArgs, InstBundle};
|
||||
use crate::map_block::MapBlock;
|
||||
use crate::utils::{query_keys, to_bytes, to_slice, fmt_big_num};
|
||||
@ -66,9 +66,9 @@ fn set_param2(inst: &mut InstBundle) {
|
||||
|
||||
let nd = block.node_data.get_mut();
|
||||
if let Some(area) = inst.args.area
|
||||
.filter(|a| !area_contains_block(&a, pos))
|
||||
.filter(|a| !a.contains_block(pos))
|
||||
{ // Modify part of block
|
||||
let overlap = area_rel_block_overlap(&area, pos).unwrap();
|
||||
let overlap = area.rel_block_overlap(pos).unwrap();
|
||||
if let Some(nid) = node_id {
|
||||
count +=
|
||||
set_in_area_node(&mut block, overlap, nid, param2_val);
|
||||
|
@ -69,6 +69,10 @@ impl Area {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn iterate(&self) -> AreaIterator {
|
||||
AreaIterator::new(self.min, self.max)
|
||||
}
|
||||
|
||||
pub fn volume(&self) -> u64 {
|
||||
(self.max.x - self.min.x + 1) as u64 *
|
||||
(self.max.y - self.min.y + 1) as u64 *
|
||||
@ -81,8 +85,18 @@ impl Area {
|
||||
&& self.min.z <= pos.z && pos.z <= self.max.z
|
||||
}
|
||||
|
||||
pub fn iterate(&self) -> AreaIterator {
|
||||
AreaIterator::new(self.min, self.max)
|
||||
pub fn contains_block(&self, block_pos: Vec3) -> bool {
|
||||
let corner = block_pos * 16;
|
||||
self.min.x <= corner.x && corner.x + 15 <= self.max.x
|
||||
&& self.min.y <= corner.y && corner.y + 15 <= self.max.y
|
||||
&& self.min.z <= corner.z && corner.z + 15 <= self.max.z
|
||||
}
|
||||
|
||||
pub fn touches_block(&self, block_pos: Vec3) -> bool {
|
||||
let corner = block_pos * 16;
|
||||
self.min.x <= corner.x + 15 && corner.x <= self.max.x
|
||||
&& self.min.y <= corner.y + 15 && corner.y <= self.max.y
|
||||
&& self.min.z <= corner.z + 15 && corner.z <= self.max.z
|
||||
}
|
||||
|
||||
pub fn to_contained_block_area(&self) -> Self {
|
||||
@ -112,6 +126,55 @@ impl Area {
|
||||
);
|
||||
Self {min, max}
|
||||
}
|
||||
|
||||
pub fn abs_block_overlap(&self, block_pos: Vec3) -> Option<Area> {
|
||||
let block_min = block_pos * 16;
|
||||
let block_max = block_min + 15;
|
||||
let node_min = Vec3 {
|
||||
x: max(self.min.x, block_min.x),
|
||||
y: max(self.min.y, block_min.y),
|
||||
z: max(self.min.z, block_min.z)
|
||||
};
|
||||
let node_max = Vec3 {
|
||||
x: min(self.max.x, block_max.x),
|
||||
y: min(self.max.y, block_max.y),
|
||||
z: min(self.max.z, block_max.z)
|
||||
};
|
||||
|
||||
if node_min.x <= node_max.x
|
||||
&& node_min.y <= node_max.y
|
||||
&& node_min.z <= node_max.z
|
||||
{
|
||||
Some(Self {min: node_min, max: node_max})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rel_block_overlap(&self, block_pos: Vec3) -> Option<Area> {
|
||||
let corner = block_pos * 16;
|
||||
let rel_min = self.min - corner;
|
||||
let rel_max = self.max - corner;
|
||||
let node_min = Vec3 {
|
||||
x: max(rel_min.x, 0),
|
||||
y: max(rel_min.y, 0),
|
||||
z: max(rel_min.z, 0)
|
||||
};
|
||||
let node_max = Vec3 {
|
||||
x: min(rel_max.x, 15),
|
||||
y: min(rel_max.y, 15),
|
||||
z: min(rel_max.z, 15)
|
||||
};
|
||||
|
||||
if node_min.x <= node_max.x
|
||||
&& node_min.y <= node_max.y
|
||||
&& node_min.z <= node_max.z
|
||||
{
|
||||
Some(Self {min: node_min, max: node_max})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Add<Vec3> for Area {
|
||||
@ -175,4 +238,33 @@ mod tests {
|
||||
iter_area(Area::new(Vec3::new(10, -99, 11), Vec3::new(10, -99, 12)));
|
||||
iter_area(Area::new(Vec3::new(0, -1, -2), Vec3::new(5, 7, 11)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_area_containment() {
|
||||
let area = Area::new(Vec3::new(-1, -32, 16), Vec3::new(30, -17, 54));
|
||||
let contained = Area::new(Vec3::new(0, -2, 1), Vec3::new(0, -2, 2));
|
||||
let touching = Area::new(Vec3::new(-1, -2, 1), Vec3::new(1, -2, 3));
|
||||
|
||||
for pos in Area::new(touching.min - 2, touching.max + 2).iterate() {
|
||||
assert_eq!(area.touches_block(pos), touching.contains(pos));
|
||||
assert_eq!(area.contains_block(pos), contained.contains(pos));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_area_block_overlap() {
|
||||
let area = Area::new(Vec3::new(-3, -3, -3), Vec3::new(15, 15, 15));
|
||||
let pairs = vec![
|
||||
(Vec3::new(-1, -1, -1),
|
||||
Some(Area::new(Vec3::new(13, 13, 13), Vec3::new(15, 15, 15)))),
|
||||
(Vec3::new(0, 0, 0),
|
||||
Some(Area::new(Vec3::new(0, 0, 0), Vec3::new(15, 15, 15)))),
|
||||
(Vec3::new(1, 1, 1), None),
|
||||
(Vec3::new(-1, 0, 0),
|
||||
Some(Area::new(Vec3::new(13, 0, 0), Vec3::new(15, 15, 15)))),
|
||||
];
|
||||
for pair in pairs {
|
||||
assert_eq!(area.rel_block_overlap(pair.0), pair.1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,130 +1,5 @@
|
||||
use std::cmp::{min, max};
|
||||
|
||||
mod vec3;
|
||||
mod area;
|
||||
|
||||
pub use vec3::Vec3;
|
||||
pub use area::Area;
|
||||
|
||||
|
||||
// TODO: Should these go in the area impl?
|
||||
pub fn area_contains_block(area: &Area, block_pos: Vec3) -> bool {
|
||||
let corner = block_pos * 16;
|
||||
area.min.x <= corner.x && corner.x + 15 <= area.max.x
|
||||
&& area.min.y <= corner.y && corner.y + 15 <= area.max.y
|
||||
&& area.min.z <= corner.z && corner.z + 15 <= area.max.z
|
||||
}
|
||||
|
||||
|
||||
pub fn area_touches_block(area: &Area, block_pos: Vec3) -> bool {
|
||||
let corner = block_pos * 16;
|
||||
area.min.x <= corner.x + 15 && corner.x <= area.max.x
|
||||
&& area.min.y <= corner.y + 15 && corner.y <= area.max.y
|
||||
&& area.min.z <= corner.z + 15 && corner.z <= area.max.z
|
||||
}
|
||||
|
||||
|
||||
pub fn area_abs_block_overlap(area: &Area, block_pos: Vec3) -> Option<Area> {
|
||||
let block_min = block_pos * 16;
|
||||
let block_max = block_min + 15;
|
||||
let node_min = Vec3 {
|
||||
x: max(area.min.x, block_min.x),
|
||||
y: max(area.min.y, block_min.y),
|
||||
z: max(area.min.z, block_min.z)
|
||||
};
|
||||
let node_max = Vec3 {
|
||||
x: min(area.max.x, block_max.x),
|
||||
y: min(area.max.y, block_max.y),
|
||||
z: min(area.max.z, block_max.z)
|
||||
};
|
||||
|
||||
if node_min.x <= node_max.x
|
||||
&& node_min.y <= node_max.y
|
||||
&& node_min.z <= node_max.z
|
||||
{
|
||||
Some(Area {min: node_min, max: node_max})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn area_rel_block_overlap(area: &Area, block_pos: Vec3) -> Option<Area> {
|
||||
let corner = block_pos * 16;
|
||||
let rel_min = area.min - corner;
|
||||
let rel_max = area.max - corner;
|
||||
let node_min = Vec3 {
|
||||
x: max(rel_min.x, 0),
|
||||
y: max(rel_min.y, 0),
|
||||
z: max(rel_min.z, 0)
|
||||
};
|
||||
let node_max = Vec3 {
|
||||
x: min(rel_max.x, 15),
|
||||
y: min(rel_max.y, 15),
|
||||
z: min(rel_max.z, 15)
|
||||
};
|
||||
|
||||
if node_min.x <= node_max.x
|
||||
&& node_min.y <= node_max.y
|
||||
&& node_min.z <= node_max.z
|
||||
{
|
||||
Some(Area {min: node_min, max: node_max})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_area_containment() {
|
||||
let area = Area::new(Vec3::new(-1, -32, 16), Vec3::new(30, -17, 54));
|
||||
let test_blocks = vec![
|
||||
// Fully contained
|
||||
(Vec3::new(0, -2, 1), true, true),
|
||||
(Vec3::new(0, -2, 2), true, true),
|
||||
// Partially contained
|
||||
(Vec3::new(-1, -2, 1), true, false),
|
||||
(Vec3::new(-1, -2, 2), true, false),
|
||||
(Vec3::new(-1, -2, 3), true, false),
|
||||
(Vec3::new(0, -2, 3), true, false),
|
||||
(Vec3::new(1, -2, 3), true, false),
|
||||
(Vec3::new(1, -2, 3), true, false),
|
||||
(Vec3::new(1, -2, 2), true, false),
|
||||
(Vec3::new(1, -2, 1), true, false),
|
||||
// Not contained
|
||||
(Vec3::new(-1, -2, 0), false, false),
|
||||
(Vec3::new(0, -2, 0), false, false),
|
||||
(Vec3::new(1, -2, 0), false, false),
|
||||
(Vec3::new(2, -2, 0), false, false),
|
||||
(Vec3::new(2, -2, 1), false, false),
|
||||
(Vec3::new(2, -2, 2), false, false),
|
||||
(Vec3::new(2, -2, 3), false, false),
|
||||
];
|
||||
|
||||
for (pos, touches, contains) in test_blocks {
|
||||
assert_eq!(area_touches_block(&area, pos), touches);
|
||||
assert_eq!(area_contains_block(&area, pos), contains);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_area_block_overlap() {
|
||||
let area = Area::new(Vec3::new(-3, -3, -3), Vec3::new(15, 15, 15));
|
||||
let pairs = vec![
|
||||
(Vec3::new(-1, -1, -1),
|
||||
Some(Area::new(Vec3::new(13, 13, 13), Vec3::new(15, 15, 15)))),
|
||||
(Vec3::new(0, 0, 0),
|
||||
Some(Area::new(Vec3::new(0, 0, 0), Vec3::new(15, 15, 15)))),
|
||||
(Vec3::new(1, 1, 1), None),
|
||||
(Vec3::new(-1, 0, 0),
|
||||
Some(Area::new(Vec3::new(13, 0, 0), Vec3::new(15, 15, 15)))),
|
||||
];
|
||||
for pair in pairs {
|
||||
assert_eq!(area_rel_block_overlap(&area, pair.0), pair.1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -99,6 +99,18 @@ impl std::ops::Sub<Self> for Vec3 {
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Sub<i32> for Vec3 {
|
||||
type Output = Self;
|
||||
|
||||
fn sub(self, rhs: i32) -> Self {
|
||||
Self {
|
||||
x: self.x - rhs,
|
||||
y: self.y - rhs,
|
||||
z: self.z - rhs
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Mul<Self> for Vec3 {
|
||||
type Output = Self;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user