Определение вхождения координат в заданную область на карте OSM. Взаимодействие JavaScript и 1С

Здравствуйте! 

Хочу поделиться способом интерактивного определения вхождения указанных координат в область с заданшаблонным радиусом охвата.

Данный способ реализован с помощью карт OpenStreetMap и библиотеки Leaflet. На инфостарте встречаются десятки статей, описывающих взаимодействие данной карты с 1С. Но т.к. подобных тем я не встречал, делюсь с форумчанами.

Итак, для начала необходимо создать текстовый макет "Карта", где будет хран внешние компонентыиться выполняемы JS код. Код с комментариями привожу ниже:

<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<link rel="stylesheet" href="/redirect.php?url=aHR0cHM6Ly91bnBrZy5jb20vbGVhZmxldEAxLjcuMS9kaXN0L2xlYWZsZXQuY3Nz"
		integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A=="
		crossorigin="" />
	<link rel="stylesheet" href="/redirect.php?url=aHR0cHM6Ly91bnBrZy5jb20vbGVhZmxldC1yb3V0aW5nLW1hY2hpbmVAbGF0ZXN0L2Rpc3QvbGVhZmxldC1yb3V0aW5nLW1hY2hpbmUuY3Nz" />
	<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"
		integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA=="
		crossorigin=""></script>
	<script src="https://unpkg.com/leaflet-routing-machine@latest/dist/leaflet-routing-machine.js"></script>
</head>

<body>
	<div id="map" class="map" style="position: absolute; top: 0px; right: 0px; bottom: 0px; left: 0px;"></div>

	<script type="text/javascript">

		//Установка начальных координат (широта и долгота и (13 - это зум))
		var map = L.map('map').setView([53.2030600, 50.1594980], 13); // Координаты г. Самара
		var markers = L.layerGroup().addTo(map);
		var circles = L.layerGroup().addTo(map);
		
		L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
			attribution: '&copy; <a href="/redirect.php?url=aHR0cHM6Ly93d3cub3BlbnN0cmVldG1hcC5vcmcvY29weXJpZ2h0">OpenStreetMap</a> contributors'
		}).addTo(map);

		map.on("click", onClick)
		//map.on("dblclick", onClickduble)

		let lat = 0;
		let lng = 0;
		let title = "";

		//Выбор точки на карте
		function onClick(e = e) {
			lat = e.latlng.lat;
			lng = e.latlng.lng;
			refreshMap();
			newMarker(lat, lng)
		}
        
        //Создает новый слой окружности на карте. Вызывается из 1С. 
		function createRadius(latitude, longitude, rad) {
			circles.clearLayers();
			let circle = new L.circle([latitude, longitude], {radius: rad});/**/
			circle.addTo(circles);
			SetViewOffice(latitude, longitude)
		} 
		
        //Отрисовка нового маркера при нажатии на карту 
		function newMarker(latitude, longitude, title) {
			lat = latitude;
			lng = longitude;
			refreshMap()
			SetViewOffice(lat, lng)
			let marker = new L.Marker([lat, lng]);/**/
			marker.bindPopup(title).openPopup();
			marker.addTo(markers);
		}

        //Функция вызывается из 1С. Возвращает координаты установленного маркера
		function returnLatLng() {
			coordinate = {
				lat,
				lng,
				title
			}

			jsonString = JSON.stringify(coordinate)
			return jsonString;
		}

		//function onClickduble(e) {
		//}

		//Очищаем карту
		function refreshMap() {
			markers.clearLayers();
		}

		//Установка отображение на текущем адресе
		function SetViewOffice(latitude, longitude) {
			map.setView([latitude, longitude], 15);
		}
	</script>
</body>
</html>
 
 Небольшое пояснение:::

 

 
 Далее, необходимо создать реквизиты формы:

 

Затем в процедуре ПриСозданииНаСервере необходимо присвоить код html, описанный выше, переменной Карта. В данной обраб автоматизацией отконсоль отчетов ке, я также заполняю ТЗ "Адреса" тестовыми данными и сразу формирую список выбора для переменной "Адрес". 

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработконсоль отчетов ка)
	МакетКарта = РеквизитФормыВЗначение("Объект").ПолучитьМакет("Карта");
	Карта = МакетКарта.ПолучитьТекст();
	
	///// Заполнение ТЗ "Адреса" тестовыми данными
	СтрокаТЗ = Адреса.Добавить();
	СтрокаТЗ.Адрес = "Самарская область, г. Самара";
	СтрокаТЗ.Широта = 53.203060;
	СтрокаТЗ.Долгота = 50.159498;
	
	СтрокаТЗ = Адреса.Добавить();
	СтрокаТЗ.Адрес = "Свердловская область, г. Екатеринбург";
	СтрокаТЗ.Широта = 56.835095;
	СтрокаТЗ.Долгота = 60.613329;
	
	СтрокаТЗ = Адреса.Добавить();
	СтрокаТЗ.Адрес = "Челябинская область, г. Челябинск";
	СтрокаТЗ.Широта = 55.165798;
	СтрокаТЗ.Долгота = 61.434271;
	
	///// Заполнение списка выбора реквизита Адрес
	ЗаполнитьСписокВыбораАдресов();
	
