Garis Tanggal Internasional membungkus

13

Menggunakan OpenLayers, saya menambahkan lapisan WFS (di GeoServer) dengan filter yang mengembalikan semua fitur (hitam) yang memotong poligon saya (kuning) yang ditempatkan di beberapa negara Amerika Latin dalam tanggal tertentu.

masukkan deskripsi gambar di sini

Namun, fitur yang melintasi secara horizontal di peta TIDAK benar-benar memotong poligon saya. Fitur ini ada di suatu tempat di samudera pasifik antara Hawaii dan Fiji dan BUKAN di Amerika Latin. Masalahnya adalah bahwa alih-alih melintasi Garis Penanggalan Internasional, itu sedang dirender di peta dengan membungkus seluruh dunia.

Fitur problamatic didefinisikan:

POLYGON ((- 179.700417 14.202717, -178.687422 13.992875.179.024138 8.24716, -179.98241 8.035567, -179.700417 14.202717))

Saya memiliki banyak fitur tanggal yang bermasalah seperti ini, tetapi mempersempitnya menjadi yang ini untuk contoh ini. Saya tidak bisa mengabaikannya dalam aplikasi saya karena saya punya banyak dari mereka.

Saya sudah mencoba menggunakan "wrapDateLine: true" di lapisan dasar dan lapisan WFS dengan hasil yang sama.

Tidak yakin apakah ini akan menjadi masalah GeoServer atau masalah OpenLayers.

Adakah yang tahu solusi untuk masalah garis tanggal internasional saya?

CaptDragon
sumber
2
Saya tidak tahu mengapa perangkat lunak memiliki masalah dengan ini, dunia datar, kan ?!
DavidF
Mungkin harus ada parameter arah.
CaptDragon
@CaptDragon Ada solusi untuk Masalah ini?
Anil
@Anil Belum ada. Tolong beri tahu saya jika Anda menemukannya.
CaptDragon

Jawaban:

6

Sayangnya ini adalah masalah yang diketahui. Masalahnya adalah bahwa geometri yang melintasi garis tanggal seperti ini bersifat mendua. Para penyaji OL dan GeoServer tidak memiliki cara mudah untuk mengetahui bahwa tujuannya adalah menempuh jalan "pendek" di seluruh dunia sehingga mereka hanya menafsirkan misalnya 170 hingga -170 cara "biasa" dan menempuh jalan jauh di seluruh dunia.

Sayangnya tidak ada solusi yang baik untuk ini kecuali untuk membagi geometri Anda yang terletak di seluruh garis data.

jdeolive
sumber
Terima kasih +1, saya setuju tetapi saya tidak dapat membagi geometri saya. Mari kita lihat apakah ada orang lain yang punya ide lain.
CaptDragon
Saya menemukan cara untuk membaginya dengan baik di OpenLayers.
CaptDragon
7

Proyeksi ulang peta Anda untuk menggunakan proyeksi yang terpecah di meridian Greenwich (atau di tempat lain) sehingga poligon yang Anda minati tidak melewati diskontinuitas di peta Anda.

Ian Turton
sumber
poligon menutupi dunia dengan cukup baik akan selalu ada poligon yang akan melewati batas. Padahal, apakah Anda tahu ada proyeksi yang tidak terpecah seperti ini?
CaptDragon
1
Semua proyeksi harus membagi dunia di suatu tempat, itu tersirat dalam matematika (kupas jeruk jika Anda tidak percaya padaku :-)). Yang dapat Anda lakukan adalah memilih proyeksi terbaik untuk tugas Anda.
Ian Turton
ya kamu benar. Saya akan membiarkan ini terbuka beberapa hari dan melihat apakah ada ide lain yang muncul. Terima kasih atas saran Anda. :-)
CaptDragon
2

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.

pengguna1593611
sumber
1
OL hanya menggunakan operator> = untuk mengetahui sisi mana yang harus digunakan ketika merencanakan. Jika Anda memberi 170 maka 190 itu akan jalan pendek; jika Anda memberi 170 lalu -170, itu akan berhasil. Jika Anda selalu "menormalkan" garis bujur antara -180 dan 180, Anda kehilangan informasi. Salah satu cara untuk mendapatkan informasi kembali adalah dengan mendikte bahwa jarak antara titik tidak diperbolehkan menjadi> 180
Rivenfall
1

Workround: Contoh

var mapserv = new OpenLayers.Layer.MapServer( "OpenLayers Basic",
                "http://vmap0.tiles.osgeo.org/wms/vmap0",
                {layers: 'basic'},
                {wrapDateLine: true} );

http://openlayers.org/dev/examples/wrapDateLine.html

