• ベストアンサー

緩やかなカーブを表現する

今、座標(pos)と移動量(mov)を持った物体OBJがあります。 座標はx,y、移動量はspeed,theta(速度,角度)を持っています。 ここで、目的地GOAL(x,yを持つ)があり、OBJはそこに向かって移動します。 OBJがGOAL付近に到着すると、OBJはランダムな座標に設定されます。 ここで、私は飛行機や車のような緩やかなカーブを表現したいと思いました。そこで、 OBJの速度は一定で、目的地についたときに、OBJとその目的地までの角度を 変数OLDthetaに保存しておき、OLDthetaから新たな目的地までの角度(OBJ.mov.theta)を引き、 それが0でなければ、OLDthetaに0.05を加減させます。そうすると、 結果的にOLD.thetaはOBJ.mov.thetaと等しくなり、緩やかなカーブも表現できると思いました。 しかし、プログラムを実行すると、緩やかなカーブはするのですが、 遠回りなカーブをしたり、放って置くといきなり不規則な移動を起こして まったく関係のないところへ行ってしまいます。 どこらへんの考えが誤っているでしょうか?どなたか回答をお願いします。 ちなみに、移動量は OBJ.pos.x += cos(OLDtheta)*OBJ.mov.speed OBJ.pos.y += sin(OLDtheta)*OBJ.mov.speed で設定しています。 一応、関係のありそうな箇所のコードを書いておきます。 (角度を求めるコード) OBJ.mov.theta = atan2 (GOAL.y - OBJ.pos.y , GOAL.x - OBJ.pos.x); if(OLDtheta - OBJ.mov.theta != 0){ ______if(OLDtheta>OBJ.mov.theta){ ____________OLDtheta -= 0.05; ______}else{ ____________OLDtheta += 0.05; ______} } (構造体) struct VEC{ ______float x,y; }; struct VEC2{ ______float speed; //スピード ______float theta; //角度 }; struct CharaData{ ______VEC pos; //座標 ______VEC2 mov; //移動量 };

質問者が選んだベストアンサー

  • ベストアンサー
  • chie65535
  • ベストアンサー率43% (8524/19373)
回答No.7

>ゴールまでの距離の二乗が速度の二乗未満ならゴール >になる理由がいまいちわかりません。 >なぜそうなるのでしょうか? 2点間の距離は、直角三角形の 底辺の2乗+高さの2乗=斜辺の2乗 の公式を使って求めます。 ですので、直角三角形の斜辺の長さは √(底辺の2乗+高さの2乗) です。 底辺3、高さ4の直角三角形なら、斜辺の長さは √(3×3+4×4)=√25=5 です。 この時「斜辺の長さ=2点間の距離」です。 「距離<速度」が成り立つ場合「現在地から1ステップで移動する長さを半径とした円内にゴールがある」と言う事です。 つまり、現時点か、次の1ステップ移動後の時点で「ゴールに最も近付く」と言う事です。 本来、ゴール判定は sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)) で距離を求め「距離<1ステップで移動する長さ(つまり速度)」で判定しなければなりません。 ですが「平方根を求めるより、単純な掛け算の方が、処理が早い」ので「『距離<速度』が成り立つ場合『距離の2乗<速度の2乗』も成り立つ、と言うのを利用し、距離を求めるのにsqrt関数を使うのを避け、代わりに速度を2乗し「距離の2乗<速度の2乗」を判定する事で、ゴール判定しています。 底辺3、高さ4の直角三角形の斜辺の長さが5以上か判定するなら if (sqrt((3*3)+(4*4)) >= 5) と書かないで if ((3*3)+(4*4) >= (5*5)) と書いた方が、処理が早いですよね。 しかも (GOAL.x - OBJ.pos.x)*(GOAL.x - OBJ.pos.x) も (GOAL.y - OBJ.pos.y)*(GOAL.y - OBJ.pos.y) も、2点の位置関係に関係なく「2乗すれば必ずプラス」になるので、そのまま足し算すれば「距離の2乗」が求まります。 なお、現在地座標も、ゴール座標も「実数」で扱っているため「演算誤差で、ぴったり重なる事は絶対にない」と思って下さい。なので「1ステップで動く距離を半径とした円内にゴールがあるか?」と言う判定を行うしかありません。 また、ピッタリ重なるコースを通っていても「速度が2以上になると、ゴールを飛び越える可能性がある」ので、やはり「円内にゴールがあるか?」と言う判定をせざるを得ません。 「進行方向と現在速度から、ゴールの真上を通過し、かつ、ゴールを飛び越えたかどうかを判定する方法」もありますが、計算量が膨大になって遅くなるくせに、判定結果の精度が「ちょっと良くなるだけ」なので、余り意味がありません(偶然にゴールのすぐ真横を通り抜けた時に、ゴールしてないと判断するようになるだけ)

