Kullanıcının bir DragBox eylemi veya Kullanıcı tarafından girilen kapsam noktaları çizme yoluyla bir İlgi Alanı dikdörtgeni oluşturmasına izin veren bir uygulama geliştirdiğim için bu sorunu bir süredir araştırıyordum. Bu maceraya başladığımda OpenLayers için tamamen yeniydim. Manuel olarak girilen genişleme noktalarıyla ilgili sorun, AOI Uluslararası Tarih Çizgisi'ni kaplarsa çizilen dikdörtgenin dünya çapında yanlış çizilmesiydi. Çok sayıda StackExchange kullanıcıları bu soruyu yalnızca bir OpenLayers yanıtlayıcısı tarafından söylenmesini istedi (ve burada yeniden yorumluyorum) "OpenLayers, çizilecek noktaların yönel niyetini bilmenin bir yolu yok, bu yüzden varsayılan ...". OpenLayer'ların tehlikeli olmaları hakkında yeterince şey öğrendiğimden ve bu sorun benim başıma geldiğinden, bu yanıt üzerine BS bayrağını yükseltmem gerekiyor. Yanıtlarıyla ilgili sorunum, koordinatları tanım olarak Üst Sağ Boylam ve Enlem ile Alt Sol Boylam ve Enlem'i belirten bir dereceye kadar yüklememdir. Sağ Üst Boylam IDL'nin Batı tarafında yer alıyorsa ve Sol Alt Boy Boyu IDL'nin Doğu tarafında yer alıyorsa, kullanıcının hangi yolu çokgeni çizmek istediği oldukça açıktır, ancak OpenLayers Boylamsal değerleri değiştirmek ve çizim yapmakta ısrar ediyor çokgen dünya çapında yanlış bir şekilde. Kapsam bildirimi ve sorunlu OpenLayers yöntem çağrısı örneği aşağıda gösterilmiştir. Sağ Üst Boylam IDL'nin Batı tarafında yer alıyorsa ve Sol Alt Boy Boyu IDL'nin Doğu tarafında yer alıyorsa, kullanıcının hangi yolu çokgeni çizmek istediği oldukça açıktır, ancak OpenLayers Boylamsal değerleri değiştirmek ve çizim yapmakta ısrar ediyor çokgen dünya çapında yanlış bir şekilde. Kapsam bildirimi ve sorunlu OpenLayers yöntem çağrısı örneği aşağıda gösterilmiştir. Sağ Üst Boylam IDL'nin Batı tarafında yer alıyorsa ve Sol Alt Boy Boyu IDL'nin Doğu tarafında yer alıyorsa, kullanıcının hangi yolu çokgeni çizmek istediği oldukça açıktır, ancak OpenLayers Boylamsal değerleri değiştirmek ve çizim yapmakta ısrar ediyor çokgen dünya çapında yanlış bir şekilde. Kapsam bildirimi ve sorunlu OpenLayers yöntem çağrısı örneği aşağıda gösterilmiştir.
// 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__: []
Gördüğünüz gibi Boyuna koordinatlar tersine döner ve böylece tam koordinat yapısını (çokgen) oluşturduktan sonra. bir çokgenÖzellik ve ardından bu özelliği bir vektöre uygulayın ve son olarak yalnızca çokgenin dünya çapında yanlış yol aldığını bulmak için çizin.
OpenLayers 4 kitaplığında bu ol.extent.boundingExtent yöntemine kazdık neden bu olduğunu anlamak gerekiyordu.
/**
* 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__: []
Kodum alanı dinamik olarak hesaplar, böylece Kullanıcı geçerli boyutlu bir AOI çokgen oluşturup oluşturmadığını belirleyebilirim. DragBox tarafından oluşturulan bir seçimi işlerken, ortaya çıkan geometri yapısından koordinatları talep ediyorum ve bir EPSG: 4326 projeksiyonu için, sarılmış bir dünyadan koordinatları döndürdüğünde, ilk 180.0 dereceyi geçen koordinatlar artmaya devam ediyor. 360.0 - 165.937 = 194.063. Alan hesaplama kodyolum aşağıdaki IDL testini kullanır ve elle girilen koordinatlar için aynı kodyolunu kullanmak için DragBox getGeometry çağrısından döndürülmüş gibi koordinat değerini simüle etmem gerekiyordu. Ben aslında 1 boyutu Yüzük numarası olan 3 boyutlu bir dizi olan bir GEOJSON çokgen yapısını test ediyorum,
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))) {
.
.
.
Bu testler bu noktada geçerse, kod IDL üzerindeki alanı hesaplamak için geliştirdiğim algoritmayı kullanır, aksi takdirde sadece diğer her yerde normal olarak hesaplar.
Daha sonra bir poligon, daha sonra bir polygonFeature oluşturmak için bu kapsamı kullanın, daha sonra bu özelliği bir vektöre uygulayın ve son olarak çizin ve bu kez doğru bir şekilde çizdim. Bu yüzden alan hesaplama problemini çözmeye yardımcı olmak için bulduğum düzeltme, çizim problemini de düzeltti.
Belki bu çözüm başka birine yardımcı olacak ya da farklı bir yöne düşündürecek. Nihayetinde IDL sorununu iki konuya ayırabildiğimde çözüm geldi. Gerçek alan hesaplaması bir diğer sorun, diğerinin poligonun IDL üzerine çizilmesidir.