Share by Email

Sending email...

Converting
GIS spatial coordinates

Different
formats and standards exist for describing geographical coordinates in GIS
systems and applications. This article explains how to convert between the most
used formats, presenting a working library written in C#.

Many coordinate systems

I have been
playing with GIS systems recently, and a thing that
fascinated me, in both good and bad way, is the existence of several types of
spatial coordinate systems to express a position of a place on the globe. For
those familiar with OGC-compliant GIS systems, you may know that the spatial_ref_sys
metadata table holds conversion data to allow conversions from one coordinate
system to another.

Each entry
in this table contains specific information such as units of measurement, where
the origin is located, and even the starting offset of a measurement. Most of
us are familiar with seeing a coordinate pair such as this:

54.852726,
-1.832299

If you have
a GPS built into your mobile phone, fire it up and watch the display. You’ll
see something similar to this coordinate pair. Note that on some devices and
apps, the coordinates may be swapped.

This
coordinate pair is known as latitude and longitude. The first
number, latitude, is the degrees north or south from the equator with north
being positive and south being negative.

The second
number, longitude, is the degrees east or west of the Prime Meridian with west being
negative and east being positive. The correct geospatial name for this
coordinate system is WGS84, generally known as World Geodetic System.

Most
commercial GPS applications and devices, however, use a different
system for expressing geo coordinates, called National Marine
Electronics Association,
more specifically NMEA 0183. This system expresses latitude and
longitude as a combination of degrees, minutes and seconds:

5321.5802
N, 00630.3372 W

The format
of the string is DDMM.mmmm for the latitude (vertical) direction and DDDMM.mmmm
for the longitude (horizontal) direction.

Starting
with the latitude measurement in the string, the first two digits are the number
of degrees, and the remaining numbers are the minutes. The numbers after the decimal
point are fractions of a minute. This gives us:

Latitude:
53 degrees, 21.5802 minutes north

For the
longitude measurement, the first three digits are the number of degrees, and
the remaining digits are the minutes. All the numbers after the decimal are
fractions of a minute.

This gives
us:

Longitude:
6 Degrees, 30.3372 minutes west

Because this
data is string data, it’s essentially an exercise in cutting the string at
specific points to derive the values you want. Once you have them, the math to
convert them to the more familiar latitude and longitude format (if you
remember that was WGS84) is very simple.

GPS
applications use the NMEA 0183 coordinate system

Converting coordinates

I have
implemented latitude and longitude as a class, GeoCoordinates, and have
exposed methods for system conversion, which include parsing and formatting
strings in the different formats.

First, we
need to separate the first two digits from the latitude string and the first
three from the longitude. This gives us the following:

53
and 21.5802 for the north direction

006
and 30.3372 for west

Because
there are 60 minutes in a degree, we must divide the minutes digits by sixty to
find what fraction of a degree they are, and then combine them with our whole
degrees. So, for our latitude:

53
+ (21.5812 / 60) will give us 53.359686 degrees.

And for our
longitude:

6
+ (30.3372 / 60) will give us 6.505620 degrees.

To finish
the conversion, we need to apply the north and west directions as positive or
negative numbers. The easiest way to manage which directions are positive or
negative is to change any west or south measurements to negative. So with our
numbers, the final coordinates in WGS84 latitude and longitude are:

53.359686,
-6.505620

Let’s see
how this translates into C# code.

Latitude and Longitude are decimal
properties of the GeoCoordinates class. I decided to use decimal
as data type as it offers higher accuracy and is less prone to loss of
precision in mathematical calculations, as compared to the floating-point data
types float and double.

Latitude
extends from the equator (0 degrees) to the North Pole (90 degrees) or the
South Pole (-90 degrees). Longitude extends from the Greenwich meridian to the
right-hand side (East) for 180 degrees, and to the left-hand side (West) for
180 degrees. Therefore, I have enforced range validation on setting the
properties.

privatedecimal _latitude;

publicdecimal Latitude

