WIP
Signed-off-by: Frank Villaro-Dixon <frank@villaro-dixon.eu>
This commit is contained in:
parent
6b3a2cfbfc
commit
f5d307e5bc
6 changed files with 231 additions and 75 deletions
25
Cargo.lock
generated
25
Cargo.lock
generated
|
@ -71,12 +71,14 @@ name = "beonew-5"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"evdev",
|
"evdev",
|
||||||
|
"evdev-rs",
|
||||||
"femtovg",
|
"femtovg",
|
||||||
"gilrs",
|
"gilrs",
|
||||||
"glutin",
|
"glutin",
|
||||||
"glutin-winit",
|
"glutin-winit",
|
||||||
"image",
|
"image",
|
||||||
"instant",
|
"instant",
|
||||||
|
"nix 0.28.0",
|
||||||
"raw-window-handle",
|
"raw-window-handle",
|
||||||
"resource",
|
"resource",
|
||||||
"winit",
|
"winit",
|
||||||
|
@ -284,6 +286,29 @@ dependencies = [
|
||||||
"thiserror",
|
"thiserror",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "evdev-rs"
|
||||||
|
version = "0.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9812d5790fb6fcce449333eb6713dad335e8c979225ed98755c84a3987e06dba"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"evdev-sys",
|
||||||
|
"libc",
|
||||||
|
"log",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "evdev-sys"
|
||||||
|
version = "0.2.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "14ead42b547b15d47089c1243d907bcf0eb94e457046d3b315a26ac9c9e9ea6d"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"libc",
|
||||||
|
"pkg-config",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fdeflate"
|
name = "fdeflate"
|
||||||
version = "0.3.4"
|
version = "0.3.4"
|
||||||
|
|
|
@ -18,3 +18,5 @@ image = { version = "0.24.0", default-features = false, features = [
|
||||||
"jpeg",
|
"jpeg",
|
||||||
"png",
|
"png",
|
||||||
] }
|
] }
|
||||||
|
evdev-rs = "0.6.1"
|
||||||
|
nix = { version = "0.28.0", features = ["fs"] }
|
||||||
|
|
|
@ -22,10 +22,9 @@ mod perf_graph;
|
||||||
pub use perf_graph::PerfGraph;
|
pub use perf_graph::PerfGraph;
|
||||||
|
|
||||||
pub fn start(
|
pub fn start(
|
||||||
#[cfg(not(target_arch = "wasm32"))] width: u32,
|
width: u32,
|
||||||
#[cfg(not(target_arch = "wasm32"))] height: u32,
|
height: u32,
|
||||||
#[cfg(not(target_arch = "wasm32"))] title: &'static str,
|
title: &'static str,
|
||||||
#[cfg(not(target_arch = "wasm32"))] resizeable: bool,
|
|
||||||
) {
|
) {
|
||||||
// This provides better error messages in debug mode.
|
// This provides better error messages in debug mode.
|
||||||
// It's disabled in release mode so it doesn't bloat up the file size.
|
// It's disabled in release mode so it doesn't bloat up the file size.
|
||||||
|
@ -34,11 +33,10 @@ pub fn start(
|
||||||
|
|
||||||
let event_loop = EventLoop::new();
|
let event_loop = EventLoop::new();
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
|
||||||
let (canvas, window, context, surface) = {
|
let (canvas, window, context, surface) = {
|
||||||
let window_builder = WindowBuilder::new()
|
let window_builder = WindowBuilder::new()
|
||||||
.with_inner_size(winit::dpi::PhysicalSize::new(width, height))
|
.with_inner_size(winit::dpi::PhysicalSize::new(width, height))
|
||||||
.with_resizable(resizeable)
|
.with_resizable(false)
|
||||||
.with_title(title);
|
.with_title(title);
|
||||||
|
|
||||||
let template = ConfigTemplateBuilder::new().with_alpha_size(8);
|
let template = ConfigTemplateBuilder::new().with_alpha_size(8);
|
||||||
|
@ -116,39 +114,11 @@ pub fn start(
|
||||||
(canvas, window, gl_context, surface)
|
(canvas, window, gl_context, surface)
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
|
||||||
let (canvas, window) = {
|
|
||||||
use wasm_bindgen::JsCast;
|
|
||||||
|
|
||||||
let canvas = web_sys::window()
|
|
||||||
.unwrap()
|
|
||||||
.document()
|
|
||||||
.unwrap()
|
|
||||||
.get_element_by_id("canvas")
|
|
||||||
.unwrap()
|
|
||||||
.dyn_into::<web_sys::HtmlCanvasElement>()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
use winit::platform::web::WindowBuilderExtWebSys;
|
|
||||||
|
|
||||||
let renderer = OpenGl::new_from_html_canvas(&canvas).expect("Cannot create renderer");
|
|
||||||
|
|
||||||
let window = WindowBuilder::new()
|
|
||||||
.with_canvas(Some(canvas))
|
|
||||||
.build(&event_loop)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let canvas = Canvas::new(renderer).expect("Cannot create canvas");
|
|
||||||
|
|
||||||
(canvas, window)
|
|
||||||
};
|
|
||||||
|
|
||||||
run(
|
run(
|
||||||
canvas,
|
canvas,
|
||||||
event_loop,
|
event_loop,
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
|
||||||
context,
|
context,
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
|
||||||
surface,
|
surface,
|
||||||
window,
|
window,
|
||||||
);
|
);
|
||||||
|
|
160
src/hid.rs
Normal file
160
src/hid.rs
Normal file
|
@ -0,0 +1,160 @@
|
||||||
|
use core::panic;
|
||||||
|
use gilrs::ev;
|
||||||
|
use nix::{
|
||||||
|
fcntl::{FcntlArg, OFlag},
|
||||||
|
sys::epoll,
|
||||||
|
};
|
||||||
|
use std::{
|
||||||
|
io,
|
||||||
|
os::fd::{AsRawFd, FromRawFd, OwnedFd},
|
||||||
|
};
|
||||||
|
|
||||||
|
use evdev;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Beo5Event {
|
||||||
|
LaserPosition(f32),
|
||||||
|
SelectionWheelRel(i32),
|
||||||
|
VolumeWheelRel(i32),
|
||||||
|
RightButtonPressed,
|
||||||
|
RightButtonReleased,
|
||||||
|
LeftButtonPressed,
|
||||||
|
LeftButtonReleased,
|
||||||
|
GoButtonPressed,
|
||||||
|
GoButtonReleased,
|
||||||
|
PowerButtonPressed,
|
||||||
|
PowerButtonReleased,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Beo5Device {
|
||||||
|
device: evdev::Device,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Beo5DeviceEvents<'a> {
|
||||||
|
events: Option<evdev::FetchEventsSynced<'a>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Beo5Device {
|
||||||
|
pub fn new_autodiscover() -> Option<Beo5Device> {
|
||||||
|
let devices = evdev::enumerate().map(|t| t.1).collect::<Vec<_>>();
|
||||||
|
for (i, d) in devices.iter().enumerate() {
|
||||||
|
if d.name().unwrap_or("Unnamed device").contains("BeoSound 5") {
|
||||||
|
println!(
|
||||||
|
"Found BeoSound 5 device at index {}: {}",
|
||||||
|
i,
|
||||||
|
d.name().unwrap()
|
||||||
|
);
|
||||||
|
// XXX Is there a better way than this into_iter.nth.unwrap ?
|
||||||
|
let mut d = devices.into_iter().nth(i).unwrap();
|
||||||
|
|
||||||
|
// From evdev's example
|
||||||
|
let raw_fd = d.as_raw_fd();
|
||||||
|
// Set nonblocking
|
||||||
|
nix::fcntl::fcntl(raw_fd, FcntlArg::F_SETFL(OFlag::O_NONBLOCK)); //("Couldn't set nonblocking");
|
||||||
|
|
||||||
|
// Create epoll handle and attach raw_fd
|
||||||
|
//let epoll_fd = epoll::epoll_create1(epoll::EpollCreateFlags::EPOLL_CLOEXEC)?;
|
||||||
|
let epoll_fd = epoll::epoll_create1(epoll::EpollCreateFlags::EPOLL_CLOEXEC).ok()?;
|
||||||
|
let epoll_fd = unsafe { OwnedFd::from_raw_fd(epoll_fd) };
|
||||||
|
let mut event = epoll::EpollEvent::new(epoll::EpollFlags::EPOLLIN, 0);
|
||||||
|
epoll::epoll_ctl(
|
||||||
|
epoll_fd.as_raw_fd(),
|
||||||
|
epoll::EpollOp::EpollCtlAdd,
|
||||||
|
raw_fd,
|
||||||
|
Some(&mut event),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
//let events = d.fetch_events().unwrap();
|
||||||
|
|
||||||
|
return Some(Beo5Device { device: d });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!("Couldn't find a Beosound 5 device! Is the Beosound 5 kernel module loaded + device connected?");
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fetch_events(&self) -> io::Result<Beo5DeviceEvents> {
|
||||||
|
let events = &mut self.device.fetch_events()?;
|
||||||
|
Ok(Beo5DeviceEvents {
|
||||||
|
events: Some(events),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_event_nonblocking(&mut self) -> Option<Beo5Event> {
|
||||||
|
if self.events.is_none() {
|
||||||
|
self.events = Some(self.device.fetch_events().unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
for ev in self.events.unwrap().into_iter() {
|
||||||
|
println!("Beosound event: {ev:?}");
|
||||||
|
// XXX What happens with the other events in the iterator?
|
||||||
|
match ev.kind() {
|
||||||
|
// Look at the beosound 5 kernel module for the correct event codes
|
||||||
|
evdev::InputEventKind::RelAxis(axis) => {
|
||||||
|
match axis {
|
||||||
|
evdev::RelativeAxisType::REL_Y => {
|
||||||
|
return Some(Beo5Event::SelectionWheelRel(ev.value()));
|
||||||
|
}
|
||||||
|
evdev::RelativeAxisType::REL_Z => {
|
||||||
|
return Some(Beo5Event::VolumeWheelRel(ev.value()));
|
||||||
|
}
|
||||||
|
// Shouldn't be any more relative axe
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
evdev::InputEventKind::AbsAxis(axis) => {
|
||||||
|
match axis {
|
||||||
|
evdev::AbsoluteAxisType::ABS_X => {
|
||||||
|
let pos_pct = ev.value() as f32 / 255.0;
|
||||||
|
return Some(Beo5Event::LaserPosition(pos_pct));
|
||||||
|
}
|
||||||
|
// Shouldn't be any other absolute axe
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
evdev::InputEventKind::Switch(switch) => {
|
||||||
|
/*
|
||||||
|
match switch {
|
||||||
|
evdev::SwitchType::LE=> {
|
||||||
|
if ev.value() == 1 {
|
||||||
|
return Beo5Event::RightButtonPressed;
|
||||||
|
} else {
|
||||||
|
return Beo5Event::RightButtonReleased;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
evdev::Switch::SW_LEFT => {
|
||||||
|
if ev.value() == 1 {
|
||||||
|
return Beo5Event::LeftButtonPressed;
|
||||||
|
} else {
|
||||||
|
return Beo5Event::LeftButtonReleased;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
evdev::Switch::SW_GO => {
|
||||||
|
if ev.value() == 1 {
|
||||||
|
return Beo5Event::GoButtonPressed;
|
||||||
|
} else {
|
||||||
|
return Beo5Event::GoButtonReleased;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
evdev::Switch::SW_POWER => {
|
||||||
|
if ev.value() == 1 {
|
||||||
|
return Beo5Event::PowerButtonPressed;
|
||||||
|
} else {
|
||||||
|
return Beo5Event::PowerButtonReleased;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Shouldn't be any other switches
|
||||||
|
_ => {
|
||||||
|
panic!("Unknown switch event: {ev:?}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
_ => {} //SYN et al
|
||||||
|
}
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
64
src/main.rs
64
src/main.rs
|
@ -1,5 +1,3 @@
|
||||||
use core::panic;
|
|
||||||
|
|
||||||
use femtovg::{
|
use femtovg::{
|
||||||
renderer::OpenGl, Align, Baseline, Canvas, Color, FontId, ImageFlags, ImageId, Paint, Path,
|
renderer::OpenGl, Align, Baseline, Canvas, Color, FontId, ImageFlags, ImageId, Paint, Path,
|
||||||
Renderer,
|
Renderer,
|
||||||
|
@ -21,14 +19,20 @@ struct Fonts {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
helpers::start(1024, 768, "Text demo", false);
|
helpers::start(1024, 768, "Text demo");
|
||||||
}
|
}
|
||||||
|
|
||||||
use glutin::prelude::*;
|
use glutin::prelude::*;
|
||||||
|
|
||||||
|
mod hid;
|
||||||
mod roundy_math;
|
mod roundy_math;
|
||||||
mod ui;
|
mod ui;
|
||||||
|
|
||||||
|
enum UiEvent<'e> {
|
||||||
|
WinitEvent(winit::event::Event<'e, ()>),
|
||||||
|
HardwareEvent(evdev::InputEvent),
|
||||||
|
}
|
||||||
|
|
||||||
fn run(
|
fn run(
|
||||||
mut canvas: Canvas<OpenGl>,
|
mut canvas: Canvas<OpenGl>,
|
||||||
el: EventLoop<()>,
|
el: EventLoop<()>,
|
||||||
|
@ -50,11 +54,6 @@ fn run(
|
||||||
println!("{}", app.name());
|
println!("{}", app.name());
|
||||||
}
|
}
|
||||||
|
|
||||||
let flags = ImageFlags::GENERATE_MIPMAPS | ImageFlags::REPEAT_X | ImageFlags::REPEAT_Y;
|
|
||||||
let image_id = canvas
|
|
||||||
.load_image_mem(&resource!("assets/pattern.jpg"), flags)
|
|
||||||
.expect("Cannot create image");
|
|
||||||
|
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
let mut prevt = start;
|
let mut prevt = start;
|
||||||
|
|
||||||
|
@ -65,12 +64,26 @@ fn run(
|
||||||
#[cfg(feature = "debug_inspector")]
|
#[cfg(feature = "debug_inspector")]
|
||||||
let mut font_texture_to_show: Option<usize> = None;
|
let mut font_texture_to_show: Option<usize> = None;
|
||||||
|
|
||||||
let mut x = 5.0;
|
let mut beo_device = hid::Beo5Device::new_autodiscover().expect("Couldn't find Beo5 device");
|
||||||
let mut y = 380.0;
|
loop {
|
||||||
|
if let Some(ev) = beo_device.get_event_nonblocking() {
|
||||||
|
println!("HW Event: {:?}", ev);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
el.run(move |event, _, control_flow| {
|
el.run(move |event, _, control_flow| {
|
||||||
*control_flow = ControlFlow::Poll;
|
*control_flow = ControlFlow::Poll;
|
||||||
|
|
||||||
|
let hw_event = beo_device.get_event_nonblocking();
|
||||||
|
match hw_event {
|
||||||
|
Some(ev) => {
|
||||||
|
println!("HW Event: {:?}", ev);
|
||||||
|
}
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
|
||||||
match event {
|
match event {
|
||||||
Event::LoopDestroyed => *control_flow = ControlFlow::Exit,
|
Event::LoopDestroyed => *control_flow = ControlFlow::Exit,
|
||||||
Event::WindowEvent { ref event, .. } => match event {
|
Event::WindowEvent { ref event, .. } => match event {
|
||||||
|
@ -91,22 +104,13 @@ fn run(
|
||||||
},
|
},
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
println!("INput");
|
if keycode == &VirtualKeyCode::Escape {
|
||||||
if *keycode == VirtualKeyCode::W {
|
*control_flow = ControlFlow::Exit;
|
||||||
y -= 0.1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if *keycode == VirtualKeyCode::S {
|
|
||||||
y += 0.1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if *keycode == VirtualKeyCode::A {
|
|
||||||
x -= 0.1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if *keycode == VirtualKeyCode::D {
|
|
||||||
x += 0.1;
|
|
||||||
}
|
}
|
||||||
|
println!("INput {:?}", keycode);
|
||||||
|
//if *keycode == VirtualKeyCode::W {
|
||||||
|
// y -= 0.1;
|
||||||
|
//}
|
||||||
|
|
||||||
if *keycode == VirtualKeyCode::NumpadAdd || *keycode == VirtualKeyCode::B {
|
if *keycode == VirtualKeyCode::NumpadAdd || *keycode == VirtualKeyCode::B {
|
||||||
println!("Add");
|
println!("Add");
|
||||||
|
@ -136,10 +140,13 @@ fn run(
|
||||||
delta: winit::event::MouseScrollDelta::LineDelta(_, y),
|
delta: winit::event::MouseScrollDelta::LineDelta(_, y),
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
|
println!("Scroll {:?}", y);
|
||||||
font_size += *y / 2.0;
|
font_size += *y / 2.0;
|
||||||
font_size = font_size.max(2.0);
|
font_size = font_size.max(2.0);
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => {
|
||||||
|
println!("{:?}", event);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
Event::RedrawRequested(_) => {
|
Event::RedrawRequested(_) => {
|
||||||
let dpi_factor = window.scale_factor();
|
let dpi_factor = window.scale_factor();
|
||||||
|
@ -186,6 +193,7 @@ fn run(
|
||||||
);
|
);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// XXX Why the save/reset/restore ?
|
||||||
canvas.save();
|
canvas.save();
|
||||||
canvas.reset();
|
canvas.reset();
|
||||||
perf.render(&mut canvas, 500.0, 5.0);
|
perf.render(&mut canvas, 500.0, 5.0);
|
||||||
|
@ -225,8 +233,6 @@ fn draw_main_menu<T: Renderer>(canvas: &mut Canvas<T>, fonts: &Fonts, beo: &ui::
|
||||||
radius: 400.0,
|
radius: 400.0,
|
||||||
};
|
};
|
||||||
|
|
||||||
println!("Canvas width: {}, height: {}", canvas_width, canvas_height);
|
|
||||||
|
|
||||||
let canvas_size = roundy_math::Point {
|
let canvas_size = roundy_math::Point {
|
||||||
x: canvas_width as f64,
|
x: canvas_width as f64,
|
||||||
y: canvas_height as f64,
|
y: canvas_height as f64,
|
||||||
|
@ -234,7 +240,7 @@ fn draw_main_menu<T: Renderer>(canvas: &mut Canvas<T>, fonts: &Fonts, beo: &ui::
|
||||||
|
|
||||||
let pts = main_menu_circle.get_equidistant_points(8, canvas_size);
|
let pts = main_menu_circle.get_equidistant_points(8, canvas_size);
|
||||||
for i in 0..pts.len() {
|
for i in 0..pts.len() {
|
||||||
println!(">>> {:?}", pts[i]);
|
//println!(">>> {:?}", pts[i]);
|
||||||
let mut paint = Paint::color(Color::hex("B7410E"));
|
let mut paint = Paint::color(Color::hex("B7410E"));
|
||||||
paint.set_font(&[fonts.bold]);
|
paint.set_font(&[fonts.bold]);
|
||||||
paint.set_text_baseline(Baseline::Top);
|
paint.set_text_baseline(Baseline::Top);
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
use std::f64::consts::PI;
|
|
||||||
//use std::f64;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Point {
|
pub struct Point {
|
||||||
|
@ -19,10 +17,6 @@ impl VirtualCircle {
|
||||||
// because I'm not clever enough to figure out how to calculate the intersection points
|
// because I'm not clever enough to figure out how to calculate the intersection points
|
||||||
// in the general case.
|
// in the general case.
|
||||||
|
|
||||||
println!(
|
|
||||||
"center: {:?}, radius: {}, viewport_size: {:?}",
|
|
||||||
self.center, self.radius, viewport_size
|
|
||||||
);
|
|
||||||
// Calculate the angles at which the circle intersects with the viewport
|
// Calculate the angles at which the circle intersects with the viewport
|
||||||
let upper_x = self.center.x - (self.radius.powf(2.) - (0. - self.center.y).powf(2.)).sqrt();
|
let upper_x = self.center.x - (self.radius.powf(2.) - (0. - self.center.y).powf(2.)).sqrt();
|
||||||
let lower_x = self.center.x
|
let lower_x = self.center.x
|
||||||
|
@ -35,27 +29,26 @@ impl VirtualCircle {
|
||||||
y: viewport_size.y,
|
y: viewport_size.y,
|
||||||
};
|
};
|
||||||
|
|
||||||
println!("up/low: {:?} {:?}", upper_point, lower_point);
|
//println!("up/low: {:?} {:?}", upper_point, lower_point);
|
||||||
|
|
||||||
let intersection_angles = (
|
let intersection_angles = (
|
||||||
(upper_point.x - self.center.x).atan2(upper_point.y - self.center.y),
|
(upper_point.x - self.center.x).atan2(upper_point.y - self.center.y),
|
||||||
(lower_point.x - self.center.x).atan2(lower_point.y - self.center.y),
|
(lower_point.x - self.center.x).atan2(lower_point.y - self.center.y),
|
||||||
);
|
);
|
||||||
println!("int angles: {:?}", intersection_angles);
|
//println!("int angles: {:?}", intersection_angles);
|
||||||
|
|
||||||
let mut points = Vec::new();
|
let mut points = Vec::new();
|
||||||
|
|
||||||
// Calculate the angle step to distribute points evenly
|
// Calculate the angle step to distribute points evenly
|
||||||
let angle_step = (intersection_angles.1 - intersection_angles.0) / (n as f64);
|
let angle_step = (intersection_angles.1 - intersection_angles.0) / (n as f64);
|
||||||
println!("angle step: {}", angle_step);
|
//println!("angle step: {}", angle_step);
|
||||||
|
|
||||||
// Generate the points
|
// Generate the points
|
||||||
for i in 0..n {
|
for i in 0..n {
|
||||||
let theta = intersection_angles.0 + angle_step * (i as f64 + 0.5);
|
let theta = intersection_angles.0 + angle_step * (i as f64 + 0.5);
|
||||||
let x = theta.sin() * self.radius + viewport_size.x;
|
let x = theta.sin() * self.radius + viewport_size.x;
|
||||||
let y = theta.cos() * self.radius + viewport_size.y - self.center.y;
|
let y = theta.cos() * self.radius + viewport_size.y - self.center.y;
|
||||||
println!("x: {}, y: {}", x, y);
|
points.push(Point { x, y });
|
||||||
points.push(Point { x: x, y: y });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
points
|
points
|
||||||
|
|
Loading…
Reference in a new issue