졸업작품으로 안전한 보행길 경로를 찾아주는 지도 프로젝트를 만들고 있는데..
우리 세상은 알고리즘처럼 2차원 배열이나 노드의 집합이 아니기때문에.. 지도를 일정한 간격으로 규격화해야했다.
이 부분이 굉장히 힘들었는데 기록으로 남겨놓으려한다.
방법
1. 출발지와 목적지의 좌표를 계산하여 사각형 범위를 구한다. ( = Map Size )
2. 범위를 2차원 배열처럼 규격화한다(?)
3. 해당 범위내에서 적합한 경로를 찾는다(??)
ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ
2번 방법을하기위해 많은 고민을 했는데
첫번째. 2차원 배열처럼 정사각형으로 해당 범위를 규격화하기.
→ 실제 지도는 이동가능한 공간이 뒤죽박죽 삐뚤빼뚤이기 때문에 적합하지 않다고 생각했다.
두번째. 육각형의 hexgon grid로 규격화하기
→ 첫번째 방법이 안된다고 생각한 후, 다시 알아봤는데 게임공간?에서는 2차원 공간을 6각형으로 나누어서 계산한다고 한다.
이걸 하면서 아래의 글이 정말 많은 도움이됬다.
배달아~ 배달 가는길 알려줘!(단호함) - 우아한형제들 기술 블로그
서론배민라이더스에서는 배달거리를 업소와 고객의 주소 정보를 이용해서 지구는 적당히(?) 둥글다는 계산으로 거리계산을 하고 있습니다. ~대충대충코드~```java double theta = from.getLongitude() - to.ge
woowabros.github.io
Django(Python)에 Hexgrid 적용하기
우선 hexgon grid의 개념이나 사용방법은 위의 블로그 글이나,
아래의 문서를 보면서 큰 개념을 잡았다.
https://www.redblobgames.com/grids/hexagons/
Red Blob Games: Hexagonal Grids
Guide to math, algorithms, and code for hexagonal grids in games
www.redblobgames.com
다행이도 hexgrid가 제공되는 오픈소스가 있었다.
여기서 힘들었던게,
- pip install hexgrid 와
- pip install hexgrid-py가 있다.
pip install hexgrid-py를 해야한다...
(오픈소스 깃허브 링크)
https://github.com/gojuno/hexgrid-py/blob/master/hexgrid.py
gojuno/hexgrid-py
Configurable hex grid on abstract surface. Contribute to gojuno/hexgrid-py development by creating an account on GitHub.
github.com
위에 개념들을 거의다 구현이 되어있다.
오픈소스 내부 코드를 보면서 본인한테 맞게 살짝살짝 변경하면서 사용하면 될 것 같다.
My Code
import hexgrid # han : pip install hexgrid-py
#그리드 그려보자
def gird_draw(request):
#-----------------return hex corner ---------------------
center=hexgrid.Point((float(startX)+float(endX))/2,(float(startY)+float(endY))/2) #중앙
rate = 110.574 / (111.320 * math.cos(37.55582994870823 * math.pi / 180)) #서울의 중앙을 잡고, 경도값에 대한 비율
grid = hexgrid.Grid(hexgrid.OrientationFlat, center, Point(rate*0.00015,0.00015), morton.Morton(2, 32)) #Point = Size
sPoint=grid.hex_at(Point(float(startX),float(startY))) # hex_at : point to hex -> 출발지 Point -> hex좌표
ePoint=grid.hex_at(Point(float(endX),float(endY))) #목적지
map_size=max(abs(sPoint.q),abs(sPoint.r)) #열col(q) 행row(r)
#return center extends neighbor : hex list
neighbor=[]
neighbor =grid.hex_neighbors(grid.hex_at(center),map_size+5) #hex_neighbor : type(Hex, int) -> list
print("hexgrid 개수 : ",len(neighbor))
#test make hex to corner
cornerlist = []
for item in neighbor:
cornerlist.append(grid.hex_corners(item))
polylist =[]
for hex in cornerlist:
hexPolygon = []
for corner in hex :
temp = [corner.y , corner.x]
hexPolygon.append(temp)
polylist.append(hexPolygon)
print("hexgrid 꼭지점 개수 : ",len(polylist))
hex_line={"type":"Feature","geometry":{"type":"Polygon","coordinates":polylist}}
hex_polygon = {"type":"FeatureCollection","features":[hex_line]}
return HttpResponse(json.dumps({'pistes' : pistes, 'hex_polygon':hex_polygon}),content_type="application/json") #python to json
여기서 살짝 설명을 해보자면 아래의 순서와 같다.
1. 중앙 잡기 (hex (0,0))
- 먼저 중앙을 잡아야한다. 구현된 오픈소스에도 필요하지만,
hexgrid의 개념을 이해하고 보다 사용하기 쉽게? 가독성 있게..? 사용하려면 중앙점을 잡고,
중앙 6각형으로 부터 이웃된 hexgrid의 좌표를 설정하는게 좋다.
2. Grid 객체 생성
grid = hexgrid.Grid(hexgrid.OrientationFlat, center, Point(rate*0.00015,0.00015), morton.Morton(2, 32)) #Point = Size
이 한줄로 객체를 생성할 수 있는데, 참조되는 파라미터를 순서대로 번호로 살펴보면
1번은, hexgrid의 2가지 타입중 Flat 타입을 고른다는 것이다. (Hexgrid의 바닥면 기준)
2번은, Center : Point 좌표를
3번은, Grid의 크기
4번은, Z곡선의 값 같은데... 솔직히 Morton이 무엇인지 잘모르겠다. 아래의 링크를 참고하여 설정했다.
(아는 사람은 언제든지 댓글한번만 달아주세요ㅠㅠ)
https://pypi.org/project/morton-py/
morton-py
Morton code pack/unpack library
pypi.org
3. 실좌표 hex좌표로 변환
.hex_at 메서드로 Point 좌표를 중심 좌표로 부터의 hex 좌표로 변환할 수 있다.
4. 이웃된 hexgrid : hex_neighbors 함수
이웃된 hexgrid를 구하고, 각 grid의 꼭지점 좌표를 봔환해준다.
* 위도(lat), 경도(lon) 순
Html 렌더링
hex_polygon으로 렌더링된 데이터를 html에서 Leaflet 라이브러리를 이용하여
polygon 형태로 map에 추가해준다.
//hex line (시각화)
tempdata = result.hex_polygon['features'][0]['geometry']['coordinates']; //hexgrid (꼭지점의 좌표를 가짐)
$.each(tempdata,function(index,grid){
L.polygon([grid]).addTo(leaf_map); // y(위도) x(경도)
});
결과
그러면 이렇게 hexgrid polygon 형태로 지도를 규격화 할수있다.
규격화된 각각의 도형은 중심좌표를 가지고 있고, 이제 이 좌표를 활용해 적합한 경로를 안내해 주고자 한다.
Polygon 위에 Markers 추가해보기
https://thalals.tistory.com/33
[Leaflet] Django에 Leaflet Marker 표시하기(Point Array)
졸업작품으로 Leaflet.js를 이용해서 map을 만드는 중 DB에 저장된 가로등 좌표를 Point로 받아와 지도위에 marker 표시를 해줄려고 한다. 1. DB에 저장된 좌표 중 범위 설정해서 가져오기 lamp = Lamp.objects.
thalals.tistory.com
전에 표시했던 가로등 마커를 polygon 위에 적용해보았다.
어려울거 없이 단순하게 polygon 코드 아래에 markers 코드를 추가해 주었다.
'Django > 개인 프로젝트1(안전한 보행길 지도)' 카테고리의 다른 글
[Django] Python 지도라이브러리 Folium 과 leaflet 차이점(Folium VS Leaflet.js) (0) | 2021.08.11 |
---|---|
Django Leaflet.js 지도 라이브러리 불러오기 (0) | 2021.08.11 |
Django Templates 폴더 App 폴더 바깥쪽으로 빼서 한번에 관리하기 (0) | 2021.08.11 |
1. Django 프로젝트 생성 (0) | 2021.08.10 |
[Leaflet] Django에 Leaflet Marker 표시하기(Point Array) (0) | 2021.05.14 |