Mapperz
sumber
Saya menggunakan WFS tautan yang Anda kirim mengatakan: "Anda dapat melakukannya dengan lapisan 'Layer.WMS' atau 'Layer.MapServer'"
CaptDragon
Jika keduanya didukung dan Anda tidak memiliki kebutuhan khusus untuk Layer.MapServer, pergi dengan Layer.WMS (yang masih bisa dilayani dari MapServer).
DavidF
@ DavidvidF: Terima kasih, tapi saya perlu menggunakan kemampuan vektor WFS.
CaptDragon
1

Dua tahun kemudian, saya terus mengalami masalah ini dengan fitur-fitur pada layer vektor. Saya menemukan file ini berisi potongan kode yang menunjukkan cara membalikkan titik akhir jika melewati dateline:

if(Math.abs(startPoint.x-endPoint.x) > 180) {
  if(startPoint.x < endPoint.x) {
    endPoint.x -= 360;
  } else {
    endPoint.x += 360;
  }
}

Memperbarui:

Sebenarnya hal di atas tidak berhasil selama lebih dari satu revolusi di seluruh dunia. Saya akhirnya melakukan INI .

masukkan deskripsi gambar di sini

CaptDragon
sumber
1

Saya telah menemukan solusi untuk ini dalam proyek saya sendiri yang mungkin atau mungkin tidak bekerja untuk Anda. Saya tahu pasti bahwa itu bekerja dengan LineStrings tapi saya tidak yakin tentang tipe geometri lainnya.

OpenLayers.Geometry.prototype.crossesDateLine = function() {
    var lastX = this.components[0];
    for (var i=0; i < this.components.length; i++) {
        if (Math.abs(this.components[i].x - lastX) > 180) return i;
        lastX = this.components[i].x;
    }
    return false;
};
OpenLayers.Geometry.prototype.dateLineFix = function() {
    var linestrings = [];
    if (this.crossesDateLine()) {
        var string1 = [];
        for (var i = 0; i < this.crossesDateLine(); i++)
            string1.push(this.components[i]);
        var ls1 = new OpenLayers.Geometry.LineString(string1);
        var string2 = [];
        for (var i = this.crossesDateLine(); i < this.components.length; i++)
            string2.push(this.components[i]);
        var ls2 = new OpenLayers.Geometry.LineString(string2);

        if (!ls1.crossesDateLine()) {
            linestrings.push(ls1);
        } else {
            var split = ls1.dateLineFix();
            for (var i = 0; i < split.components.length; i++)
                linestrings.push(split.components[i]);
        }
        if (!ls2.crossesDateLine()) {
            linestrings.push(ls2);
        } else {
            var split = ls2.dateLineFix();
            for (var i = 0; i < split.components.length; i++)
                linestrings.push(split.components[i]);
        }
    } else {
        linestrings.push(this);
    }
    return new OpenLayers.Geometry.MultiLineString(linestrings);
};

Fungsi dateLineFix secara rekursif melintasi LineString yang diberikan untuk setiap segmen yang melewati garis tanggal. Kemudian memotong mereka menjadi dua pada garis data dan mengembalikan semua segmen yang dihasilkan sebagai MultiLineString.

Ini berfungsi dengan baik untuk tujuan saya (menggambar kotak lat-lon kutub).

Scott Odle
sumber
0

Saya punya beberapa masalah dengan dateline dan berhasil memperbaiki semuanya. Anda dapat mencoba mengikuti.

  1. Perbarui nilai kotak pembatas lapisan GeoServer secara manual untuk menutupi poligon Anda tanpa merusak dan lihat apakah itu memecahkan masalah.

  2. Salah satu perbaikan yang telah saya lakukan di Openlayers adalah ubin yang hilang ketika melewati dateline dari + ve bujur ke -ve. http://trac.osgeo.org/openlayers/ticket/2754 Tidak yakin apakah itu berlaku untuk WFS. Anda bisa mendapatkan versi pengembangan openlayers terbaru dan mencoba.

Senthil
sumber
0

Saya telah menemui masalah ini dengan LineStrings dan menciptakan solusi untuk itu. Saya tidak yakin apakah itu akan membantu Anda dengan Poligon. Anda dapat melihatnya di repl.it saya di sini: https://repl.it/@gpantic/OpenLayersSplitRouteOverPacific

gpantic
sumber
1
Jika itu menjawab pertanyaan, harap tambahkan semua info ke jawaban Anda alih-alih memberikan tautan.
BERA
0

EPSG: 3832 (WGS84 PDC) adalah proyeksi terpusat di Samudra Pasifik. Ini akan memperdagangkan masalah penyeberangan IDL untuk masalah penyeberangan Perdana Meridian. Ini mungkin bukan masalah tergantung pada apa yang Anda gambarkan. Saya juga menemukan masalah di dekat Lingkaran Kutub Utara dan Antartika.

Kredit diberikan ke artikel ini .

Akan
sumber