// line_symmetry.cpp --- 多角形が線対称かどうか判定する。
// Copyright (C) 2013 片山博文MZ. All rights reserved.
#include <iostream>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <cmath>
using namespace std;

// 実数型。
typedef double numeric_t;

// 位置ベクトルの比較の際の許容される誤差。
const numeric_t TOLERANCE1 = 0.25;

// 単位ベクトルの比較の際の許容される誤差。
const numeric_t TOLERANCE2 = 0.015625;

// 平面ベクトル。
class Point2D
{
public:
    numeric_t m_x, m_y;

public:
    Point2D()
    {
    }
    Point2D(numeric_t x, numeric_t y) : m_x(x), m_y(y)
    {
    }
    Point2D(const Point2D& p) : m_x(p.m_x), m_y(p.m_y)
    {
    }

    void GetXY(numeric_t& x, numeric_t& y) const
    {
        x = m_x; y = m_y;
    }
    void SetXY(numeric_t x, numeric_t y)
    {
        m_x = x; m_y = y;
    }
    bool IsZero() const
    {
        return Length() <= TOLERANCE1;
    }
    void SetZero()
    {
        m_x = m_y = 0;
    }

    // 長さ。
    numeric_t Length() const
    {
        return sqrt(m_x * m_x + m_y * m_y);
    }
    // 垂直なベクトル。
    Point2D Perpendicular() const
    {
        return Point2D(m_y, -m_x);
    }
    // 単位ベクトル。
    Point2D Unit() const
    {
        return *this / Length();
    }

    Point2D& operator=(const Point2D& p)
    {
        m_x = p.m_x; m_y = p.m_y;
        return *this;
    }
    Point2D& operator+=(const Point2D& p)
    {
        m_x += p.m_x; m_y += p.m_y;
        return *this;
    }
    Point2D& operator-=(const Point2D& p)
    {
        m_x -= p.m_x; m_y -= p.m_y;
        return *this;
    }
    Point2D& operator*=(numeric_t d)
    {
        m_x *= d; m_y *= d;
        return *this;
    }
    Point2D& operator/=(numeric_t d)
    {
        m_x /= d; m_y /= d;
        return *this;
    }

    friend Point2D operator+(const Point2D& p1, const Point2D& p2)
    {
        Point2D p(p1);
        p += p2;
        return p;
    }
    friend Point2D operator-(const Point2D& p1, const Point2D& p2)
    {
        Point2D p(p1);
        p -= p2;
        return p;
    }

    friend bool operator==(const Point2D& p1, const Point2D& p2)
    {
        numeric_t dx = p2.m_x - p1.m_x, dy = p2.m_y - p1.m_y;
        return sqrt(dx * dx + dy * dy) <= TOLERANCE1;
    }
    friend bool operator!=(const Point2D& p1, const Point2D& p2)
    {
        return !(p1 == p2);
    }

    friend numeric_t operator*(const Point2D& p1, const Point2D& p2)
    {
        return p1.m_x * p2.m_x + p1.m_y * p2.m_y;
    }

    friend Point2D operator*(const Point2D& p1, numeric_t d)
    {
        Point2D p(p1);
        p *= d;
        return p;
    }
    friend Point2D operator/(const Point2D& p1, numeric_t d)
    {
        Point2D p(p1);
        p /= d;
        return p;
    }
    friend Point2D operator*(numeric_t d, const Point2D& p1)
    {
        return p1 * d;
    }

    // 中点。
    friend Point2D MidPoint(const Point2D& p1, const Point2D& p2)
    {
        return Point2D((p1.m_x + p2.m_x) / 2, (p1.m_y + p2.m_y) / 2);
    }

    friend ostream& operator<<(ostream& o, const Point2D& p)
    {
        o << "(" << p.m_x << ", " << p.m_y << ")";
        return o;
    }

    // 一直線上にあるかどうか？
    friend bool OnOneLine(const Point2D& p1, const Point2D& p2, const Point2D& p3)
    {
        return ((p2 - p1).Unit() - (p3 - p2).Unit()).Length() <= TOLERANCE2;
    }
};

