Saya telah meneliti masalah ini cukup lama karena saya telah mengembangkan sebuah aplikasi yang memungkinkan pengguna untuk menghasilkan persegi panjang Area of Interest baik melalui tindakan DragBox atau merencanakan pengguna memasukkan titik batas. Ketika saya memulai petualangan ini, saya benar-benar baru di OpenLayers. Masalah dengan titik-titik luas yang dimasukkan secara manual adalah bahwa jika AOI menutupi Dateline Internasional, persegi yang ditarik akan ditarik dengan cara yang salah di seluruh dunia. Banyak pengguna StackExchange telah bertanya tentang masalah ini hanya untuk diberitahu oleh responden OpenLayers bahwa (dan saya memparafrasekan di sini) "OpenLayers tidak memiliki cara untuk mengetahui arah pengarahan dari poin yang akan ditarik sehingga defaultnya ...". Eh, saya harus mengibarkan bendera BS pada respons itu karena saya sekarang telah belajar cukup tentang OpenLayers menjadi berbahaya dan masalah ini telah terjadi pada saya. Masalah yang saya miliki dengan tanggapan mereka adalah bahwa saya memuat koordinat untuk tingkat yang, menurut definisi, menentukan Garis Bujur Kanan dan Lintang serta Garis Bujur Kiri dan Lintang. Jika Bujur Kanan Atas terletak di sisi Barat IDL dan Bujur Kiri Bawah terletak di sisi Timur IDL, cukup jelas ke arah mana pengguna ingin merencanakan poligon dan OpenLayers bersikeras menukar nilai-nilai Longitudinal dan menggambar poligon dengan cara yang salah di seluruh dunia. Contoh deklarasi tingkat dan pemanggilan metode OpenLayers yang bermasalah ditunjukkan di bawah ini. Jika Bujur Kanan Atas terletak di sisi Barat IDL dan Bujur Kiri Bawah terletak di sisi Timur IDL, cukup jelas ke arah mana pengguna ingin merencanakan poligon dan OpenLayers bersikeras menukar nilai-nilai Longitudinal dan menggambar poligon dengan cara yang salah di seluruh dunia. Contoh deklarasi tingkat dan pemanggilan metode OpenLayers yang bermasalah ditunjukkan di bawah ini. Jika Bujur Kanan Atas terletak di sisi Barat IDL dan Bujur Kiri Bawah terletak di sisi Timur IDL, cukup jelas ke arah mana pengguna ingin merencanakan poligon dan OpenLayers bersikeras menukar nilai-nilai Longitudinal dan menggambar poligon dengan cara yang salah di seluruh dunia. Contoh deklarasi tingkat dan pemanggilan metode OpenLayers yang bermasalah ditunjukkan di bawah ini.
// 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__: []
Seperti yang Anda lihat, koordinat Longitudinal dibalik dan setelah itu Anda membuat struktur koordinat penuh, sebuah poligon. poligonFitur dan kemudian menerapkan fitur itu ke vektor dan akhirnya plot hanya untuk menemukan bahwa poligon berjalan dengan cara yang salah di seluruh dunia.
Saya perlu mencari tahu mengapa ini terjadi, jadi saya menggali metode ol.extent.boundingExtent di perpustakaan OpenLayers 4.
/**
* 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__: []
Kode saya menghitung area secara dinamis sehingga saya dapat menentukan apakah Pengguna telah membuat poligon AOI berukuran valid. Ketika saya memproses seleksi yang dihasilkan DragBox, saya meminta koordinat dari struktur geometri yang dihasilkan dan untuk proyeksi EPSG: 4326 ketika mengembalikan koordinat dari dunia yang dibungkus, koordinat yang melewati 180,0 derajat pertama terus bertambah sehingga alasan perhitungan lonUR dari 360.0 - 165.937 = 194.063. Codepath perhitungan area saya menggunakan tes IDL berikut dan untuk menggunakan codepath yang sama untuk koordinat yang dimasukkan secara manual, saya perlu mensimulasikan nilai koordinat seolah-olah telah dikembalikan dari panggilan getGeometry DragBox. Saya sebenarnya sedang menguji struktur poligon GEOJSON yang merupakan array 3 dimensi dengan dimensi 1 sebagai nomor Cincin,
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))) {
.
.
.
Jika tes ini lulus pada titik ini kode menggunakan algoritma yang saya kembangkan untuk menghitung area di atas IDL atau hanya menghitungnya seperti biasa di tempat lain.
Saya kemudian menggunakan tingkat ini untuk membuat poligon, kemudian poligonFitur, kemudian menerapkan fitur itu ke vektor dan akhirnya memplotnya dan kali ini diplot dengan benar. Jadi perbaikan yang saya lakukan untuk membantu memecahkan masalah perhitungan area saya juga memperbaiki masalah plot.
Mungkin solusi ini akan membantu orang lain atau membuat mereka berpikir ke arah yang berbeda. Solusi datang kepada saya ketika saya akhirnya dapat memecahkan masalah IDL menjadi dua masalah. Perhitungan area aktual adalah satu masalah dengan yang lain adalah merencanakan poligon di atas IDL.