/****************************/
/* 抽象クラス */
/* coded by Y.Suganuma */
/****************************/
#include <iostream>
#include <math.h>
#include <stdlib.h>
/****************/
/* クラスFigure */
/****************/
class Figure {
public:
double s; // 図形の面積
virtual void input() = 0; // データの入力,純粋仮想関数
virtual void menseki() = 0; // 面積の計算,純粋仮想関数
void print(int sw) // 結果の出力
{
if (sw == 0)
std::cout << " 与えられた楕円の面積は " << s << " です\n";
else
std::cout << "与えられた多角形の面積は " << s << " です\n";
}
};
/*****************/
/* クラスEllipse */
/*****************/
class Ellipse : public Figure {
double a, b; // 楕円の長径と短径
public:
void input() // データの入力
{
std::cout << "楕円の長径は? ";
std::cin >> a;
std::cout << "楕円の短径は? ";
std::cin >> b;
}
void menseki() // 楕円の面積
{
s = 4.0 * atan(1.0) * a * b;
}
};
/*****************/
/* クラスPolygon */
/*****************/
class Polygon : public Figure {
int n; // 点の数
int *m; // 点の番号
double **p; // 各点の座標
double men(int, double **, int *);
double sankaku(int, int, int *, double **);
int check1(int, int, int *, double **);
int check2(int, int, int *, double **);
public:
// コンストラクタ
Polygon (int n1)
{
if (n1 < 3) {
std::cout << "3点以上与えてください\n";
exit(1);
}
else {
n = n1;
m = new int [n];
p = new double * [n];
for (int i1 = 0; i1 < n; i1++)
p[i1] = new double [2];
}
}
// デストラクタ
~Polygon ()
{
if (n > 0) {
for (int i1 = 0; i1 < n; i1++)
delete [] p[i1];
delete [] p;
delete [] m;
}
}
// データの入力
void input()
{
std::cout << "各点の座標の入力(反時計回り)\n";
for (int i1 = 0; i1 < n; i1++) {
std::cout << " " << i1+1 << " 番目の点のx座標は? ";
std::cin >> p[i1][0];
std::cout << " " << i1+1 << " 番目の点のy座標は? ";
std::cin >> p[i1][1];
}
}
// 多角形の面積
void menseki()
{
for (int i1 = 0; i1 < n; i1++)
m[i1] = i1;
s = men(n, p, m);
}
};
/******************************/
/* 多角形の面積を再帰的に計算 */
/* n : 点の数 */
/* p : 点の座標 */
/* m : 点番号 */
/* return : 面積 */
/******************************/
double Polygon::men(int n, double **p, int *m)
{
double s = 0.0;
if (n == 3) // 三角形
s = sankaku(n, 0, m, p);
else {
int sw1 = 0;
for (int i1 = 0; i1 < n && sw1 == 0; i1++) {
int sw = check1(n, i1, m, p); // 多角形の中?
if (sw == 0) {
sw = check2(n, i1, m, p); // 中に他の点がある?
if (sw == 0) {
s = sankaku(n, i1, m, p); // i1から始まる三角形
for (int i2 = i1+1; i2 < n-1; i2++) // 点を除く
m[i2] = m[i2+1];
s += men(n-1, p, m); // (n-1)この点からなる多角形
sw1 = 1;
}
}
}
}
return s;
}
/***********************/
/* 三角形の面積の計算 */
/* n : 点の数 */
/* k : 開始点番号 */
/* m : 点番号 */
/* p : 点の座標 */
/* return : 面積 */
/***********************/
double Polygon::sankaku(int n, int k, int *m, double **p)
{
int k1 = m[k];
int k2 = (k == n-1) ? m[0] :m[k+1];
int k3;
if (k < n-2)
k3 = m[k+2];
else
k3 = (k == n-2) ? m[0] : m[1];
double x1 = p[k2][0] - p[k1][0];
double y1 = p[k2][1] - p[k1][1];
double r1 = sqrt(x1 * x1 + y1 * y1);
double t1 = atan2(y1, x1);
x1 = p[k3][0] - p[k1][0];
y1 = p[k3][1] - p[k1][1];
double r2 = sqrt(x1 * x1 + y1 * y1);
double t2 = atan2(y1, x1);
double t3 = t2 - t1;
double s = fabs(0.5 * r1 * r2 * sin(t3));
return s;
}
/****************************************/
/* 三角形が多角形の内部か否かのチェック */
/* n : 点の数 */
/* k : 開始点番号 */
/* m : 点番号 */
/* p : 点の座標 */
/* return : =0 : 内部である */
/* =1 : 内部でない */
/****************************************/
int Polygon::check1(int n, int k, int *m, double **p)
{
double pi = 4.0 * atan2(1.0, 1.0);
int k1 = m[k];
int k2 = (k == n-1) ? m[0] :m[k+1];
int k3;
if (k < n-2)
k3 = m[k+2];
else
k3 = (k == n-2) ? m[0] : m[1];
double x1 = p[k3][0] - p[k1][0];
double y1 = p[k3][1] - p[k1][1];
double t1 = atan2(y1, x1);
x1 = p[k2][0] - p[k1][0];
y1 = p[k2][1] - p[k1][1];
double t2 = atan2(y1, x1);
double t3 = t2 - t1;
if (t3 > pi)
t3 -= 2.0 * pi;
else {
if (t3 < -pi)
t3 += 2.0 * pi;
}
int sw = 0;
if (t3 > 0.0)
sw = 1;
return sw;
}
/************************************************/
/* 三角形内に他の頂点が存在するか否かのチェック */
/* n : 点の数 */
/* k : 開始点番号 */
/* m : 点番号 */
/* p : 点の座標 */
/* return : =0 : 存在しない */
/* =1 : 存在する */
/************************************************/
int Polygon::check2(int n, int k, int *m, double **p)
{
double pi = 4.0 * atan2(1.0, 1.0);
int k1 = m[k];
int k2 = (k == n-1) ? m[0] :m[k+1];
int k3, sw = 0;
if (k1 < n-2)
k3 = m[k+2];
else
k3 = (k == n-2) ? m[0] : m[1];
double x1 = p[k2][0] - p[k1][0];
double y1 = p[k2][1] - p[k1][1];
double t10 = atan2(y1, x1);
x1 = p[k3][0] - p[k2][0];
y1 = p[k3][1] - p[k2][1];
double t11 = atan2(y1, x1);
x1 = p[k1][0] - p[k3][0];
y1 = p[k1][1] - p[k3][1];
double t12 = atan2(y1, x1);
for (int i1 = 0; i1 < n && sw == 0; i1++) {
if (i1 != k1 && i1 != k2 && i1 != k3) {
x1 = p[m[i1]][0] - p[k1][0];
y1 = p[m[i1]][1] - p[k1][1];
double t2 = atan2(y1, x1);
double t3 = t2 - t10;
if (t3 > pi)
t3 -= 2.0 * pi;
else {
if (t3 < -pi)
t3 += 2.0 * pi;
}
if (t3 > 0.0) {
x1 = p[m[i1]][0] - p[k2][0];
y1 = p[m[i1]][1] - p[k2][1];
double t2 = atan2(y1, x1);
t3 = t2 - t11;
if (t3 > pi)
t3 -= 2.0 * pi;
else {
if (t3 < -pi)
t3 += 2.0 * pi;
}
if (t3 > 0.0) {
x1 = p[m[i1]][0] - p[k3][0];
y1 = p[m[i1]][1] - p[k3][1];
t2 = atan2(y1, x1);
t3 = t2 - t12;
if (t3 > pi)
t3 -= 2.0 * pi;
else {
if (t3 < -pi)
t3 += 2.0 * pi;
}
if (t3 > 0.0)
sw = 1;
}
}
}
}
return sw;
}
/*************/
/* main 関数 */
/*************/
int main()
{
/*
楕円
*/
Ellipse e1;
e1.input();
e1.menseki();
e1.print(0);
/*
多角形
*/
int n;
std::cout << "点の数は? ";
std::cin >> n;
Polygon p1(n);
p1.input();
p1.menseki();
p1.print(1);
return 0;
}