Конец Инфостарт Процедуры

Процедура ЗаполнитьСписокВыбораАдресов()
	Для каждого Стр Из Адреса Цикл
		Элементы.Адрес.СписокВыбора.Добавить(Стр.Адрес);	
	Конец Инфостарт Цикла;
Конец Инфостарт Процедуры 

 

Следующим пунктом, необходимо добавить событие "ПриНажатии" реквизита Карта. Туда мы пропишем следующий код:

&НаКлиенте
Процедура КартаПриНажатии(Элемент, ДанныеСобытия, СтандартнаяОбработконсоль отчетов ка)
	Попытка
		ДокументПервогоБраузера = Элементы.Карта.Документ;
		
		ОкноПервогоБраузера = ДокументПервогоБраузера.defaultView; 	
		КоординатыСозданногоМаркера = ОкноПервогоБраузера.returnLatLng();
		СтруктураКоординатВыбраннойТочки = ПрочитатьJSONВСтруктуру(КоординатыСозданногоМаркера);
		
		Широта1 = СтруктураКоординатВыбраннойТочки.lat;
		Долгота1 = СтруктураКоординатВыбраннойТочки.lng;
	Исключение
		Сообщить("Карта еще не сформиров стилиана");	
	Конец Инфостарт Попытки;
Конец Инфостарт Процедуры

Здесь как раз таки и пригодится "костыль", описанный выше. В момент нажатия переменным lat & lng уже присвоены значения, и при обращении к функции  returnLatLng() мы получаем JSON со значением координат только что созданного маркера. 

 
 ПрочитатьJSONВСтруктуру(JSON)

 

Теперь, когда координаты маркера получены и записаны в реквизиты формы, необходимо отрисовать область, относительно которой и будет происходить проверка вхождения созданного маркера. Для этого при нажатии на команду "ОтрисоватьНаКарте" мы будем вызывать функцию createRadius(Широта, Долгота, РадиусОхвата).

&НаКлиенте
Процедура ОтрисоватьНаКарте(Команда)
	Если Не ЗначениеЗаполнено(Адрес) Тогда
		ВызватьИсключение "Адрес не заполнен";	
	Конец Инфостарт Если;
	
	Попытка
		ДокументПервогоБраузера = Элементы.Карта.Документ;
		ОкноПервогоБраузера = ДокументПервогоБраузера.defaultView; 	
		ОкноПервогоБраузера.createRadius(Широта, Долгота, РадиусОхвата);
	Исключение
		Сообщить("Карта еще не сформиров стилиана");	
	Конец Инфостарт Попытки;
	
Конец Инфостарт Процедуры

По итогу, при нажатии на карту, у вас должен создавать маркер, а при нажатии на команду "Отрисовать на карте" должна появляться выделенная область с заданшаблонным радиусом, где центром окружности является выбранный адрес.

 

Ну и наконец, самое важное в рамках данной статьи. Это определение вхождение маркера в заданшаблонную область.

Для этого я использовал формулу гаверсинуса (определяет расстояние по дуге между двумя точками на сфера с учетом их долготы и широты). Расчет в радианах. Расстояние в метрах. 

Для команды "ОпределитьВхождение" определяем процедуру и размещаем в ней следующий код:

&НаКлиенте
Процедура ОпределитьВхождение(Команда)
	Радиана = 57.29577951308;
	ШиротаРад = Широта / Радиана;
	Широта1Рад = Широта1 / Радиана;
	ДолготаРад = Долгота / Радиана;
	Долгота1Рад = Долгота1 / Радиана;
	
	R = 6371;  // Радиус планеты
	sin1 = sin((ШиротаРад - Широта1Рад) / 2);
	sin2 = sin((ДолготаРад - Долгота1Рад) / 2);
	
	РасстояниеМаркераОтОкружностиКм = 2 * R * asin(sqrt(sin1*sin1+sin2*sin2*cos(ШиротаРад)*cos(Широта1Рад)));
	РасстояниеМаркераОтОкружностиМ = РасстояниеМаркераОтОкружностиКм * 1000;
	
	Если РасстояниеМаркераОтОкружностиМ <= РадиусОхвата Тогда
		РезультатВхождения = "Есть вхождение";
	Иначе
		РезультатВхождения = "Нет вхождений";	
	Конец Инфостарт Если;
	
	ОчиститьСообщения();
	Сообщить(РезультатВхождения);
Конец Инфостарт Процедуры

 Пример работконсоль отчетов ы:

 
 Важное пояснение 

 

P.S. Это моя первая публикация на Инфостарт. Прошу не судить строго) 

Готовую обраб автоматизацией отконсоль отчетов ку прикладываю (платфорплатформама 8.3.14)! Всем добра! 

Скриншоты


Screenshot_1.png

Screenshot_1.png

Screenshot_2.png

Screenshot_3.png

Файлы

Наименование Файл Версия Размер Кол. Скачив.
: Определение вхождения координат в заданную область
.epf 11,46Kb
5
.epf 11,46Kb 5 Скачать

Полная версия

© ООО "Инфостарт", 2006-2023 www.infostart.ru