ฉันได้ทำการค้นคว้าปัญหานี้มาระยะหนึ่งแล้วเนื่องจากฉันได้พัฒนาแอพพลิเคชั่นที่อนุญาตให้ผู้ใช้สร้างสี่เหลี่ยมผืนผ้าของพื้นที่ที่น่าสนใจไม่ว่าจะผ่านการกระทำของ DragBox หรือพล็อตที่ผู้ใช้ป้อน เมื่อฉันเริ่มการผจญภัยครั้งนี้ฉันยังใหม่กับ OpenLayers อย่างสมบูรณ์ ปัญหาของคะแนนขอบเขตที่ป้อนด้วยตนเองคือถ้า AOI ครอบคลุม International Dateline การลากเส้นสี่เหลี่ยมจะถูกวาดผิดไปทั่วโลก ผู้ใช้ StackExchange จำนวนมากได้ถามเกี่ยวกับปัญหานี้เท่านั้นที่จะได้รับการบอกกล่าวจากผู้ตอบ OpenLayers ว่า (และฉันกำลังถอดความที่นี่) "OpenLayers ไม่มีหนทางที่จะรู้ถึงจุดประสงค์ทิศทางของจุดที่จะดึงออกมา เอ่อฉันต้องยกธง BS เกี่ยวกับคำตอบนั้นเนื่องจากฉันได้เรียนรู้มากพอเกี่ยวกับ OpenLayers ว่าเป็นอันตรายและปัญหานี้เกิดขึ้นกับฉัน ปัญหาที่ฉันมีเมื่อมีการตอบสนองคือฉันโหลดพิกัดในขอบเขตที่ตามคำจำกัดความระบุลองจิจูดบนขวาและละติจูดรวมถึงลองจิจูดล่างซ้ายและละติจูด ถ้าลองจิจูดด้านบนขวาตั้งอยู่บนฝั่งตะวันตกของ 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 แล้วนำคุณลักษณะนั้นไปใช้กับเวกเตอร์และในที่สุดก็พล็อตมันเท่านั้นที่จะพบว่ารูปหลายเหลี่ยมนั้นผิดไปทั่วโลก
ฉันต้องคิดว่าทำไมสิ่งนี้จึงเกิดขึ้นดังนั้นฉันจึงเข้าสู่วิธีการ ol.extent.boundingExtent นี้ในไลบรารี 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__: []
รหัสของฉันคำนวณพื้นที่แบบไดนามิกเพื่อให้ฉันสามารถตรวจสอบว่าผู้ใช้ได้สร้างรูปหลายเหลี่ยม AOI ขนาดที่ถูกต้องหรือไม่ เมื่อฉันกำลังประมวลผลการเลือก DragBox ที่สร้างขึ้นฉันกำลังร้องขอพิกัดจากโครงสร้างเรขาคณิตที่เกิดขึ้นและสำหรับการประมาณการ EPSG: 4326 เมื่อมันส่งคืนพิกัดจากโลกที่ถูกห่อพิกัดที่ผ่านมา 180.0 องศาแรกเพิ่มขึ้นอย่างต่อเนื่อง 360.0 - 165.937 = 194.063 codepath การคำนวณพื้นที่ของฉันใช้การทดสอบ IDL ต่อไปนี้และเพื่อใช้ codepath เดียวกันสำหรับพิกัดที่ป้อนด้วยตนเองฉันจำเป็นต้องจำลองค่าพิกัดราวกับว่ามันถูกส่งคืนจากการเรียก DragBox getGeometry ฉันกำลังทดสอบโครงสร้างรูปหลายเหลี่ยมของ GEOJSON ซึ่งเป็นอาร์เรย์ 3 มิติโดยที่มิติที่ 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 ไม่เช่นนั้นจะคำนวณตามปกติทุกที่อื่น
จากนั้นฉันก็ใช้ขอบเขตนี้เพื่อสร้างรูปหลายเหลี่ยมจากนั้นรูปหลายเหลี่ยมคุณสมบัติแล้วนำคุณลักษณะนั้นไปใช้กับเวกเตอร์และในที่สุดก็พล็อตมันและคราวนี้มันถูกพล็อตถูกต้อง ดังนั้นการแก้ไขฉันมาด้วยเพื่อช่วยแก้ปัญหาการคำนวณพื้นที่ที่ฉันยังแก้ไขปัญหาการพล็อต
บางทีวิธีนี้อาจช่วยคนอื่นหรือทำให้พวกเขาคิดไปในทิศทางอื่น การแก้ปัญหามาถึงฉันเมื่อในที่สุดฉันก็สามารถแบ่งปัญหาของ IDL ออกเป็นสองประเด็น การคำนวณพื้นที่จริงเป็นปัญหาหนึ่งโดยอีกประเด็นหนึ่งเป็นการพล็อตของรูปหลายเหลี่ยมบน IDL