• 締切済み

正三角形の頂点の座標を求めるプログラムについて

先日、C++言語を使った学校の授業の課題で次のような問題が出されました。 「ある正三角形の2点の頂点の座標を入力し、残り1点の頂点の座標を計算するプログラムを作成しなさい。ただし、正三角形の3辺が同じ長さであるという特性を用いて作成しなさい。座標の有効桁数は小数点以下3桁とする。」 僕は最初、回転行列を用いて計算を行うプログラムを作成して提出したのですが、再提出をくらいました。どうやら、回転行列や方程式は使ってはいけないようです。 それならば、一体どのようなコードを作成すればよいのでしょう?皆さんの力を貸して下さい。

みんなの回答

回答No.3

円周上の点を使うと、角度の刻みが大きいと正しい解が求まりません。 この問題の場合、 2点から等距離にある点の集合は、2点を結んだ線分の中点を通り、線分に直交する直線になる ことを利用してはどうでしょうか。中点の座標から0.001刻みで直線状の点を計算し、計算された点と既知の点との距離が2点間の距離に最も近くなればそれが求める点となります。直線が鉛直線でなければx座標を、鉛直線ならy座標を刻んでいけばいいと思います。 高校の幾何学で解いてしまっては、プログラミングの勉強にならないから、あえて制限しているんだと思いますが。

  • bran111
  • ベストアンサー率49% (512/1037)
回答No.2

この程度の問題に膨大な行数が必要なんですか。プログラム以前に高校の幾何の問題でしょう。 正三角形の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を求める方法もありますがやってみると式がかったるくてやめました。

回答No.1

「3辺が同じ長さである特性を用いて」「方程式を使わずに」ということは力業で近似値を求めよという意味かな? 正三角形の既知の頂点を p0, p1 としその距離を r とした時、点 p0 を中心とした半径 r の円周上に存在する点 p = (x, y) の x, y を小数点以下 3 桁の精度となるように刻んで評価し、点 p と p1 との距離が r に最も近くなる位置が求める正三角形の頂点、というような解放でしょうか。

osker01
質問者

補足

回答ありがとうございます! なるほど、円周上で点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;          }       }    } } しかし、このプログラムだと、入力した数値によっては、計算結果が表示されなくなる場合がありました。どんな数値を入力してもしっかり計算結果が表示されるようにするには、どこを改善すれば良いのでしょうか?長くなってすみません。

