Saya mencoba membuat lokasi acak di dekat lokasi saya. Yang saya inginkan adalah membuat pasangan garis lintang / bujur secara acak di dalam lingkaran 200 meter di sekitar lokasi saya.
Ini adalah rumus yang saya buat (dengan bantuan orang-orang di StackOverFlow): (Angka acak antara -1 dan 1) * radius + (bujur lama) = bujur baru dalam radius bujur lama
(Angka acak antara -1 dan 1) * radius + (lintang lama) = lintang baru dalam radius lintang lama
Masalahnya adalah bahwa ada sesuatu yang aneh terjadi dengan implementasi saya karena semua lokasi acak terlalu dekat dengan pusat lokasi saya, tampaknya rumus tersebut tidak mencakup seluruh jari-jari.
Adakah yang tahu apa yang salah dengan formula saya?
Diedit untuk menampilkan implementasi java saat ini:
public static Location getLocation(Location location, int radius) {
Random random = new Random();
// Convert radius from meters to degrees
double radiusInDegrees = radius / METERS_IN_DEGREES;
double x0 = location.getLongitude() * 1E6;
double y0 = location.getLatitude() * 1E6;
double u = random.nextInt(1001) / 1000;
double v = random.nextInt(1001) / 1000;
double w = radiusInDegrees * Math.sqrt(u);
double t = 2 * Math.PI * v;
double x = w * Math.cos(t);
double y = w * Math.sin(t);
// Adjust the x-coordinate for the shrinking of the east-west distances
double new_x = x / Math.cos(y0);
// Set the adjusted location
Location newLocation = new Location("Loc in radius");
newLocation.setLongitude(new_x + x0);
newLocation.setLatitude(y + y0);
return newLocation;
}
Saya tidak yakin apa yang saya lakukan salah, karena lokasi baru dibuat di tengah laut.
Ada ide?
sumber
random.nextInt(1001)/1000
akan mengembalikan nilai lebih besar dari 1 sekitar 0,1% dari waktu Mengapa Anda tidak menggunakanrandom.nextDouble
ataurandom.nextFloat
? (ii) Mengalikanx0
dany0
oleh1E6
agak misterius; sepertinya tidak akan menghasilkan hasil yang benar.Jawaban:
Ini rumit karena dua alasan: pertama, membatasi titik-titik pada lingkaran alih-alih persegi; kedua, memperhitungkan distorsi dalam perhitungan jarak.
Banyak GIS menyertakan kemampuan yang secara otomatis dan transparan menangani kedua komplikasi. Namun, tag di sini menunjukkan bahwa deskripsi algoritma-independen GIS mungkin diinginkan.
Untuk menghasilkan titik secara seragam, acak, dan mandiri dalam lingkaran jari-jari r di sekitar lokasi (x0, y0), mulailah dengan menghasilkan dua nilai acak seragam independen u dan v dalam interval [0, 1). (Inilah yang disediakan oleh hampir setiap generator angka acak.) Hitung
Titik acak yang diinginkan ada di lokasi (x + x0, y + y0).
Saat menggunakan koordinat geografis (lat, lon), maka x0 (garis bujur) dan y0 (garis lintang) akan dalam derajat tetapi r kemungkinan besar berada dalam meter (atau kaki atau mil atau pengukuran linear lainnya). Pertama, konversikan jari-jari r menjadi derajat seolah-olah Anda berada di dekat khatulistiwa. Di sini, ada sekitar 111.300 meter dalam satu derajat.
Kedua, setelah menghasilkan x dan y seperti pada langkah (1), sesuaikan koordinat x untuk penyusutan jarak timur-barat:
Titik acak yang diinginkan ada di lokasi (x '+ x0, y + y0). Ini adalah prosedur perkiraan. Untuk jari-jari kecil (kurang dari beberapa ratus kilometer) yang tidak melampaui kedua kutub bumi, biasanya akan sangat akurat sehingga Anda tidak dapat mendeteksi kesalahan apa pun bahkan ketika menghasilkan puluhan ribu titik acak di sekitar masing-masing pusat (x0, y0) .
sumber
Diimplementasikan untuk Javascript:
sumber
Implementasi yang benar adalah:
Saya menghapus ketergantungan pada perpustakaan eksternal untuk membuatnya lebih mudah diakses.
sumber
Jawaban yang diterima dan turunannya tidak bekerja untuk saya. Hasilnya sangat tidak akurat.
Implementasi yang benar dalam javascript:
Inti penuh di sini
Dalam jawaban yang diterima - saya menemukan bahwa titik didistribusikan dalam elips dengan lebarnya 1,5 kali tinggi (di Panama) dan 8 kali tingginya (di utara Swedia). Jika saya menghapus penyesuaian x coord dari jawaban @ whuber elips terdistorsi dengan cara lain, 8 kali lebih tinggi dari lebarnya.
Kode dalam jawaban saya didasarkan pada algoritma dari sini
Di bawah ini Anda dapat melihat dua jsfiddles yang menunjukkan masalah dengan elips peregangan
Algoritma yang benar
Algoritma terdistorsi
sumber
whuberPointAtDistance()
:x1 = (w * Math.cos(t)) / Math.cos(y0 * (Math.PI / 180))
.Dengan Python
Keluaran
Jarak antara titik adalah 0.288044147914 Jarak antara titik adalah 0.409557451806 Jarak antara titik adalah 0.368260305716 Jarak antara titik adalah 0.340720560546 Jarak antara titik adalah 0.453773334731 Jarak antara titik adalah 0.460608754561 Jarak antara titik adalah 0.497188825576 Jarak antara titik adalah 0.497188825576 Jarak antara titik adalah 0.497188825576. Jarak antara titik adalah 0.503691568896 Jarak antara titik adalah 0.175153349209 Jarak antara titik adalah 0.195149463735 Jarak antara titik adalah 0.424094009858 Jarak antara titik adalah 0.286807741494 Jarak antara titik adalah 0.558049206307 Jarak antara titik adalah 0.498612171417 Jarak antara titik adalah 0.498612171417 Jarak antara titik adalah 0.498612171417
sumber
Anda dapat memeriksa hasil perhitungan Anda di sini . Gulir ke bawah ke bagian yang disebut "Titik tujuan diberi jarak dan bantalan dari titik awal". Bahkan ada formula JavaScript sederhana di bagian bawah untuk mengimplementasikannya. Anda masih perlu menghasilkan bantalan acak $ \ theta $ dalam radian (diukur searah jarum jam dari utara), meskipun itu harus cukup lurus ke depan. Rumus-rumus ini mengasumsikan bumi bulat (meskipun berbentuk ellipsoidal), yang cukup baik karena menghasilkan kesalahan hingga 0,3%.
sumber
Implementasi untuk Swift
Dapatkan lat dan lng dari geoencoder dan meneruskannya ke fungsi ini
Dalam contoh saya di atas saya mendapatkan garis lintang dan garis bujur dari geoencoding nama negara, karena setiap kali, nama negara memberikan garis lintang dan garis bujur yang sama, yang juga di tengah negara, jadi saya perlu keacakan.
sumber
private void drawPolyline (lat ganda, lng ganda) {
sumber