{

get

{

return _latitude;

}

set

{

if (value < -90.0M || value > 90.0M)

{

thrownewArgumentOutOfRangeException("Latitude must
be between -90.0 and 90.0.");

}

_latitude = value;

}

}

privatedecimal _longitude;

publicdecimal Longitude

{

get

{

return _longitude;

}

set

{

if (value < -180.0M || value > 180.0M)

{

thrownewArgumentOutOfRangeException("Longitude must
be between -180.0 and 180.0.");

}

_longitude = value;

}

}

Latitude and Longitude as C#
properties

The GeoCoordinates
class expresses coordinates in WGS84 format (that is, decimal values). We want
to convert coordinates from the format in use in GPS applications (NMEA 0183),
which is expressed in degrees and minutes. For example, our hypothetical
application would have a simple instruction like the following one:

string degrees = "5321.5802 N, 00630.3372 W";

GeoCoordinates
coords = GeoCoordinates.FromNMEA0183(degrees);

The static
function FromNMEA0183 converts the string representation of coordinates
into its decimal elements.

The method to convert from
textual to decimal representation of coordinates

After some
obvious validation, the coordinates’ string is split into its two elements of
latitude and longitude, separated by comma, and each element is then parsed
separately. ParseLatitude and ParseLongitude are very similar
methods, but I decided to implement them individually to avoid confusing “if”
conditions to handle either element of the geo coordinates. I’ll describe the
code for ParseLatitude in this article, the full source code is available on CodePlex.

There is a
lot of validation in place, as you would expect, to make sure the input string
is in the expected format. The process of conversion of coordinates, basically,
takes places into three steps:

1.Read the degrees
portion and convert into an integer number; if the number is higher than 90,
throw an out-of-range exception.

dd = int.Parse(coords.Substring(0, 2));

if (dd > 90)

{

thrownewArgumentOutOfRangeException();

}

2.Read the minutes
portion, including decimals, and convert into a double number; minutes are read
after extracting them from the string representation, by taking out the initial
two digits for degrees, and any trailing non-numeric signs (for N or S). Range
validation is also applied.

3.Put all together
by adding the minutes to the degrees and converting into decimal; sign is also applied
depending on the direction of the latitude (North is positive, South is
negative).

decimal latitude = Convert.ToDecimal(dd + mm / 60);

if (coords.EndsWith("S", StringComparison.OrdinalIgnoreCase))

{

latitude = decimal.Negate(latitude);

}

Exactly the same
logic applies to parsing longitude, with the obvious difference on the input
format.

Printing coordinates

After
parsing input values, we now want to produce something in output, specifically
represent coordinates in either format NMEA0183 or WGS84. Code-wise, we need
something to print out coordinates as a string, for example:

The FormatNMEA0183
is pretty straightforward, with the latitude and longitude components formatted
individually. As an output, we want to obtain a string with the latitude and
longitude coordinates separated by comma, as in 5321.5802 N, 00630.3372 W

privatestring FormatNMEA0183()

{

string latitude = FormatLatitudeDegrees(this.Latitude);

string longitude = FormatLongitudeDegrees(this.Longitude);

return$"{latitude}, {longitude}";

}

To format
latitude, we need to convert from a decimal number into DDMM.mmmm, e.g.
53.359686 à 5321.5802 N

Formatting
coordinates into WGS84 is even easier, as implemented in the FormatWGS84
method; all we need to do is to combine latitude and longitude in a
comma-separated string, e.g. 53.359686, 6.505620.

A flexible Default Value for your DateTime propertiesWhen creating an MVC application with Entity Framework, it is possible to set default values for most properties in a model using the DefaultValue attribute. However, no much flexibility is offered for a DateTime property. This article presents a custom validation attribute for DateTime types that accepts different formats for defining the default value of the property.

Adding a Secured Geo-located Audit TrailHow I built a social sharing component for my own web site and added a secured geo-located audit trail. Step by step, let’s analyse technologies and source code for developing this component.

Adding Social Sharing to a Web SiteHow I built a social sharing component for my own web site and added a secured geo-located audit trail. Step by step, let’s analyse technologies and source code for developing this component.

Bring your “A” game to ESPC16With just over 3 weeks to go to Europe's largest gathering of SharePoint & Office 365 professionals, take a look at these tips that will help you get the most out of ESPC16…

Building an MVC application for SharePointLearn how to write code to perform basic operations with the SharePoint 2013 .NET Framework client-side object model (CSOM), and build an ASP.NET MVC application that retrieves information from a SharePoint server.

CIO vs CTOWhat are the synergies and differences of the roles of a Chief Information Officer and a Chief Technology Officer? An open conversation about two roles with one mission…

Coded UI test automation of MVC applications with Visual StudioWhether you are a software developer, tester, administrator or analyst, this article can help you master different types of UI testing of an MVC application, by using Visual Studio for creating coded UI test suites that can be automated for continuous execution.

Define your Performance Testing strategy with Visual StudioPerformance Testing is an essential part of software testing, with the specific goal of determining how a system performs in terms of responsiveness and stability under a particular workload. In this series of posts we’ll define and execute a good strategy for testing performance of an application using Visual Studio.

GIS Location Services in Dynamics CRMA design paper about implementing GIS-based services for a local Council in Dynamics CRM, structuring address data, and delivering location services in the form of WebAPI endpoints via an Enterprise Service Bus.

Group or Team?All teams are groups but not all groups are teams. What defines a group and what a team? When do we need one over the other one?

Mirroring an iPad on your laptopHave you ever wanted to see your iPhone or iPad on a larger screen? Play games, watch movies, demo apps or present to your computer from your iPhone or iPad. Reflector mirrors iOS devices on big screens wirelessly using iOS built-in AirPlay mirroring.

Mobilize your SharePoint workflowsBuild workflow applications in SharePoint that can be accessed on mobile devices using the Nintex solution for business process mobilization.

Natural String SortingHave you ever desired to have in your code a way to order a sequence of strings in the same way as Windows does for files whose name contains a mix of letters and numbers? Natural string sorting is not natively supported in .NET but can be easily implemented by specialising a string comparer and adding a few extensions to the enumerable string collection.

Software Development Management in 11 stepsWhat it takes to be a great Software Development Manager? I have been building software for the last 15 years and have collected a few stories and experiences to share. Some I have used as questions when interviewing candidates. In 11 points, this is my story to date.

SOLID SharePoint apps with MVCPractical code examples of ASP.NET MVC applications that connect to a SharePoint Server and comply with the SOLID principles.

The art of outsourcing projectsOutsourcing may look financially attractive, but working with companies in far-off lands introduces challenges that, if not considered properly, can drive any project to failure. Let’s explore some common pitfalls when working with offshore partners and a common-sense approach to work around them.

The value of hashtagsCustomers expect a modern approach to advertising. Digital advertising can leverage evolving technology to provide just-in-time, just-at-the-right-place promotions.

We don't need no Yoda's syntaxThere is an urban myth in the programmers’ community that the so called “Yoda’s syntax” performs better when checking an object for nullity. Let's demystify it...