# Tests for geo helper (geo_helper.py)
#
# See http://gagravarr.org/code/ for updates and information
#
# Nick Burch - 30/05/2007

import unittest
import geo_helper

class TestGeoHelper(unittest.TestCase):
	def testWGSlatlongXYZ(self):
		"""Test turning WGS84 lat+long into X,Y,Z"""
		lat = 52.65797559953351
		long = 1.7160665447977752
		height = 0

		res = geo_helper.turn_llh_into_xyz(lat,long,height,'wgs84')

		exp_x = 3875269.630
		exp_y = 116102.964
		exp_z = 5047546.920
	
		self.assertAlmostEquals(res[0],exp_x,3,"X didn't match")
		self.assertAlmostEquals(res[1],exp_y,3,"Y didn't match")
		self.assertAlmostEquals(res[2],exp_z,3,"Z didn't match")

	def testOSGBlatlongXYZ(self):
		"""Test turning OSGB lat+long into X,Y,Z"""
		lat = 52.6575703056
		long = 1.7179215833
		height = 24.700

		res = geo_helper.turn_llh_into_xyz(lat,long,height,'osgb')

		exp_x = 3874938.849
		exp_y = 116218.624
		exp_z = 5047168.208

		self.assertAlmostEquals(res[0],exp_x,3,"X didn't match")
		self.assertAlmostEquals(res[1],exp_y,3,"Y didn't match")
		self.assertAlmostEquals(res[2],exp_z,3,"Z didn't match")

	def testOSGBXYSlatlong(self):
		"""Test turning OSGB X,Y,Z into lat+long"""
		x = 3874938.849
		y = 116218.624
		z = 5047168.208

		res = geo_helper.turn_xyz_into_llh(x,y,z,'osgb')

		exp_lat = 52.6575703056
		exp_long = 1.7179215833
		exp_height = 24.700

		self.assertAlmostEquals(res[0],exp_lat,3,"Lat didn't match")
		self.assertAlmostEquals(res[1],exp_long,3,"Long didn't match")
		self.assertAlmostEquals(res[2],exp_height,3,"Height didn't match")

	def testWGS84xyztoOSGBxyz(self):
		"""Test turning WGS84 X,Y,Z into OSGB X,Y,Z"""
		x = 3909833.018
		y = -147097.138
		z = 5020322.478

		res = geo_helper.turn_xyz_into_other_xyz(x,y,z,'wgs84','osgb')

		exp_x = 3909460.068
		exp_y = -146987.302 # OS claims .301
		exp_z = 5019888.070

		self.assertAlmostEquals(res[0],exp_x,3,"X didn't match")
		self.assertAlmostEquals(res[1],exp_y,3,"Y didn't match")
		self.assertAlmostEquals(res[2],exp_z,3,"Z didn't match")

	def testWGS84toOSGB(self):
		"""Test turning WGS84 lat+long into OSGB lat+long"""
		lat = 52.65797559953351
		long = 1.7160665447977752
		height = 0

		xyz = geo_helper.turn_llh_into_xyz(lat,long,height,'wgs84')

		new_xyz = geo_helper.turn_xyz_into_other_xyz(xyz[0],xyz[1],xyz[2],'wgs84','osgb')
		res = geo_helper.turn_xyz_into_llh(new_xyz[0],new_xyz[1],new_xyz[2],'osgb')

		exp_lat = 52.657570301933156
		exp_long = 1.717921580645096

		self.assertAlmostEquals(res[0],exp_lat,4,"Lat didn't match")
		self.assertAlmostEquals(res[1],exp_long,4,"Long didn't match")

		# Check direct
		res = geo_helper.turn_wgs84_into_osgb36(lat,long,height)
		self.assertAlmostEquals(res[0],exp_lat,4,"Lat didn't match")
		self.assertAlmostEquals(res[1],exp_long,4,"Long didn't match")

	def testWGS84toOSGB(self):
		"""Test turning OSGB lat+long into WGS84 lat+long"""
		lat = 52.657570301933156
		long = 1.717921580645096
		height = 0

		xyz = geo_helper.turn_llh_into_xyz(lat,long,height,'osgb')

		new_xyz = geo_helper.turn_xyz_into_other_xyz(xyz[0],xyz[1],xyz[2],'osgb','wgs84')
		res = geo_helper.turn_xyz_into_llh(new_xyz[0],new_xyz[1],new_xyz[2],'wgs84')

		exp_lat = 52.65797559953351
		exp_long = 1.7160665447977752

		self.assertAlmostEquals(res[0],exp_lat,4,"Lat didn't match")
		self.assertAlmostEquals(res[1],exp_long,4,"Long didn't match")

		# Check direct
		res = geo_helper.turn_osgb36_into_wgs84(lat,long,height)
		self.assertAlmostEquals(res[0],exp_lat,4,"Lat didn't match")
		self.assertAlmostEquals(res[1],exp_long,4,"Long didn't match")

	def testOSGBintoEN(self):
		""" Test turning OSGB lat+long into OSGB easting and northing"""
		lat = 52.6575703056
		long = 1.7179215833

		res = geo_helper.turn_osgb36_into_eastingnorthing(lat,long)

		exp_e = 651409.903
		exp_n = 313177.270

		self.assertAlmostEquals(res[0],exp_e,3,"Easting didn't match")
		self.assertAlmostEquals(res[1],exp_n,3,"Northing didn't match")

	def testENintoOSGB(self):
		""" Test turning OSGB easting and northing into OSGB lat+long"""
		e = 651409.903
		n = 313177.270

		res = geo_helper.turn_eastingnorthing_into_osgb36(e,n)

		exp_lat = 52.6575703056
		exp_long = 1.7179215833

		self.assertAlmostEquals(res[0],exp_lat,5,"Lat didn't match")
		self.assertAlmostEquals(res[1],exp_long,5,"Long didn't match")

	def test6Fix(self):
		""" Test turning OSGB easting and northing into a 6 figure grid ref"""
		easting = 651409.903
		northing = 313177.270

		res = geo_helper.turn_easting_northing_into_six_fig(easting,northing)

		exp_6f = "TG514131"
		self.assertEquals(res,exp_6f,"6fig wrong")

	def testTurnWGS84_into_OSIEen(self):
		""" Test turning WGS84 lat+long into OSIE easting+northing"""
		lat = 53.3472
		long = -6.2592

		# Transform
		xyz = geo_helper.turn_llh_into_xyz(lat,long,0,'wgs84')
		nxyz = geo_helper.turn_xyz_into_other_xyz(xyz[0],xyz[1],xyz[2],'wgs84','osie')
		nll = geo_helper.turn_xyz_into_llh(nxyz[0],nxyz[1],nxyz[2],'osie')

		# To e+n
		en = geo_helper.turn_latlong_into_eastingnorthing(nll[0],nll[1],'osie')

		exp_e = 316000.0
		exp_n = 234400.0

		# Need to make them 0.316 etc, so we can test to decimal places
		nen = [0,0]
		nen[0] = en[0] / 1000000.0
		nen[1] = en[1] / 1000000.0
		exp_e = exp_e / 1000000.0
		exp_n = exp_n / 1000000.0

		self.assertAlmostEquals(nen[0],exp_e,4,"Easting didn't match")
		self.assertAlmostEquals(nen[1],exp_n,4,"Northing didn't match")


	def testDistanceBearing(self):
		""" Test finding the distance and bearing between two points"""
		start_lat = 53.15056
		start_long = -1.844444
		end_lat =   52.20472
		end_long =    0.140556

		res = geo_helper.calculate_distance_and_bearing(start_lat,start_long,end_lat,end_long)

		exp_d = 170100.06398
		exp_bearing = 127.372

		self.assertAlmostEquals(res[0],exp_d,3,"Distance didn't match")
		self.assertAlmostEquals(res[1],exp_bearing,3,"Bearing didn't match")


	def testTurnLLToCassini(self):
		""" Test turning a lat + long into cassini easting and northings """
		lat = 53.0
		long = -2.0

		res = geo_helper.turn_latlong_into_cassini_en(lat,long,'osgb')

		exp_e = 150716.014 / geo_helper.feet_per_meter
		exp_n = -80134.9 / geo_helper.feet_per_meter

		self.assertAlmostEquals(res[0], exp_e, 3, "Wrong easting")
		self.assertAlmostEquals(res[1], exp_n, 1, "Wrong northing")


	def testTurnCassiniToLL(self):
		""" Test turning a cassini easting + northing into a lat + long"""
		easting = 150716.014 / geo_helper.feet_per_meter
		northing = -80134.916 / geo_helper.feet_per_meter

		res = geo_helper.turn_cassini_en_into_latlong(easting,northing,'osgb')

		exp_lat = 53.0
		exp_long = -2.0

		self.assertAlmostEquals(res[0], exp_lat, 3, "Wrong lat")
		self.assertAlmostEquals(res[1], exp_long, 3, "Wrong long")

	def testIE(self):
		start_e = 123456
		start_n = 234567

		lat,long = geo_helper.turn_eastingnorthing_into_osie36(start_e,start_n)

		# TODO: Check lat+long are right

		e,n = geo_helper.turn_osie36_into_eastingnorthing(lat,long)

		self.assertAlmostEquals(e, start_e, 2, "Wrong e")
		self.assertAlmostEquals(n, start_n, 2, "Wrong n")
		
		wgs_lat, wgs_long, h = geo_helper.turn_osie36_into_wgs84(lat, long, 0)

		# TODO: Check wgs lat+long are right

		i_lat, i_long, h = geo_helper.turn_wgs84_into_osie36(wgs_lat,wgs_long,0)

		self.assertAlmostEquals(i_lat, lat, 4, "Wrong lat")
		self.assertAlmostEquals(i_long, long, 4, "Wrong long")

if __name__ == '__main__':
	unittest.main()