int main(void)
{
    int i, j, n, i1, i2;
    numeric_t x, y, g;
    Point2D mp, unit, p1, p2, p3, q, r;
    vector<Point2D> polygon;
    bool f;

    // 入力。
    cout << "多角形の頂点の個数: ";
    cin >> n;
    if (n < 0)
    {
        cout << "データが不正です。" << endl;
        return 1;
    }
    for (i = 0; i < n; i++)
    {
        cout << "頂点#" << (i + 1) << "のx座標とy座標: ";
        cin >> x >> y;
        polygon.push_back(Point2D(x, y));
    }

    // 重複した頂点を取り除く。
    f = false;
    for (i = 0; i < n - 1; i++)
    {
        p1 = polygon[i];
        p2 = polygon[i + 1];
        if (p1 == p2)
        {
            memmove(&polygon[i], &polygon[i + 1], (n - i - 1) * sizeof(Point2D));
            polygon.resize(--n);
            i--;
            f = true;
        }
    }
    if (n > 1)
    {
        p1 = polygon[n - 1];
        p2 = polygon[0];
        if (p1 == p2)
        {
            polygon.resize(--n);
            f = true;
        }
    }
    if (f)
        cout << "重複した頂点を取り除きました。" << endl;

    // 約180度の角の頂点を取り除く。
    f = false;
    for (i = 0; i < n - 2; i++)
    {
        p1 = polygon[i];
        p2 = polygon[i + 1];
        p3 = polygon[i + 2];
        if (OnOneLine(p1, p2, p3))
        {
            memmove(&polygon[i + 1], &polygon[i + 2], (n - i - 2) * sizeof(Point2D));
            polygon.resize(--n);
            i--;
            f = true;
        }
    }
    while (n > 2)
    {
        p1 = polygon[n - 2];
        p2 = polygon[n - 1];
        p3 = polygon[0];
        if (OnOneLine(p1, p2, p3))
        {
            polygon.resize(--n);
            f = true;
            continue;
        }
        break;
    }
    while (n > 2)
    {
        p1 = polygon[n - 1];
        p2 = polygon[0];
        p3 = polygon[1];
        if (OnOneLine(p1, p2, p3))
        {
            memmove(&polygon[0], &polygon[1], (n - 1) * sizeof(Point2D));
            polygon.resize(--n);
            f = true;
            continue;
        }
        break;
    }
    if (f)
        cout << "約180度の角の頂点を取り除きました。" << endl;

    // 表示。
    if (n > 0)
    {
        for (i = 0; i < n; i++)
        {
            cout << "頂点#" << (i + 1) << ": " << polygon[i] << endl;
        }
    }
    else
    {
        cout << "頂点はありません。" << endl;
    }

    // ０角形、１角形、２角形は、常に線対称。
    if (n <= 2)
    {
        cout << "頂点が2個以下なので線対称です。" << endl;
        return 0;
    }

    // 頂点の角の二等分線が対称の軸か？
    for (i = 0; i < n; i++)
    {
        // 隣り合う３頂点。
        p1 = polygon[(i - 1 + n) % n];
        p2 = polygon[i];
        p3 = polygon[(i + 1) % n];

        // 角に隣り合う２辺の長さが等しいか？
        if (fabs((p2 - p1).Length() - (p3 - p2).Length()) <= TOLERANCE1)
        {
            // 角に隣り合う２頂点の中点。
            mp = MidPoint(p1, p3);

            // 角の二等分線に平行な単位ベクトル。
            if ((mp - p2).IsZero())
                unit = (p3 - p1).Perpendicular().Unit();
            else
                unit = (mp - p2).Unit();

            f = true;
            for (j = 1; j <= n / 2; j++)
            {
                // 対称か判定する２頂点のインデックス。
                i1 = (i - j + n) % n;
                i2 = (i + j) % n;

                g = (polygon[i1] - mp) * unit;      // 中点から垂線までの長さ。
                q = mp + unit * g;                  // 対称の軸上の点（垂線と交わる）。
                r = q - (polygon[i1] - q);          // 軸に対して対称な位置。
                //cout << "1%%" << (r - polygon[i2]).Length() << endl;
                if (r != polygon[i2])
                {
                    f = false;
                    break;
                }
            }

            if (f)
            {
                cout << "頂点#" << (i + 1) << "で線対称です。" << endl;
                return 0;
            }
        }
    }

    // 辺の垂直二等分線が対称の軸か？
    for (i = 0; i < n; i++)
    {
        // 隣り合う２頂点。
        p1 = polygon[i];
        p2 = polygon[(i + 1) % n];

        // 辺の中点。
        mp = MidPoint(p1, p2);

        // 辺に対する垂直単位ベクトル。
        if ((p2 - p1).Perpendicular().IsZero())
            unit.SetZero();
        else
            unit = (p2 - p1).Perpendicular().Unit();

        f = true;
        for (j = 1; j < (n + 1) / 2; j++)
        {
            // 対称か判定する２頂点のインデックス。
            i1 = (i - j + n) % n;
            i2 = (i + j + 1) % n;

            g = (polygon[i1] - mp) * unit;          // 中点から垂線までの長さ。
            q = mp + unit * g;                      // 対称の軸上の点（垂線と交わる）。
            r = q - (polygon[i1] - q);              // 軸に対して対称な位置。
            //cout << "2%%" << (r - polygon[i2]).Length() << endl;
            if (r != polygon[i2])
            {
                f = false;
                break;
            }
        }

        if (f)
        {
            cout << "頂点#" << (i + 1) << "と頂点#" << ((i + 1) % n + 1) <<
                "の間で線対称です。" << endl;
            return 0;
        }
    }

    cout << "線対称ではありません。" << endl;
    return 0;
}