morogon
質問者

お礼

なるほど、 わかりやすい解説ありがとうございます。 しっかりと理解することが出来ました。 問題は一応、解決することができましたので 回答は締め切らせていただきます。 この質問に回答してくださった全ての方 どうもありがとうございましたm(_ _)m

その他の回答 (6)

  • chie65535
  • ベストアンサー率43% (8524/19373)
回答No.6

追記。 速度が一定で旋回角度に上限があると、最小旋回半径以上には旋回できません。最小旋回半径で円を描き、その内側にあるゴールには辿り付けません。 そこで、加速と減速の処理を施し、以下のソースコードのように、最小旋回半径が小さくなるようにしてあげる必要が出ます。 void ObjMove(void) {   float NEWtheta,delta,Length;   NEWtheta = atan2(GOAL.y - OBJ.pos.y , GOAL.x - OBJ.pos.x); /* 目標の方向 */   if (NEWtheta < 0.0) NEWtheta += 6.28318530717958; /* 目標の方向を0~360度に補正 */   delta = OBJ.mov.theta - NEWtheta; /* 自分から見た目標の方向を求める */   if ((delta >= -0.05) && (delta <= 0.05)){     OBJ.mov.theta = NEWtheta; /* 目標が殆ど正面にある */   }else{     if (delta < 0.0) delta += 6.28318530717958; /* 自分から見た目標の方向を0~360度に補正 */     if (delta <= 3.14159265358979){ /* 目標は右にある */       OBJ.mov.theta -= 0.05;       if (OBJ.mov.theta < 0.0) OBJ.mov.theta += 6.28318530717958; /* 角度がマイナスになったらプラスに補正 */     }else{ /* 目標は左にある */       OBJ.mov.theta += 0.05;       if (OBJ.mov.theta > 6.28318530717958) OBJ.mov.theta -= 6.28318530717958; /* 角度が360度を超えたら360度戻す */     }   }   OBJ.pos.x += cos(OBJ.mov.theta)*OBJ.mov.speed; /* 位置更新 */   OBJ.pos.y += sin(OBJ.mov.theta)*OBJ.mov.speed; /* 位置更新 */   if ((delta < 0.05) || (delta > 6.23318530717958)){ /* 目標が正面にある場合 */     OBJ.mov.speed *= 1.1; /* 10%加速する */     if (OBJ.mov.speed > 10.0) {       OBJ.mov.speed = 10.0; /* 但し10.0以上には加速しない */     }   }else if ((delta > 1.570796326794895) && (delta < 4.712388980384685)){ /* 目標が後方にある場合 */     OBJ.mov.speed /= 1.1; /* 10%減速する */     if (OBJ.mov.speed <= 0.01) {       OBJ.mov.speed = 0.01; /* 但し0.01以下には加速しない */     }   }   Length = (GOAL.x - OBJ.pos.x)*(GOAL.x - OBJ.pos.x)+(GOAL.y - OBJ.pos.y)*(GOAL.y - OBJ.pos.y); /* ゴールまでの距離の2乗が */   if (Length < OBJ.mov.speed * OBJ.mov.speed) { /* 速度の2乗未満ならゴール */     GOAL.x = 新しいゴール;     GOAL.y = 新しいゴール;   } } このルーチンも「最低速度」と「旋回角度の上限」があるので、最小旋回半径の円の内側にゴールがあると、辿り付けません。 参考として、上記ルーチンでの「軌跡」を添付しておきます(画面上の「×」が「次々に出現するゴール」です)

