이미지의 네 점 중 한 점($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;
}
댓글
댓글 쓰기