Узнать, находится ли точка внутри многоугольника — JAVA jts/awt/geotools

У меня есть случайное число координат для многоугольника, взятого из шейп-файла.

-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

Теперь мне нужно проверить, находится ли точка (33.63705, -112.17563) внутри этого многоугольника.

Меня беспокоит то, что мои координаты не вписываются в тип данных int.

Вот что я пробовал:

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) {
        }

    }

}

Я знал, что преобразование двойного числа в строку и обратно в целое все равно не сработает.

Как я могу решить, находится ли точка в многоугольнике для отрицательных прореженных значений? Пожалуйста помоги.


person Mike    schedule 17.01.2019    source источник


Ответы (1)


Используя SimpleFeature, вы можете вызвать getDefaultGeometry и получить объект Geometry. После приведения к Geometry должен быть метод contains, который будет принимать класс Point.

Кроме того, вы не хотите использовать класс java.awt.Polygon. Вместо этого вы будете использовать классы геометрии org.locationtech.jts.

person GeoMesaJim    schedule 17.01.2019
comment
Вы просто потрясающие! - person Mike; 17.01.2019
comment
Я более чем счастлив помочь! - person GeoMesaJim; 18.01.2019
comment
Спасибо, Джим, однако я не вижу метода contains(Points.class). Требуется только объект Geography. Как мне передать Point (Double, Double) в contains? Я пробовал импорт VividSolutions и LocationTech для класса Geometry. - person Mathomatic; 17.06.2019
comment
Это означало, что Geometry не Geography объект. - person Mathomatic; 17.06.2019
comment
Point является подклассом Geometry. Вы можете использовать GeometryFactory для создания точки из координаты, используя этот метод: locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/ и у Coordinate есть конструктор, который принимает две точки: locationtech.github.io/ jts/javadoc/org/locationtech/jts/geom/ . Для самых простых случаев использования это может показаться излишним. - person GeoMesaJim; 18.06.2019