Skip to content

Commit e55a940

Browse files
committed
cleanup
1 parent 229a752 commit e55a940

File tree

5 files changed

+115
-71
lines changed

5 files changed

+115
-71
lines changed

navpointmatrixcli/Cargo.toml

+3
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,6 @@ clap = { workspace = true }
99
log = { workspace = true }
1010
pathfinding = { workspace = true }
1111
geo = "0.29.3"
12+
13+
[dev-dependencies]
14+
regex = "1.11.1"

navpointmatrixcli/src/cli.rs

+11-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1+
use clap::{Args, Parser, Subcommand, ValueEnum};
12
use std::path::PathBuf;
23

3-
use clap::{Args, Parser, Subcommand};
4-
54
/// Patrician 3 navpoint matrix calculation
65
#[derive(Parser, Debug)]
76
#[command(version, about, long_about = None)]
@@ -54,7 +53,17 @@ pub struct ConnectedNodesFromNavigationDataArgs {
5453
#[arg(long = "navigation-vector", value_name = "navigation-vector-file")]
5554
pub navigation_vector_file: PathBuf,
5655

56+
/// F
57+
#[arg(long = "calculation-mode", value_name = "calculation-mode")]
58+
pub mode: ConnectedNodesMode,
59+
5760
/// Path to the output connected nodes file
5861
#[arg(long = "output", value_name = "output-file")]
5962
pub output_file: PathBuf,
6063
}
64+
65+
#[derive(Debug, Clone, Copy, ValueEnum)]
66+
pub enum ConnectedNodesMode {
67+
BresenhamLine,
68+
//P3,
69+
}

navpointmatrixcli/src/connected_nodes.rs

+100-11
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
use p3_api::data::{navigation_matrix::NavigationMatrix, navigation_vector::NavigationVector, navpoint_matrix::NavpointMatrix};
22

3+
use crate::cli::ConnectedNodesMode;
4+
5+
#[derive(Debug, Clone)]
36
pub struct ConnectedNodes {
47
pub connected_nodes: Vec<(u16, u16)>,
58
}
@@ -37,12 +40,12 @@ impl ConnectedNodes {
3740
neighbours
3841
}
3942

