package com.esri; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Envelope; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.geom.Point; import com.vividsolutions.jts.geom.prep.PreparedGeometry; import com.vividsolutions.jts.geom.prep.PreparedGeometryFactory; import com.vividsolutions.jts.index.ItemVisitor; import com.vividsolutions.jts.index.SpatialIndex; import com.vividsolutions.jts.index.strtree.STRtree; import org.apache.hadoop.conf.Configuration; import org.geotools.data.DataStore; import org.geotools.data.shapefile.ShapefileDataStoreFactory; import org.geotools.data.simple.SimpleFeatureCollection; import org.geotools.data.simple.SimpleFeatureSource; import org.geotools.geometry.jts.JTSFactoryFinder; import org.geotools.util.NullProgressListener; import org.opengis.feature.Feature; import org.opengis.feature.FeatureVisitor; import org.opengis.feature.Property; import java.io.File; import java.io.IOException; import java.net.URL; import java.util.HashMap; import java.util.List; import java.util.Map; /** */ public class SearchShapefileIndexPolygon extends SearchAbstract implements ItemVisitor { final class PreparedFeature { Feature feature; PreparedGeometry preparedGeometry; private PreparedFeature( final Feature feature, final PreparedGeometry preparedGeometry) { this.feature = feature; this.preparedGeometry = preparedGeometry; } } private GeometryFactory m_geometryFactory = JTSFactoryFinder.getGeometryFactory(); private Point m_point; private Coordinate m_coordinate = new Coordinate(); private Envelope m_envelope = new Envelope(); private double m_buffer; private SpatialIndex m_spatialIndex; private String m_geometryName; private List<ColumnInterface> m_columnList; @Override public void setup( final Configuration configuration, final List<ColumnInterface> columnList) throws IOException { m_spatialIndex = new STRtree(); m_buffer = configuration.getFloat(GeoEnrichmentJob.KEY_BUFFER, 0.000001F); final URL url = getUrl(configuration); final ShapefileDataStoreFactory factory = new ShapefileDataStoreFactory(); final Map params = new HashMap(); params.put(ShapefileDataStoreFactory.URLP.key, url); final DataStore dataStore = factory.createDataStore(params); try { final String[] typeNames = dataStore.getTypeNames(); final SimpleFeatureSource featureSource = dataStore.getFeatureSource(typeNames[0]); m_geometryName = featureSource.getSchema().getGeometryDescriptor().getLocalName(); final SimpleFeatureCollection featureCollection = featureSource.getFeatures(); featureCollection.accepts(new FeatureVisitor() { public void visit(final Feature feature) { final Geometry geometry = (Geometry) feature.getProperty(m_geometryName).getValue(); final PreparedGeometry preparedGeometry = PreparedGeometryFactory.prepare(geometry); m_spatialIndex.insert(geometry.getEnvelopeInternal(), new PreparedFeature(feature, preparedGeometry)); } }, new NullProgressListener()); } finally { dataStore.dispose(); } } protected URL getUrl(final Configuration configuration) throws IOException { final File file = new File("./shapefile"); return file.toURI().toURL(); } @Override public boolean search( final double lon, final double lat, final List<ColumnInterface> columnList) throws IOException { m_columnList = columnList; resetColumns(columnList); m_coordinate.x = lon; m_coordinate.y = lat; m_point = m_geometryFactory.createPoint(m_coordinate); final double xmin = m_coordinate.x - m_buffer; final double ymin = m_coordinate.y - m_buffer; final double xmax = m_coordinate.x + m_buffer; final double ymax = m_coordinate.y + m_buffer; m_envelope.init(xmin, xmax, ymin, ymax); m_spatialIndex.query(m_envelope, this); return m_found; } @Override public void visitItem(final Object o) { final PreparedFeature preparedFeature = (PreparedFeature) o; if (preparedFeature.preparedGeometry.contains(m_point)) { m_found = true; for (final ColumnInterface column : m_columnList) { final Property property = preparedFeature.feature.getProperty(column.getQualifier()); if (property != null) { column.setWeight(column.toDouble(property.getValue())); } } } } }