- 締切済み
正三角形の頂点の座標を求めるプログラムについて
先日、C++言語を使った学校の授業の課題で次のような問題が出されました。 「ある正三角形の2点の頂点の座標を入力し、残り1点の頂点の座標を計算するプログラムを作成しなさい。ただし、正三角形の3辺が同じ長さであるという特性を用いて作成しなさい。座標の有効桁数は小数点以下3桁とする。」 僕は最初、回転行列を用いて計算を行うプログラムを作成して提出したのですが、再提出をくらいました。どうやら、回転行列や方程式は使ってはいけないようです。 それならば、一体どのようなコードを作成すればよいのでしょう?皆さんの力を貸して下さい。
- みんなの回答 (3)
- 専門家の回答
みんなの回答
- m-take0220
- ベストアンサー率60% (477/782)
円周上の点を使うと、角度の刻みが大きいと正しい解が求まりません。 この問題の場合、 2点から等距離にある点の集合は、2点を結んだ線分の中点を通り、線分に直交する直線になる ことを利用してはどうでしょうか。中点の座標から0.001刻みで直線状の点を計算し、計算された点と既知の点との距離が2点間の距離に最も近くなればそれが求める点となります。直線が鉛直線でなければx座標を、鉛直線ならy座標を刻んでいけばいいと思います。 高校の幾何学で解いてしまっては、プログラミングの勉強にならないから、あえて制限しているんだと思いますが。
- bran111
- ベストアンサー率49% (512/1037)
この程度の問題に膨大な行数が必要なんですか。プログラム以前に高校の幾何の問題でしょう。 正三角形の2点P1(x1,y1),P2(x2,y2)の頂点の座標を入力し、残り1点Q(x,y)の頂点の座標を計算するプログラムを作成しなさい。 r=[(x1-x2)^2+(y1-y2)^2]^(1/2) θ=arctan[(y2-y1)/(x2-x1)] とすると x=x1+rcos(θ+60°)=x1+r(cosθcos60°-sinθsin60°)=x1+r(cosθ-√3sinθ)/2 y=y1+rsin(θ+60°)=y1+r(sinθcos60°+cosθsin60°)=y1+r(sinθ+√3cosθ)/2 実は x=x1+rcos(θ-60°)=x1+r(cosθcos60°+sinθsin60°)=x1+r(cosθ+√3sinθ)/2 y=y1+rsin(θ-60°)=y1+r(sinθcos60°-cosθsin60°)=y1+r(sinθ-√3cosθ)/2 も解ということはわかりますね。 arctanは多分-π/2~π/2の間で定義されるいわゆる主値でトラブルが出る場合があります。特にx1=x2のようなときエラーが出るかもしれないので調整が必要です。 以上の解も回転行列かどうか知れませんが最も素直に思いつく簡単な式です。 P1を中心、半径rの円とP2を中心、半径rの円の交点としてQを求める方法もありますがやってみると式がかったるくてやめました。
- Takami Torao(@koiroha)
- ベストアンサー率29% (18/61)
「3辺が同じ長さである特性を用いて」「方程式を使わずに」ということは力業で近似値を求めよという意味かな? 正三角形の既知の頂点を p0, p1 としその距離を r とした時、点 p0 を中心とした半径 r の円周上に存在する点 p = (x, y) の x, y を小数点以下 3 桁の精度となるように刻んで評価し、点 p と p1 との距離が r に最も近くなる位置が求める正三角形の頂点、というような解放でしょうか。
補足
回答ありがとうございます! なるほど、円周上で点pを回転させ、半径の長さと近似された距離の座標を表示するわけですね。koirohaさんのアドバイスを参考に、さっそく以下のコードを作成してみました。 #include <iostream> #include <math.h> using namespace std; struct zahyo{ double x; double y; }; //角度を弧度法での表記に直す関数 double kodoho(double k) { return k / 180 * 3.1415; } //辺と距離の差の絶対値を求める関数 double zettai(double x, double y) { double z = x - y; return fabs(z); } int main() { zahyo ten[2];//入力する2点の座標の宣言 double abuso, kaku; double x, y; double kyori2, kyori; //ここでは、1点目の座標をA点、2点目の座標をB点、求める座標をC点とする for (int i = 0; i < 2; i++){ cout << i + 1 << "点目のx座標を入力してください。\n"; cin >> ten[i].x; cout << i + 1 << "点目のy座標を入力してください。\n"; cin >> ten[i].y; } if (ten[0].x == ten[1].x && ten[0].y == ten[1].y) cout << "2点の座標はそれぞれ違う位置を入力してください。\n"; else{ //正三角形の辺の長さを求める double hen2; hen2 = (ten[1].x - ten[0].x) * (ten[1].x - ten[0].x) + (ten[1].y - ten[0].y) * (ten[1].y - ten[0].y); double hen = sqrt(hen2); zahyo cten; //C点の座標1点目の計算 for (int i = 0; i < 360; i++){ //A点を中心に、半径henの長さの円を描きその円周上にC点をおいて //時計回りに1度ずつ移動させる //なお、スタート地点はA点の真上からとする kaku = kodoho(i); x = hen * sin(kaku); cten.x = ten[0].x + x; y = hen * cos(kaku); cten.y = ten[0].y + y; //さらに、B点とC点との間の距離を求める kyori2 = (cten.x - ten[1].x) * (cten.x - ten[1].x) + (cten.y - ten[1].y) * (cten.y - ten[1].y); kyori = sqrt(kyori2); //このあたりで、辺と距離の差の絶対値を求める abuso = zettai(hen, kyori); if (abuso < 0.005){ //求めた値を小数点3桁以下で四捨五入する cten.x *= 1000; cten.x = int(cten.x + .5 - (cten.x < 0)); cten.x /= 1000; cten.y *= 1000; cten.y = int(cten.y + .5 - (cten.y < 0)); cten.y /= 1000; cout << "(" << cten.x << ", " << cten.y << ") \n"; break; } } //C点の座標2点目の計算 for (int i = 0; i > -360; i--){ kaku = kodoho(i); x = hen * sin(kaku); cten.x = ten[0].x + x; y = hen * cos(kaku); cten.y = ten[0].y + y; kyori2 = (cten.x - ten[1].x) * (cten.x - ten[1].x) + (cten.y - ten[1].y) * (cten.y - ten[1].y); kyori = sqrt(kyori2); abuso = zettai(hen, kyori); if (abuso < 0.005){ cten.x *= 1000; cten.x = int(cten.x + .5 - (cten.x < 0)); cten.x /= 1000; cten.y *= 1000; cten.y = int(cten.y + .5 - (cten.y < 0)); cten.y /= 1000; cout << "(" << cten.x << ", " << cten.y << ") \n"; break; } } } } しかし、このプログラムだと、入力した数値によっては、計算結果が表示されなくなる場合がありました。どんな数値を入力してもしっかり計算結果が表示されるようにするには、どこを改善すれば良いのでしょうか?長くなってすみません。