이미지의 네 점 중 한 점(P_3)을 이동시켜 크기를 조정하려고 합니다.
여기서 한 가지 조건이 있는데 기존의 X-Y 비율을 지켜야 한다는 것입니다.
비율은 아래와 같이 정의할 수 있습니다. ratio = \frac{|\overrightarrow{P_4 - P_3}|}{|\overrightarrow{P_2 - P_1}|} P_2의 x 값을 P의 x으로 바꾸고 length = \overrightarrow{|P_2 - P_1|}의 길이를 구합니다.
P_4의 y값은 앞서 구한 length에 ratio를 곱하여 구할 수 있습니다. {P_4}_.y = {P_1}_.y + length * ratio 위에서는 아주 특수한 경우에 대해서 생각을 했었고 우리는 일반적인 경우(회전된 경우 포함)에 대해서 처리해야만 합니다. 우선 {P_2}^\prime는 아래와 같이 구할 수 있습니다. \begin{align} AxisX &= \frac{\overrightarrow{P_2 - P_1}}{\overrightarrow{|P_2 - P_1|}}\\ dot &= AxisX \cdot \overrightarrow{P - P_1}\\ {P_2}^\prime &= P_1 + AxisX * dot\\ \end{align} 그리고 {P_4}^\prime는 아래와 같이 구할 수 있습니다. \begin{align} AxisY &= \frac{\overrightarrow{P_4 - P_1}}{\overrightarrow{|P_4 - P_1|}}\\ {P_4}^\prime &= P_1 + AxisY * dot*ratio\\ \end{align} 최종적으로 {P_3}^\prime는 아래와 같습니다. {P_3}^\prime = P_1 + AxisX *dot + AxisY * dot * ratio 이로써 기존의 비율을 유지한 채 직사각형의 크기를 바꿀 수 있습니다.
아래는 샘플 코드입니다. 긴 변을 기준으로 ratio를 구하고 계산하였습니다.
여기서 한 가지 조건이 있는데 기존의 X-Y 비율을 지켜야 한다는 것입니다.
비율은 아래와 같이 정의할 수 있습니다. ratio = \frac{|\overrightarrow{P_4 - P_3}|}{|\overrightarrow{P_2 - P_1}|} P_2의 x 값을 P의 x으로 바꾸고 length = \overrightarrow{|P_2 - P_1|}의 길이를 구합니다.
P_4의 y값은 앞서 구한 length에 ratio를 곱하여 구할 수 있습니다. {P_4}_.y = {P_1}_.y + length * ratio 위에서는 아주 특수한 경우에 대해서 생각을 했었고 우리는 일반적인 경우(회전된 경우 포함)에 대해서 처리해야만 합니다. 우선 {P_2}^\prime는 아래와 같이 구할 수 있습니다. \begin{align} AxisX &= \frac{\overrightarrow{P_2 - P_1}}{\overrightarrow{|P_2 - P_1|}}\\ dot &= AxisX \cdot \overrightarrow{P - P_1}\\ {P_2}^\prime &= P_1 + AxisX * dot\\ \end{align} 그리고 {P_4}^\prime는 아래와 같이 구할 수 있습니다. \begin{align} AxisY &= \frac{\overrightarrow{P_4 - P_1}}{\overrightarrow{|P_4 - P_1|}}\\ {P_4}^\prime &= P_1 + AxisY * dot*ratio\\ \end{align} 최종적으로 {P_3}^\prime는 아래와 같습니다. {P_3}^\prime = P_1 + AxisX *dot + AxisY * dot * ratio 이로써 기존의 비율을 유지한 채 직사각형의 크기를 바꿀 수 있습니다.
아래는 샘플 코드입니다. 긴 변을 기준으로 ratio를 구하고 계산하였습니다.
/* 움직일 포인터를 구함 */ int idx = (this as IPath).PointSet.FindIndex(x => x.Equals(pt)); var OppositeP = (idx + path.PointSet.Count / 2) % path.PointSet.Count; var PreviousP = (idx + (path.PointSet.Count - 1)) % path.PointSet.Count; var NextP = (idx + 1) % path.PointSet.Count; var PrevV = path.PointSet[PreviousP] - path.PointSet[OppositeP]; double PrevLength = PrevV.Length; PrevV.Normalize(); var NextV = path.PointSet[NextP] - path.PointSet[OppositeP]; double NextVLength = NextV.Length; NextV.Normalize(); double _dx = P.X - path.PointSet[OppositeP].X; double _dy = P.Y - path.PointSet[OppositeP].Y; var dir = new Vector(_dx, _dy); if (PrevLength > NextVLength) { double ratio = NextVLength / PrevLength; double dot = MathSet.DotProduct(PrevV.X, PrevV.Y, dir.X, dir.Y); path.PointSet[PreviousP] = path.PointSet[OppositeP] + PrevV * dot; path.PointSet[NextP] = path.PointSet[OppositeP] + NextV * dot * ratio; path.PointSet[idx] = path.PointSet[OppositeP] + PrevV * dot + NextV * dot * ratio; } else { double ratio = PrevLength / NextVLength; double dot = MathSet.DotProduct(NextV.X, NextV.Y, dir.X, dir.Y); path.PointSet[PreviousP] = path.PointSet[OppositeP] + PrevV * dot * ratio; path.PointSet[NextP] = path.PointSet[OppositeP] + NextV * dot; path.PointSet[idx] = path.PointSet[OppositeP] + PrevV * dot * ratio + NextV * dot; }
댓글
댓글 쓰기