Sunday, May 13, 2007

Datum and Distance calculating in Actionscript 3.0

Tanya Datum?

Untuk menunjukkan suatu posisi di bumi kita, sudah pasti diperlukan koordinat. Satu titik koordinat terdiri atas latitude dan longitude (garis lintang dan garis bujur). Penggambaran garis-garis latitude dan longitude akan berupa jaring (tile) bidang-bidang kotak bila dilihat dari peta / map 2D. Tetapi untuk peta yang lebih baik biasanya mampu menunjukkan tile dari latitude dan longitude yang bervariasi bentuk bidangnya (agak membulat), dari yang kotak sampai trapesium sampai segitiga, ini dimaksudkan untuk menunjukkan perhitungan matematis permukaan bumi yang membulat (geosphere)! Sampai disini bisa dibayangkan?

Bentuk bidang (yang dibentuk tile latitude dan longitude) yang berbeda-beda tadi digunakan untuk memetakan area-area ditempat yang berbeda dipermukaan bumi. Konsep ini dikenal sebagai ellipsoid. Sebuah Datum akan bereferensi kepada bentuk bidang tertentu tadi dipermukaan bumi, ini disebut dengan Rujukan Ellipsoid. Dari semua Datum yang dikenal, semuanya memiliki dua perbedaan utama, yaitu posisi asal (origins) tempat referensi dipermukaan bumi, dan rotasi (terhadap kelengkungan permukaan bumi), akibatnya kedua faktor ini akan mempengaruhi representasi numerik dari suatu posisi.

Kenapa anda mesti repot dengan Datum?

Bila anda memiliki 2 peta suatu wilayah, dan keduanya memiliki grid latitude dan longitude yang digambar dengan Datum yang berbeda, maka bentuk ellipsoid dari setiap tile di grid yang terdapat dikedua peta tersebut akan berbeda. Misalnya suatu wilayah di Australia bila dibandingkan di kedua peta yang masing-masing memakai Datum AGD66 dan WGS 84 akan menunjukkan perbedaan posisi yang mencapai 200 meter (0,1 mil). Bayangkan bila sebuah rudal salah sasaran hanya karena perbedaan Datum antara komandan dan juru tembak.

Untungnya setiap GPS devices sudah mempunyai kebijakan tentang Datum dalam penggunaan navigasinya. Pada merk Garmin dan Magellan, konstanta Datum yang digunakan selalu WGS 84 (default), sedangkan Lowrance/Eagle sebagian besar mengkuti WGS 84.

Salah satu penerapan Datum yang berguna : Pengukuran jarak antara 2 posisi di geosphere.

Pengukuran jarak antara 2 posisi di objek bulat-absolut tidak persis sama dengan permukaan bumi. Dan pasti sangat berbeda bila dibandingkan dengan pengukuran posisi di bidang datar yang cukup memakai Pythagoras. Dikarenakan bumi tidak bulat sempurna karena bentuknya yang sedikit mendatar di kedua kutubnya terhadap radius ekuator.

Sebuah Rujukan Ellipsoid (Reference Ellipsoid) yang diwakili Datum biasanya terdiri dari 4 parameter :
  • Radius Ekuatorial (a)
  • Faktor Flattening/ perataan (f) (berbanding terbalik, sehingga dituliskan 1/f).
  • Delta a (selisih Radius Ekuatorial suatu Datum dengan Radius Ekuatorial Datum WGS 84) dalam meter
  • Delta f (selisih Faktor Flattening suatu Datum dengan Faktor Flattening Datum WGS 84) dikalikan dengan 10^4.

WGS 84 mempunyai Radius Ekuatorial 6378137.0 dan Faktor Flattening 1/298.257223563.
Sampai saat ini aku mengetahui ada sekitar 23 Datum yang terdaftar di Reference Ellipsoid List

Selanjutnya cara perhitungan jarak antara 2 posisi di geosphere akan hampir sama dengan perhitungan di objek bulat-absolut, tinggal memperhitungkan faktor parameter yang berpengaruh diatas.

