โปรแกรมแปลงพิกัด แบบเขียนเอง

ที่จริงแล้ว ผมได้สูตรคำนวนนี้มานานแล้ว ซึ่งมีอยู่สองสูตรคือ
1.แปลงพิกัดภูมิศาสตร์(geographic) เป็น พิกัดกริด(UTM,MGRS)
2.แปลงพิกัดกริด(UTM,MGRS) เป็น พิกัดภูมิศาสตร์(geographic)

สูตรแรกผมเอามาเรียบเรียงและทดลอง จนเขียนเป็นโปรแกรมไว้ใช้งาน ตั้งแต่เมื่อสองปีที่แล้ว
ส่วนสูตรที่ 2 ดองไว้ก่อนเพราะยังไม่จำเป็นต้องใช้ แต่พอดีว่าวันนี้ว่างๆเลยเข้าไปดูเนื้อหาในแฟนเพจของตัวเอง (เพจก็เน่า)
ซึ่งผมได้เขียนบันทึกเกี่ยวกับสูตรนี้ไว้ และก็เริ่มนึกขึ้นมาได้ว่า ตอนที่เราคัดลอกสูตรนี้มา เขาใช้เครื่องหมายทางคณิตศาสตร์ค่อนข้างจะเยอะ
บางอันก็เอามาเรียบเรียงใหม่ไม่ได้ตรงกับของเดิมเปะๆ ก็เลยเกิดความสงสัยว่า มีพิมพ์ผิดบ้างเปล่าน๊า เพราะตั้งแต่ลอกไว้ก็ยังไม่ได้ตรวจสอบสักครั้ง

และวิธีตรวจสอบที่ชัดเจนที่สุดคือ ลองเอามาคำนวนดู แต่จะให้มากดเครื่องคิดเลข หรือ พิมพ์ลงเอ็กเซลก็คงไม่เวิร์คนะ งั้นเขียนโปรแกรมเลยแล้วกัน
วันนี้ว่างๆอยู่ด้วย

ผมออกแบบตามภาพนี้ครับ

กล่องข้อความสองอันบนผมตั้งชื่อว่า X_Text และ Y_Text ตามลำดับครับ
คอมโบบ๊อก ตั้งชื่อว่า zone_text และในรายการค่า ผมใส่ตัวเลขไว้ คือ 1 ถึง 60 (โลกแบ่งเป็น 60 โซน ในระบบ UTM)
กล่องข้อความอันล่างสุดเอาไว้แสดงผมลัพธ์ ผมตั้งชื่อว่า Text_result
และด้านล่างนี้คือโค้ดของโปรแกรมนี้ครับ
Public Class Form1
    Public X, Y, K0, a, b, ec, e1sq, arc, mu, ei _
     , Ca, Cb, Ccc, Cd, phi1 _
     , C1, T1, N1, R1, D _
     , fact1, fact2, fact3, fact4 _
     , lof1, lof2, lof3 _
     , Latitude, Longitude As Double
    Public Zone, ZoneCM As Integer
    Public target As String
    Public Function convert()
        'X คือ ระยะ Easting
        'Y คือ ระยะ Northing
        K0 = 0.9996
        'อ่านค่า X และ Y
        X = X_Text.Text
        Y = Y_Text.Text
        'อ่านค่าโซน
        Zone = zone_text.Text
        'ถ้าใช้ค่า Datum WGS 84 เราจะต้องใช้ค่า
        a = 6378137.0
        b = 6356752.314
        ec = Math.Sqrt(1 - (b / a) ^ 2)
        e1sq = ec * ec / (1 - ec * ec)
        arc = Y / K0
        mu = arc / (a * (1 - ec ^ 2 / 4 - 3 * ec ^ 4 / 64 - 5 * ec ^ 6 / 256))
        ei = (1 - (1 - ec * ec) ^ (1 / 2)) / (1 + (1 - ec * ec) ^ (1 / 2))
        Ca = 3 * ei / 2 - 27 * ei ^ 3 / 32
        Cb = 21 * ei ^ 2 / 16 - 55 * ei ^ 4 / 32
        Ccc = 151 * ei ^ 3 / 96
        Cd = 1097 * ei ^ 4 / 512
        phi1 = mu + Ca * Math.Sin(2 * mu) + Cb * Math.Sin(4 * mu) + Ccc * Math.Sin(6 * mu) + Cd * Math.Sin(8 * mu)
        C1 = e1sq * Math.Cos(phi1) ^ 2 'C1 ในต้นฉบับใช้ Q0
        T1 = Math.Tan(phi1) ^ 2 'ในต้นฉบับใช้ T0
        N1 = a / (1 - (ec * Math.Sin(phi1)) ^ 2) ^ (1 / 2) 'ในต้นฉบับใช้ N0
        R1 = a * (1 - ec * ec) / (1 - (ec * Math.Sin(phi1)) ^ 2) ^ (3 / 2) 'ในต้นฉบับใช้ R0
        D = (500000 - X) / (N1 * K0) 'ในต้นฉบับใช้ dd0 และ 500000 - X ถูกคำนวนไว้ก่อน
        fact1 = N1 * Math.Tan(phi1) / R1
        fact2 = D * D / 2
        fact3 = (5 + 3 * T1 + 10 * C1 - 4 * C1 * C1 - 9 * e1sq) * D ^ 4 / 24
        fact4 = (61 + 90 * T1 + 298 * C1 + 45 * T1 * T1 - 252 * e1sq - 3 * C1 * C1) * D ^ 6 / 720
        lof1 = D
        lof2 = (1 + 2 * T1 + C1) * D ^ 3 / 6
        lof3 = (5 - 2 * C1 + 28 * T1 - 3 * C1 ^ 2 + 8 * e1sq + 24 * T1 ^ 2) * D ^ 5 / 120
        'ส่วนนี้ทางต้นฉบับหาค่าไว้ก่อนในเมนเพจ
        If Zone > 0 Then
            ZoneCM = 6 * Zone - 183
        Else
            ZoneCM = 3
        End If
        Latitude = 180 * (phi1 - fact1 * (fact2 + fact3 + fact4)) / Math.PI
        Longitude = ZoneCM - (((lof1 - lof2 + lof3) / Math.Cos(phi1)) * 180 / Math.PI)
        Text_result.Text = Latitude & "," & Longitude
        target = "https://www.google.com/maps/place/" & Latitude & "," & Longitude
        Return ""
    End Function
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        convert()
    End Sub
    Private Sub LinkLabel1_LinkClicked(sender As Object, e As LinkLabelLinkClickedEventArgs) Handles LinkLabel1.LinkClicked
        System.Diagnostics.Process.Start(target)
    End Sub
    Private Sub X_Text_TextChanged(sender As Object, e As EventArgs) Handles X_Text.TextChanged
        On Error Resume Next
        convert()
    End Sub
    Private Sub Y_Text_TextChanged(sender As Object, e As EventArgs) Handles Y_Text.TextChanged
        On Error Resume Next
        convert()
    End Sub
End Class
แสดงความคิดเห็น
โปรดศึกษาและยอมรับนโยบายข้อมูลส่วนบุคคลก่อนเริ่มใช้งาน อ่านเพิ่มเติมได้ที่นี่