2

I am trying to take a lat/lon and find which country the lat/lon is located in.

Below is a boilerplate of code I found to accomplish this, which was found in this post (Reverse Geocode latitude longitude with Geotools using Natural Earth Shapefiles in Java )

SpatialIndexFeatureCollection countries;
final static FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2();
final static public String countryFile ="/data/natural_earth/10m_cultural/10m_admin_0_countries.shp";

public SimpleGeoCoder() throws IOException {
  // load the country shapefile
  URL countryURL = DataUtilities.fileToURL(new File(countryFile));
  HashMap<String, Object> params = new HashMap<>();
  params.put("url", countryURL);
  DataStore ds = DataStoreFinder.getDataStore(params);
  if (ds == null) {
    throw new IOException("couldn't open " + params.get("url"));
  }
  Name name = ds.getNames().get(0);
  countries = new SpatialIndexFeatureCollection(ds.getFeatureSource(name).getFeatures());
}

GeometryFactory gf = new GeometryFactory();
Point london = gf.createPoint(new Coordinate(0.0, 51.0));

public SimpleFeatureCollection lookup(Point p) {
  Filter f = ff.contains(ff.property("the_geom"), ff.literal(p));
  return countries.subCollection(f);
 }

SimpleFeatureIterator itr = features.features();
try {
  while (itr.hasNext()) {
    SimpleFeature f = itr.next();
    System.out.println(f.getAttribute("NAME"));
  }
} finally {
  itr.close();
}

Most of the time this solution works, however there seems to be cases where a lat/lon will not be found within the Natural Earth shapefiles. A perfect example would be for the city of Miami Florida (25.761681, -80.191788) when using the shapefile "10m_cultural/10m_admin_0_countries.shp".

My original solution was to use the shapefile "110m_cultural/110m_admin_0_countries.shp" the Miami example will be fine. However I have found a few other examples which occur within the 110m shapefile and I don't know what the solution is. Do I use both the 10m and the 110m shapefiles? Or is there some setting or something else I need to do to accurately solve this issue?

1
  • If you want more accurate info, you need to use more accurate data. Even the 1:10million natural earth data is too coarse around coastlines (see example). I'd look at extracting national boundaries from openstreetmap. The dataset will be much bigger though. Or look at an online geocoding API.
    – user2856
    Commented Jun 29, 2018 at 1:01

1 Answer 1

1

This is nothing to do with the code and everything to do with the "accuracy" (or generalisation) of the data.

As you can see here the coastline is placed in very different places depending on the level of generalisation applied, this is because the Natural Earth files are designed to look good at scales of 1:110M, 1:50M & 1:10M but this image is at 1:500K.

Also you will see that the location of Miami from Natural Earth (the red dot) has been adjusted to fall within the US polygon to make it look cartographically good, whereas your Miami location is a little further south and east and so falls outside some of the polygons.

Depending on your area of interest you will be able to find "better" coastlines (and country boundaries) by looking for national and regional mapping agencies.

enter image description here

1
  • Thank you for the explanation. Would you have any recommendations of better shapefiles which I can use? Unfortunately my requirement doesn't allow me to use any online APIs and it all have to be offline. Thanks again! Commented Jun 29, 2018 at 14:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.