三角形の内接円と辺の接点を結ぶ三角形をジェルゴンヌ三角形と呼ぶ。
三角形 のジェルゴンヌ三角形を とおくと、位置ベクトルに関して以下の関係が成り立つ。 ただし、
三角形の頂点の座標を入力してそのジェルゴンヌ三角形のジェルゴンヌ三角形の頂点の座標を出力するプログラムを、以下のように書いた。
#include <stdio.h>
#include <math.h>
int
main()
{
double xA, yA, xB, yB, xC, yC;
double xA1, yA1, xB1, yB1, xC1, yC1;
double xA2, yA2, xB2, yB2, xC2, yC2;
double a, b, c, sa, sb, sc;
double a1, b1, c1, sa1, sb1, sc1;
scanf("%lf%lf%lf%lf%lf%lf", &xA, &yA, &xB, &yB, &xC, &yC);
a = hypot(xB - xC, yB - yC);
b = hypot(xC - xA, yC - yA);
c = hypot(xA - xB, yA - yB);
sa = (b + c - a) / 2;
sb = (c + a - b) / 2;
sc = (a + b - c) / 2;
xA1 = fma(xB, sc, xC * sb) / a;
yA1 = fma(yB, sc, yC * sb) / a;
xB1 = fma(xC, sa, xA * sc) / b;
yB1 = fma(yC, sa, yA * sc) / b;
xC1 = fma(xA, sb, xB * sa) / c;
yC1 = fma(yA, sb, yB * sa) / c;
a1 = hypot(xB1 - xC1, yB1 - yC1);
b1 = hypot(xC1 - xA1, yC1 - yA1);
c1 = hypot(xA1 - xB1, yA1 - yB1);
sa1 = (b1 + c1 - a1) / 2;
sb1 = (c1 + a1 - b1) / 2;
sc1 = (a1 + b1 - c1) / 2;
xA2 = fma(xB1, sc1, xC1 * sb1) / a1;
yA2 = fma(yB1, sc1, yC1 * sb1) / a1;
xB2 = fma(xC1, sa1, xA1 * sc1) / b1;
yB2 = fma(yC1, sa1, yA1 * sc1) / b1;
xC2 = fma(xA1, sb1, xB1 * sa1) / c1;
yC2 = fma(yA1, sb1, yB1 * sa1) / c1;
printf("%15.10f %15.10f %15.10f %15.10f %15.10f %15.10f\n", xA2, yA2, xB2, yB2, xC2, yC2);
return 0;
}
main関数だけですべての処理を行っていて見通しが悪いので、三角形の頂点の座標からそのジェルゴンヌ三角形の頂点の座標を計算する関数gergonne_triangleを使う形に改良した。
#include <stdio.h>
#include <math.h>
void
gergonne_triangle(double, double, double, double, double, double, double *, double *, double *, double *, double *, double *);
void
gergonne_triangle(
double xA, double yA, double xB, double yB, double xC, double yC,
double *pA, double *qA, double *pB, double *qB, double *pC, double *qC)
{
double a, b, c, sa, sb, sc;
double xA1, yA1, xB1, yB1, xC1, yC1;
a = hypot(xB - xC, yB - yC);
b = hypot(xC - xA, yC - yA);
c = hypot(xA - xB, yA - yB);
sa = (b + c - a) / 2;
sb = (c + a - b) / 2;
sc = (a + b - c) / 2;
xA1 = fma(xB, sc, xC * sb) / a;
yA1 = fma(yB, sc, yC * sb) / a;
xB1 = fma(xC, sa, xA * sc) / b;
yB1 = fma(yC, sa, yA * sc) / b;
xC1 = fma(xA, sb, xB * sa) / c;
yC1 = fma(yA, sb, yB * sa) / c;
*pA = xA1;
*qA = yA1;
*pB = xB1;
*qB = yB1;
*pC = xC1;
*qC = yC1;
}
int
main()
{
double xA, yA, xB, yB, xC, yC;
double xA1, yA1, xB1, yB1, xC1, yC1;
double xA2, yA2, xB2, yB2, xC2, yC2;
scanf("%lf%lf%lf%lf%lf%lf", &xA, &yA, &xB, &yB, &xC, &yC);
gergonne_triangle(xA, yA, xB, yB, xC, yC, &xA1, &yA1, &xB1, &yB1, &xC1, &yC1);
gergonne_triangle(xA1, yA1, xB1, yB1, xC1, yC1, &xA2, &yA2, &xB2, &yB2, &xC2, &yC2);
printf("%15.10f %15.10f %15.10f %15.10f %15.10f %15.10f\n", xA2, yA2, xB2, yB2, xC2, yC2);
return 0;
}
引数を12個も取る関数は使いづらいので、構造体を使ってさらに見通しを良くしたい。
(動作確認をしたい方は、上の見通しの悪いプログラムも動かして自分の描いたプロと結果を比較すると良い)
以下に書き足す形でプログラムを完成させよ。
#include <stdio.h>
#include <math.h>
struct point {
double x, y; /* x : x座標, y : y座標 */
};
struct triangle {
struct point A, B, C; /* A : 頂点A, B : 頂点B, C : 頂点C */
};
struct triangle gergonne_triangle(struct triangle);
/*
* 関数 gergonne_triangle の定義が必要
*/
int
main()
{
struct triangle t, t1, t2;
scanf("%lf%lf%lf%lf%lf%lf", &t.A.x, &t.A.y, &t.B.x, &t.B.y, &t.C.x, &t.C.y);
t1 = gergonne_triangle(t);
t2 = gergonne_triangle(t1);
printf("%15.10f %15.10f %15.10f %15.10f %15.10f %15.10f\n", t2.A.x, t2.A.y, t2.B.x, t2.B.y, t2.C.x, t2.C.y);
return 0;
}
以下に書き足す形でプログラムを完成させよ。
#include <stdio.h>
#include <math.h>
struct point {
double x, y; /* x : x座標, y : y座標 */
};
struct triangle {
struct point A, B, C; /* A : 頂点A, B : 頂点B, C : 頂点C */
};
void gergonne_triangle(const struct triangle *, struct triangle *);
/*
* 関数 gergonne_triangle の定義が必要
*/
int
main()
{
struct triangle t, t1, t2;
scanf("%lf%lf%lf%lf%lf%lf", &t.A.x, &t.A.y, &t.B.x, &t.B.y, &t.C.x, &t.C.y);
gergonne_triangle(&t, &t1);
gergonne_triangle(&t1, &t2);
printf("%15.10f %15.10f %15.10f %15.10f %15.10f %15.10f\n", t2.A.x, t2.A.y, t2.B.x, t2.B.y, t2.C.x, t2.C.y);
return 0;
}
以下に書き足す形でプログラムを完成させよ。
#include <stdio.h>
#include <math.h>
struct point {
double coordinates[2]; /* coordinates[0] : x座標, coordinates[1] : y座標 */
};
struct triangle {
struct point vertices[3]; /* vertices[0] : 頂点A, vertices[1] : 頂点B, vertices[2] : 頂点C */
};
struct triangle gergonne_triangle(struct triangle);
/*
* 関数 gergonne_triangle の定義が必要
*/
int
main()
{
struct triangle t[3];
scanf("%lf%lf%lf%lf%lf%lf",
&t[0].vertices[0].coordinates[0], &t[0].vertices[0].coordinates[1],
&t[0].vertices[1].coordinates[0], &t[0].vertices[1].coordinates[1],
&t[0].vertices[2].coordinates[0], &t[0].vertices[2].coordinates[1]);
t[1] = gergonne_triangle(t[0]);
t[2] = gergonne_triangle(t[1]);
printf("%15.10f %15.10f %15.10f %15.10f %15.10f %15.10f\n",
t[2].vertices[0].coordinates[0], t[2].vertices[0].coordinates[1],
t[2].vertices[1].coordinates[0], t[2].vertices[1].coordinates[1],
t[2].vertices[2].coordinates[0], t[2].vertices[2].coordinates[1]);
return 0;
}
以下に書き足す形でプログラムを完成させよ。
#include <stdio.h>
#include <math.h>
struct point {
double coordinates[2]; /* coordinates[0] : x座標, coordinates[1] : y座標 */
};
struct triangle {
struct point vertices[3]; /* vertices[0] : 頂点A, vertices[1] : 頂点B, vertices[2] : 頂点C */
};
void gergonne_triangle(const struct triangle *, struct triangle *);
/*
* 関数 gergonne_triangle の定義が必要
*/
int
main()
{
struct triangle t[3];
scanf("%lf%lf%lf%lf%lf%lf",
&t[0].vertices[0].coordinates[0], &t[0].vertices[0].coordinates[1],
&t[0].vertices[1].coordinates[0], &t[0].vertices[1].coordinates[1],
&t[0].vertices[2].coordinates[0], &t[0].vertices[2].coordinates[1]);
gergonne_triangle(&t[0], &t[1]);
gergonne_triangle(&t[1], &t[2]);
printf("%15.10f %15.10f %15.10f %15.10f %15.10f %15.10f\n",
t[2].vertices[0].coordinates[0], t[2].vertices[0].coordinates[1],
t[2].vertices[1].coordinates[0], t[2].vertices[1].coordinates[1],
t[2].vertices[2].coordinates[0], t[2].vertices[2].coordinates[1]);
return 0;
}