morogon
質問者

お礼

具体的なコードを書いてくださったおかげで、 思うような動きを実現することが出来ました! 考え方は大体わかりましたが、最後の ゴールまでの距離の二乗が速度の二乗未満ならゴール になる理由がいまいちわかりません。 なぜそうなるのでしょうか?

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.5

始点と終点を結んだ線分が円弧の弦になります 移動開始の角度がその時点での円弧の接線の角度ですから これらから円の中心を求めて 単位時間で移動する円弧上の点群を計算して移動させる といったアルゴリズムの方がいいように思います 開始時の角度と弦の角度から時計回り、反時計回りは決定できそうです 始点から単位時間移動した後の接線の角度の変位が 0.05radとは限らないと思いますが ・・・

morogon
質問者

お礼

そうですね、考え方は大体は理解できました。 しかし、曲線を描くように移動させる方法がまったく検討がつきません。 もう少しいろいろと数学を勉強するべきなのでしょうが、 趣味の範疇でやっているのでいまいちプログラミングと両立できません。 ご回答ありがとうございました。 因みに、0.05はいろいろと値を弄ってみて、適当だと思った値です。

  • chie65535
  • ベストアンサー率43% (8524/19373)
回答No.4

まず、 OBJ.mov.theta = atan2 (GOAL.y - OBJ.pos.y , GOAL.x - OBJ.pos.x); は「移動し、OBJ.posが変更されるたびに、再計算」すること。 次に if(OLDtheta - OBJ.mov.theta != 0){     if(OLDtheta>OBJ.mov.theta){         OLDtheta -= 0.05;     }else{         OLDtheta += 0.05;     } } のロジックではダメ。「方向」の概念が組み込まれてないので、反対方向に舵を切り続けます。 以下のようにしましょう。 float delta; delta = OBJ.mov.theta - OLDtheta; if ((delta >= -0.05) && (delta <= 0.05)){     OLDtheta = OBJ.mov.theta; /* 方向が目標の角度に近い */ }else{     if (delta < 0.0) delta += 6.28318530717958; /* 自分から見た目標の方向を(0~360度で)求める */     if (delta >= 3.14159265358979){ /* 目標は右にある */         OLDtheta -= 0.05;         if (OLDtheta < 0.0) OLDtheta += 6.28318530717958; /* 角度がマイナスになったらプラスに補正 */     }else{ /* 目標は左にある */         OLDtheta += 0.05;         if (OLDtheta > 6.28318530717958) OLDtheta -= 6.28318530717958; /* 角度が360度を超えたら360度戻す */     } } なお、これでも「近くに新しい目標が出ると、目標の真横をすり抜ける」ので「目標までの距離と、近寄っているか遠ざかっているかで、加速、減速する」必要があるでしょう。 また「目標への到達判断」も「座標の一致」ではなく「距離」で判定し、真上をすり抜けしないように判定しましょう(例えば、速度10で、残り5の距離まで近付いたら、次のステップでは目標の無効側の距離5の地点に移動してしまいますから、この場合は「到着した」と判定しないといけない)

noname#140971
noname#140971
回答No.3

× 速度20に加速したら、その時点での座標を始点として適当な中間点のY座標をプラスして再計算。 ○ 速度20に加速したら、その時点での座標を始点として適当な中間点のXY座標をプラスして再計算。

morogon
質問者

お礼

ごめんなさい プログラミングは初心者ですが、 数学に至っては、ベクトルや三角関数は完全に独学なので その理論をプログラムで表現できないです。 しかし、考え方自体は大体理解できました ベジェ曲線のようなものでしょうか。

noname#140971
noname#140971
回答No.2

補足: 速度と補完値の関係 速度10の時の中間点で全体の軌跡を計算。 速度20に加速したら、その時点での座標を始点として適当な中間点のY座標をプラスして再計算。 これで、らしくは見えると思いますよ。

noname#140971
noname#140971
回答No.1