40-
pub fn from_navigation_matrix(navigation_vector: &NavigationVector, navigation_matrix: &NavigationMatrix) -> Self {
43+
pub fn from_navigation_matrix_p3(navigation_vector: &NavigationVector, navigation_matrix: &NavigationMatrix, mode: ConnectedNodesMode) -> Self {
4144
let mut nodes = vec![];
4245
for (source_index, source) in navigation_vector.points.iter().enumerate() {
4346
println!("Calculating neighbours for node {source_index}");
4447
for (destination_index, destination) in navigation_vector.points.iter().enumerate() {
45-
if is_connected(*source, *destination, navigation_matrix) {
48+
if is_connected(*source, *destination, navigation_matrix, mode) {
4649
nodes.push((source_index as _, destination_index as _))
4750
}
4851
}
@@ -66,23 +69,32 @@ impl ConnectedNodes {
6669
}
6770
}
6871

69-
fn is_connected(p0: (i16, i16), p1: (i16, i16), navigation_matrix: &NavigationMatrix) -> bool {
72+
fn is_connected(p0: (i16, i16), p1: (i16, i16), navigation_matrix: &NavigationMatrix, mode: ConnectedNodesMode) -> bool {
7073
if p0 == p1 {
7174
return true;
7275
}
7376

74-
// Bresenham's Line Algorithm
75-
let (mut x0, mut y0) = p0;
76-
let (x1, y1) = p1;
77+
let line = match mode {
78+
ConnectedNodesMode::BresenhamLine => get_bresenham_line(p0.0, p0.1, p1.0, p0.1),
79+
//ConnectedNodesMode::P3 => get_p3_line(p0.0, p0.1, p1.0, p0.1),
80+
};
81+
for point in line {
82+
if navigation_matrix.data[point.0 as usize + navigation_matrix.width as usize * point.1 as usize] == 1 {
83+
return false;
84+
}
85+
}
86+
true
87+
}
88+
89+
pub fn get_bresenham_line(mut x0: i16, mut y0: i16, x1: i16, y1: i16) -> Vec<(i16, i16)> {
90+
let mut path = Vec::with_capacity(42);
7791
let dx = (x1 - x0).abs();
7892
let sx = if x0 < x1 { 1 } else { -1 };
79-
let dy = -(y1 - y0).abs();
93+
let dy = -((y1 - y0).abs());
8094
let sy = if y0 < y1 { 1 } else { -1 };
8195
let mut error = dx + dy;
8296
loop {
83-
if navigation_matrix.data[x0 as usize + navigation_matrix.width as usize * y0 as usize] == 1 {
84-
return false;
85-
}
97+
path.push((x0, y0));
8698
let e2 = 2 * error;
8799
if e2 >= dy {
88100
if x0 == x1 {
@@ -99,6 +111,83 @@ fn is_connected(p0: (i16, i16), p1: (i16, i16), navigation_matrix: &NavigationMa
99111
y0 += sy;
100112
}
101113
}
114+
path
115+
}
116+
117+
pub fn get_p3_line(mut x0: i16, mut y0: i16, x1: i16, y1: i16) -> Vec<(i16, i16)> {
118+
let mut path = Vec::with_capacity(42);
119+
path.push((x0, y0));
120+
let dx_abs = (x1 - x0).abs();
121+
let dy_abs = (y1 - y0).abs();
122+
let sx = if x0 < x1 { 1 } else { -1 };
123+
let sy = if y0 < y1 { 1 } else { -1 };
124+
125+
let mut diff = dx_abs;
126+
let steps = dx_abs;
127+
for _ in 0..steps {
128+
// 0x0044477A
129+
x0 += sx; // Apply x step
130+
diff += 2 * dy_abs; // Add 2*dy to diff
131+
if diff >= 2 * dx_abs {
132+
// 0x00444784
133+
diff -= 2 * dx_abs;
134+
if diff == 0 {
135+
path.push((x0, y0));
136+
y0 += sy;
137+
} else {
138+
y0 += sy;
139+
path.push((x0, y0));
140+
}
141+
} else {
142+
// 0x00444793
143+
path.push((x0, y0));
144+
}
145+
}
146+
147+
path
148+
}
149+
150+
#[cfg(test)]
151+
mod tests {
152+
use std::{
153+
fs,
154+
path::{Path, PathBuf},
155+
};
156+
157+
use regex::Regex;
102158

103-
navigation_matrix.data[x0 as usize + navigation_matrix.width as usize * y0 as usize] == 0
159+
use super::*;
160+
161+
#[test]
162+
fn it_works() {
163+
test_file(&PathBuf::from("tests/lines/line1.txt"));
164+
test_file(&PathBuf::from("tests/lines/line2.txt"));
165+
test_file(&PathBuf::from("tests/lines/line3.txt"));
166+
}
167+
168+
fn test_file(path: &Path) {
169+
let data = fs::read_to_string(path).unwrap();
170+
let mut lines: Vec<&str> = data.split("\n").collect();
171+
let header = lines.remove(0);
172+
let header_re = Regex::new(r"^\((\d+)\, (\d+)\) -> \((\d+)\, (\d+)\)").unwrap();
173+
let line_re = Regex::new(r"^\((\d+)\, (\d+)\)").unwrap();
174+
let header_captures = header_re.captures(header).unwrap();
175+
let x0: i16 = header_captures.get(1).unwrap().as_str().parse().unwrap();
176+
let y0: i16 = header_captures.get(2).unwrap().as_str().parse().unwrap();
177+
let x1: i16 = header_captures.get(3).unwrap().as_str().parse().unwrap();
178+
let y1: i16 = header_captures.get(4).unwrap().as_str().parse().unwrap();
179+
180+
let mut calculated_line = get_p3_line(x1, y1, x0, y0);
181+
calculated_line.remove(0);
182+
calculated_line.pop();
183+
println!("{calculated_line:?}");
184+
for (i, line) in lines.iter().enumerate() {
185+
let line_captures = line_re.captures(line).unwrap();
186+
let x: i16 = line_captures.get(1).unwrap().as_str().parse().unwrap();
187+
let y: i16 = line_captures.get(2).unwrap().as_str().parse().unwrap();
188+
println!("({}, {})", calculated_line[i].0, calculated_line[i].1);
189+
assert_eq!(x, calculated_line[i].0);
190+
assert_eq!(y, calculated_line[i].1);
191+
}
192+
}
104193
}

navpointmatrixcli/src/main.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ use std::{
1010

1111
pub(crate) mod cli;
1212
pub(crate) mod connected_nodes;
13-
pub(crate) mod ordered_f32;
1413

1514
fn main() {
1615
let cli = Cli::parse();
@@ -53,7 +52,7 @@ fn build_connected_nodes_from_navpoint_matrix(args: ConnectedNodesFromNavpointMa
5352
fn build_connected_nodes_from_navigation_data(args: ConnectedNodesFromNavigationDataArgs) {
5453
let navigation_matrix = NavigationMatrix::deserialize(&fs::read(args.navigation_matrix_file).unwrap());
5554
let navigation_vector = NavigationVector::deserialize(&fs::read(args.navigation_vector_file).unwrap());
56-
let connected_nodes = ConnectedNodes::from_navigation_matrix(&navigation_vector, &navigation_matrix);
55+
let connected_nodes = ConnectedNodes::from_navigation_matrix_p3(&navigation_vector, &navigation_matrix, args.mode);
5756
fs::write(args.output_file, connected_nodes.serialize()).unwrap();
5857
}
5958

navpointmatrixcli/src/ordered_f32.rs

-56
This file was deleted.

0 commit comments

Comments
 (0)