From 6db7c73ff08d913b91ab257bf9a3b24f5decc0b1 Mon Sep 17 00:00:00 2001
From: random-geek <35757396+random-geek@users.noreply.github.com>
Date: Tue, 9 Mar 2021 00:14:54 -0800
Subject: [PATCH] Turn area functions into methods
---
src/commands/clone.rs | 12 ++--
src/commands/fill.rs | 6 +-
src/commands/overlay.rs | 18 +++--
src/commands/replace_nodes.rs | 10 ++-
src/commands/set_param2.rs | 6 +-
src/spatial/area.rs | 96 +++++++++++++++++++++++++-
src/spatial/mod.rs | 125 ----------------------------------
src/spatial/vec3.rs | 12 ++++
8 files changed, 129 insertions(+), 156 deletions(-)
diff --git a/src/commands/clone.rs b/src/commands/clone.rs
index 3903b84..fb81094 100644
--- a/src/commands/clone.rs
+++ b/src/commands/clone.rs
@@ -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");
diff --git a/src/commands/fill.rs b/src/commands/fill.rs
index 57a0ba9..54e9ef0 100644
--- a/src/commands/fill.rs
+++ b/src/commands/fill.rs
@@ -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());
diff --git a/src/commands/overlay.rs b/src/commands/overlay.rs
index c8713b0..231ab05 100644
--- a/src/commands/overlay.rs
+++ b/src/commands/overlay.rs
@@ -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);
diff --git a/src/commands/replace_nodes.rs b/src/commands/replace_nodes.rs
index 5d88f89..dcd660a 100644
--- a/src/commands/replace_nodes.rs
+++ b/src/commands/replace_nodes.rs
@@ -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)
diff --git a/src/commands/set_param2.rs b/src/commands/set_param2.rs
index 0ab1c3f..fcd1305 100644
--- a/src/commands/set_param2.rs
+++ b/src/commands/set_param2.rs
@@ -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);
diff --git a/src/spatial/area.rs b/src/spatial/area.rs
index 8b13b08..bc23242 100644
--- a/src/spatial/area.rs
+++ b/src/spatial/area.rs
@@ -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 {
+ 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 {
+ 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 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);
+ }
+ }
}
diff --git a/src/spatial/mod.rs b/src/spatial/mod.rs
index 3b7fe2b..1bb1ee4 100644
--- a/src/spatial/mod.rs
+++ b/src/spatial/mod.rs
@@ -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 {
- 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 {
- 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);
- }
- }
-}
diff --git a/src/spatial/vec3.rs b/src/spatial/vec3.rs
index 59f98b5..e0252cc 100644
--- a/src/spatial/vec3.rs
+++ b/src/spatial/vec3.rs
@@ -99,6 +99,18 @@ impl std::ops::Sub for Vec3 {
}
}
+impl std::ops::Sub 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 for Vec3 {
type Output = Self;