プログラマではなくて単なるアパレル関係のデザイナです。 で、適当に聞き流してください。 始点と中間点と終点の3点があって、その間をスムーズな曲線を描くのが課題かと思います。 >1つの関数あるいはデータ列が与えられたとき、 >それを多項式などの関数で近似することを考える。 >補完法では与えられた点を通るような近似式を作り、 >それ以外の点の値を求めることになる。 で、始点と中間点と終点の3点の間に50個なら50個の点座標を発生。 で、後は、座標間を移動するタイムを設定。 つまり、最初から予定の軌道計算は終っていたが良いと思います。 ※上述の引用は、スプライン関数(図形描画ソフトでの自由定規)のそれです。 ※ですから、本当の軌道計算のそれとは違います。 ※本当の軌道計算になりますと、もっと、別の考えになろうかと思います。

関連するQ&A

  • 複製したMCを指定した座標へ配置したいのですが

    こんにちは。 初歩的な質問で申し訳ないのですがよろしくお願いします。 attachMoiveでライブラリ内のMCを数十個複製しそれらをステージ内に 配置する際、4x4、6x6といったように均等に数十個配置する事は 出来るのですが均等に配置するのではなく自分の指定した座標に 1つ1つ配置したいのです。 色々調べましたら、自分の配置したい各場所の各座標(x,y)を 配列を使い変数にするのだと思い、自分なりに作ってみましたところ 1つは指定した座標に配置出来たのですが2つ目以降が上手く 配置出来ません。 var i; var num=50; //複製するmcの数 var pos = {x:50, y:100}; //1つ目の指定座標。              //ここで残り49個のmcの座標も指定。 for (i=0; i<num; i++) { _root.attachMovie("mc", "mc"+i, i); var mc_obj = eval("_root.mc"+i); mc_obj._x = pos._x; mc_obj._y = pos._y; } 一応頭の中ではこういうスクリプトを考えてますが多分間違いが あり何かが足りないのだと思います。 var posのところで2つ目以降の座標の指定の仕方と forの中でmc_obj._xとmc_obj._yにどのように50個分指定した 座標へ配置設定をしてやるのかお分かりくださる方がいらっしゃれば ご教授くださいますようよろしくお願いします。

    • ベストアンサー
    • Flash
  • サインカーブの周期

    あまりサインカーブの事が判っていませんが アドバイスをお願いいたします。 求めたいのは、サインカーブを描いたグラフの周期です。 振幅=yとθ=0の時のグラフの傾き角度を指定する事で 1/4周期のx?を求めたいのですが。どんな式になるのでしょうか? 通常、振幅=1 θ=0の時45°(cos(0)=1)だと 1/4周期のxは1だと思うのですが 式が良くわかりません 宜しくお願いいたします

  • プログラミングの課題、手伝ってください!!

    この俺が書いたプログラムを見てわかるとおり、今は1つのボールにしか、ファンクションがきいていない状況になってます。 これを3つのボール個々に大きさが代わったり、速さが変わったり、でてくるロケーションが変わったりするファンクションをきかせたいんです。 int width =600, height = 600; float d = random(5,40); float d1 = random(5,40); float d2 = random(5,40); float d3 = random(5,40); float x = random(0,width); float x1 = random(0,width); float x2 = random(0,width); float x3 = random(0,width); float y =0; float y1 =0; float y2 =0; float y3 =0; float speed1 = random(1,5); float speed2 = random(2,4); float speed3 = random(1,9); void setup() { size(width,height); background(255); smooth(); noStroke(); } void draw() { background(255); x1 = x1; y1 = y1; speed1 = speed1; d1 = d1; fill(255,0,0); ellipse(x,y,d,d); if(y<=height) { y= y + speed1; d= d1; } else { speed1 = random(1,5); d = random(5,40); y = 0; x = random(0,width); } x2 = x2; y2 = y2; speed2 = speed2; d2 = d2; fill(0,255,0); ellipse(x,y,d,d); if(y<=height) { y= y + speed2; d = d2; } else { speed2 = random(2,4); y = 0; d = random(5,40); x = random(0,width); } x3 = x3; y3 = y3; speed3 = speed3; d3 = d3; fill(0,0,255); ellipse(x,y,d,d); if(y<=height) { y= y + speed3; d= d3; } else { speed3 = random(1,9); y = 0; d = random(5,40); x = random(0,width); } } よろしくお願いします。

  • 関数の出力引数をクラスにするには?

    既出、または基礎の質問でしたらすみません。 ここでも他の検索エンジンでも見つけられなかったので。。。 C++です。 クラスを出力する関数を作りたいのですが、うまくできません。 ソースは以下のとおりです。問題は、プログラム下方のf1(),f2(),main()です。 長くて、そして見づらくてすみません・・・ //////////// #include<stdio.h> class test{ private: int num; float *vec; public: test(int n=1); //ctor ~test(); //dtor int getnum(){return num;} float* getvec(); void set(int,float*); void show(); }; test::test(int n){ num = n; vec = new float[n]; for(int i=0; i<n; i++) vec[i] = (float)i; } test::~test() {delete[] vec;} float* test::getvec(){ float *v; v = new float[num]; for(int i=0; i<num; i++) v[i] = vec[i]; return v; } void test::set(int n, float *v){ num = n; vec = new float[n]; for(int i=0; i<n; i++) vec[i] = v[i]; } void test::show(){ for(int i=0; i<num; i++) printf("%d: %g\n",i,vec[i]); } void f1(test &x, test &y){ int n; float *v; n = x.getnum(); v = x.getvec(); for(int i=0; i<n-1; i++) v[i] = 2.0*v[i]; y.set(n-1,v); } test f2(test x){ test y; //* int n; float *v; n = x.getnum(); v = x.getvec(); for(int i=0; i<n-1; i++) v[i] = 2.0*v[i]; y.set(n-1,v); return y; //** } void main(){ test x,y; int n = 4; float v[4] = {1.0,2.0,3.0,4.0}; printf("x:\n"); x.set(n,v); x.show(); printf("f1:\n"); f1(x,y); y.show(); printf("f2:\n"); y=f2(x); y.show(); } //////////// これを実行すると x: 0: 1 1: 2 2: 3 3: 4 f1: 0: 2 1: 4 2: 6 f2: 0: 7.38979e-38 1: 7.38979e-38 2: 6 となります。 関数f2がうまく動かない理由がわかりません。。。 出力引数にクラスはとれないのでしょうか?? よろしくお願いします。

  • エクセルで回転する座標の出し方

    エクセルで回転する座標の出し方 (例) 座標X100、Y100の点から好きな角度を回したときのX、Yの座標の求め方 回転中心はX0、Y0 回転方向は反時計回り 例で言えば X141.421、Y0  が0度       X0、Y141.421  が90度       X-141.421、Y0 が180度       X0、Y-141.421 が270度 エクセルでの問題点は 1.角度計算がラジアンになる デグリも関数はあるけど書式がわからない  無理やり(PI()/180)などを使ってるがアークタンジェントでは書式がわからない 2.正と負の計算式・答えが負になるときの処理ができない  回転角度が270度とか 今電卓で打っているのは 100/100=ATAN ----------------------最初の角度 100*100+100*100の答えのルート--------回転中心からの直線距離 最初の角度+動かしたい角度------------求めたい座標の角度 SIN求めたい座標の角度*直線距離-------Y座標 答え COS求めたい座標の角度*直線距離-------X座標 答え 最初のX、Y座標と 動かしたい角度を入れると答えが出るような 物が作りたいです よろしくお願いします エクセル2000 WINXP

  • 2つのMC(ドラッグで移動可能)から等しい距離にMCを配置したい

    ドラッグで移動可能な二つのムービークリップMCAとMCBから等しい距離の位置に三つ目のムービークリップMCCを配置したいです。 MCCはMCA、MCBがドラッグで移動されると、MCAとMCBへの距離が等しい位置(厳密に等しくなくても良い)に移動させたいです。(結果、3つのムービークリップは一直線上に並ぶ) オーサリングツールは『ParaFla!』ActionSctiptは1.0相応で以下の様に作ってみましたが、いつまで経っても落ち着かないので改善したいです。 ※スクリプトのスペースは全角で記述。 ※ベクトルの計算に『HAKUHIN's home page』で公開されているライブラリを使用しました。 http://hakuhin.hp.infoseek.co.jp/main/as/vector.html ■ライブラリの取り込み _root上に配置したスクリプトに #FILE "vec2d.as" と記述。 ■MCA、MCB _root上にMCAを深度0、[固定]で配置。 _root上にMCBを深度1、[固定]で配置。 MCAとMCBにテキストで●を配置。 MCAとMCBに以下スクリプトを記述。 on (press){  this.startDrag(); // ドラッグを開始する } - on (release, releaseOutside){  this.stopDrag (); // ドラッグを解除する } ■MCC _root上にMCCを深度2に配置。 MCCにテキストで●を配置し、以下スクリプトを記述。 onClipEvent (enterFrame){  c_to_a = _root.Vec2dCreate(_root.MCA._x-_x,_root.MCA._y-_y);  c_to_b = _root.Vec2dCreate(_root.MCB._x-_x,_root.MCB._y-_y);  length_c_to_a=_root.Vec2dLength(c_to_a);  length_c_to_b=_root.Vec2dLength(c_to_b);  if(length_c_to_a > length_c_to_b){   long=c_to_a;  }else{   long=c_to_b;  }  pos_c = _root.Vec2dCreate(_x,_y);  long=_root.Vec2dNormalize(long);  long=_root.Vec2dScale(long, 5);  pos=_root.Vec2dAdd(pos_c,long);  _x=pos.x;  _y=pos.y; } 上記のようにして作成したものを以下に置きます。 http://carken.web.fc2.com/osiete/test.html 動かしてみると、いつまでたっても、細かく動いて止まってくれません。 厳密に同じ距離でなくても良く、ある程度見た目にOKかなってところで止まるようにしたいです。 アドバイスありましたら、よろしくお願いいたします。

    • ベストアンサー
    • Flash
  • 【Objective-C】arc4random

    皆様こんばんは。 Objective-C(Cocos2Dフレームワーク)でiPhoneアプリ開発をしております。 ランダム関数「arc4random」および「arc4random_uniform」についての質問宜しいでしょうか。 以下のように、あるレイヤーに対して画面内のランダムな位置へ4回連続移動するアクションメソッドを組んだのですが、初回の移動アクション(for文の変数jの値が0の時)のみ、arc4random_uniform()を噛ませたX座標(pos_x[0])とY座標(pos_y[0])が同値となってしまいます。 つまり、y=x上の座標にしか移動出来ません。これはarc4random()に置き換えてみてもダメでした。 2回目のループ以降(j >= 1)ではランダムな位置へ移動してくれるのですが、どうにも腑に落ちません。擬似乱数に対して根本的な認識不足があるのでしょうか? 具体的な原因・解決法などございましたら、ご教示頂ければ幸いです。 宜しくお願い致します。 ========================================================= - (void)randomAction:(id)sender{ CCLayer *layerI = (CCLayer *)[self getChildByTag:imgLayerLockOn];//アクション実行中のレイヤーを呼び出し [layerI stopAllActions];//実行中のアクションを停止 CGSize winSize = [[CCDirector sharedDirector] winSize];//画面サイズを取得 int win_width = winSize.width;//横幅を代入 int win_height = winSize.height;//縦幅を代入 NSMutableArray *moveRandomActions = [NSMutableArray array];//CCSequenceに組み込むアクション用の空配列 for (int j = 0; j < 5; j++){ int pos_x[j]; int pos_y[j]; pos_x[j] = arc4random_uniform(win_width);★ランダムなX座標取得 pos_y[j] = arc4random_uniform(win_height);★ランダムなY座標を取得 CCLOG(@"j == %d, pos_x is %d, pos_y is %d", j, pos_x[j], pos_y[j]);//■ログ:取得したランダム座標 id moveRandom[j]; moveRandom[j] = [CCMoveTo actionWithDuration:2 position:ccp(pos_x[j], pos_y[j])]; [moveRandomActions addObject:moveRandom[j]]; } id moveRandomSequence = [CCSequence actionWithArray:moveRandomActions];//配列にアクションを代入 id moveRandomEaseOut = [CCEaseOut actionWithAction:moveRandomSequence rate:2];//総アクションの減速効果 [layerI runAction:moveRandomEaseOut]; }  ■CCLOGの出力結果例■  ログ1:j == 0, pos_x is 40, pos_y is 40 (※←初回のみ同値となってしまう)  ログ2:j == 1, pos_x is 128, pos_y is 306  ログ3:j == 2, pos_x is 247, pos_y is 86  ・  ・  

  • java の配列についての質問です。

    java の配列についての質問です。 java 及び C++についての知識は初心者です。 public abstract class Plan implements Shapeable { Shape[] shape = new Shape[5]; Shape[0] = new Rectangle(10,10,10,10); // x,y 座標 及び 長さ、高さ Shape[1] = new Triangle(10,10,30,10,20,20); // 3点間の座標        Shape[2] = new Triangle(20,10,40,10,30,20);        Shape[3] = new Triangle(15,15,35,15,25,25); Shape[4] = new Circle(20,20,20); // 円の座標と半径     public float[] calculaterAreas(){ ??????????????????? } 内容としては複雑なのですが、三角形、四角形、円の面積をShapeというclassの配列にあるデータ(座標や長さなど) を使ってShapeの配列のデータを置き換えてfloatのデータとして返すんですが・・・・。どうやっていいのかさっぱり わかりません。面積については、Rectangle,Triangle,Circleのクラスでそれぞれ計算できるようになっているのですが、それを持ってくる方法もわかりません・・・どうしたらいいのか教えてください 宜しくお願いします。 ちなみに Rectangle,Triangle,Circle class の area の メソットは --- Rectangle class public class Rectangle extends Shape{ int x; int y; int width; int height; public float area(Rectangle r) { return r.width * r.height; } --- Circle class public class Circle extends Shape{ int x; int y; int radius; public float area(Circle c) { return (float) (c.x * c.y * 3.14); } } --- Triangle class public class Triangle extends Shape{ int x; int y; int x2; int y2; int x3; int y3; public float area(Triangle t) { float dt1,dt2,dt3; float s1; float area1; dt1 = Point.distance(x, y); // Point は dt2 = Point.distance(x2, y2); dt3 = Point.distance(x3, y3); s1 = (dt1+dt2+dt3)/2; area1 = (float) Math.sqrt((s1-dt1)*(s1-dt2)*(s1-dt3)); return area1; } } *** Shape class public abstract class Shape implements Shapeable { public abstract float area(Shape obj); } *** Shapeable インターフェイス public interface Shapeable { float area (Shape obj); } ** コンストラクター等は省略してあります。

    • ベストアンサー
    • Java
  • 続、VB 座標軸の回転?

    昨日 http://okwave.jp/qa/q7871613.html で質問したものです。 プログラムを作っていて上手に動かないので再度質問です。 xx = x0 - cx yy = y0 - cy x= xx * cosA - yy * sinA + cx y= xx * sinA + yy * cosA + cy x0 = x y0 = y xx:Xの中心からの相対座標 yy:Yの中心からの相対座標 x0:Xの現在地 y0:Yの現在地 cx:三角形の中心X cy:三角形の中心Y x:座標変換後のX y:座標変換後のY A:角度 このようにプログラムしたのですが、回転をさせると渦巻き状に広がってしまいます。 以下のようにプログラミングしたつもりなのですが、うまくいきません。 悪そうな部分を教えてくれるとありがたいです。 >> リーダーの座標を実座標を差し引いて原点(0,0)とし、メンバーの座標をリーダーからの相対座標(x1,y1)(x2,y2)・・・・とします 例えばメンバー(x1,y1)をリーダー中心に半時計周りへ10度回転させた場合の、移動先の座標を(xx1,yy1)とすると・・・ θ=10度(VBではラジアン単位へ変換してください) xx1=x1 * cosθ - y1 * sinθ yy1=x1 * sinθ + y1 * cosθ これで回転して移動した先xx1、yy1が求まります。 最初に差し引いた実座標を足して戻して完成です。

  • ヘッダファイルと構造体

    typedef struct{ float x; float y; float z; }Point; typedef struct { struct Point p1; struct Point p2; }Rect; とヘッダファイルに入力しコンパイルしてみると struct Point p1; struct Point p2; のPointが未定義の構造体とエラーが出ます。 どのように書けばいいのでしょう??

専門家に質問してみよう