Более

Точка трансформации с помощью NetTopologySuite

Точка трансформации с помощью NetTopologySuite


Я изучаю, как мы можем использовать NetTopologySuite для решения задачи геообработки. на основе некоторого примера кода, который я нашел, я смог собрать воедино образец приложения, которое читает шейп-файл и проверяет, попадает ли точка в многоугольник. Проблема в том, что я имею в виду WGS84, но шейп-файл находится в EPSG: 2810. Мне нужно преобразовать входную точку в CRS шейп-файла.

Как преобразовать точку из WGS в EPSG: 2810 с помощью NetTopologySuite 1.13.3?

Вот часть кода, который у меня есть:

строка shpFilename = @ "C: …  polygons.shp"; GeometryFactory factory = new GeometryFactory (); varordinate = новая координата (-90.00, 45.00); var point = factory.CreatePoint (координаты);

Я также должен отметить, что когда я вручную конвертирую из WGS84 в проектируемую систему и использую эти преобразованные значения, мой код работает так, как задумано. Это подтверждает, что речь идет о преобразовании координат перед попыткой определить, попадают ли они в полигон.


Стандартный способ преобразования координат точка-точка в NTS - использование библиотеки ProjNet4GeoAPI.

Вот пример преобразования координат, взятый из модульных тестов:

public void TestTransformListOfCoordinates () {CoordinateSystemFactory csFact = new CoordinateSystemFactory (); CoordinateTransformationFactory ctFact = new CoordinateTransformationFactory (); ICoordinateSystem utm35ETRS = csFact.CreateFromWkt ("PROJCS [" ETRS89 / ETRS-TM35  ", GEOGCS [" ETRS89  », DATUM [" D_ETRS_1989  ", SPHEROID [" GRS_1980,21], 6378227137 ПРИЕМ [ "Гринвич ", 0], ЕДИНИЦА [ "Градус ", 0,017453292519943295]], ПРОЕКЦИЯ [ "Поперечный_ меркатор "], ПАРАМЕТР [ "широта_начина ", 0], ПАРАМЕТР [ "центральный_меридиан " , 27], ПАРАМЕТР [ "коэффициент_масштабности ", 0,9996], ПАРАМЕТР [ "ложный_вкус ", 500000], ПАРАМЕТР [ "false_northing ", 0], ЕДИНИЦА [ "метр ", 1]] ") ; IProjectedCoordinateSystem utm33 = ProjectedCoordinateSystem.WGS84_UTM (33, истина); ICoordinateTransformation trans = ctFact.CreateFromCoordinateSystems (utm35ETRS, utm33); Координата [] точек = новая координата [] {новая координата (290586.087, 6714000), новая координата (290586.392, 6713996.224), новая координата (290590.133, 6713973.772), новая координата (290594.111, 6713957.416), 6713943.667), новая координата (6713957.416), 6713943.667. новая координата (290596.701, 6713939.485)}; Координата [] tpoints = trans.MathTransform.TransformList (points) .ToArray (); for (int i = 0; i 

Столкнулся с такой же необходимостью. Я тоже нашел пример из теста. Они раскрыли подробности. Но такой подход неудобен при работе с типом IGeometry (IPoint, ILineString и т. Д.).

После некоторого исследования я нашел, как преобразовать геометрию более удобным способом (Спасибо репозиторию NTS на github :)

1) мы должны создать преобразование:

ICoordinateTransformation Wgs84ToWebMercator = (new CoordinateTransformationFactory ()) .CreateFromCoordinateSystems (GeographicCoordinateSystem.WGS84, ProjectedCoordinateSystem.WebMercator);

2) объявить фильтр, который будет перебирать геометрическую последовательность и заставит все работать:

открытый класс CoordinateTransformationFilter: ICoordinateSequenceFilter {частный только для чтения ICoordinateTransformation _transformation; public CoordinateTransformationFilter (преобразование ICoordinateTransformation) {_transformation = преобразование ?? выбросить новое исключение ArgumentNullException ($ "{nameof (преобразование)} не может быть нулевым."); } ///  /// Да, всегда верно. ///  public bool Done => true; ///  /// Автоматический вызов метода IGeometry.GeometryChanged () после преобразования. ///  public bool GeometryChanged => true; публичный фильтр void (ICoordinateSequence seq, int i) {_transformation.MathTransform.Transform (seq); }}

3) создать фильтр:

var transformFilter = новый CoordinateTransformationFilter (Wgs84ToWebMercator);

4) Прибыль:

// Получить точку из любого места в WGS84 (также известном как EPSG: 4326) IPoint srcPoint =…; // Вы можете пропустить это. Но ваша геометрия изменится. IPoint projectedPoint = srcPoint.Clone () как IPoint; // Здесь происходит волшебство. Наша точка в WebMercator (он же EPSG: 3857) projectedPoint.Apply (transformFilter);

ОБНОВЛЕНИЕ 2019-07-09: это решение для ProjNET4GeoAPI v1.4.1. Я предполагаю, что с новой версией он работать не будет.


Ответ отлично работает с очками. Но если вы сделаете это с полигонами с отверстиями, точки будут возвращаться не по порядку. Затем, когда вы снова превратите эти точки в многоугольник, он будет жаловаться на то, что LineStrings не закрывается.

В итоге я использовал библиотеку ProjNet для построения своего преобразования, а затем у NetTopologySuite есть утилита, которая обрабатывает многоугольники.

Выглядит примерно так. Вы можете получить текст проекции WKT на сайте SpatialReference.org. Вы можете легко расширить его для всех типов геометрии.

статический GeoAPI.Geometries.IPolygon ProjectGeometry (GeoAPI.Geometries.IPolygon polygeo, строка FromWKT, строка ToWKT) {var SourceCoordSystem = new CoordinateSystemFactory (). CreateFromWkt (FromWKT); var TargetCoordSystem = новая фабрика координатной системы (). CreateFromWkt (ToWKT); var trans = new CoordinateTransformationFactory (). CreateFromCoordinateSystems (SourceCoordSystem, TargetCoordSystem); var poly = NetTopologySuite.CoordinateSystems.Transformations.GeometryTransform.TransformPolygon (polygeo.Factory, polygeo, trans.MathTransform); return poly; }

Обновлять
Приведенный выше код не работает с новой версией NetTopologySuite. Ниже представлена ​​обновленная версия, которая работает с NetTopologySuite 2.0.0.

статический NetTopologySuite.Geometries.Geometry ProjectGeometry (NetTopologySuite.Geometries.Geometry geom, строка FromWKT, строка ToWKT) {var SourceCoordSystem = new CoordinateSystemFactory (). CreateFromWkt (FromWKT); var TargetCoordSystem = новая фабрика координатной системы (). CreateFromWkt (ToWKT); var trans = new CoordinateTransformationFactory (). CreateFromCoordinateSystems (SourceCoordSystem, TargetCoordSystem); var projGeom = Transform (geom, trans.MathTransform); return projGeom; } статическое преобразование NetTopologySuite.Geometries.Geometry (геометрия NetTopologySuite.Geometries.Geometry, преобразование MathTransform) {geom = geom.Copy (); geom.Apply (новый MTF (преобразование)); вернуть geom; } запечатанный класс MTF: NetTopologySuite.Geometries.ICoordinateSequenceFilter {закрытый только для чтения MathTransform _mathTransform; общедоступный MTF (MathTransform mathTransform) => _mathTransform = mathTransform; public bool Done => false; public bool GeometryChanged => true; общедоступный фильтр void (NetTopologySuite.Geometries.CoordinateSequence seq, int i) {double x = seq.GetX (i); двойной y = seq.GetY (i); двойной z = seq.GetZ (i); _mathTransform.Transform (ссылка x, ссылка y, ссылка z); seq.SetX (я, х); seq.SetY (i, y); seq.SetZ (i, z); }}