This documentation is automatically generated by online-judge-tools/verification-helper
#include "Geometry/Triangle.hpp"
#pragma once
#include "./Geometric.hpp"
#include "./Vec2.hpp"
#include "./Line.hpp"
#include "./Circle.hpp"
#include <tuple>
#include <cassert>
namespace Geometric {
struct Triangle {
Vec2 p1, p2, p3;
static LD area(LD a, LD b, LD c) {
LD s = (a + b + c) / 2;
return sqrt(s * (s - a) * (s - b) * (s - c));
}
Triangle() = default;
Triangle(const Vec2& _p1, const Vec2& _p2, const Vec2& _p3)
: p1(_p1), p2(_p2), p3(_p3) {
assert(abs(iSP(p1, p2, p3)) == 1);
}
std::tuple<LD, LD, LD> sides() const {
return {distance(p2, p3), distance(p1, p3), distance(p1, p2)};
}
LD area() const {
return abs((p1.x - p3.x) * (p2.y - p3.y) - (p2.x - p3.x) * (p1.y - p3.y)) / 2;
}
// 内接円
Circle incircle() const {
auto [l1, l2, l3] = sides();
LD s = l1 + l2 + l3;
LD x = (p1.x * l1 + p2.x * l2 + p3.x * l3) / s;
LD y = (p1.y * l1 + p2.y * l2 + p3.y * l3) / s;
s /= 2;
LD r = sqrt((s - l1) * (s - l2) * (s - l3) / s);
return Circle(x, y, r);
}
// 外接円
Circle cirnumscribed_circle() const {
Line l1((p1 + p2) / 2, (p1 + p2) / 2 + (p1 - p2).rotate270());
Line l2((p1 + p3) / 2, (p1 + p3) / 2 + (p1 - p3).rotate270());
Vec2 center = *cross_point(l1, l2);
return Circle(center, distance(center, p1));
}
friend std::ostream& operator<<(std::ostream& os, const Triangle& t) {
return os << '(' << t.p1 << ", " << t.p2 << ", " << t.p3 << ')';
}
friend std::istream& operator>>(std::istream& is, Triangle& t) {
return is >> t.p1 >> t.p2 >> t.p3;
}
};
} // namespace Geometric
#line 2 "Geometry/Geometric.hpp"
#include <iostream>
#include <vector>
#include <algorithm>
#include <optional>
namespace Geometric {
using LD = long double;
constexpr long double PI = 3.14159265358979323846, EPS = 1e-12;
// a > 0 : +1
// a = 0 : 0
// a < 0 : -1
constexpr int sgn(LD a);
constexpr LD deg_to_rad(LD deg);
constexpr LD rad_to_deg(LD rad);
struct Vec2;
struct Line;
struct Segment;
struct Rect;
struct Circle;
struct Polygon;
// AB から見て BC が左に曲がる : +1
// AB から見て BC が右に曲がる : -1
// ABC, CBA の順に一直線上に並ぶ : +2
// ACB, BCA の順に一直線上に並ぶ : 0
// BAC, CAB の順に一直線上に並ぶ : -2
int iSP(const Vec2& a, const Vec2& b, const Vec2& c);
// ∠ABC が鋭角 : 0, 直角 : 1, 鈍角 : 2
int angle_type(const Vec2& a, const Vec2& b, const Vec2& c);
// ∠ABC の値 (radian)
LD angle(const Vec2& a, const Vec2& b, const Vec2& c);
// 距離
LD distance(const Vec2& v1, const Vec2& v2);
LD distance(const Vec2& v, const Line& l);
LD distance(const Vec2& v, const Segment& s);
LD distance(const Vec2& v, const Circle& c);
LD distance(const Line& l, const Vec2& v);
LD distance(const Line& l1, const Line& l2);
LD distance(const Segment& s, const Vec2& v);
LD distance(const Segment& s1, const Segment& s2);
LD distance(const Circle& c, const Vec2& v);
LD distance(const Circle& c1, const Circle& c2);
// 交差判定 (内包しているときも true を返す)
bool intersect(const Vec2& v1, const Vec2& v2);
bool intersect(const Vec2& v, const Line& l);
bool intersect(const Vec2& v, const Segment& l);
bool intersect(const Vec2& v, const Circle& c);
bool intersect(const Vec2& v, const Rect& r);
bool intersect(const Vec2& v, const Polygon& p);
bool intersect(const Line& l, const Vec2& v);
bool intersect(const Line& l1, const Line& l2);
bool intersect(const Line& l, const Circle& c);
bool intersect(const Segment& l, const Vec2& v);
bool intersect(const Segment& s1, const Segment& s2);
bool intersect(const Segment& s, const Circle& c);
bool intersect(const Circle& c, const Vec2& v);
bool intersect(const Circle& c, const Line& l);
bool intersect(const Circle& c, const Segment& s);
bool intersect(const Circle& c1, const Circle& c2);
bool intersect(const Circle& c, const Rect& r);
bool intersect(const Rect& r, const Vec2& v);
bool intersect(const Rect& r1, const Rect& r2);
bool intersect(const Rect& r, const Circle& c);
bool intersect(const Polygon& p, const Vec2& v);
// 接するか判定
bool tangent(const Vec2& v1, const Vec2& v2);
bool tangent(const Vec2& v, const Line& l);
bool tangent(const Vec2& v, const Segment& l);
bool tangent(const Vec2& v, const Circle& c);
bool tangent(const Vec2& v, const Rect& r);
bool tangent(const Vec2& v, const Polygon& p);
bool tangent(const Line& l, const Vec2& v);
bool tangent(const Line& l, const Circle& c);
bool tangent(const Line& l, const Rect& r);
bool tangent(const Segment& l, const Vec2& v);
bool tangent(const Circle& c, const Vec2& v);
bool tangent(const Circle& c, const Line& l);
bool tangent(const Circle& c1, const Circle& c2);
bool tangent(const Rect& r, const Vec2& v);
bool tangent(const Rect& r, const Line& l);
bool tangent(const Polygon& p, const Vec2& v);
// 交点
std::optional<Vec2> cross_point(const Line& l1, const Line& l2);
std::optional<Vec2> cross_point(const Segment& s1, const Segment& s2);
std::vector<Vec2> cross_points(const Line& l, const Circle& c);
std::vector<Vec2> cross_points(const Segment& s, const Circle& c);
std::vector<Vec2> cross_points(const Circle& c, const Line& l);
std::vector<Vec2> cross_points(const Circle& c, const Segment& s);
std::vector<Vec2> cross_points(const Circle& c1, const Circle& c2);
// 円の接線
std::vector<Vec2> tangent_to_circle(const Circle& c, const Vec2& v);
} // namespace Geometric
#line 4 "Geometry/Vec2.hpp"
#include <utility>
#include <cmath>
namespace Geometric {
struct Vec2 {
LD x, y;
static constexpr bool compare_x(const Vec2& v1, const Vec2& v2) {
return v1.x < v2.x;
}
static constexpr bool compare_y(const Vec2& v1, const Vec2& v2) {
return v1.y < v2.y;
}
static constexpr bool compare_xy(const Vec2& v1, const Vec2& v2) {
return std::make_pair(v1.x, v1.y) < std::make_pair(v2.x, v2.y);
}
static constexpr bool compare_yx(const Vec2& v1, const Vec2& v2) {
return std::make_pair(v1.y, v1.x) < std::make_pair(v2.y, v2.x);
}
static constexpr Vec2 zero() {
return Vec2(0, 0);
}
constexpr Vec2() : x(0), y(0) {}
constexpr Vec2(LD _x, LD _y) : x(_x), y(_y) {}
Vec2(LD rad) : x(std::cos(rad)), y(std::sin(rad)) {}
constexpr bool operator==(const Vec2& v) const {
return sgn(x - v.x) == 0 && sgn(y - v.y) == 0;
}
constexpr bool operator!=(const Vec2& v) const {
return !(*this == v);
}
constexpr Vec2 operator+() const {
return *this;
}
constexpr Vec2 operator-() const {
return {-x, -y};
}
constexpr Vec2 operator+(const Vec2& v) const {
return Vec2(*this) += v;
}
constexpr Vec2 operator-(const Vec2& v) const {
return Vec2(*this) -= v;
}
constexpr Vec2 operator*(const Vec2& v) const {
return Vec2(*this) *= v;
}
constexpr Vec2 operator/(const Vec2& v) const {
return Vec2(*this) /= v;
}
constexpr Vec2 operator+(LD n) const {
return Vec2(*this) += n;
}
constexpr Vec2 operator-(LD n) const {
return Vec2(*this) -= n;
}
constexpr Vec2 operator*(LD n) const {
return Vec2(*this) *= n;
}
constexpr Vec2 operator/(LD n) const {
return Vec2(*this) /= n;
}
constexpr Vec2& operator+=(const Vec2& v) {
x += v.x;
y += v.y;
return *this;
}
constexpr Vec2& operator-=(const Vec2& v) {
x -= v.x;
y -= v.y;
return *this;
}
constexpr Vec2& operator*=(const Vec2& v) {
x *= v.x;
y *= v.y;
return *this;
}
constexpr Vec2& operator/=(const Vec2& v) {
x /= v.x;
y /= v.y;
return *this;
}
constexpr Vec2& operator+=(LD n) {
x += n;
y += n;
return *this;
}
constexpr Vec2& operator-=(LD n) {
x -= n;
y -= n;
return *this;
}
constexpr Vec2& operator*=(LD n) {
x *= n;
y *= n;
return *this;
}
constexpr Vec2& operator/=(LD n) {
x /= n;
y /= n;
return *this;
}
constexpr LD operator[](size_t i) const {
return i == 0 ? x : i == 1 ? y : 0;
}
constexpr std::pair<LD, LD> pair() const {
return {x, y};
}
LD manhattan(const Vec2& v) const {
return std::abs(x - v.x) + std::abs(y - v.y);
}
constexpr LD length_square() const {
return dot(*this);
}
LD length() const {
return std::sqrt(length_square());
}
// 内積
constexpr LD dot(const Vec2& v) const {
return x * v.x + y * v.y;
}
// 外積
constexpr LD cross(const Vec2& v) const {
return x * v.y - y * v.x;
}
// 正規化(長さを1にした)ベクトル
Vec2 normalized() const {
return *this / length();
}
// 原点中心に rad 回転した座標
Vec2 rotation(LD rad) const {
LD c = std::cos(rad), s = std::sin(rad);
return {x * c - y * s, x * s + y * c};
}
// 原点中心の円上に乗っているとしたときの偏角
LD angle() const {
return std::atan2(y, x);
}
// 正射影
Vec2 projection(const Line& l) const;
// 鏡映変換
Vec2 reflection(const Line& l) const;
constexpr Vec2 rotate90() const {
return {y, -x};
}
constexpr Vec2 rotate180() const {
return {-x, -y};
}
constexpr Vec2 rotate270() const {
return {-y, x};
}
friend std::ostream& operator<<(std::ostream& os, const Vec2& v) {
return os << '(' << v.x << ", " << v.y << ')';
}
friend std::istream& operator>>(std::istream& is, Vec2& v) {
return is >> v.x >> v.y;
}
};
} // namespace Geometric
#line 6 "Geometry/Line.hpp"
#include <tuple>
#line 8 "Geometry/Line.hpp"
namespace Geometric {
namespace internal {
struct LineBase {
protected:
constexpr LineBase() = default;
constexpr LineBase(const Vec2& _begin, const Vec2& _end)
: begin(_begin), end(_end) {}
constexpr LineBase(LD begin_x, LD begin_y, LD end_x, LD end_y)
: begin(begin_x, begin_y), end(end_x, end_y) {}
public:
Vec2 begin, end;
constexpr LineBase operator+(const Vec2& v) {
return LineBase(*this) += v;
}
constexpr LineBase operator-(const Vec2& v) {
return LineBase(*this) -= v;
}
constexpr LineBase& operator+=(const Vec2& v) {
begin += v;
end += v;
return *this;
}
constexpr LineBase& operator-=(const Vec2& v) {
begin -= v;
end -= v;
return *this;
}
constexpr Vec2 vec() const {
return end - begin;
}
constexpr Vec2 counter_vec() const {
return begin - end;
}
// 平行判定
constexpr bool is_parallel(const LineBase& l) const {
return sgn(vec().cross(l.vec())) == 0;
}
// 直交判定
constexpr bool is_orthogonal(const LineBase& l) const {
return sgn(vec().dot(l.vec())) == 0;
}
friend std::ostream& operator<<(std::ostream& os, const LineBase& l) {
return os << '(' << l.begin << ", " << l.end << ')';
}
friend std::istream& operator>>(std::istream& is, LineBase& l) {
return is >> l.begin >> l.end;
}
};
} // namespace internal
struct Line : internal::LineBase {
constexpr Line() = default;
constexpr Line(const Vec2& _begin, const Vec2& _end) : LineBase(_begin, _end) {}
constexpr Line(LD begin_x, LD begin_y, LD end_x, LD end_y)
: LineBase(begin_x, begin_y, end_x, end_y) {}
constexpr Line(const LineBase& l) : LineBase(l) {}
// ax + by + c = 0 の式に変形する
std::tuple<LD, LD, LD> abc() const {
if (sgn(begin.x - end.x) == 0) {
return {1, 0, -begin.x};
} else {
LD slope = (end.y - begin.y) / (end.x - begin.x);
return {slope, -1, begin.y - begin.x * slope};
}
}
};
struct Segment : internal::LineBase {
constexpr Segment() = default;
constexpr Segment(const Vec2& _begin, const Vec2& _end) : LineBase(_begin, _end) {}
constexpr Segment(LD begin_x, LD begin_y, LD end_x, LD end_y)
: LineBase(begin_x, begin_y, end_x, end_y) {}
constexpr Segment(const LineBase& l) : LineBase(l) {}
};
} // namespace Geometric
#line 5 "Geometry/Circle.hpp"
namespace Geometric {
struct Circle {
Vec2 center;
LD r;
constexpr Circle() : center(), r(0) {}
constexpr Circle(LD _r) : center(), r(_r) {}
constexpr Circle(LD _x, LD _y, LD _r) : center(_x, _y), r(_r) {}
constexpr Circle(const Vec2& _c, LD _r) : center(_c), r(_r) {}
constexpr bool operator==(const Circle& c) const {
return center == c.center && sgn(r - c.r) == 0;
}
constexpr bool operator!=(const Circle& c) const {
return !(*this == c);
}
constexpr Circle& operator+(const Vec2& v) const {
return Circle(*this) += v;
}
constexpr Circle& operator-(const Vec2& v) const {
return Circle(*this) -= v;
}
constexpr Circle& operator+=(const Vec2& v) {
center += v;
return *this;
}
constexpr Circle& operator-=(const Vec2& v) {
center -= v;
return *this;
}
constexpr LD top_y() const {
return center.y - r;
}
constexpr LD bottom_y() const {
return center.y + r;
}
constexpr LD left_x() const {
return center.x - r;
}
constexpr LD right_x() const {
return center.x + r;
}
constexpr Vec2 top() const {
return center - Vec2(0, r);
}
constexpr Vec2 bottom() const {
return center + Vec2(0, r);
}
constexpr Vec2 left() const {
return center - Vec2(r, 0);
}
constexpr Vec2 right() const {
return center + Vec2(r, 0);
}
constexpr LD area() const {
return r * r * PI;
}
constexpr LD perimeter() const {
return 2 * r * PI;
}
// c が this に含まれる(一致するときも true を返す)
bool contains(const Circle& c) const {
return sgn(distance(center, c.center) + c.r - r) <= 0;
}
friend std::ostream& operator<<(std::ostream& os, const Circle& c) {
return os << '(' << c.center.x << ", " << c.center.y << ", " << c.r << ')';
}
friend std::istream& operator>>(std::istream& is, Circle& c) {
return is >> c.center >> c.r;
}
};
} // namespace Geometric
#line 7 "Geometry/Triangle.hpp"
#include <cassert>
namespace Geometric {
struct Triangle {
Vec2 p1, p2, p3;
static LD area(LD a, LD b, LD c) {
LD s = (a + b + c) / 2;
return sqrt(s * (s - a) * (s - b) * (s - c));
}
Triangle() = default;
Triangle(const Vec2& _p1, const Vec2& _p2, const Vec2& _p3)
: p1(_p1), p2(_p2), p3(_p3) {
assert(abs(iSP(p1, p2, p3)) == 1);
}
std::tuple<LD, LD, LD> sides() const {
return {distance(p2, p3), distance(p1, p3), distance(p1, p2)};
}
LD area() const {
return abs((p1.x - p3.x) * (p2.y - p3.y) - (p2.x - p3.x) * (p1.y - p3.y)) / 2;
}
// 内接円
Circle incircle() const {
auto [l1, l2, l3] = sides();
LD s = l1 + l2 + l3;
LD x = (p1.x * l1 + p2.x * l2 + p3.x * l3) / s;
LD y = (p1.y * l1 + p2.y * l2 + p3.y * l3) / s;
s /= 2;
LD r = sqrt((s - l1) * (s - l2) * (s - l3) / s);
return Circle(x, y, r);
}
// 外接円
Circle cirnumscribed_circle() const {
Line l1((p1 + p2) / 2, (p1 + p2) / 2 + (p1 - p2).rotate270());
Line l2((p1 + p3) / 2, (p1 + p3) / 2 + (p1 - p3).rotate270());
Vec2 center = *cross_point(l1, l2);
return Circle(center, distance(center, p1));
}
friend std::ostream& operator<<(std::ostream& os, const Triangle& t) {
return os << '(' << t.p1 << ", " << t.p2 << ", " << t.p3 << ')';
}
friend std::istream& operator>>(std::istream& is, Triangle& t) {
return is >> t.p1 >> t.p2 >> t.p3;
}
};
} // namespace Geometric