放物線を包絡線で描くにはもう一つほかの方法がある。
「直線 L 上の任意の点 Q と L 上にない点 P の間の直線 PQ と、
直線 L上で交わる直線群」の包絡線は放物線になる。
描いてみる
t = Turtle ! create 1 lineWidth (red) lineColor. NUM = 51. SWEEP_ANGLE = 120. LENGTH = 100. TLENGTH = 300. [ | i ; deg | deg = SWEEP_ANGLE * (i-1) / (NUM-1) - ( SWEEP_ANGLE/2 ) + 270. t ! (red) lineColor 1 linewidth penup 0 (LENGTH) moveto. t ! pendown (deg) direction (LENGTH/cos(deg-270)) forward penup. t ! makefigure. t ! (blue) lineColor 1 linewidth. t ! penup 90 leftturn (TLENGTH) forward. t ! 180 leftturn pendown (TLENGTH*2) forward. t ! makefigure. ] ! (NUM) repeat.放物線ぽいのが出てきた。
中央の点から角度を変えながら、LENGTH/cosθ長の直線(赤)を引き、その端点から直行する線(青)を描いている。
一見、直行しているように見えないがそれは目の錯覚。
跳ね返りを使って描く
上のコードは cos で辺長を決めていたが、今度は三角関数は使わずにタートルの collision を使って描いてみよう。
- 底辺を描く。
- タートルの角度を決めて底辺にぶつかるまで少しずつ進む。
- ぶつかったら直角に左右に線を引く。
t = Turtle ! create 10 lineWidth (Green) lineColor 0.1 scale.
FLOOR = t ! penup -300 0 moveto pendown 300 0 moveto penup makefigure.
t ! 1 lineWidth.
// 底辺に到達したときの処理
TLENGTH = 300.
t:collision = [ | o | 
  // 他角度軌跡との衝突や反射後の底辺との衝突は回避
  [ (o == FLOOR) ! ( self:collisioned ! not) allTrue ] ! then [
    self:collisioned = true.
    ! makefigure.
    ! (blue) lineColor 1 linewidth.
    ! penup 90 leftturn (TLENGTH) forward.
    ! 180 leftturn pendown (TLENGTH*2) forward.
    ! makefigure.
  ] execute.
].
NUM = 51.
SWEEP_ANGLE = 120. //掃角
LENGTH = 100.
[ | i ; deg |
  deg = SWEEP_ANGLE * (i-1) / (NUM-1) - ( SWEEP_ANGLE/2 ) + 270.
  t ! penup 0 (LENGTH) moveto (deg) direction.
  t ! (red) lineColor 1 linewidth  pendown.
  t:collisioned = false.
  [ t:collisioned ! not] ! while [ t ! 1 forward ] execute.
  t ! makefigure.
] ! (NUM) repeat.
長くなったがこちらの方がドリトルっぽいコードかもしれない。
できる図形は先ほどのものと大体同じ形。
底辺は衝突判定が突き抜けないように少し太く描いてある。
包絡線が放物線であることを確認する。
できた包絡線が放物線になっていることを確認する。
固定点 P の座標を ( 0,P )、動点Qの座標を(q,0)とすると、
包絡線を構成する直線群は、
y=(q/P)(x-q)
であらわされる。
これをパラメータ q で整理すると次の式が得られる。
q2 - xq + yP = 0 
qが実数解をもつためにはこの式の判別式D(b2-4ac) が非負でなければならない。
D = x2 - 4yP ≧ 0 
y ≧ (1/4P)x2
今度は前回の記事の放物線とは違って最初から正立しているので簡単に放物線の式になった。



0 件のコメント:
コメントを投稿