2D 좌표에서 사각형 맵을 사용한다면 마름모 외각의 좌표를 쓸 일이 많습니다.
기준 좌표에서 마름모로 퍼지는 영역을 체크해야 하는 일이 많기 때문이죠.
로봇 대전에서 볼 수 있는 이것이 바로 마름모 영역입니다.
이 마름모 영역을 구하려면 마름모의 외곽 좌표를 알아야 하죠.
2D사각형 맵은 아래와 같이 구성됩니다.
우리가 구해야 할 값은 A를 기준으로 하는 범위입니다.
B0는 Y - 1, B1은 X + 1 입니다.
그러면 C3은 어떻게 구할까요? A에 X와 Y가 1씩 더해주면 됩니다.
그러면 D4는?
그렇습니다. 3번째 칸부터는 기존 방식으로 외곽선 좌표를 구할 수가 없습니다.
방법이야 몇 가지 있습니다만 무식한 방법으로는
1) 모든 셀을 검사한 후
2) 기준 좌표와 거리를 계산해서(대각선 거리)
3) 일정 거리 안에 있으면 범위 안이라고 판단하는 방법이 있습니다.
모든 셀을 검사해야 하니 당연히 부하가 심한 방법입니다 ㅎㅎㅎ
당연히 모든 칸을 계산하거나 할 필요는 없습니다.
꼭짓점(D0, D3, D6, D9) 의 값을 구한 후 각 대각선으로 가면서 각 꼭짓점 직전까지 구하면 쉽게 구할 수 있습니다.
그림으로 봅시다.
D0를 구하고, Y+1, X-1 하여 D11과 D10을 구합니다.
이 방법으로 다른 꼭지점에서부터 대각선 좌표를 구할 수 있습니다.
코드화를 만들어 봅시다.
.NET으로 만듭니다.
예제는 WPF입니다.
D0를 구한 후 D11과 D10을 구하는 것을 먼저 구해 봅시다
//외곽선 좌표
List<Point> pointRange = new List<Point>();
//기준 좌표에서부터 거리
int nRange = 3;
for (int i = 0; i < nRange; ++i)
{
//1.위에서 왼쪽으로
pointRange.Add(new Point(5 - i, 4 - nRange + i));
}
7번 줄 : 기준 좌표로부터 3칸(0~2) 떨어져 있는 좌표만큼 찾습니다.
10번 줄 : Point(5, 4)가 기준점의 좌표입니다.
Point(5, 4 - 3) 하면 D0의 값이 나옵니다.
Point(5 - 1, 4 - 3 + 1) 하면 D11,
Point(5 - 2, 4 - 3 + 2) 하면 D10 의 좌표가 나옵니다.
이제 파라미터를 받아서 E0에서도 쓸 수 있도록 함수로 만들어 봅시다.
/// <summary>
/// 해당 중심점을 기준으로 마름모 칸에 해당하는 외곽선의 좌표를 구해 리턴합니다.
/// 마이너스(-)값도 출력 됩니다.
/// </summary>
/// <param name="nRange">기준으로 부터 거리</param>
/// <param name="nCenterX">기준X</param>
/// <param name="nCenterY">기준Y</param>
/// <returns>외곽선 좌표 리스트</returns>
private List<Point> DiamondTile(int nRange, int nCenterX, int nCenterY)
{
//외곽선 좌표
List<Point> pointRange = new ListList<Point>();
for (int i = 0; i < nRange; ++i)
{
//1.위에서 왼쪽으로
pointRange.Add(new Point(nCenterX - i, nCenterY - nRange + i));
}
return pointRange;
}
17번 줄 : D10과 D11의 값을 구하기 위해 i값으로 가중을 해줍니다.
이제 위와 같은 방법으로 다른 꼭짓점들의 좌표를 구할 수 있습니다.
for (int i = 0; i < nRange; ++i)
{
//1.위에서 왼쪽으로
pointRange.Add(new Point(nCenterX - i, nCenterY - nRange + i));
//2.왼쪽에서 아래쪽으로
pointRange.Add(new Point(nCenterX - nRange + i, nCenterY + i));
//3.아래에서 오른쪽으로
pointRange.Add(new Point(nCenterX + i, nCenterY + nRange - i));
//4.오른쪽에서 윗쪽으로
pointRange.Add(new Point(nCenterX + nRange - i, nCenterY - i));
}
4번 줄 : D0 -> D10
7번 줄 : D9 -> D7
10번 줄 : D6 -> D4
13번 줄 : D3 -> D1
이 함수는 최소/최대 범위를 체크하지 않으므로
맵 밖으로 나갔는지 여부는 확인할 수 없습니다.
셈플 코드 : github - dang-gun/DotNetSamples/RhombusOutlinePoint
만들어 놓고나면 별게 아닌데 만들때 고생하는 함수입니다.