#include <bits/stdc++.h>
using namespace std;
ifstream in("triangulare.in");
ofstream out("triangulare.out");
const int kMaxN = 55;
const double kEps = 1e-7;
typedef pair<double, double> Point;
typedef pair<Point, Point> Segment;
int N;
vector< Point > polygon, triangulation;
bool IsZero(const double& x)
{
return fabs(x) < kEps;
}
double Determinant(const Point& a, const Point& b, const Point& c)
{
return (b.first - a.first)*(c.second - a.second) - (b.second - a.second)*(c.first - a.first);
}
bool IsInsidePolygon(const Point& p)
{
Point q(1000000, rand() % 1000000);
bool isInside = false;
for (int i = 0; i < N; ++i)
{
int j = (i + 1) % N;
if (Determinant(p, polygon[i], polygon[j])*Determinant(q, polygon[i], polygon[j]) > 0
&& Determinant(polygon[i], p, q)*Determinant(polygon[j], p, q) < -kEps)
isInside ^= true;
}
return isInside;
}
bool IntIntervals(double left1, double right1, double left2, double right2)
{
if (left1 > left2)
{
swap(left1, left2);
swap(right1, right2);
}
return right1 - left2 > kEps;
}
bool IntSegments(const Segment& a, const Segment& b)
{
if (IsZero(Determinant(a.first, a.second, b.first)) && IsZero(Determinant(a.first, a.second, b.second)))
{
if (IntIntervals( min(a.first.first, a.second.first), max(a.first.first, a.second.first),
min(b.first.first, b.second.first), max(b.first.first, b.second.first) )
|| IntIntervals( min(a.first.second, a.second.second), max(a.first.second, a.second.second),
min(b.first.second, b.second.second), max(b.first.second, b.second.second) ))
return true;
else
return false;
}
return (Determinant(a.first, a.second, b.first)*Determinant(a.first, a.second, b.second) < -kEps
&& Determinant(b.first, b.second, a.first)*Determinant(b.first, b.second, a.second) < -kEps);
}
bool CheckCut(Segment cutSegment)
{
for (int i = 0; i < N; ++i)
{
if (IntSegments(cutSegment, Segment(polygon[i], polygon[(i + 1) % N])))
return false;
}
for (auto& it : triangulation)
{
if (IntSegments(cutSegment, Segment(polygon[it.first], polygon[it.second])))
return false;
}
return IsInsidePolygon(Point( (cutSegment.first.first + cutSegment.second.first)/2,
(cutSegment.first.second+ cutSegment.second.second)/2 ));
}
int main()
{
srand(time(NULL));
int testCount;
in >> testCount;
while (testCount--)
{
in >> N;
polygon.resize(N);
for (auto& it : polygon)
in >> it.first >> it.second;
triangulation.clear();
for (int i = 0; i < N; ++i)
{
for (int j = (i + 2) % N; (j + 1) % N != i; j = (j + 1) % N)
{
if (CheckCut(Segment(polygon[i], polygon[j])))
triangulation.push_back({ min(i, j), max(i, j) });
}
}
sort(triangulation.begin(), triangulation.end());
for (auto it : triangulation)
out << it.first << ' ' << it.second << '\n';
}
return 0;
}
//Trust me, I'm the Doctor!