Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save hgavert/b9aa32b7a2e81c6e6d00d2ee65b47776 to your computer and use it in GitHub Desktop.
Save hgavert/b9aa32b7a2e81c6e6d00d2ee65b47776 to your computer and use it in GitHub Desktop.

How to map GPS locations to Grid Database from Statistics Finland

Keywords: Tilastokeskus, Ruututietokanta, GPS, WGS84, EUREF-FIN, ETRS89-TM35FIN

The grid of the DB

The Grid database contains 250m x 250m squares. The square is definied by the x- and y-koordinates of the lower left corner of the grid. This corner defines the square. In the database, they are even meters without decimals.

Matching GPS point to Grid DB

This example is using Scala and the Sanoma-CDA / maxmind-geoip2-scala library. To use that library, you should doanload it and publish either locally or to your artifactory.

Conversion from GPS to Grid DB coordinates

Conversion is done simply by:

import com.sanoma.cda.geo.Point
import com.sanoma.cda.geo.CoordinateConversions._

val GPS_point = Point(60.1672065,24.943796)

val EUREF_FIN = wgs842etrs89tm35fin(GPS_point)
// EUREF_FIN: (Double, Double) = (6671809.459860587,385901.3059246596)

Matching to DB

Matching to DB squares is easy as you recall that the square is defined by the lower left corner. Therefore define a helper function:

def floorTo250m(c: Double) = {
	def toStr(d: Double) = d.intValue.toString
	val floored = math.floor(c / 250.0) * 250.0
	toStr(floored)
}

// and I suggest you combine the coordinates for example like this (and do the same in the DB):

def pointToGridID(p: (Double, Double)): String = {
	floorTo250m(p._1) + ":" +floorTo250m(p._2)
}

// For example:
val gridID = pointToGridID(EUREF_FIN)
//gridID: String = 6671750:385750

And then you can use that gridID to join to the data in the Grid DB if you created the same concatenated field in there (or join with 2 fields if you didn't concatenate these).

Square from Grid DB to GPS coordinates

Coordinates

If you need to plot the squares with GPS coordinates, you should probably convert all the square corners separately, like this:

val lowerLeftCorner = ("6671750","385750")

def gridIDToGPSSquare(llc: (String, String)) = {
	val northing = llc._1.toDouble
	val easting = llc._2.toDouble
	val corners = List(
		(northing, easting), 
		(northing + 250, easting), 
		(northing, easting + 250), 
		(northing + 250, easting + 250) 
	)
	corners.map(etrs89tm35fin2wgs84)
}

gridIDToGPSSquare(lowerLeftCorner)
//List[com.sanoma.cda.geo.Point] = List(Point(60.16663063879607,24.94110472172945), Point(60.16887394708703,24.940964317230154), Point(60.166700521644,24.94560657539308), Point(60.168943836243876,24.945466477366548))

Example KML

Or you can create a KML out of this for example like this:

import com.sanoma.cda.geo._
import com.sanoma.cda.geo.KML._

val square = Polygon(gridIDToGPSSquare(lowerLeftCorner))

val squarePlacemark = polygon2KMLPlacemark(poly = square, name = "test square", height = 1.0, lineColorHex = Some(rgb2KMLColor(rgb = (1.0, 0.0, 0.0))), polyColorHex = Some(rgba2KMLColor(1.0, 0.0, 0.0, 0.7)))

val docs = List(getKMLFolder("squares", List(squarePlacemark)))
val master = getKMLMasterDoc(docs)

// and then write it like this:
import scala.xml.XML
val out = new java.io.PrintWriter("foo.kml")
XML.write(out, master, "utf-8", xmlDecl = true, doctype = null)
out.close

// master is:
/*
master: scala.xml.Elem =
<kml xmlns="http://www.opengis.net/kml/2.2">
      <Document id="Geo areas">
        <open>1</open>
      <Folder id="squares">
      <name>squares</name>
      <open>0</open>
      <visibility>1</visibility>
      <Placemark>
      <name>test square</name>
      <visibility>1</visibility>
      <Style>
          <LineStyle><color>FF0000FF</color></LineStyle><PolyStyle><color>B30000FF</color></PolyStyle>
        </Style>
      <Polygon id="P_test square">
        <extrude>1</extrude>
        <altitudeMode>relativeToGround</altitudeMode>
        <outerBoundaryIs>
          <LinearRing id="LR_test square">
            <coordinates>
              24.94110472172945,60.16663063879607,1.0 24.940964317230154,60.16887394708703,1.0 24.94560657539308,60.166700521644,1.0 2...

*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment