Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find if a point is inside a polygon - JAVA jts / awt / geotools

I have a random number of coordinates for a polygon taken from a shapefile.

-119.00072399999999 35.36158, -118.99903 35.361576, -118.999026 35.362579, -118.999023 35.363482, -118.999019 35.36432, -118.999408 35.364847999999995, -118.999406 35.365564, -118.999402 35.366516, -118.999398 35.367467999999995, -118.999394 35.368438, -118.999256 35.368438, -118.998232 35.368441

I now have to check if a point (33.63705, -112.17563) is inside this polygon.

My concern is that, my coordinates doesn't fit into an int datatype.

Here is what I have tried:

import java.awt.Polygon;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.geotools.data.DataStore;
import org.geotools.data.DataStoreFinder;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.feature.DefaultFeatureCollection;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.geometry.jts.JTSFactoryFinder;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.Point;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;

public class ReadShapeFile {

    public static void main(String[] args) {

        File file = new File("D:\\shapefile201806\\tl_2018_06_bg.shp");

        try {
            Map<String, String> connect = new HashMap<String, String>();
            connect.put("url", file.toURI().toString());

            DataStore dataStore = DataStoreFinder.getDataStore(connect);
            String[] typeNames = dataStore.getTypeNames();
            String typeName = typeNames[0];

            System.out.println("Reading content : " + typeName);

            SimpleFeatureSource featureSource = dataStore.getFeatureSource(typeName);
            SimpleFeatureCollection collection = featureSource.getFeatures();
            SimpleFeatureIterator iterator = collection.features();

            try {
                while (iterator.hasNext()) {

                    SimpleFeature feature = iterator.next();
                    String featureString = feature.toString();

                    List<String> polygonList = new ArrayList<String>();

                    String polygonCoordinates = StringUtils.substringBetween(featureString, "(((", ")))");
                    System.out.println(polygonCoordinates);
                    polygonList = Arrays.asList(polygonCoordinates.split(","));

                    SimpleFeatureTypeBuilder b = new SimpleFeatureTypeBuilder();

                    b.setName("MyFeatureType");
                    b.setCRS(DefaultGeographicCRS.WGS84);
                    b.add("location", Point.class);
                    final SimpleFeatureType TYPE = b.buildFeatureType();

                    SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(TYPE);
                    GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory();
                    SimpleFeature pointFeature = featureBuilder.buildFeature(null);
                    DefaultFeatureCollection featureCollection = new DefaultFeatureCollection("internal", TYPE);
                    featureCollection.add(pointFeature);

                    try {
                        Polygon polygon = new Polygon();
                        for (int i = 0; i < polygonList.size(); i++) {
                            String[] splitAxis = (polygonList.get(i).split("\\s+"));
                            polygon.addPoint(Integer.valueOf(splitAxis[0]), Integer.valueOf(splitAxis[1]));
                        }

                        boolean isInside = polygon.contains(33.63705,  -112.17563);
                        System.out.println(isInside);

                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }

            } finally {
                iterator.close();
            }

        } catch (Throwable e) {
        }

    }

}

I knew that converting a double to string and back to integer is not going to work anyway.

How can I achieve the solution whether a point is in the polygon for negative decimated values? Please help.

like image 415
Mike Avatar asked Jan 17 '19 12:01

Mike


People also ask

How does Java define a polygon object?

Internally, a polygon comprises of a list of (x,y) coordinate pairs, where each pair defines a vertex of the polygon, and two successive pairs are the endpoints of a line that is a side of the polygon. The first and final pairs of (x,y) points are joined by a line segment that closes the polygon.


1 Answers

Using your SimpleFeature, you can call getDefaultGeometry and get a Geometry object. Once you cast to a Geometry, there should be a contains method which would take a Point class.

Also, you don't want to use the java.awt.Polygon class. Instead you'll be using org.locationtech.jts Geometry classes.

like image 174
GeoJim Avatar answered Oct 24 '22 05:10

GeoJim