#apply
#include "../_include.txt"
#include "../../define/_vector2.txt"

/*
@param
円の中心点x
y
移動後の中心点x
y
半径
線分の始点x
y
線分の長さ(左)
線分の半径(左)
線分の長さ(右)
線分の半径(右)
線分の角度
回転後の角度

@return
衝突時間 (-1:衝突なし)
円の中心点x
y
法線x
y
衝突点x
y
衝突点における速度x
y
*/
cev[CEV_CIRCLE_TO_ROTATING_SEGMENT] .name(">>>>動く円と回る線分の衝突") bl {
    defv {
        r_time = TV_RETURN
        r_cx1
        r_cy1
        r_nx
        r_ny
        r_hx
        r_hy
        r_wx
        r_wy

        a_sx1 = TV_CIRCLE_TO_ROTATING_SEGMENT
        a_sy1
        a_ex1
        a_ey1
        a_ra1
        a_sx2
        a_sy2
        a_lengthL
        a_radiusL
        a_lengthR
        a_radiusR
        a_angleS
        a_angleE//13

        sumRad
        hit
        lnx
        lny
        lcx
        lcy
        left
        right
        chkIdx
        chkTime
        chkAngle
        chkDist
        chkRad
        ax
        ay
        bx
        by
        hnx
        hny//32
    }

    def {
        //判定回数
        MAX_CHECK = 8
        UNIT_ANGLE = 10
        UNIT_LOOP = (360 * UNIT_ANGLE)//一回転
    }

    //返り値を初期化
    r_time = -1

    //簡易判定
    //円と軸+半径
    sumRad = a_ra1 + max(a_radiusL + a_lengthL, a_radiusR + a_lengthR)
    V2_ifRectOverlap_ex(a_sx1, a_ex1, a_sx2, a_sx2, sumRad,
    EMPTY_BLOCK, ABORT_BLOCK)

    //フリッパーの直線部分の法線
    lnx = muldiv(a_radiusL - a_radiusR, UNIT_NORMAL, a_lengthL + a_lengthR)
    lny = sqrt(UNIT_NORMAL * UNIT_NORMAL - lnx * lnx, 1)

    //簡易判定用のフリッパーの幅
    sumRad = a_ra1 + max(a_radiusL, a_radiusR)
    left  = muldiv(lnx, a_radiusL, UNIT_NORMAL) - a_lengthL//左端の円と線分の境目
    right = muldiv(lnx, a_radiusR, UNIT_NORMAL) + a_lengthR//右端の円と線分の境目

    //判定開始
    hit = FALSE
    @loop MAX_CHECK .dst(chkIdx) bl {
        //時間
        chkTime = lerp(0, UNIT_SECOND, chkIdx, MAX_CHECK - 1)
        //線分の角度
        chkAngle = lerp(a_angleS, a_angleE, chkTime, UNIT_SECOND)
        //線分を基準とする玉の位置
        V2_lerp(ax, a_sx1, a_ex1, chkTime, UNIT_SECOND)
        V2_asSub(ax, a_sx2)
        V2_rotate(lcx, ax, -chkAngle, UNIT_ANGLE)

        //直線と円の距離を判定する
        @if `abs(lcy) <= sumRad bl {
            //線分と判定する
            @if `left <= lcx && lcx <= right bl {
                chkRad = a_ra1
                V2_set(ax, lnx, lny * (lcy > 0 ? 1 : -1))
                V2_muldiv(bx, ax, a_radiusL, UNIT_NORMAL)

                //線分と円の中心点の距離(内積)
                chkDist = ((lcx - bx) * ax + (lcy - by) * ay) / UNIT_NORMAL
                @if chkDist <= chkRad bl {
                    //法線
                    V2_copy(hnx, ax)

                    hit = TRUE
                    @break

                }

            //両端の円と判定する
            } .else bl {
                //左端
                @if lcx <= left bl {
                    chkRad = a_ra1 + a_radiusL
                    V2_set(ax, lcx + a_lengthL, lcy)

                //右端
                } .elif right <= lcx bl {
                    chkRad = a_ra1 + a_radiusR
                    V2_set(ax, lcx - a_lengthR, lcy)

                //例外
                } .else bl {
                    @continue

                }

                //円と円の距離
                //ゼロ除算を避ける為、重なっている場合はスルーする
                V2_magSq(chkDist, ax)
                @if `chkDist > 0 && chkDist <= chkRad * chkRad bl {
                    //距離
                    chkDist = sqrt(chkDist, 1)
                    //法線
                    V2_muldiv(hnx, ax, UNIT_NORMAL, chkDist)

                    hit = TRUE
                    @break

                }

            }

        }

    }

    //衝突していない
    @if hit == FALSE ABORT_BLOCK

    //法線
    V2_rotate(r_nx, hnx, chkAngle, UNIT_ANGLE)

    //衝突時の円の位置 = lerp(円の位置, 円の移動後の位置, 衝突時間, 時間単位) + 法線 * めり込み量
    //depth = chkRad - chkDist
    V2_lerp(r_cx1, a_sx1, a_ex1, chkTime, UNIT_SECOND)
    V2_asAddMuldiv(r_cx1, r_nx, chkRad - chkDist, UNIT_NORMAL)
    
    //衝突点 = 衝突時の円の位置 - 法線 * 円の半径
    V2_addMuldiv(r_hx, r_cx1, r_nx, -a_ra1, UNIT_NORMAL)

    //衝突点における速度
    @if a_angleS == a_angleE bl {
        //回転していない場合はゼロ
        V2_set(r_wx, 0, 0)

    } .else bl {
        //軸から衝突点までの差
        V2_sub(ax, r_hx, a_sx2)

        //距離
        V2_mag(bx, ax)
        bx = max(bx, 1)

        //周速度
        V2_getCircumSpeed(by, bx, a_angleE - a_angleS, UNIT_LOOP)

        //衝突点における速度
        V2_set(r_wx,
        muldiv(-ay, by, bx),
        muldiv( ax, by, bx)
        )

    }

    //衝突時間を返す
    r_time = chkTime

}