六帖のかたすみ

DVを受けていた男性。家を脱出して二周目の人生を生きています。自閉症スペクトラム(受動型)です。http://rokujo.org/ に引っ越しました。

列車の始点と終点

列車オブジェクトを画面上に配置するにあたって、その座標が問題となる。路線の上にそのまんま乗せると、上り電車と下り電車が衝突する。怖いし見づらい。したがって、若干線路からずらす必要がある。
日本の電車は左側通行なので、上図でいうと直線ABから一定距離離れた直線A1B'上を列車が動けばよい。この一定距離をrとする。
まず点A1の位置を求める。駅Aの位置を(Xa, Ya), 駅Bの位置を(Xb, Yb)とする。ベクトルABは(Xb-Xa, Yb-Ya)となる。
左側通行を実現するために単位法線ベクトルN=(Nx, Ny)を求める。ABを左側に90度回転して、さらにABの長さで割る。ABを90度回転したベクトルは(Ya-Yb, Xb-Xa)なので
Nx = (Ya-Yb) * Math.sqrt((Xb-Xa)^2 + (Yb-Ya)^2)
Ny = (Xb-Xa) * Math.sqrt((Xb-Xa)^2 + (Yb-Ya)^2)
あとはこれをr倍して(Xa, Ya)に足してやれば、点A1の位置が求まる。これが列車の始点になる。rは見た目から考えて一定値にはにならないだろう。倍率やスキンに応じて変更する。
次に駅Bの停車位置B1を求める。B1は駅Bに法線ベクトルを足したB'の位置ではない。B'とB''の間をつなぐ経路が必要だ。これを実現するため、駅Cに登場してもらう必要がある。B, CをBCから一定距離離した点B'', C'を考える。すると直線A1B'と直線B''Cの交点が、求める列車の停止位置B1になる。
さてB'、B''、C'はA1と同じ手法を使って求められるので、あとは、2直線の交点を求める作業だけだ。二元連立方程式を使ってもいいけど、でもそれだと万が一X軸Y軸に垂直な直線になった時困るなぁ。と思って探していたら、ちゃんと交点を求める手法があった。外積を使うらしい。
4点からなる交点の求め方 画像処理ソリューション
この式を使うなら、それぞれA1=(X1, Y1), B'=(X2, Y2), B''=(X3, Y3), C'=(X4, Y4)とすれば
S1 = {(X4 - X3) * (Y1 - Y3) - (Y4 - Y3) * (X1 - X3)} / 2
S2 = {(X4 - X3) * (Y3 - Y2) - (Y4 - Y3) * (X3 - X2)} / 2
交点の座標は
X = X1 + (X2 - X1) * S1 / (S1 + S2)
Y = Y1 + (Y2 - Y1) * S1 / (S1 + S2)
なんと4行で書ける!エレガントすぎる!図形的には、外積で三角形の面積S1とS2を求め、その比を使ってベクトルを定数倍する、という意味になる。これは素晴らしい。
あとは、順次C1,D1と列車の位置を求めていくことになる。他線への乗り入れがあることを考えると、列車の位置は駅によって一定ではない。列車ごとにそれぞれ計算することになるだろう。また、行き先表示の文字列は、上りは左側・下りは右側、なんて単純にはならないから、さっき求めた単位法線ベクトルを使って、線路と垂直な位置に文字を配置するとよいのでは。