Test script in python for coordinate transformation formulas between
authorAki Koskinen <maemo@akikoskinen.info>
Sun, 31 Jan 2010 15:52:16 +0000 (17:52 +0200)
committerAki Koskinen <maemo@akikoskinen.info>
Sun, 31 Jan 2010 15:55:21 +0000 (17:55 +0200)
KKJxy and WGS84latlon coordinates.

tests/coord_trans_proto.py [new file with mode: 0644]

diff --git a/tests/coord_trans_proto.py b/tests/coord_trans_proto.py
new file mode 100644 (file)
index 0000000..5ac26c9
--- /dev/null
@@ -0,0 +1,248 @@
+# -*- coding: utf-8 -*-
+
+# Adapted from http://positio.rista.net/en/pys60gps/src/KKJWGS84.py
+
+import math
+
+
+# Constants
+# Longitude0 and Center meridian of KKJ bands
+KKJ_ZONE_INFO = { 0: (18.0,  500000.0), \
+                  1: (21.0, 1500000.0), \
+                  2: (24.0, 2500000.0), \
+                  3: (27.0, 3500000.0), \
+                  4: (30.0, 4500000.0), \
+                  5: (33.0, 5500000.0), \
+                }
+
+###########################################################################
+# Function:  KKJ_Zone_I
+###########################################################################
+def KKJ_Zone_I(KKJI):
+    ZoneNumber = math.floor((KKJI/1000000.0))
+    if ZoneNumber < 0 or ZoneNumber > 5:
+        ZoneNumber = -1
+    return ZoneNumber
+
+###########################################################################
+# Function:  KKJ_Zone_Lo
+###########################################################################
+def KKJ_Zone_Lo(KKJlo):
+    # determine the zonenumber from KKJ easting
+    # takes KKJ zone which has center meridian
+    # longitude nearest (in math value) to
+    # the given KKJ longitude
+    ZoneNumber = 5
+    while ZoneNumber >= 0:
+        if math.fabs(KKJlo - KKJ_ZONE_INFO[ZoneNumber][0]) <= 1.5:
+            break
+        ZoneNumber = ZoneNumber - 1
+    return ZoneNumber
+
+###########################################################################
+# Function:  KKJlalo_to_KKJxy
+###########################################################################
+def KKJlalo_to_KKJxy(INP, ZoneNumber):
+    Lo = math.radians(INP['Lo']) - math.radians(KKJ_ZONE_INFO[ZoneNumber][0])
+    a  = 6378388.0            # Hayford ellipsoid
+    f  = 1/297.0
+    b  = (1.0 - f) * a
+    bb = b * b
+    c  = (a / b) * a
+    ee = (a * a - bb) / bb
+    n = (a - b)/(a + b)
+    nn = n * n
+    cosLa = math.cos(math.radians(INP['La']))
+    NN = ee * cosLa * cosLa
+    LaF = math.atan(math.tan(math.radians(INP['La'])) / math.cos(Lo * math.sqrt(1 + NN)))
+    cosLaF = math.cos(LaF)
+    t   = (math.tan(Lo) * cosLaF) / math.sqrt(1 + ee * cosLaF * cosLaF)
+    A   = a / ( 1 + n )
+    A1  = A * (1 + nn / 4 + nn * nn / 64)
+    A2  = A * 1.5 * n * (1 - nn / 8)
+    A3  = A * 0.9375 * nn * (1 - nn / 4)
+    A4  = A * 35/48.0 * nn * n
+    OUT = {}
+    OUT['P'] = A1 * LaF - \
+        A2 * math.sin(2 * LaF) + \
+            A3 * math.sin(4 * LaF) - \
+                A4 * math.sin(6 * LaF)
+    OUT['I'] = c * math.log(t + math.sqrt(1+t*t)) + \
+        500000.0 + ZoneNumber * 1000000.0
+    return OUT
+      
+###########################################################################
+# Function:  KKJxy_to_KKJlalo
+###########################################################################
+def KKJxy_to_KKJlalo(KKJ):
+    # Scan iteratively the target area, until find matching
+    # KKJ coordinate value.  Area is defined with Hayford Ellipsoid.
+
+    LALO = {}
+    ZoneNumber = KKJ_Zone_I(KKJ['I'])
+    MinLa = math.radians(59.0)
+    MaxLa = math.radians(70.5)
+    MinLo = math.radians(18.5)
+    MaxLo = math.radians(32.0)
+    
+    i = 1
+    while (i < 35):
+        DeltaLa = MaxLa - MinLa
+        DeltaLo = MaxLo - MinLo
+        LALO['La'] = math.degrees(MinLa + 0.5 * DeltaLa)
+        LALO['Lo'] = math.degrees(MinLo + 0.5 * DeltaLo)
+        KKJt = KKJlalo_to_KKJxy(LALO, ZoneNumber)
+        if (KKJt['P'] < KKJ['P']):
+            MinLa = MinLa + 0.45 * DeltaLa
+        else:
+            MaxLa = MinLa + 0.55 * DeltaLa
+        if (KKJt['I'] < KKJ['I']):
+            MinLo = MinLo + 0.45 * DeltaLo
+        else:
+            MaxLo = MinLo + 0.55 * DeltaLo
+        i = i + 1
+        
+    return LALO
+
+###########################################################################
+# Function:  KKJlalo_to_WGS84lalo
+###########################################################################
+def KKJlalo_to_WGS84lalo(KKJ):
+    La = KKJ['La']
+    Lo = KKJ['Lo']
+    dLa = math.radians( 0.124867E+01      + \
+                        -0.269982E+00 * La + \
+                        0.191330E+00 * Lo + \
+                        0.356119E-02 * La * La + \
+                        -0.122312E-02 * La * Lo + \
+                        -0.335514E-03 * Lo * Lo ) / 3600.0
+    dLo = math.radians(-0.286111E+02      + \
+                        0.114183E+01 * La + \
+                        -0.581428E+00 * Lo + \
+                        -0.152421E-01 * La * La + \
+                        0.118177E-01 * La * Lo + \
+                        0.826646E-03 * Lo * Lo ) / 3600.0
+    WGS = {}
+    WGS['La'] = math.degrees(math.radians(KKJ['La']) + dLa)
+    WGS['Lo'] = math.degrees(math.radians(KKJ['Lo']) + dLo)
+    return WGS
+
+###########################################################################
+# Function:  WGS84lalo_to_KKJlalo
+###########################################################################
+def WGS84lalo_to_KKJlalo(WGS):
+    La = WGS['La']
+    Lo = WGS['Lo']
+    dLa = math.radians(-0.124766E+01      +           0.269941E+00 * La +                          -0.191342E+00 * Lo +  -0.356086E-02 * La * La +                          0.122353E-02 * La * Lo +                           0.335456E-03 * Lo * Lo ) / 3600.0
+    dLo = math.radians( 0.286008E+02      + \
+                        -0.114139E+01 * La + \
+                        0.581329E+00 * Lo + \
+                        0.152376E-01 * La * La + \
+                        -0.118166E-01 * La * Lo + \
+                        -0.826201E-03 * Lo * Lo ) / 3600.0
+    KKJ = {}
+    KKJ['La'] = math.degrees(math.radians(WGS['La']) + dLa)
+    KKJ['Lo'] = math.degrees(math.radians(WGS['Lo']) + dLo)
+    return KKJ
+      
+###########################################################################
+# Function:  KKJxy_to_WGS84lalo
+###########################################################################
+# Input:     dictionary with ['P'] is KKJ Northing
+#                            ['I'] in KKJ Eeasting
+# Output:    dictionary with ['La'] is latitude in degrees (WGS84)
+#                            ['Lo'] is longitude in degrees (WGS84)
+###########################################################################
+def KKJxy_to_WGS84lalo(KKJin):
+    KKJz = KKJxy_to_KKJlalo(KKJin)
+    WGS = KKJlalo_to_WGS84lalo(KKJz)
+    return WGS
+
+###########################################################################
+# Function:  WGS84lalo_to_KKJxy
+###########################################################################
+# Input:     dictionary with ['La'] is latitude in degrees (WGS84)
+#                            ['Lo'] is longitude in degrees (WGS84)
+# Output:    dictionary with ['P'] is KKJ Northing
+#                            ['I'] in KKJ Eeasting
+###########################################################################
+def WGS84lalo_to_KKJxy(WGSin):
+    KKJlalo = WGS84lalo_to_KKJlalo(WGSin)
+    ZoneNumber = KKJ_Zone_Lo(KKJlalo['Lo'])
+    KKJxy = KKJlalo_to_KKJxy(KKJlalo, ZoneNumber)
+    return KKJxy
+
+###########
+# Test code
+###########
+
+class testCoordinate:
+    def __init__(self, x, y, lon, lat):
+        self.x = x
+        self.y = y
+        self.lon = lon
+        self.lat = lat
+
+testData = []
+# Test data extracted from example on page
+# http://developer.reittiopas.fi/pages/fi/http-get-interface.php
+testData.append(testCoordinate(2556686, 6682815, 25.02051, 60.2528))
+testData.append(testCoordinate(2546340, 6675352, 24.832, 60.18713))
+testData.append(testCoordinate(2557985, 6685213, 25.04465, 60.27414))
+testData.append(testCoordinate(2556532, 6682578, 25.01767, 60.2507))
+testData.append(testCoordinate(2524959, 6686629, 24.44804, 60.2902))
+testData.append(testCoordinate(2559094, 6693721, 25.06718, 60.35033))
+testData.append(testCoordinate(2556861, 6683030, 25.02373, 60.25471))
+testData.append(testCoordinate(2556888, 6682971, 25.0242, 60.25417))
+testData.append(testCoordinate(2560257, 6698983, 25.08981, 60.39737))
+testData.append(testCoordinate(2562518, 6686969, 25.12709, 60.28923))
+testData.append(testCoordinate(2536615, 6673635, 24.65643, 60.1727))
+testData.append(testCoordinate(2559118, 6693833, 25.06764, 60.35133))
+testData.append(testCoordinate(2559182, 6693629, 25.06874, 60.34949))
+testData.append(testCoordinate(2556947, 6682640, 25.02518, 60.25119))
+testData.append(testCoordinate(2556822, 6682723, 25.02294, 60.25196))
+testData.append(testCoordinate(2559089, 6693605, 25.06705, 60.34929))
+testData.append(testCoordinate(2546445, 6675512, 24.83393, 60.18855))
+testData.append(testCoordinate(2556964, 6682609, 25.02547, 60.25091))
+testData.append(testCoordinate(2556740, 6682861, 25.0215, 60.25321))
+testData.append(testCoordinate(2559002, 6694007, 25.06559, 60.35291))
+
+
+def testKKJxytoWGS84lalo(x, y):
+    test = { 'P': y, 'I': x }
+    result = KKJxy_to_WGS84lalo(test)
+    return [result['Lo'], result['La']]
+
+testsPass = True
+
+# Test transforming from KKJxy to WGS84latlon
+for t in testData:
+    [lon, lat] = testKKJxytoWGS84lalo(t.x, t.y)
+    if math.fabs(t.lon - lon) < 0.001 and math.fabs(t.lat - lat) < 0.001:
+        pass
+    else:
+        print "Got: (",lon,lat,"), expected: (",t.lon,t.lat,")"
+        testsPass = False
+
+if testsPass:
+    print "All tests in testKKJxytoWGS84lalo passed"
+
+
+def testWGS84lalotoKKJxy(lon, lat):
+    test = { 'La': lat, 'Lo': lon }
+    result = WGS84lalo_to_KKJxy(test)
+    return [result['I'], result['P']]
+
+testsPass = True
+
+# Test transforming from WGS84latlon to KKJxy
+for t in testData:
+    [x, y] = testWGS84lalotoKKJxy(t.lon, t.lat)
+    if abs(t.x - x) < 2 and abs(t.y - y) < 2:
+        pass
+    else:
+        print "Got: (",x,y,"), expected: (",t.x,t.y,")"
+        testsPass = False
+
+if testsPass:
+    print "All tests in testWGS84lalotoKKJxy passed"