[TypeScript] 제스처로 대화하기. #13 - 플릭(with. 범위) 편

이번 편은 이전 편으로부터 이어집니다.

플릭의 이동 범위를 제한하고 싶다면 어떻게 해야 할까요? 단순히 계산 시마다 대상이 유효한 범위 내에 있는지 확인할 수도 있을 것입니다. 하지만 이는 다소 비합리적으로 보일 수 있습니다. 우리는 조금 더 영리한 방법으로 이를 해결할 수 있습니다.

최대 변위

변위가 아래를 만족해야 한다고 합시다.

$$\begin{aligned} & s \leq k \end{aligned}$$

우리는 수식을 다음과 같이 전개할 수 있습니다.

$$\begin{aligned} & s = v_0t + \frac{1}{2}at^2 \leq k \\ & at^2 + 2v_0t - 2k \leq 0 \\ & a(t^2 + \frac{2}{a}v_0t - \frac{2}{a}k) \leq 0 \end{aligned}$$

만약 \(t^2 + \frac{2}{a}v_0t - \frac{2}{a}k = 0\) 이라면,

$$\begin{aligned} & t^2 + \frac{2}{a}v_0t - \frac{2}{a}k = 0 \\ & t^2 + \frac{2}{a}v_0t + (\frac{v_0}{a})^2 = (\frac{v_0}{a})^2 + \frac{2}{a}k \\ & (t + \frac{v_0}{a})^2 = (\frac{v_0}{a})^2 + \frac{2}{a}k \\ & t + \frac{v_0}{a} = \pm\sqrt{(\frac{v_0}{a})^2 + \frac{2}{a}k} \\ & t = -\frac{v_0}{a}\pm\sqrt{(\frac{v_0}{a})^2 + \frac{2}{a}k} \\ & t = -\frac{v_0\pm\sqrt{{v_0}^2 + 2ak}}{a} \end{aligned}$$

이므로,

$$a(t + \frac{v_0 + \sqrt{{v_0}^2 + 2ak}}{a})(t + \frac{v_0 - \sqrt{{v_0}^2 + 2ak}}{a}) \leq 0$$

이다. 따라서 \(a < 0\) 일 경우,

$$\begin{aligned} & (t + \frac{v_0 + \sqrt{{v_0}^2 + 2ak}}{a})(t + \frac{v_0 - \sqrt{{v_0}^2 + 2ak}}{a}) \geq 0 \\ & t \leq -\frac{v_0 - \sqrt{{v_0}^2 + 2ak}}{a} \lor t \geq -\frac{v_0 + \sqrt{{v_0}^2 + 2ak}}{a} \end{aligned}$$

\(a \geq 0\) 일 경우,

$$\begin{aligned} & (t + \frac{v_0 + \sqrt{{v_0}^2 + 2ak}}{a})(t + \frac{v_0 - \sqrt{{v_0}^2 + 2ak}}{a}) \leq 0 \\ & t \geq -\frac{v_0 + \sqrt{{v_0}^2 + 2ak}}{a} \land t \leq -\frac{v_0 - \sqrt{{v_0}^2 + 2ak}}{a} \end{aligned}$$

그리고 \(0 \leq t \leq -\frac{v_0}{a}\) 이므로, \(a < 0\) 일 경우,

$$\begin{aligned} & 0 \leq t \leq min(-\frac{v_0}{a}, -\frac{v_0 - \sqrt{{v_0}^2 + 2ak}}{a}) \\ & 0 \leq t \leq -\frac{v_0 - \sqrt{{v_0}^2 + 2ak}}{a} \end{aligned}$$

\(a \geq 0\) 일 경우,

$$\begin{aligned} & max(0, -\frac{v_0 + \sqrt{{v_0}^2 + 2ak}}{a}) \leq t \leq min(-\frac{v_0}{a}, -\frac{v_0 - \sqrt{{v_0}^2 + 2ak}}{a}) \\ & max(0, -\frac{v_0 + \sqrt{{v_0}^2 + 2ak}}{a}) \leq t \leq -\frac{v_0}{a} \end{aligned}$$

최소 변위

\(s \geq k\) 인 경우에는 부등호 방향이 반대가 되므로 결과는 아래와 같습니다. \(a < 0\) 일 경우,

$$\begin{aligned} & (t + \frac{v_0 + \sqrt{{v_0}^2 + 2ak}}{a})(t + \frac{v_0 - \sqrt{{v_0}^2 + 2ak}}{a}) \leq 0 \\ & t \geq -\frac{v_0 - \sqrt{{v_0}^2 + 2ak}}{a} \land t \leq -\frac{v_0 + \sqrt{{v_0}^2 + 2ak}}{a} \end{aligned}$$

