DragBox 작업을 통해 또는 사용자가 입력 한 확장 점을 플롯하여 관심 영역 사각형을 생성 할 수있는 응용 프로그램을 개발하면서이 문제를 꽤 오랫동안 연구 해 왔습니다. 이 모험을 시작했을 때 저는 OpenLayers를 처음 접했습니다. 수동으로 입력 한 확장 점의 문제는 AOI가 국제 날짜 표시 줄을 덮으면 그려진 사각형이 전 세계에 잘못된 방식으로 그려 질 수 있다는 것입니다. 수많은 StackExchange 사용자는 OpenLayers 응답자 만이 문제에 대해 물어 보았습니다. "(여기에서 설명하고 있습니다.)"OpenLayers는 그려 질 점의 방향 의도를 알 수 없으므로 기본값입니다. " 어, OpenLayers에 대해 충분히 배웠고이 문제가 저에게 일어나면서 그 응답에 대해 BS 깃발을 올려야합니다. 응답에 대한 문제는 정의에 따라 왼쪽 위 경도 및 위도뿐만 아니라 오른쪽 위 경도 및 위도를 지정하는 범위의 좌표를로드한다는 것입니다. 오른쪽 위 경도가 IDL의 서쪽에 있고 왼쪽 아래 경도가 IDL의 동쪽에있는 경우 사용자가 다각형을 플롯하려는 방법은 분명하지만 OpenLayers는 경도 값을 바꾸고 드로잉을 요구합니다. 전 세계에서 다각형이 잘못된 방식으로 익스텐트 선언 및 문제가있는 OpenLayers 메소드 호출 샘플이 아래에 표시되어 있습니다. 오른쪽 위 경도가 IDL의 서쪽에 있고 왼쪽 아래 경도가 IDL의 동쪽에있는 경우 사용자가 다각형을 플롯하려는 방법은 분명하지만 OpenLayers는 경도 값을 바꾸고 드로잉을 요구합니다. 전 세계에서 다각형이 잘못된 방식으로 익스텐트 선언 및 문제가있는 OpenLayers 메소드 호출 샘플이 아래에 표시되어 있습니다. 오른쪽 위 경도가 IDL의 서쪽에 있고 왼쪽 아래 경도가 IDL의 동쪽에있는 경우 사용자가 다각형을 플롯하려는 방법은 분명하지만 OpenLayers는 경도 값을 바꾸고 드로잉을 요구합니다. 전 세계에서 다각형이 잘못된 방식으로 익스텐트 선언 및 문제가있는 OpenLayers 메소드 호출 샘플이 아래에 표시되어 있습니다.
// I would start out with the following entered values as an example
lonLL = 175.781; // minX
latLL = 13.992; // minY
lonUR = -165.937;// maxX
latUR = 25.945; // maxY
// I would then make the following call
var manCoordEntryExtent = ol.extent.boundingExtent([[lonLL,latLL], [lonUR, latUR]]);
// Looking at the resulting structure in the debugger I get:
0: -165.937 // minX
1: 13.992 // minY
2: 175.781 // maxX
3: 25.945 // maxY
length: 4
__proto__: []
보시다시피 세로 좌표가 반전되어 전체 좌표 구조 인 다각형을 만듭니다. polygonFeature를 클릭 한 다음 해당 지형지 물을 벡터에 적용하고 마지막으로 다각형이 전 세계에서 잘못된 방향으로 이동 함을 알기 위해 플롯합니다.
OpenLayers 4 라이브러리에서이 ol.extent.boundingExtent 메소드를 파헤쳐 서 왜 이런 일이 발생했는지 알아 내야했습니다.
/**
* Build an extent that includes all given coordinates.
*
* @param {Array.<ol.Coordinate>} coordinates Coordinates.
* @return {ol.Extent} Bounding extent.
* @api
*/
ol.extent.boundingExtent = function(coordinates) {
var extent = ol.extent.createEmpty();
for (var i = 0, ii = coordinates.length; i < ii; ++i) {
ol.extent.extendCoordinate(extent, coordinates[i]);
}
return extent;
};
It first calls ol.extent.createEmpty to initially create an extent structure
/**
* Create an empty extent.
* @return {ol.Extent} Empty extent.
* @api
*/
ol.extent.createEmpty = function() {
return [Infinity, Infinity, -Infinity, -Infinity];
};
// It then iterates thru the number of coordinates and fills in the extent structure values, however...
// Here is where the problem is. Notice the complete lack of any explanation as to what the hell this
// method is doing. Why is it doing what it does? All I know is that it cannot handle plots across
// the IDL and it corrupts your extent structure if you try.
/**
* @param {ol.Extent} extent Extent.
* @param {ol.Coordinate} coordinate Coordinate.
*/
ol.extent.extendCoordinate = function(extent, coordinate) {
if (coordinate[0] < extent[0]) {
extent[0] = coordinate[0];
}
if (coordinate[0] > extent[2]) {
extent[2] = coordinate[0];
}
if (coordinate[1] < extent[1]) {
extent[1] = coordinate[1];
}
if (coordinate[1] > extent[3]) {
extent[3] = coordinate[1];
}
};
// The solution was for me to test for IDL myself and if found then create an empty extent and populate it myself manually.
// Using the same extent coordinates as before
lonLL = 175.781; // minX
latLL = 13.992; // minY
lonUR = -165.937;// maxX
latUR = 25.945; // maxY
// I test for Dateline instance (Dont have to worry about the potential of there being a polygon covering both Meridian
// and Anti-meridian as a valid polygon is limited to a maximum size of just over 12 million square kilometers.)
if ((lonLL > 0.0) && (lonUR < 0.0)) {
// Manually build the coordinates for the Area calculation as the boundingExtent
// codepath corrupts an extent to be plotted across the Dateline
var manCoordEntryExtent = ol.extent.createEmpty();
manCoordEntryExtent[0] = lonLL;
manCoordEntryExtent[1] = latLL;
manCoordEntryExtent[2] = lonUR + 360.0;
manCoordEntryExtent[3] = latUR;
} else {
var manCoordEntryExtent = ol.extent.boundingExtent([[lonLL,latLL], [lonUR, latUR]]);
}
// Looking at the resulting structure in the debugger I get:
0: 175.781 // minX
1: 13.992 // minY
2: 194.063 // maxX
3: 25.945 // maxY
length: 4
__proto__: []
내 코드는 사용자가 유효한 크기의 AOI 다각형을 만들 었는지 확인할 수 있도록 영역을 동적으로 계산합니다. DragBox 생성 선택을 처리 할 때 결과 지오메트리 구조에서 좌표를 요청하고 EPSG : 4326 투영을 위해 래핑 된 세계에서 좌표를 반환 할 때 처음 180.0도를 지난 좌표는 계속 증가하므로 lonUR 계산의 이유는 360.0-165.937 = 194.063. 내 영역 계산 코드 경로는 다음 IDL 테스트를 사용하며 DragBox getGeometry 호출에서 반환 된 것처럼 좌표 값을 시뮬레이션하는 데 필요한 수동 입력 좌표에 동일한 코드 경로를 사용합니다. 실제로 GEOJSON 다각형 구조를 테스트하고 있는데, 1 차원은 링 번호이며
function getArea(coords, extent) {
// Test for Western side of Dateline instance
if (((coords[0][0][0] <= -180.0) && (coords[0][2][0] > -180.0)) ||
// Test for Eastern side of Dateline instance
((coords[0][0][0] < 180.0) && (coords[0][2][0] >= 180.0))) {
.
.
.
이 테스트가이 시점을 통과하면 코드는 IDL을 통해 면적을 계산하기 위해 개발 한 알고리즘을 사용합니다. 그렇지 않으면 다른 곳에서는 정상적으로 계산합니다.
그런 다음이 범위를 사용하여 다각형을 작성한 다음 polygonFeature를 만든 다음 해당 기능을 벡터에 적용하고 마지막으로 플롯하면 이번에는 올바르게 플롯됩니다. 그래서 내가 해결 한 영역 계산 문제를 해결하는 데 도움이되는 수정도 플로팅 문제를 수정했습니다.
이 솔루션은 다른 사람에게 도움이되거나 다른 방향으로 생각하게 할 수 있습니다. 마침내 IDL 문제를 두 가지 문제로 나눌 수 있었을 때 해결책이 나에게 왔습니다. 실제 면적 계산은 IDL에 다각형을 플로팅하는 문제 중 하나였습니다.