シンプルで記述しやすい幾何ライブラリを作りました（C++、Python）

　幾何問題に時間がかかるのがストレスだったので、主に自分用にライブラリを作りました。ちなみに幾何ライブラリの代表的なものでは https://ei1333.github.io/luzhiled/ があり、これにほとんどの機能が揃っているのですが、コンパイルが上手くいかなかったり、必要としている API を見つけるのに時間がかかったりすることが多かったので（自分が慣れていないせいで、このライブラリが悪いとかそういうことではないです）、自分用に機能を絞って作り直した、という感じです。

　インクルード、インポートは最小限に、簡潔に記述できるものを目指して作っています。

　※以下のライブラリは二次元空間用です。「外積」は、正確には外積のスカラーとして扱っています。

# C++

```c++
#include <iostream>
#include <math.h>
using namespace std;

struct Point
{
    double x = 0;
    double y = 0;

    void rot(double angle)
    {
        double new_x = x * cos(angle) - y * sin(angle);
        double new_y = x * sin(angle) + y * cos(angle);
        x = new_x;
        y = new_y;
    }

    void rot(int degree)
    {
        double pi = atan(1) * 4;
        double angle = double(degree) / 180 * pi;
        rot(angle);
    }

    double norm()
    {
        return sqrt(x * x + y * y);
    }

    double arg()
    {
        return atan2(y, x);
    }

    double operator*(Point &other)
    {
        return x * other.x + y * other.y;
    }

    double operator^(Point &other)
    {
        return x * other.y - y * other.x;
    }

    Point operator+(Point &other)
    {
        Point ans;
        ans.x = x + other.x;
        ans.y = y + other.y;
        return ans;
    }

    Point operator-(Point &other)
    {
        Point ans;
        ans.x = x - other.x;
        ans.y = y - other.y;
        return ans;
    }

    int ccw(Point B, Point C)
    {
        Point A = *this;
        Point AB = B - A;
        Point AC = C - A;
        double cross = AB ^ AC;
        if (cross > 0)
        {
            return 1;
        }
        else if (cross == 0)
        {
            return 0;
        }
        else
        {
            return -1;
        }
        return true;
    }
};

ostream &operator<<(ostream &os, Point p)
{
    os << "(" << p.x << "," << p.y << ")";
    return os;
}
```

## 説明

　インクルードする必要があるライブラリは `math.h` のみです。

### メンバ

- `x` $x$ 座標を返します。
- `y` $y$ 座標を返します。

### メソッド

- `norm()` 長さを出します
- `arg()` 偏角を出します。
- `rot(a)` 点を回転させます。`double`を入力した場合はラジアンとして、`int` を入力した場合は度として扱います。
- `ccw(A,B)` この点に対して、他の 2 点 $A,B$ が反時計回りに並んでいるかを検出します。1 は反時計回り、0 は同一直線上、-1 は時計回りです。

　また、演算子をオーバーロードしているので、`Point` 同士で演算ができます。

### オペレータ

- `+` それぞれの座標を足し算したものを返します。
- `-` それぞれの座標を引き算したものを返します。
- `*` `Point` を作用させた場合は内積を、`double` を作用させた場合はスカラー倍にしたものを返します。
- `^` 外積を返します。

## 具体例

```c++
int main(void)
{
    Point A({1, 2});
    cout << A << endl; // (1,2)
    A.rot(90); // int を代入しているので 90 度回転
    cout << A << endl; // (-2,1)
    Point B({3, 4});
    cout << A + B << endl; // (1,5)
    cout << A - B << endl; // (-5,3)
    cout << A * B << endl; // -2 内積
    cout << A * 2 << endl; // (-4,2) スカラー倍
    cout << (A ^ B) << endl; // -11 外積
}
```

# Python

```python
from math import atan2, cos, pi, sin, sqrt


class Point:

    def __init__(self, x=0.0, y=0.0) -> None:
        self.x = x
        self.y = y
        self.norm = sqrt(self.x**2 + self.y**2)
        self.arg = atan2(self.y, self.x)

    def rot(self, angle) -> None: # angle is float/int
        if type(angle) == int:
            angle = angle/180*pi
        self.x, self.y = self.x * \
            cos(angle) - self.y*sin(angle), self.x * \
            sin(angle) + self.y*cos(angle)

    def __add__(self, other: 'Point') -> 'Point':
        return Point(self.x + other.x, self.y + other.y)

    def __sub__(self, other: 'Point') -> 'Point':
        return Point(self.x - other.x, self.y - other.y)

    def __mul__(self, other): # float/int -> Point, or Point -> float
        if type(other) == float or type(other) == int:
            return Point(self.x*other, self.y*other)
        return self.x * other.x + self.y * other.y

    def __xor__(self, other: 'Point') -> float:
        return self.x * other.y - self.y * other.x

    def ccw(self, B: 'Point', C: 'Point') -> int:
        AB = B - self
        AC = C - self
        cross = AB ^ AC
        if cross > 0:
            return 1
        elif cross == 0:
            return 0
        else:
            return -1

    def __str__(self) -> str:
        return f'({self.x},{self.y})'
```

## 説明

　インポートする必要があるライブラリは `math` のみです。

### メンバ

- `x` $x$ 座標を返します。
- `y` $y$ 座標を返します。
- `norm` 長さを出します
- `arg` 偏角を出します。

### メソッド

- `rot(a)` 点を回転させます。`float`を入力した場合はラジアンとして、`int` を入力した場合は度として扱います。
- `ccw(A,B)` この点に対して、他の 2 点 $A,B$ が反時計回りに並んでいるかを検出します。1 は反時計回り、0 は同一直線上、-1 は時計回りです。

### オペレータ

- `+` それぞれの座標を足し算したものを返します。
- `-` それぞれの座標を引き算したものを返します。
- `*` `Point` を作用させた場合は内積を、`double` を作用させた場合はスカラー倍にしたものを返します。
- `^` 外積を返します。

## 具体例

```python
A = Point(1, 2)
print(A) # (1,2)
A.rot(90) # int を代入しているので 90 度回転
print(A) # (-2.0,1.0000000000000002)
B = Point(3, 4)
print(A+B) # (1.0,5.0)
print(A-B) # (-5.0,-3.0)
print(A*B) # -1.9999999999999991 // 内積
print(A*2) # (-4.0,2.0000000000000004) // スカラー倍
print(A ^ B) # -11.0 // 外積
```

# Validation

　随時追加

- [B - Counterclockwise Rotation](https://atcoder.jp/contests/abc259/submissions/34422077) C++
- [B - Counterclockwise Rotation](https://atcoder.jp/contests/abc259/submissions/34422170) Python