関連するQ&A

  • 3次元の物体、例えば正四面体の頂点のデータを取得したとします。正四面体

    3次元の物体、例えば正四面体の頂点のデータを取得したとします。正四面体は1つの面は三角形ですので3つの点の(x,y,z)座標が得られていることになります。で、それが4面なので4セットあることになります。さて、質問ですが、その面に対する物体の”外向き”単位法線ベクトルを計算することを考えます。法線ベクトルは割りと簡単に計算できますが、外向きか、内向きかを判別するアルゴリズムにはどのようなものがあるでしょうか。その1つの面(3つの点)だけだったら物体の全体像がわからないのでその他の点(残り1つですが)を使うことになると思いますが。どのようになるでしょうか。 また、正n面体の物体ではどうなるのでしょうか。正でなくn面体ならどうなるかという問題があります。 面構成する頂点の座標が与えられているというのが基本の前提条件です。よろしくお願いします。

  • 正方形の一次変換

    注:以下の説明で行列は2×2の正方行列で(左上,右上,左下,右下)の順 xy座標平面において、y≧0の部分にあり、頂点の一つが原点にある正方形の内で一次変換         (x`,y`)=(7,√3,√3,5)(x,y) ・・・・・(1) によって長方形になるものを求めよ。 という問題で、正方形の1頂点の座標を(a,b)とおいて他2頂点の座標を定め、移された点を(1)で求めた後、 ・辺同士が直交する ・対辺の長さが等しい など求めてみましたが、式が一つになってしまい、(a,b)が求まりません。 どなたか、解答のアプローチなどご存知の方、教えていただきたいです。

  • x座標、y座標がともに正の整数となる点

    方程式2x+3y=50のグラフ上にあり、x座標、y座標がともに正の整数となる点は何個あるか求めなさい という問題のわかりやすい解き方を教えてください。 地道に数えていく以外の方法があれば知りたいです。よろしくお願いいたします。

  • 三角の頂点から伸びるヒモが交わる一点は?

    床に置いた三角形の頂点に空間の1点からひもを伸ばせばヒモの長さは決まる。 それぞれのヒモの長さも三平方の定理で決まる。これはできる。 それでは長さがまちまちの三本のひもが床の三角形の頂点から伸びていたら、 三本まとめて持てば空間の1点(床の下にも1点)の直交座標は決まる。  (x-a)^2 + (y-b)^2 + (z-c)^2 = r^2 が球の方程式 だから、3つの球の交わる交点を連立方程式で解いていくのか?  パソコンで計算できる式にするためには???  分からなくなりました。どなたかお願いします。

  • ワールド座標系で回転

    こんにちは。3Dプログラムの仕事の指示を受けました。 3Dプログラムは無知でして見よう見まねで行っています。 現在回転行列について困っています。 正方形のモデルをY軸に45度、X軸に45度回転させようとしています。 現在はモデルのローカル座標系で回転するのでY軸の回転でローカル座標系が変わった後にX軸で回転します。これを相対変換と言えばよろしいのでしょうか。 WorldMatrix = RotationX(AngleX) ; WorldMatrix *= RotationY(AngleY) ; WorldMatrix *= RotationZ(AngleZ) ; 上記の回転ではなく、ワールド座標系で回転させたいのですが、このときの回転行列はどのようにして求めればよろしいのでしょうか? Y軸に45度回転させても座標系はそのまま。そしてX軸で45度させるためにはどのようにすればよろしいのでしょうか? わかりづらいですが添付した図のようになればと思っています。

  • 基数変換プログラム

    10進から2進に変換といった簡単な変換はできるのですが、求められているのが、 「M進の固定小数点表現から、M’進の表現を得る」というもので、「整数部・小数部の桁数はそれぞれ200桁まで格納でき、小数点は指定した桁数で打ちきれること」 というもので、難しすぎて全くわかりません。 分かる方、よろしくお願いします!!

  • 新しい実数の構成:自然数→正の実数→実数

    次のような実数の構成はあるのでしょうか? まず、10進法の表記により自然数を構成します。 0を含めます。 0,1,2,3,4,5,6,7,8,9,10, 11、12、・・・ といった数を考えます。 ケタ数は有限です。 順序関係は、まず、ケタの大小を比べ、ケタが同じであれば、最大ケタの数字を比べます。 0~9までの加法と乗法を九九として決め、一般の自然数の加法と乗法は筆算により定めます。 つぎに、小数点以下を考えます。 まず、小数点以下のケタ数が有限なる数を考えても、順序関係と加法・乗法はいままでと同様です。 そして、小数点以下のケタ数が無限なる数を考えます。 順序関係はいままでに追加して、 1=1.000・・・=0.999・・・ といったことなどを考えます。 加法と乗法の筆算も、「左から計算」していけばいいと思います。 このとき、新しく除法も考えられます。 これで、正の実数が構成できたと思いますが、 最後に、小数点以上のケタ数が無限なる数を考えます。 たとえば、 ・・・1212.12  とか ・・・333.333・・・ 順序関係はうまくいきませんが、 ・・・999+1=・・・000=0 と考えると、 ・・・999=-1 といった意味になり、 3をかけることで、 ・・・997=-3 といった意味になったり、 3でわることで、 ・・・333=-1/3 といった意味になったりします。 また、加法と乗法の筆算は、「小数点を中心に左右へ計算」していけば整合性が得られると思われます。 そして、減法・除法も考えられると思います。 つまり、負の実数が構成されたと思います。 結局、左右に無限に続く10進法表記で、実数とその加減乗除が構成されたと思います。 このような、実数の構成はあるのでしょうか? また、不備がありましたら指摘ください。

  • 回転行列が分かっているとき、基準座標に対してどれだ

    回転行列が分かっているとき、基準座標に対してどれだけ動いたかどうやって調べる? 座標系0(基準座標系)と座標系1があります。 0から1へのZYXオイラー角回転行列1R0がわかっています。 このとき,座標系1であらわされた動き(加速度)a1x,a1y,a1zを座標系0で表わすにはどう計算すればいいですか? よろしくお願いします.

  • 三角形の外接円の中心座標を求めるプログラム

    三点の座標(x1,y1),(x2,y2),(x3,y3)が与えられたときに、三角形の外接円の中心座標と半径を求めるプログラムが欲しいです。 垂直二等分線の交点を求めるやり方は既に知っているのですが、連立方程式になってしまいます。 ですので出来ればこれを一発で求められる連立じゃない式が欲しいのですが、ご存じないでしょうか? x = 何とか y = 何とか みたいな感じです。 Javaでやろうとしていますが、計算式さえわかれば自分で書けると思うので、中心座標のx,yを求める式を教えて下さい。 過去質問を探してみましたが、みんな連立方程式で解けば良いとおっしゃっていまして…

  • 座標です。

    問題は以下です。 正四面体の3つの頂点がA(1,3,0)、B(3.5.0)、C(3,3,2)であるとき、 第4の頂点Dの座標を求めよ。 私は D(x,y,z)として長さを求めて連立して解こうとしたのですが 文字が全て消去されてしまいます。 私の計算ミスでしょうか?正しい解答をお願いします。

専門家に質問してみよう