4

So I'm writing a Java app, and I've got an ESRI Shapefile which contains the borders of all the U.S. states. What I need is to be able to determine whether any given lat/lon point is within a specified distance from ANY state border line - i.e., I will not be specifying a particular border line, just need to see whether the point is close to any of them.

The solution does NOT have to be very precise at all; e.g. I don't need to be dealing with measuring perpendicular to the border, or whatever. Just checking to see if going X meters north, south, east or west would result in crossing a border would be more than sufficient. The solution DOES have to be computationally efficient, as I'll be performing a huge number of these calculations.

I'm planning to use the GeoTools library (though if there's a simpler option, I'm all for it) with the Shapefile plugin. What I don't really understand is: Once I've got the shapefile loaded into memory, how do I check to see whether I'm near a border?

Thanks! -Dan

geographika
  • 6,458
  • 4
  • 38
  • 56
DanM
  • 7,037
  • 11
  • 51
  • 86
  • given "does not have to be very precise", I'd assume it does not have to account for the curve of the earth? this sounds like a very tough problem to solve without brute forcing it (checking every single line)... good luck – jwl May 27 '09 at 19:15
  • Correct. Does not have to account for curvature of the earth, at least not in any meaningful sense. – DanM May 27 '09 at 19:18

3 Answers3

7

Assuming JTS for Geometry which is what is included in GeoTools:

public boolean pointIsClose( File file, Point targetPoint,double distance) {


  boolean ret = false;
  Map connect = new HashMap();
  connect.put("url", file.toURL());
  DataStore dataStore = DataStoreFinder.getDataStore(connect);


  FeatureSource featureSource = dataStore.getFeatureSource(typeName);
  FeatureCollection collection = featureSource.getFeatures();
  FeatureIterator iterator = collection.features();



  try {
    while (iterator.hasNext()) {
      Feature feature = iterator.next();
      Geometry sourceGeometry = feature.getDefaultGeometry();
      ret= sourceGeometry.isWithinDistance(targetPoint, distance );
    }
  } finally {
    iterator.close();
  }
  return ret;
}

The double number will have to come from the CRS which will define the units in which the calculation will be performed.

These are the geotools imports:

import org.geotools.data.DataStore;
import org.geotools.data.DataStoreFinder;
import org.geotools.data.FeatureSource;
import org.geotools.feature.Feature;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.FeatureIterator;
import org.geotools.geometry.jts.JTS;
import org.geotools.referencing.CRS;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
Clint
  • 8,988
  • 1
  • 26
  • 40
  • this could be improved by only considering the state that the point is within by using a contains query to bring back just one state. – Ian Turton Jul 18 '14 at 11:25
2

If you just want to know if point A is within X meters of a state border and X is constant and you don't care which border it is, you can precompute the negative space as a series of boxes. Then all you have to do is a contains check for each of those boxes against the point. If none of them match, you're not in the negative space.

Jherico
  • 28,584
  • 8
  • 61
  • 87
1

If you can somehow extract the shape for each state from the shapefile, create an envelope that is x meters on a side (with your point in the exact center) and see if those two shapes intersect, you'll be able to answer the question.

If I was using ESRI's ArcGIS Engine, I'd use an ISpatialFilter with the point defined in the geometry (possibly with a buffer) and query that against the States shapefile. Any result(s) returned would indicate that the point was near a state. I'm unfamiliar with GeoTools and, while browsing through their documentation, I didn't come across anything that looked like that type of functionality, but they must have it. You may want to look for examples of how to use GeoTools to perform spatial queries on shapefiles.

Michael Todd
  • 16,679
  • 4
  • 49
  • 69