三次元幾何の基本要素
(geometry-3d/geometry-base.hpp)
- View this file on GitHub
- Last update: 2026-07-25 02:01:37+09:00
- Include:
#include "geometry-3d/geometry-base.hpp"
三次元幾何で用いる点とベクトルの基本演算を扱う.
三次元空間上の点とベクトルを Point3D で表す.座標型と誤差判定は二次元幾何と共通で,それぞれ long double, EPS = 1e-10.
-
dot(a, b):内積を返す. -
cross(a, b):外積を返す. -
triple(a, b, c):スカラー三重積 $a\cdot(b\times c)$ を返す. -
abs(p):ベクトルの長さを返す. -
norm(p):ベクトルの長さの二乗を返す. -
normalize(p):pと同じ向きの単位ベクトルを返す.零ベクトルは与えてはならない. -
angle(a, b):二つの非零ベクトルがなす角を $[0,\pi]$ で返す. -
equals(a, b):二点間の距離がEPS未満か判定する.
Depends on
Required by
三次元空間上の直線
(geometry-3d/line.hpp)
三次元空間上の平面
(geometry-3d/plane.hpp)
三次元空間上の線分
(geometry-3d/segment.hpp)
三次元空間上の円と球
(geometry-3d/sphere.hpp)
三次元空間上の三角形
(geometry-3d/triangle.hpp)
Verified with
Code
#pragma once
#include "geometry/geometry-base.hpp"
template <class R>
struct Point3DBase {
using P = Point3DBase;
R x, y, z;
Point3DBase() : x(0), y(0), z(0) {}
Point3DBase(R _x, R _y, R _z) : x(_x), y(_y), z(_z) {}
P operator+(const P& r) const { return {x + r.x, y + r.y, z + r.z}; }
P operator-(const P& r) const { return {x - r.x, y - r.y, z - r.z}; }
P operator-() const { return {-x, -y, -z}; }
P operator*(R r) const { return {x * r, y * r, z * r}; }
P operator/(R r) const { return {x / r, y / r, z / r}; }
P& operator+=(const P& r) { return (*this) = (*this) + r; }
P& operator-=(const P& r) { return (*this) = (*this) - r; }
P& operator*=(R r) { return (*this) = (*this) * r; }
P& operator/=(R r) { return (*this) = (*this) / r; }
bool operator<(const P& r) const {
if (x != r.x) return x < r.x;
return y != r.y ? y < r.y : z < r.z;
}
bool operator==(const P& r) const {
return x == r.x && y == r.y && z == r.z;
}
bool operator!=(const P& r) const { return !((*this) == r); }
friend P operator*(R r, const P& p) { return p * r; }
friend R dot(const P& l, const P& r) {
return l.x * r.x + l.y * r.y + l.z * r.z;
}
friend P cross(const P& l, const P& r) {
return {l.y * r.z - l.z * r.y, l.z * r.x - l.x * r.z,
l.x * r.y - l.y * r.x};
}
friend R norm(const P& p) { return dot(p, p); }
friend R abs(const P& p) { return sqrt(norm(p)); }
friend istream& operator>>(istream& is, P& p) {
return is >> p.x >> p.y >> p.z;
}
friend ostream& operator<<(ostream& os, const P& p) {
return os << p.x << " " << p.y << " " << p.z;
}
};
using Point3D = Point3DBase<Real>;
using Points3D = vector<Point3D>;
Real triple(const Point3D& a, const Point3D& b, const Point3D& c) {
return dot(a, cross(b, c));
}
Point3D normalize(const Point3D& p) {
Real len = abs(p);
assert(len > EPS);
return p / len;
}
Real angle(const Point3D& a, const Point3D& b) {
Real d = abs(a) * abs(b);
assert(d > EPS);
return acos(clamp(dot(a, b) / d, (Real)-1, (Real)1));
}
bool equals(const Point3D& a, const Point3D& b) { return abs(a - b) < EPS; }
/**
* @brief 三次元幾何の基本要素
* @docs docs/geometry-3d/geometry-base.md
*/#line 2 "geometry-3d/geometry-base.hpp"
#line 2 "geometry/geometry-base.hpp"
#include <bits/stdc++.h>
using Real = long double;
constexpr Real EPS = 1e-10;
constexpr Real PI = 3.141592653589793238462643383279L;
bool equals(Real x, Real y) { return fabs(x - y) < EPS; }
int sign(Real a) { return equals(a, 0) ? 0 : (a > 0 ? 1 : -1); }
template <class R>
struct PointBase {
using P = PointBase;
R x, y;
PointBase() : x(0), y(0) {}
PointBase(R _x, R _y) : x(_x), y(_y) {}
template <typename T, typename U>
PointBase(const pair<T, U>& p) : x(p.first), y(p.second) {}
P operator+(const P& r) const { return P{x + r.x, y + r.y}; }
P operator-(const P& r) const { return P{x - r.x, y - r.y}; }
P operator-() const { return P{-x, -y}; }
P operator*(R r) const { return P{x * r, y * r}; }
P operator/(R r) const { return P{x / r, y / r}; }
P& operator+=(const P& r) { return (*this) = (*this) + r; }
P& operator-=(const P& r) { return (*this) = (*this) - r; }
P& operator*=(R r) { return (*this) = (*this) * r; }
P& operator/=(R r) { return (*this) = (*this) / r; }
bool operator<(const P& r) const { return x != r.x ? x < r.x : y < r.y; }
bool operator==(const P& r) const { return x == r.x and y == r.y; }
bool operator!=(const P& r) const { return !((*this) == r); }
P rotate(R rad) const {
return {x * cos(rad) - y * sin(rad), x * sin(rad) + y * cos(rad)};
}
P rotate90() const { return {-y, x}; }
R real() const { return x; }
R imag() const { return y; }
friend P operator*(R r, const P& p) { return p * r; }
friend R real(const P& p) { return p.x; }
friend R imag(const P& p) { return p.y; }
friend R dot(const P& l, const P& r) { return l.x * r.x + l.y * r.y; }
friend R cross(const P& l, const P& r) { return l.x * r.y - l.y * r.x; }
friend R abs(const P& p) { return sqrt(p.x * p.x + p.y * p.y); }
friend R norm(const P& p) { return p.x * p.x + p.y * p.y; }
friend R arg(const P& p) { return atan2(p.y, p.x); }
friend istream& operator>>(istream& is, P& p) {
R a, b;
is >> a >> b;
p = P{a, b};
return is;
}
friend ostream& operator<<(ostream& os, const P& p) {
return os << p.x << " " << p.y;
}
};
using Point = PointBase<Real>;
using Points = vector<Point>;
// relative position of c from a->b
int ccw(const Point& a, const Point& b, const Point& c) {
Point x = b - a, y = c - a;
if (cross(x, y) > EPS) return +1; // counter-clockwise
if (cross(x, y) < -EPS) return -1; // clockwise
if (dot(x, y) < -EPS) return +2; // collinear in the order c-a-b
if (norm(x) + EPS < norm(y)) return -2; // collinear in the order a-b-c
return 0; // collinear in the order a-c-b
}
/**
* @brief 二次元幾何の基本要素
* @docs docs/geometry/geometry-base.md
*/
#line 4 "geometry-3d/geometry-base.hpp"
template <class R>
struct Point3DBase {
using P = Point3DBase;
R x, y, z;
Point3DBase() : x(0), y(0), z(0) {}
Point3DBase(R _x, R _y, R _z) : x(_x), y(_y), z(_z) {}
P operator+(const P& r) const { return {x + r.x, y + r.y, z + r.z}; }
P operator-(const P& r) const { return {x - r.x, y - r.y, z - r.z}; }
P operator-() const { return {-x, -y, -z}; }
P operator*(R r) const { return {x * r, y * r, z * r}; }
P operator/(R r) const { return {x / r, y / r, z / r}; }
P& operator+=(const P& r) { return (*this) = (*this) + r; }
P& operator-=(const P& r) { return (*this) = (*this) - r; }
P& operator*=(R r) { return (*this) = (*this) * r; }
P& operator/=(R r) { return (*this) = (*this) / r; }
bool operator<(const P& r) const {
if (x != r.x) return x < r.x;
return y != r.y ? y < r.y : z < r.z;
}
bool operator==(const P& r) const {
return x == r.x && y == r.y && z == r.z;
}
bool operator!=(const P& r) const { return !((*this) == r); }
friend P operator*(R r, const P& p) { return p * r; }
friend R dot(const P& l, const P& r) {
return l.x * r.x + l.y * r.y + l.z * r.z;
}
friend P cross(const P& l, const P& r) {
return {l.y * r.z - l.z * r.y, l.z * r.x - l.x * r.z,
l.x * r.y - l.y * r.x};
}
friend R norm(const P& p) { return dot(p, p); }
friend R abs(const P& p) { return sqrt(norm(p)); }
friend istream& operator>>(istream& is, P& p) {
return is >> p.x >> p.y >> p.z;
}
friend ostream& operator<<(ostream& os, const P& p) {
return os << p.x << " " << p.y << " " << p.z;
}
};
using Point3D = Point3DBase<Real>;
using Points3D = vector<Point3D>;
Real triple(const Point3D& a, const Point3D& b, const Point3D& c) {
return dot(a, cross(b, c));
}
Point3D normalize(const Point3D& p) {
Real len = abs(p);
assert(len > EPS);
return p / len;
}
Real angle(const Point3D& a, const Point3D& b) {
Real d = abs(a) * abs(b);
assert(d > EPS);
return acos(clamp(dot(a, b) / d, (Real)-1, (Real)1));
}
bool equals(const Point3D& a, const Point3D& b) { return abs(a - b) < EPS; }
/**
* @brief 三次元幾何の基本要素
* @docs docs/geometry-3d/geometry-base.md
*/