A Free and Open Source Library to convert between Lat/Lon, and SVY21.
The Ruby version is packaged as a gem.
To install
gem "svy21", "~> 1.0.1"
Usage
require 'svy21'
# 570 Ang Mo Kio Avenue 10
# lat/lon
lat_lon = SVY21.svy21_to_lat_lon(39105.269, 30629.967)
puts "latitude: #{lat_long[0]}"
puts "longitude: #{lat_long[1]}"
# svy21
northing_easting = SVY21.lat_lon_to_svy21(1.3699278977737488, 103.85695034976467)
puts "northing: #{northing_easting[0]}"
puts "easting: #{northing_easting[1]}"
The Python script is a ready-to-use converter. Run with python -i SVY21.py
.
# Initialization
>>> cv = SVY21()
# Computing SVY21 from Lat/Lon
>>> (lat, lon) = (1.2949192688485278, 103.77367436885834)
>>> (N, E) = cv.computeSVY21(lat, lon)
>>> (N, E)
(30811.26429645264, 21362.157043860374)
# Computing Lat/Lon from SVY21
>>> (lat, lon) = cv.computeLatLon(N, E)
>>> (lat, lon)
(1.2949192688483109, 103.77367436887495)
The package net.qxcg.svy21
contains all necessary files.
The static class SVY21
performs actual conversions. The classes SVY21Coordinate
and LatLonCoordinate
are immutable types that store SVY21 and Latitude/Longitude respectively. Conversions using SVY21
return new copies of either coordinate type.
// Required files are in this package.
import net.qxcg.svy21.*;
// Creating a latlon Coordinate.
LatLonCoordinate coord1 = new LatLonCoordinate(1.2949192688485278, 103.77367436885834);
// Conversion using coordinate method.
SVY21Coordinate result = coord1.asSVY21();
// Conversion using library.
result = SVY21.computeSVY21(coord1);
// It is also possible perform conversion directly using two plain 'double' types.
double lat = coord1.getLatitude();
double lon = coord1.getLongitude();
result = SVY21.computeSVY21(lat, lon);
// The reverse conversion also can be done using all three methods.
LatLonCoordinate reverseResult = result.asLatLon();
reverseResult = SVY21.computeLatLon(result);
double northing = result.getNorthing();
double easting = result.getEasting();
reverseResult = SVY21.computeLatLon(northing, easting);
// Initialization
var cv = new SVY21();
// Computing SVY21 from Lat/Lon
var lat = 1.2949192688485278;
var lon = 103.77367436885834;
var result = cv.computeSVY21(lat, lon);
console.log(result);
// Computing Lat/Lon from SVY21
var resultLatLon = cv.computeLatLon(result.N, result.E);
console.log(resultLatLon);
The C# implementation was ported from the Java implementation, and includes the same tests (executable in Visual Studio.)
Unlike the Java implementation, however, LatLongCoordinate
and Svy21Coordinate
are mutable.
The included solution can be built to produce a class library (SVY21.dll
) which can be included in any project.
Alternatively, the three classes (LatLongCoordinate
, Svy21Coordinate
, and Svy21
) can be included directly.
// Creating a Lat/Long Coordinate.
LatLongCoordinate latLong = new LatLongCoordinate(1.2949192688485278, 103.77367436885834);
// "Ask" the object to convert itself.
Svy21Coordinate converted = latLong.ToSvy21Coordinate();
// Conversion using library.
converted = Svy21.ComputeSvy21(latLong);
// Conversion can also be done directly using two doubles.
double latitude = latLong.Latitude;
double longitude = latLong.Longitude;
converted = Svy21.ComputeSvy21(latitude, longitude);
// Conversion from SVY21 to Latitude/Longitude can also be done using all three methods.
LatLongCoordinate reverse = converted.ToLatLongCoordinate();
reverse = Svy21.ComputeLatitudeLongitude(converted);
double northing = converted.Northing;
double easting = converted.Easting;
reverse = Svy21.ComputeLatitudeLongitude(northing, easting);
// Initialization
SVY21 svy21;
// Computing SVY21 from Lat/Lon
double lat = 1.2949192688485278;
double lon = 103.77367436885834;
double northing, easting;
svy21.latLonToSVY21(lat, lon, &northing, &easting);
printf("%lf %lf\n", northing, easting);
// Computing Lat/Lon from SVY21
svy21.SVY21ToLatLon(northing, easting, &lat, &lon);
printf("%lf %lf\n", lat, lon);
The "Protected Areas And Protected Places Act" found here lists some SVY21 points that correspond to vertices of hard-to-miss plots of land in Singapore.
You can try converting some of the Northing, Easting coordinates to Latitude and Longitude, and viewing the plot of land on Google Maps to verify their accuracy.
Like all floating-point computations, converting back and forth between Lat/Lon and SVY21 will cause the loss of precision.
In the Python example above, note that the input Lat/Lon and output Lat/Lon are very slightly different. Repeating the process a few more times will compound this difference.
The useful precision of the output also depends on the precision of the inputs.
- Setting the origin's latitude and longitude, represented by
oLat
andoLon
respectively, to the official SVY21 datum specified here results in computation being a bit off (when compared to a Google Maps satellite image) for the above sample points. However, the rounded values of(1.366666, 103.833333)
give accurate results.
This library makes use of the equations in the following page:
Transverse Mercator Transformation Formulae
Feel free to port the code to other languages, and submit a pull request if you do!
- Code quality. This library was developed during a Hackathon, and needs to be brought up to production standard.
- Automated and/or more comprehensive tests.
Isaac Low
Jonathan Ong
Chua Wei Kuan
If you used this library in your project and found it useful, let us know!
Created during Hack & Roll '13 by NUS Hackers