\(a \geq 0\) 일 경우,

$$\begin{aligned} & (t + \frac{v_0 + \sqrt{{v_0}^2 + 2ak}}{a})(t + \frac{v_0 - \sqrt{{v_0}^2 + 2ak}}{a}) \geq 0 \\ & t \leq -\frac{v_0 + \sqrt{{v_0}^2 + 2ak}}{a} \lor t \geq -\frac{v_0 - \sqrt{{v_0}^2 + 2ak}}{a} \end{aligned}$$

마찬가지로 \(0 \leq t \leq -\frac{v_0}{a}\) 이므로, \(a < 0\) 일 경우,

$$\begin{aligned} & max(0, -\frac{v_0 - \sqrt{{v_0}^2 + 2ak}}{a}) \leq t \leq min(-\frac{v_0}{a}, -\frac{v_0 + \sqrt{{v_0}^2 + 2ak}}{a}) \\ & max(0, -\frac{v_0 - \sqrt{{v_0}^2 + 2ak}}{a}) \leq t \leq -\frac{v_0}{a} \end{aligned}$$

\(a \geq 0\) 일 경우,

$$\begin{aligned} & 0 \leq t \leq min(-\frac{v_0}{a}, -\frac{v_0 + \sqrt{{v_0}^2 + 2ak}}{a}) \\ & 0 \leq t \leq -\frac{v_0 + \sqrt{{v_0}^2 + 2ak}}{a} \end{aligned}$$

\(t\)의 범위

따라서 \(t\)의 범위는 \(a < 0\) 일 경우,

$$\begin{aligned} & max(0, -\frac{v_0 - \sqrt{{v_0}^2 + 2ak_{min}}}{a}) \leq t \leq min(-\frac{v_0}{a}, -\frac{v_0 - \sqrt{{v_0}^2 + 2ak_{max}}}{a}) \\ & max(0, -\frac{v_0 - \sqrt{{v_0}^2 + 2ak_{min}}}{a}) \leq t \leq -\frac{v_0 - \sqrt{{v_0}^2 + 2ak_{max}}}{a} \end{aligned}$$

\(a \geq 0\) 일 경우, 일 경우,

$$\begin{aligned} & max(0, -\frac{v_0 + \sqrt{{v_0}^2 + 2ak_{max}}}{a}) \leq t \leq min(-\frac{v_0}{a}, -\frac{v_0 + \sqrt{{v_0}^2 + 2ak_{min}}}{a}) \\ & max(0, -\frac{v_0 + \sqrt{{v_0}^2 + 2ak_{max}}}{a}) \leq t \leq -\frac{v_0 + \sqrt{{v_0}^2 + 2ak_{min}}}{a} \end{aligned}$$

초기 시점 즉, \(t = 0\) 일 때, 대상이 유효 범위 내에 존재함을 가정하면 아래와 같이 단순화할 수 있습니다.

\(a < 0\) 일 경우,

$$t \leq -\frac{v_0 - \sqrt{{v_0}^2 + 2ak_{max}}}{a}$$

\(a \geq 0\) 일 경우,

$$t \leq -\frac{v_0 + \sqrt{{v_0}^2 + 2ak_{min}}}{a}$$

또 \({v_0}^2 + 2ak < 0\) 인 경우, 허근을 가지므로 어떠한 경우에도 경계에 도달할 수 없습니다. 따라서 아래와 같이 단순화할 수 있습니다.

$$t \leq -\frac{v_0}{a}$$

코드로 나타내면 다음과 같습니다.

function findDuration(
    initialVelocity: number,
    acceleration: number,
    minDisplacement: number,
    maxDisplacement: number
): number {
    if(acceleration === 0) { return Infinity; }

    let D = initialVelocity ** 2 +
        2 * acceleration * (
            acceleration < 0 ?
                maxDisplacement :
                minDisplacement
        );
    return D > 0 ?
        -(initialVelocity + Math.sign(acceleration) * Math.sqrt(D)) / acceleration :
        -initialVelocity / acceleration;
}

시리즈는 다음 편에서 계속됩니다. 읽어주셔서 감사합니다!

묻고 답하기

개인적인 판단에 의해 적절하다고 여겨지는 경우, 모두가 볼 수 있도록 이곳에 문답이 추가됩니다. 그렇지 않더라도 질문에 대한 답변은 별도로 이루어집니다.