#![allow(dead_code)]
use std::f32::consts::PI;
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct Circle {
pub center: [f32; 3],
pub radius: f32,
pub normal: [f32; 3],
pub color: [f32; 4],
pub segments: u32,
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct CircleBatch {
pub circles: Vec<Circle>,
}
#[allow(dead_code)]
pub fn new_circle(center: [f32; 3], radius: f32) -> Circle {
Circle {
center,
radius,
normal: [0.0, 1.0, 0.0],
color: [1.0, 1.0, 1.0, 1.0],
segments: 32,
}
}
#[allow(dead_code)]
pub fn generate_circle_vertices(circle: &Circle) -> Vec<[f32; 3]> {
let n = circle.segments.max(3);
let mut verts = Vec::with_capacity(n as usize);
for i in 0..n {
let angle = 2.0 * PI * (i as f32) / (n as f32);
verts.push([
circle.center[0] + circle.radius * angle.cos(),
circle.center[1],
circle.center[2] + circle.radius * angle.sin(),
]);
}
verts
}
#[allow(dead_code)]
pub fn new_circle_batch() -> CircleBatch {
CircleBatch { circles: Vec::new() }
}
#[allow(dead_code)]
pub fn add_circle(batch: &mut CircleBatch, circle: Circle) {
batch.circles.push(circle);
}
#[allow(dead_code)]
pub fn clear_circle_batch(batch: &mut CircleBatch) {
batch.circles.clear();
}
#[allow(dead_code)]
pub fn circle_count(batch: &CircleBatch) -> usize {
batch.circles.len()
}
#[allow(dead_code)]
pub fn circle_circumference(c: &Circle) -> f32 {
2.0 * PI * c.radius
}
#[allow(dead_code)]
pub fn circle_area(c: &Circle) -> f32 {
PI * c.radius * c.radius
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new_circle() {
let c = new_circle([0.0, 0.0, 0.0], 1.0);
assert!((c.radius - 1.0).abs() < 1e-6);
}
#[test]
fn test_generate_vertices() {
let c = new_circle([0.0, 0.0, 0.0], 1.0);
let verts = generate_circle_vertices(&c);
assert_eq!(verts.len(), 32);
}
#[test]
fn test_vertex_on_circle() {
let c = new_circle([0.0, 0.0, 0.0], 1.0);
let verts = generate_circle_vertices(&c);
let dist = (verts[0][0].powi(2) + verts[0][2].powi(2)).sqrt();
assert!((dist - 1.0).abs() < 1e-4);
}
#[test]
fn test_new_batch() {
let b = new_circle_batch();
assert!(b.circles.is_empty());
}
#[test]
fn test_add_circle() {
let mut b = new_circle_batch();
add_circle(&mut b, new_circle([0.0, 0.0, 0.0], 1.0));
assert_eq!(circle_count(&b), 1);
}
#[test]
fn test_clear() {
let mut b = new_circle_batch();
add_circle(&mut b, new_circle([0.0, 0.0, 0.0], 1.0));
clear_circle_batch(&mut b);
assert_eq!(circle_count(&b), 0);
}
#[test]
fn test_circumference() {
let c = new_circle([0.0, 0.0, 0.0], 1.0);
assert!((circle_circumference(&c) - 2.0 * PI).abs() < 1e-4);
}
#[test]
fn test_area() {
let c = new_circle([0.0, 0.0, 0.0], 1.0);
assert!((circle_area(&c) - PI).abs() < 1e-4);
}
#[test]
fn test_offset_center() {
let c = new_circle([1.0, 2.0, 3.0], 1.0);
let verts = generate_circle_vertices(&c);
for v in &verts {
let dx = v[0] - 1.0;
let dz = v[2] - 3.0;
let dist = (dx * dx + dz * dz).sqrt();
assert!((dist - 1.0).abs() < 1e-4);
}
}
#[test]
fn test_min_segments() {
let mut c = new_circle([0.0, 0.0, 0.0], 1.0);
c.segments = 1;
let verts = generate_circle_vertices(&c);
assert_eq!(verts.len(), 3);
}
}