Форум программистов, компьютерный форум, киберфорум
setood
Войти
Регистрация
Восстановить пароль
Карта форума Блоги Сообщество Поиск Заказать работу  
Оценить эту запись

CSharp. Определяем район по адресу

Запись от setood размещена 18.08.2019 в 13:27

В данной записи, хочу рассказать, как решал задачу распределения списка организации по районам города. Из входных данных использовались адреса, введенные в базу в ручную сотрудниками, поэтому были весьма не консистентыми, некоторый содержали и индекса и город и улицу и адрес дома, некоторые не содержали даже указания города.
Изучение Api известных карт (Google, binq, Yandex), показало, что хоть они и знают про районы города, выдавать по запросу их не хотят.
В результате принял решение:
  1. cначала с помощью вышеуказанных сервисов определить геокоординату адреса
  2. затем сформировать массивы геокоординат точек - углов регионов города (полигоны)
  3. определить в какой из полигонов попадает координата адреса.
Так как бесплатное использование сервисов ограничивает кол-во запросов (порядка 10-25тыс.) нужно было использовать сразу несколько из них. Для этого использовал библиотеку: https://github.com/chadly/Geocoding.net
Сначала нужно получить ApiKey на используемых сервисах. например для гугла тут: https://developers.google.com/maps/documentation/javascript/get-api-key

далее создаем объекты - геокодеры:
C#
1
2
3
4
5
6
public static Geocoding.IGeocoder[] Geocoders { get; } =
            new Geocoding.IGeocoder[]
            {
                new Geocoding.Google.GoogleGeocoder(@"Ваш API=KEY"),
                new Geocoding.Microsoft.BingMapsGeocoder(@"Ваш API=KEY~********~******-fjvUGlbOS-9-************"),
            };
Далее по адресу получаем список-совпадений:
C#
1
2
 var geocoder = geocoders[geocoderIndex];
IEnumerable<Geocoding.Address> addresses = await geocoder.GeocodeAsync(match);
Первые элементы будут иметь большую релевантность, я всегда использовал первый.
Получить широту и долготу можно так:
C#
1
2
var addres = addresses.FirstOrDefault();
return new PointF(addres.Coordinates.Latitude, addres.Coordinates.Longitude);
Дальше нужно создать полигоны районов. Открываем Гугл мэпс, вводим название города и района(округа), появляется контур- граница района. Прокликиваем по порядку каждую точку границы, внизу появляется её широта и долгота:
Нажмите на изображение для увеличения
Название: 2019-08-18_15-59-35.png
Просмотров: 123
Размер:	373.3 Кб
ID:	5510
Собираем все точки района в массив:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 public static DistrictsDetector.District[] OmskDistricts { get; } =
            new DistrictsDetector.District[]
            {
                new DistrictsDetector.District("Tsentral'nyy Okrug", new DistrictsDetector.MapPoint[]
                {
                    new DistrictsDetector.MapPoint(55.032336f, 73.334465f),
                    new DistrictsDetector.MapPoint(55.033914f, 73.342365f),
                    new DistrictsDetector.MapPoint(55.027420f, 73.352678f),......
                }),
                new DistrictsDetector.District("Oktyabr'skiy Okrug", new DistrictsDetector.MapPoint[]
                {
                    new DistrictsDetector.MapPoint(54.975745, 73.399492 ),
                    new DistrictsDetector.MapPoint(54.978650, 73.448036 ),
                    new DistrictsDetector.MapPoint(54.983776, 73.448425 ),......
                }),
Создаем функцию определения попадания точки в полигон:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
private static bool IsPointInPolygon(MapPoint[] polygon, MapPoint point)
        {
            bool isInside = false;
            for (int i = 0, j = polygon.Length - 1; i < polygon.Length; j = i++)
            {
                if (((polygon[i].Longitude > point.Longitude) != (polygon[j].Longitude > point.Longitude)) &&
                (point.Latitude < (polygon[j].Latitude - polygon[i].Latitude) * (point.Longitude - polygon[i].Longitude) / (polygon[j].Longitude - polygon[i].Longitude) + polygon[i].Latitude))
                {
                    isInside = !isInside;
                }
            }
            return isInside;
        }
И проверяем попадание точки в каждый из районов.
MissionComplete

Посмотреть исходный код тестового проекта можно на ГИТхабе: https://github.com/setood/DistrictsDetector
Вам нужно будет указать ваши Api-key, и ввести полигоны нужных вам районов (там только Омск). Можно определять либо один конкретный адрес, либо загрузить файл- базу.
Нажмите на изображение для увеличения
Название: 2019-08-18_16-22-54.png
Просмотров: 205
Размер:	11.2 Кб
ID:	5511
Размещено в Без категории
Показов 1158 Комментарии 0
Всего комментариев 0
Комментарии
 
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru