二次元ユークリッド幾何 - 点の定義
概要
- 点またはベクトルの定義
- L2ノルム
::norm
- 外積
::det
- 偏角
::arg
- 二点間の距離
::distance
- 演算
- 同値
==
, !=
- 和差
+
, -
- 内積
*
- スカラ倍
*
/
実装
/// Geometry2D - Definition of Point
use crate::almost_equal; // IGNORE
#[derive(Debug, Clone, Copy)]
pub struct Point(pub f64, pub f64);
impl Point {
pub fn new(x: f64, y: f64) -> Self {
Self(x, y)
}
pub fn zero() -> Point {
Point(0.0, 0.0)
}
pub fn norm(&self) -> f64 {
(*self * *self).sqrt()
}
pub fn quadrance(&self) -> f64 {
*self * *self
}
pub fn det(&self, other: &Point) -> f64 {
self.0 * other.1 - self.1 * other.0
}
pub fn arg(&self) -> f64 {
let x = self.0 / self.norm();
let y = self.1 / self.norm();
y.atan2(x)
}
pub fn distance(&self, other: &Point) -> f64 {
(*self - *other).norm()
}
}
impl PartialEq for Point {
fn eq(&self, other: &Point) -> bool {
almost_equal!(self.0, other.0) && almost_equal!(self.1, other.1)
}
fn ne(&self, other: &Point) -> bool {
!(self == other)
}
}
impl Eq for Point {}
impl std::ops::Add for Point {
type Output = Point;
fn add(self, other: Point) -> Point {
Point(self.0 + other.0, self.1 + other.1)
}
}
impl std::ops::Neg for Point {
type Output = Point;
fn neg(self) -> Point {
Point(-self.0, -self.1)
}
}
impl std::ops::Sub for Point {
type Output = Point;
fn sub(self, other: Point) -> Point {
self + (-other)
}
}
// scalar multiplication
impl std::ops::Mul<Point> for f64 {
type Output = Point;
fn mul(self, other: Point) -> Point {
Point(self * other.0, self * other.1)
}
}
impl std::ops::Mul<f64> for Point {
type Output = Point;
fn mul(self, other: f64) -> Point {
Point(other * self.0, other * self.1)
}
}
// inner-product
impl std::ops::Mul<Point> for Point {
type Output = f64;
fn mul(self, other: Point) -> f64 {
self.0 * other.0 + self.1 * other.1
}
}
impl std::ops::Div<f64> for Point {
type Output = Point;
fn div(self, other: f64) -> Point {
Point(self.0 / other, self.1 / other)
}
}
#[macro_export]
macro_rules! almost_equal {
($x:expr, $y:expr) => {
($x - $y).abs() < 1e-6
};
}
#[cfg(test)]
mod test_point {
use crate::geometry2d::point::*;
#[test]
fn norm() {
assert_eq!(Point(1.0, 0.0).norm(), 1.0);
assert_eq!(Point(3.0, 4.0).norm(), 5.0);
}
#[test]
fn distance() {
assert_eq!(Point(0.0, 0.0).distance(&Point(3.0, 0.0)), 3.0);
assert_eq!(Point(0.0, 0.0).distance(&Point(3.0, 4.0)), 5.0);
}
#[test]
fn arithmetic() {
assert_eq!(Point(1.0, 2.0) * -1.0, Point(-1.0, -2.0));
assert_eq!(Point(1.0, 2.0) * Point(1.0, -1.0), -1.0);
assert_eq!(Point(1.0, 2.0) / 2.0, Point(0.5, 1.0));
assert_eq!(Point(1.0, 2.0) + Point::zero(), Point(1.0, 2.0));
assert_eq!(Point(1.0, 2.0) - Point(0.0, 1.0), Point(1.0, 1.0));
}
}