first commit - hilbert 2d poly

This commit is contained in:
EvilMuffinHa 2022-06-16 17:10:32 -04:00
commit ac732863d3
4 changed files with 482 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target

331
Cargo.lock generated Normal file
View File

@ -0,0 +1,331 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "adler"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "adler32"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bytemuck"
version = "1.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdead85bdec19c194affaeeb670c0e41fe23de31459efd1c174d049269cf02cc"
[[package]]
name = "byteorder"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "color_quant"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
[[package]]
name = "crc32fast"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
dependencies = [
"cfg-if",
]
[[package]]
name = "crossbeam-channel"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53"
dependencies = [
"cfg-if",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e"
dependencies = [
"cfg-if",
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1145cf131a2c6ba0615079ab6a638f7e1973ac9c2634fcbeaaad6114246efe8c"
dependencies = [
"autocfg",
"cfg-if",
"crossbeam-utils",
"lazy_static",
"memoffset",
"scopeguard",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38"
dependencies = [
"cfg-if",
"lazy_static",
]
[[package]]
name = "deflate"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73770f8e1fe7d64df17ca66ad28994a0a623ea497fa69486e14984e715c5d174"
dependencies = [
"adler32",
"byteorder",
]
[[package]]
name = "either"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
[[package]]
name = "gif"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3a7187e78088aead22ceedeee99779455b23fc231fe13ec443f99bb71694e5b"
dependencies = [
"color_quant",
"weezl",
]
[[package]]
name = "hermit-abi"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
"libc",
]
[[package]]
name = "hilbert"
version = "0.1.0"
dependencies = [
"image",
]
[[package]]
name = "image"
version = "0.23.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24ffcb7e7244a9bf19d35bf2883b9c080c4ced3c07a9895572178cdb8f13f6a1"
dependencies = [
"bytemuck",
"byteorder",
"color_quant",
"gif",
"jpeg-decoder",
"num-iter",
"num-rational",
"num-traits",
"png",
"scoped_threadpool",
"tiff",
]
[[package]]
name = "jpeg-decoder"
version = "0.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "229d53d58899083193af11e15917b5640cd40b29ff475a1fe4ef725deb02d0f2"
dependencies = [
"rayon",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.126"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
[[package]]
name = "memoffset"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
dependencies = [
"autocfg",
]
[[package]]
name = "miniz_oxide"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435"
dependencies = [
"adler32",
]
[[package]]
name = "miniz_oxide"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b"
dependencies = [
"adler",
"autocfg",
]
[[package]]
name = "num-integer"
version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
dependencies = [
"autocfg",
"num-traits",
]
[[package]]
name = "num-iter"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-rational"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-traits"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
dependencies = [
"autocfg",
]
[[package]]
name = "num_cpus"
version = "1.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
dependencies = [
"hermit-abi",
"libc",
]
[[package]]
name = "png"
version = "0.16.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6"
dependencies = [
"bitflags",
"crc32fast",
"deflate",
"miniz_oxide 0.3.7",
]
[[package]]
name = "rayon"
version = "1.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d"
dependencies = [
"autocfg",
"crossbeam-deque",
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f"
dependencies = [
"crossbeam-channel",
"crossbeam-deque",
"crossbeam-utils",
"num_cpus",
]
[[package]]
name = "scoped_threadpool"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8"
[[package]]
name = "scopeguard"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "tiff"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a53f4706d65497df0c4349241deddf35f84cee19c87ed86ea8ca590f4464437"
dependencies = [
"jpeg-decoder",
"miniz_oxide 0.4.4",
"weezl",
]
[[package]]
name = "weezl"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c97e489d8f836838d497091de568cf16b117486d529ec5579233521065bd5e4"

9
Cargo.toml Normal file
View File

@ -0,0 +1,9 @@
[package]
name = "hilbert"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
image = "0.23.14"

141
src/main.rs Normal file
View File

@ -0,0 +1,141 @@
use image::{ImageBuffer, Rgb, RgbImage};
trait Distance<const N: usize> {
fn dist(&self, a: [f64; N], b: [f64; N]) -> Result<f64, &'static str>;
}
struct HilbertPoly {
vertices: Vec<[f64; 2]>
}
#[allow(dead_code)]
struct Euclidean<const N: usize>();
impl<const N: usize> Distance<N> for Euclidean<N> {
fn dist(&self, a: [f64; N], b: [f64; N]) -> Result<f64, &'static str> {
Ok(a.iter().zip(b.iter()).map(|x| (x.1 - x.0) * (x.1 - x.0)).sum::<f64>().sqrt())
}
}
#[allow(dead_code)]
struct Manhattan<const N: usize>();
impl<const N: usize> Distance<N> for Manhattan<N> {
fn dist(&self, a: [f64; N], b: [f64; N]) -> Result<f64, &'static str> {
Ok(a.iter().zip(b.iter()).map(|x| f64::abs(x.1 - x.0)).sum::<f64>())
}
}
impl<const N: usize> Distance<N> for HilbertPoly {
fn dist(&self, a: [f64; N], b: [f64; N]) -> Result<f64, &'static str> {
// 2d Hilbert Convex Polygon, 3d is slightly different as it will be to a side (edge of
// convex set )
if N != 2 {
return Err("Dim != 2");
};
// Get edges.
let mut edges = self.vertices.windows(2).map(|x| [x[0], x[1]]).collect::<Vec<[[f64; 2]; 2]>>();
edges.push([self.vertices[0], self.vertices[self.vertices.len() - 1]]);
// Assert that the Hilbert convex set is convex.
let mut prev = 0.0;
let mut curr;
for i in 0..N {
let edge_one = edges[i];
let edge_two = edges[(i + 1) % N];
curr = (edge_one[1][0] - edge_one[0][0]) * (edge_two[1][1] - edge_one[0][1]) -
(edge_one[1][1] - edge_one[0][1]) * (edge_two[1][0] - edge_one[0][0]);
if curr != 0.0 {
if curr * prev < 0.0 {
return Err("Not convex.");
} else {
prev = curr;
}
}
}
// Check if points are both inside the set
let (mut i, mut j, mut c) = (0, self.vertices.len() - 1, false);
loop {
if i >= self.vertices.len() {
break;
}
if ((self.vertices[i][1] > a[1]) != (self.vertices[j][1] > a[1])) && (a[0] < (self.vertices[j][0] - self.vertices[i][0]) * (a[1] - self.vertices[i][1]) / (self.vertices[j][1] - self.vertices[i][1]) + self.vertices[i][0]) {
c = !c;
}
j = i;
i += 1;
}
if !c {
return Err("First point not in set.");
}
let (mut i, mut j, mut c) = (0, self.vertices.len() - 1, false);
loop {
if i >= self.vertices.len() {
break;
}
if ((self.vertices[i][1] > b[1]) != (self.vertices[j][1] > b[1])) && (b[0] < (self.vertices[j][0] - self.vertices[i][0]) * (b[1] - self.vertices[i][1]) / (self.vertices[j][1] - self.vertices[i][1]) + self.vertices[i][0]) {
c = !c;
}
j = i;
i += 1;
}
if !c {
return Err("Second point not in set.");
}
// Intersect the line with each polygon side
let slope = (b[1] - a[1]) / (b[0] - a[0]);
let p_intersect = edges.into_iter().map(|p| {
let edge_slope = (p[1][1] - p[0][1]) / (p[1][0] - p[0][0]);
let d = edge_slope - slope;
if d == 0.0 {
None
} else {
Some([((edge_slope * p[0][0] - p[0][1]) - (slope * a[0] - a[1])) / d, ((slope * (edge_slope * p[0][0] - p[0][1])) - (edge_slope * (slope * a[0] - a[1]))) / d])
}
}).filter(|x| x.is_some()).map(|x| x.map_or([0.0, 0.0], |x| x)).collect::<Vec<[f64; 2]>>();
// Find the closest distance
let a_closest = p_intersect.clone().into_iter().map(|p| (p, (p[0] - a[0]) * (p[0] - a[0]) + (p[1] - a[1]) * (p[1] - a[1]))).min_by(|a, b| a.1.partial_cmp(&b.1).unwrap()).unwrap();
let b_closest = p_intersect.into_iter().map(|p| (p, (p[0] - b[0]) * (p[0] - b[0]) + (p[1] - b[1]) * (p[1] - b[1]))).min_by(|a, b| a.1.partial_cmp(&b.1).unwrap()).unwrap();
let pb = f64::sqrt((a_closest.0[0] - b[0]) * (a_closest.0[0] - b[0]) + (a_closest.0[1] - b[1]) * (a_closest.0[1] - b[1]));
let pa = f64::sqrt(a_closest.1);
let aq = f64::sqrt((b_closest.0[0] - a[0]) * (b_closest.0[0] - a[0]) + (b_closest.0[1] - a[1]) * (b_closest.0[1] - a[1]));
let bq = f64::sqrt(b_closest.1);
Ok(f64::ln((pb * aq) / (pa * bq)))
}
}
fn naive_voronoi_2d(metric: &mut dyn Distance<2>, w: u32, h: u32, points: Vec<(u32, u32)>) {
let mut image: RgbImage = ImageBuffer::new(w, h);
// All points must be in the width / height
for p in points {
assert!(p.0 <= w);
assert!(p.1 <= h);
}
for i in 0..w {
for j in 0..h {
}
}
}
fn main() {
let triangle = HilbertPoly { vertices: vec![[-8.0, 0.0], [8.0, 0.0], [0.0, 8.0]] };
println!("{}", triangle.dist([-2.0, 2.0], [2.0, 2.0]).unwrap());
}