GeoMesa Utils

Useful utilities are found in the geomesa-utils module.

Simple Feature Wrapper Generation

GeoMesa can be used to generate Scala value classes for simple feature types defined in TypeSafe Config files. Classes will be generated for any feature types found on the classpath. To use with Maven, add the following snippet to your pom, specifying the package you would like the generated class to reside in:

<dependencies>
  <dependency>
    <groupId>org.locationtech.geomesa</groupId>
    <artifactId>geomesa-utils_${scala.binary.version}</artifactId>
  </dependency>
</dependencies>

<build>
  <plugins>
    <plugin>
      <groupId>org.codehaus.mojo</groupId>
      <artifactId>exec-maven-plugin</artifactId>
      <version>3.0.0</version>
      <executions>
        <execution>
          <id>generate-sft-wrappers</id>
          <phase>generate-sources</phase>
          <goals>
            <goal>java</goal>
          </goals>
          <configuration>
            <mainClass>org.locationtech.geomesa.utils.geotools.GenerateRichFeatureModels</mainClass>
            <addResourcesToClasspath>true</addResourcesToClasspath>
            <cleanupDaemonThreads>false</cleanupDaemonThreads>
            <killAfter>-1</killAfter>
            <arguments>
              <argument>${project.basedir}</argument>
              <argument>com.example.geomesa</argument>
            </arguments>
          </configuration>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

Geohash

Geohashes are a geocoding system that uses a Z-order curve to hierarchically subdivide the latitude/longitude grid into progressively smaller bins. The length of a Geohash in bits indicates its precision.

For example, the table below shows Geohash bounding boxes around the point (-78.48, 38.03) with increasing levels of precision in units of bits (the coordinates are rounded to three decimal places for clarity):

bits bounding box centroid geohash
1 -180.000 -90.000, 0.000 90.000 -90.000 0.000 0
2 -180.000 0.000, 0.000 90.000 -90.000 45.000 01
3 -90.000 0.000, 0.000 90.000 -45.000 45.000 011
4 -90.000 0.000, 0.000 45.000 -45.000 22.500 0110
5 -90.000 0.000, -45.000 45.000 -67.500 22.500 01100
6 -90.000 22.500, -45.000 45.000 -67.500 33.750 011001
7 -90.000 22.500, -67.500 45.000 -78.750 33.750 0110010
8 -90.000 33.750, -67.500 45.000 -78.750 39.375 01100101
9 -78.750 33.750, -67.500 45.000 -73.125 39.375 011001011
10 -78.750 33.750, -67.500 39.375 -73.125 36.563 0110010110
11 -78.750 33.750, -73.125 39.375 -75.938 36.563 01100101100
12 -78.750 36.563, -73.125 39.375 -75.938 37.969 011001011001
13 -78.750 36.563, -75.938 39.375 -77.344 37.969 0110010110010
14 -78.750 37.969, -75.938 39.375 -77.344 38.672 01100101100101
15 -78.750 37.969, -77.344 39.375 -78.047 38.672 011001011001010
16 -78.750 37.969, -77.344 38.672 -78.047 38.320 0110010110010100
17 -78.750 37.969, -78.047 38.672 -78.398 38.320 01100101100101000
18 -78.750 37.969, -78.047 38.320 -78.398 38.145 011001011001010000
19 -78.750 37.969, -78.398 38.320 -78.574 38.145 0110010110010100000
20 -78.750 37.969, -78.398 38.145 -78.574 38.057 01100101100101000000
21 -78.574 37.969, -78.398 38.145 -78.486 38.057 011001011001010000001
22 -78.574 37.969, -78.398 38.057 -78.486 38.013 0110010110010100000010
23 -78.486 37.969, -78.398 38.057 -78.442 38.013 01100101100101000000101
24 -78.486 38.013, -78.398 38.057 -78.442 38.035 011001011001010000001011
25 -78.486 38.013, -78.442 38.057 -78.464 38.035 0110010110010100000010110

The bounding boxes corresponding to the Geohashes in the table above are shown as red polygons on this map:

../../_images/geohash-cville.png

The org.locationtech.geomesa.utils.geohash.GeoHash class provides tools for working with Geohashes. The data for the table above may be generated with the following Scala code:

import org.locationtech.geomesa.utils.geohash.GeoHash

for (p <- 1 to 25) {
  val gh = GeoHash(-78.48, 38.03, p)
  println(s"""$p ${gh.bbox.toText} ${gh.getPoint.toText} ${gh.toBinaryString}""")
}

Base-32 Encoding

Geohashes are encoded as strings with the following base-32 representation:

dec binary base-32 dec binary base-32
0 00000 0 16 10000 h
1 00001 1 17 10001 j
2 00010 2 18 10010 k
3 00011 3 19 10011 m
4 00100 4 20 10100 n
5 00101 5 21 10101 p
6 00110 6 22 10110 q
7 00111 7 23 10111 r
8 01000 8 24 11000 s
9 01001 9 25 11001 t
10 01010 b 26 11010 u
11 01011 c 27 11011 v
12 01100 d 28 11100 w
13 01101 e 29 11101 x
14 01110 f 30 11110 y
15 01111 g 31 11111 z

By this convention, the 25-bit Geohash that contains (-78.48, 38.03) described above would be encoded as “dqb0q”:

01100 10110 01010 00000 10110
----- ----- ----- ----- -----
  d     q     b     0     q