메뉴
HN
Hacker News • 54일 전

산가브리엘 산맥에서 가장 접근하기 어려운 지점 찾기

IMP
5/10
핵심 요약

이 글은 OpenStreetMap 데이터와 보로노이 다이어그램(Voronoi diagram) 알고리즘을 활용하여, 산가브리엘 산맥에서 도로나 등산로로부터 가장 멀리 떨어진 '접근 불가능의 극점(Pole of Inaccessibility)'을 계산하는 과정을 설명합니다. 복잡한 3D 지형 데이터 대신 적절한 수학적 근사(평면 투영 및 오차 무시)를 적용하여 연산을 단순화하고 효율적으로 결과를 도출한 기술적 접근이 흥미롭습니다. 개발자와 데이터 분석가에게 지리 공간 데이터를 처리하고 최적화하는 실용적인 사례를 제공합니다.

번역된 본문

원문 제목: 산가브리엘 산맥의 접근 불가능의 극점(Poles of Inaccessibility)

소스: hackernews

업데이트: 저는 가장 먼 극점(Pole)을 방문해서 그곳에 기록부(register)를 설치해 두었습니다: https://eispiraten.com/viewtopic.php?t=7040 . 꼭 방문해서 서명해 보세요! 또한 미국 본토(48개 주)에 대해서도 유사한 분석을 실행해 보았습니다.

어느 날 친구와 함께 등산을 하던 중, '산가브리엘 산맥에서 가장 접근하기 어려운 지점은 어디일까?'라는 질문이 나왔습니다. 여기서 '접근 가능하다'는 것의 기준은 근처에 도로나 등산로가 있다는 것을 의미합니다. 저는 이 질문에 답해보기로 결심했습니다. 결과물로 나온 코드는 새 리포지토리에 있습니다: https://github.com/dkogan/inaccessibility.

이러한 지점은 '접근 불가능의 극점(Pole of Inaccessibility)'이라고 불리며, 주어진 객체들(여기서는 도로 등)으로부터 최대한 멀리 떨어진 지점을 의미합니다. 이러한 극점의 위치는 지구상에서 가장 내륙 깊숙한 곳이나 육지로부터 가장 머디 바다 한가운데 같은 형태로 잘 알려져 있습니다. 여기서는 범위를 산가브리엘 산맥으로 한정하고, 도로와 등산로에서 최대한 벗어나는 곳을 찾고자 합니다.

접근 방식

입력 데이터 처리 OpenStreetMap에는 모든 도로와 등산로를 매핑할 수 있는 오픈 데이터가 있습니다. 이것이 우리의 입력 데이터셋입니다. 2D 기하학에서 '접근 불가능의 극점'을 계산하는 가장 좋은 방법은, 우리가 피하고자 하는 기하학적 객체들에 대한 보로노이 다이어그램(Voronoi diagram)을 구성한 뒤, 가장 멀리 떨어진 지점에 해당하는 보로노이 정점(vertex)을 찾는 것입니다.

하지만 우리가 사는 세상은 2D가 아니며, 타원체 위에 다양한 고도가 존재합니다. 이 분석의 궁극적인 목적은 '야외 탐험가들이 방문할 수 있는 장소를 찾아내고 다른 사람들에게 증명하는 것'이므로 극단적인 정확도는 필요하지 않습니다. 따라서 세상을 '국소적으로 평면'이라고 가정하고, 보로노이 다이어그램 기반의 방법을 사용하는 것으로 충분하다고 판단했습니다.

그래서 조회 영역의 중심점에서 지구 표면에 접하는 평면(tangent plane)을 하나 만들고, 모든 입력 지점을 이 평면에 투영했습니다. 예를 들어 대양처럼 넓은 지역의 극점을 찾을 때는 이 방식이 통하지 않겠지만, 이 산맥에서는 잘 작동합니다. 이 접면을 계산할 때는 지구가 완벽한 구형이라고 가정했습니다. 접점에서 멀어지면서 평면을 따라 이동할수록 고도 오차는 다음과 같이 커집니다: E = sqrt(R_earth^2 + d^2) - R_earth. 산가브리엘 산맥은 폭이 약 80km이고, 접면이 그 중앙에 위치하므로 최악의 경우 d = 40km이며 이때 오차는 약 125m 정도입니다. 이 정도면 충분히 훌륭한 결과입니다.

(플롯 출처 생략)

지형(고도 차이)은 거리 측정 기준에 포함시키면 보로노이 다이어그램보다 훨씬 복잡한 알고리즘이 필요하므로 무시했으며, 이렇게 하면 '접근 불가능성'의 개념을 더 명확하게 유지할 수 있습니다.

접근 불가능의 극점 계산 저는 가장 기본적인 보로노이 알고리즘을 사용하고 싶었기 때문에, 입력 데이터를 선분이 아닌 '점들의 집합'으로만 표현했습니다. 합리적인 정확도를 얻기 위해 모든 도로를 최소 100m마다 한 번씩 점으로 샘플링했습니다.

이제 2D 평면에 충분히 빽빽한 점 집합이 생겼으니, 여기에 보로노이 다이어그램을 구성합니다. 아무런 제약이 없으면 가장 먼 지점은 한쪽으로 무한히 멀어지는 곳에 위치할 것이므로, 일반적으로 해를 '입력 점들의 볼록 껍질(convex hull) 내부'로 제한합니다. 즉, 접근 불가능의 극점은 보로노이 정점 위에 있거나, 보로노이 모서리와 볼록 껍질의 교차점에 있게 됩니다.

제 경우 조회 영역의 가장자리(평지 쪽)가 내부(산악 지역)보다 도로가 더 많으므로, 극점이 볼록 껍질 위에 놓여 있지 않을 것이라고 단순 가정했습니다. 조회 지역 밖의 모든 보로노이 정점을 무시하면 되기 때문에 구현이 훨씬 단순해집니다. 그러므로 저는 모든 보로노이 정점을 살펴보고, 인접한 입력 점 사이의 거리를 확인한 다음, 해당 거리가 가장 큰 정점을 찾아 반환하면 됩니다.

구현 처리 과정의 각 단계는 각자의 독립적인 프로그램으로 작성되었습니다. 이렇게 하면 구현이 단순해지고 각 부분을 개별적으로 다루기 쉽습니다.

데이터 가져오기 먼저 OSM(OpenStreetMap)을 쿼리합니다. 이 작업은 query.sh 스크립트로 수행됩니다. 이 스크립트는 쿼리(조회) 영역의 구석 좌표들을 입력으로 받아... (이하 생략)