Case 1 : Pengukuran jarak 2 posisi di geosphere dengan Datum WGS 84 di Actionscript 3.0

Ringkasnya kita langsung membuat static class dengan nama Distance (Class ini kupakai pada proyek pembuatan Map Vector Sampit di Flex 2.0.1), dan Flash Player API yang diperlukan adalah flash.geom.Point (Nggak perlu panjang lebar lagi kan? Ntar malah dikira mau bikin Wiki entries, he3x!).


package com.dy.utils
{
import flash.geom.Point;

/**
* Class Distance untuk mengukur jarak 2 posisi di Geosphere.
* Datum WGS 84
*/

public class Distance
{

/**
* Static var : Radius Ekuatorial
*/

private static const a:Number = 6378137;

/**
* Static var : Faktor Flattening/ perataan
*/


private static const f:Number = 1/298.257223563;

private static const f2:Number = 2*f - f*f;

/**
* Fungsi utama untuk pengukuran.
* Point.y = latitude dengan format dd.ddddd
* Point.x = longitude dengan format dd.ddddd
* @param point1 Posisi awal pengukuran
* @param point2 Posisi akhir pengukuran
*
* @return Jarak
*/


public static function measure( point1:Point, point2:Point):Number{

/*
* Cari representasi 3D dari posisi awal
*/

var fSinB1:Number = Math.sin(point1.y * Math.PI/180);
var fCosB1:Number = Math.cos(point1.y * Math.PI/180);
var fSinL1:Number = Math.sin(point1.x * Math.PI/180);
var fCosL1:Number = Math.cos(point1.x * Math.PI/180);
//perhitungkan Radius Ekuatorial terhadap posisi awal var N1:Number = a /Math.sqrt(1 - f2 * fSinB1 * fSinB1);
var X1:Number = N1*fCosB1*fCosL1;
var Y1:Number = N1*fCosB1*fSinL1;
var Z1:Number = (1 - f2)*N1*fSinB1;

/*
* Cari representasi 3D dari posisi akhir
*/


var fSinB2:Number = Math.sin(point2.y*Math.PI/180);
var fCosB2:Number = Math.cos(point2.y*Math.PI/180);
var fSinL2:Number = Math.sin(point2.x*Math.PI/180);
var fCosL2:Number = Math.cos(point2.x*Math.PI/180);
//perhitungkan Radius Ekuatorial terhadap posisi akhir var N2:Number = a/Math.sqrt(1 - f2*fSinB2*fSinB2);
var X2:Number = N2*fCosB2*fCosL2;
var Y2:Number = N2*fCosB2*fSinL2;
var Z2:Number = (1 - f2)*N2*fSinB2;

//cari selisih jaraknya

var D:Number = Math.sqrt((X1 - X2)*(X1 - X2) + (Y1 - Y2)*(Y1 - Y2) + (Z1 - Z2)*(Z1 - Z2));
var R:Number = N1;
var D2:Number = 2*R* Math.asin(.5*D/R);

return D2;
}

}
}



Download Class Distance di-sini

Coba di aplikasi di bawah ini (Flash Player 9 required):




Case 2 : Hasil Pengukuran Benchmark.


Pengukuran posisi antara Point(lon:36.91672, lat:55.73837) dan Point(lon:37.35804, lat:57.14513) menghasilkan 158989.00805546957 meter atau 158.99 km di Actionscript 3.0. Dibawah ini hasil perbandingan pengukuran jarak yang identik dari beberapa mapping software untuk cross cek :

  • MapSource : 156,10 km
  • OZI : 159,07 km
  • GPSMapEdit : 158.7 km
  • Actionscript 3.0 : 158.99 km

Tuh kan beda? Untuk Actionscript 3.0 perbedaan mungkin karena hasil penanganan float yang diwakili oleh type variable Number oleh Flash Payer yang tidak persis sama dengan di bahasa native C/C++ kali? Lha yang bikin bingung, bukannya MapSource, OZI dan GPSMapEdit sama-sama native? malah ikutan beda satu sama lain? Ada penjelasan?

No comments: