hyperbolic_drawing 1.0.0

Manipulate and display elements of 2D hyperbolic space (ℍ²)
Documentation
use std::f32::consts::LN_2;

use hyperbolic_drawing::{svg::PoincareFrame, IdealPoint, Motor, Point};
use svg::{node::element::{Circle, Path}, Document};

const LEN: u32 = 2048;
const RAD: u32 = LEN / 2;
const HAR: u32 = LEN / 4;

fn main() {
	let mut document = Document::new()
		.set("viewBox", (0, 0, LEN, LEN));

	let frame = PoincareFrame {
		center_x: RAD as f32,
		center_y: RAD as f32,
		radius: RAD as f32,
	};
	document = document.add(frame.frame_svg().set("stroke", "none").set("fill", "white"));

	for i in -10..=10 {
		let horo_edge = Point::on_x(i as f32 * LN_2);
		let (x, _) = horo_edge.poincaré();
		let r = (1.0 - x) * HAR as f32;
		document = document.add(Circle::new()
			.set("cx", r)
			.set("cy", RAD)
			.set("r", r)
			.set("fill", "none")
			.set("stroke", "black")
			.set("stroke-width", 4)
		);
	}

	let mut path = frame.path_svg();
	for i in -30..=30 {
		let motor = Motor::horolation(IdealPoint::WEST, i as f32 * 0.5);
		path = path
			.move_to(motor.apply(Point::on_x(-10.0).into_weighted()))
			.line_to(motor.apply(Point::on_x(10.0).into_weighted()));
	}
	let path = Path::new()
		.set("fill", "none")
		.set("stroke", "black")
		.set("stroke-width", 4)
		.set("d", path.finish());
	document = document.add(path);

	svg::write(std::io::stdout(), &document).unwrap();
}