원문 보기
원문 보기 (영어)
Dima Kogan Tags Archives RSS Github Home / Notes / 2015 / 05 / Poles of Inaccessibility in the San Gabriel Mountains Updates I visited the furthest Pole and placed a register there: https://eispiraten.com/viewtopic.php?t=7040 . Do visit and sign in! Also I ran a similar analysis for the contiguous US So I was out hiking with a friend, and a question came up about where the least accessible point of the San Gabriel Mountains was, with "accessible" defined as having a road or trail nearby. I decided to answer this question. The resulting code is in a fresh repository: https://github.com/dkogan/inaccessibility . This is called the Pole of Inaccessibility : a point that is as far away as possible from a given set of objects. Locations of such poles are known for the most landlocked spot on earth or most far away from land. Here we limit ourselves to the San Gabriel Mountains, and try to stay away from roads and trails. Approach Input data processing OpenStreetMap has open data I can use to map out all the roads and trails. This is the input dataset. For 2D geometry, the best approach to compute the Pole of Inaccessibility appears to be to construct a Voronoi diagram of the geometry we're trying to stay away from, and to find the Voronoi vertex corresponding to the furthest-away point. Our world is not 2D. Instead, it has varying elevation sitting on top of an ellipsoid. The grand purpose here is to compute a location that hardy people can visit and to tell everybody they did it, so extreme accuracy is not required. Thus I claim that assuming the world is locally-flat and using the Voronoi-diagram-based method is sufficient. So I construct a plane that best describes my query area and project all my input points to this plane. I use a plane that is tangent to the Earth's surface at the center of the query area. This clearly wouldn't work if trying to find the pole of inaccessibility of something as large as an ocean, for instance, but it works here. To compute the tangent plane, I assume the Earth is spherical. As I move along the tangent plane away from the point of tangency, the elevation error grows: E = sqrt(R earth 2 + d 2 ) - R earth The San Gabriels are about 80km across, and the tangent plane sits in the middle, so at worst d = 40km and the error is about 125m. That's plenty good enough. Plot ( source ): I ignore the ellipsoid shape of the Earth outright. I ignore the topography as well, since including it in my distance metrics would require a fancier algorithm than making a Voronoi diagram, and it would make the notion of "inaccessibility" more ambiguous. Pole of Inaccessibility computation I want to use the most basic Voronoi algorithm, so I represent my input as a set of points only; no line segments. To get reasonable accuracy, I make sure to sample each road at least every 100m. Now that I have my set of dense-enough points in 2D, I construct the Voronoi diagram. Without constraints the furthest-away point would be infinitely far off to one side, so generally people constrain the solution to lie within the convex hull of the input points. This means that the Pole of Inaccessibility lies either on a Voronoi vertex or at an intersection of a Voronoi edge and the convex hull of the input. In my case there are generally more roads at the edges of my query area that in the interior (less stuff in the mountains than in the flats), so I simply assume that the Pole of Inaccessibility is not on the convex hull. This simplifies my implementation since I simply ignore all the Voronoi vertices that are outside of the query region. So I need to look at every Voronoi vertex, check the distance between it and an adjacent input point, and return the vertex with the largest such distance. Implementation Each step in the process lives in its own program. This simplifies implementation and makes it easy to work on each piece separately. Data import First we query OSM. This is done with the query.sh script. It takes in corners of the query area, constructs the query, sends it off to the server, and stores the result. query.sh takes 4 arguments; lat0, lon0, lat1, lon1, and stores its output in a file called query_$lat0_$lon0_$lat1_$lon1.json . The query uses the OSM Overpass query language . By default I simply look at all the roads, trails (everything with a highway tag): [out:json]; way ["highway"] ($lat0,$lon0,$lat1,$lon1); (._;>;); out; If I want to only consider roads in my computation (allow trails), then I can exclude trails from the query: [out:json]; way ["highway"] ["highway" != "footway" ] ["highway" != "path" ] ($lat0,$lon0,$lat1,$lon1); (._;>;); out; Sample invocation: $ ./query.sh 34.1390884 -118.4944153 34.5020298 -117.5852966 % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 28.3M 0 28.3M 0 138 72803 0 --:--:-- 0:06:48 --:--:-- 138k $ ls -lh query* -rw-r--r-- 1 dkogan dkogan 29M May 6 04:12 query_34.1390884_-118.4944153_34.5020298_-117.5852966.json Data massaging Next, I take the lat/lon pairs, map them to the tangent plane and make sure the data is sufficiently dense. This is done by the massage_input.pl script. It takes in the query_....json file we just obtained, and generates a points_$lat0_$lon0_$lat1_$lon1.dat file that is a list of (x,y) tuples in my plane. There's a small header of 4 values, representing the bounds of my data so that I can reject outlying vertices, as described earlier. Sample invocation: $ ./massage_input.pl query_34.1390884_-118.4944153_34.5020298_-117.5852966.json $ ls -lh points* -rw-r--r-- 1 dkogan dkogan 4.3M May 6 04:20 points_34.1390884_-118.4944153_34.5020298_-117.5852966.dat Pole of Inaccessibility computation Now we can compute the Voronoi diagram. I use boost::polygon to do this. I had concerns that this step would be prohibitively slow, but the algorithm and this implementation are quick-enough such that this "just works". The points_....dat file is inputs on standard input. Note that this is different from the other tools that read a file on the commandline instead. For each Voronoi vertex I get an arbitrary neighboring edge, and an arbitrary neighboring cell. The distance between the vertex and the cell center is identical for any such edge, cell by definition of a Voronoi vertex. I keep track of the cell with the largest distance between the vertex and the cell center, and I report the vertex with the largest such distance as my Pole of Inaccessibility. Sample invocation: $ ./voronoi < points_34.1390884_-118.4944153_34.5020298_-117.5852966.dat furthest point center, surrounding points: 25541 -78 25308 4259 21223 -543 26931 -4192 distance: 4342.873206 Bam! So the Pole of Inaccessibility is about 4.3 km from the nearest trail/road. The coordinates here are in my 2D tangent plane, which isn't super useful. Now I convert them to lat/lon and I'm done. Unmapping the planar coordinates I do this with the massaging script as before simply by passing the coords in on the commandline: $ ./massage_input.pl query_34.1390884_-118.4944153_34.5020298_-117.5852966.json 25541 -78 25308 4259 21223 -543 26931 -4192 34.3206972918426,-117.761740671673 34.3597096140465,-117.764149633831 34.3165155855012,-117.808770212857 34.2837076589351,-117.746734473897 OK. Done. Results I did this three times avoiding all roads, trails avoiding all roads avoiding all paved, driveable roads All Poles of Inaccessibility are above the East Fork of the San Gabriel River, by Ross Mountain and Iron Mountain: pole lat,lon distance to nearest (m) roads,trails 34.3204, -117.7617 4343 roads only 34.3108, -117.7474 5677 paved roads 34.2992, -117.7167 8157 This is shown nicely on the map: http://caltopo.com/m/4N7A Looks like the bounding spots for the roads,trails point are the road up to South Mt Hawkins, the PCT on top of Mt. Baden-Powell and the trail at the Bridge to Nowhere. The bounding spots for the roads-only point is the same road up to South Mt Hawkins, the Cabin Flat Campground and Shoem