Leaflet конвертирование координат

Не знаете, где задать вопрос? Задавайте здесь.
USide
Новоприбывший
Сообщения: 10
Зарегистрирован: 27 май 2024, 11:11
Репутация: 0
Откуда: СПБ

Leaflet конвертирование координат

Сообщение USide » 27 май 2024, 11:16

День добрый,не знаю где уже задать вопрос на родном языке(ибо с англ слегка сложно) нашел данный форум.
Есть такая задачка что не могу решить 2й день уже.
Есть карта Leaflet с такими углами:

Код: Выделить всё

  //Верхний левый 0,0
  //Верхний правый 0,256
  //Нижний левый -256,0
  //Нижний правый -256,256
И есть игровая карта:

Код: Выделить всё

  //Верхний левый 0,16348
  //Верхний правый 16348,16348
  //Нижний левый 0,0
  //Нижний правый 16348,0
Соответственно карта не географическая а плоская.Из тайтлов 256х256
В данный момент переводить координаты я пытаюсь так:

Код: Выделить всё

    var scale = 16384 / 256;
    var x = (scale * e.latlng.lng).toFixed(4);
    var y = (scale * (256 + e.latlng.lat)).toFixed(4); // Инвертируем ось Y
Но это вызывает разброс сильный.На карте оригинале и у меня.
Подскажите пожалуйста как это победить и как например размещать круги,маркеры используя игровые координаты но с конвертированием в Leaflet или же как-то изменить просто сетку координат?

AlexRomantsov
Завсегдатай
Сообщения: 328
Зарегистрирован: 24 мар 2022, 05:54
Репутация: 141
Ваше звание: хм, сам не знал
Откуда: Томск

Re: Leaflet конвертирование координат

Сообщение AlexRomantsov » 27 май 2024, 13:21

Не ясно, какие значения углов leaflet вы привели. //Нижний левый -256,0 - это что? Пиксели? Метры? В каком масштабе (уровне)? С каким охватом - весь глобус? Четверть? В карте leaflet что, OpenStreetMap или свои слои?
Возможно, имеет смысл создать проекцию (систему координат) для игровых координат, тогда leaflet сможет самостоятельно проецировать ваши маркеры на свои карты.

USide
Новоприбывший
Сообщения: 10
Зарегистрирован: 27 май 2024, 11:11
Репутация: 0
Откуда: СПБ

Re: Leaflet конвертирование координат

Сообщение USide » 27 май 2024, 13:55

AlexRomantsov писал(а):
27 май 2024, 13:21
Не ясно, какие значения углов leaflet вы привели. //Нижний левый -256,0 - это что? Пиксели? Метры? В каком масштабе (уровне)? С каким охватом - весь глобус? Четверть? В карте leaflet что, OpenStreetMap или свои слои?
Возможно, имеет смысл создать проекцию (систему координат) для игровых координат, тогда leaflet сможет самостоятельно проецировать ваши маркеры на свои карты.
Карта своя не географическая.
Я пытаюсь создать карту по аналогии https://dayz.xam.nu/deerisle#4470.00;8980.00;4 под свой проект для админ панели.
Для теста пока тайтлы от туда же использую.
Там работает эта система как раз.

Код: Выделить всё

//Нижний левый -256,0
Это я получаю через клик в нижнем левом углу через

Код: Выделить всё

console.log('Ваши координаты карты:', e.latlng);
Я понимаю что мне нужна своя проекция но не понимаю как ее создать.
Чтобы отсчет шел с нижнего левого угла 0,0 и верхний правый угол стал 16348,16348

Мне советовали подобное:

Код: Выделить всё

function init() {
    var width = 16348;
    var height = 16348;

    var minZoom = 2;
    var maxZoom = 6;
    var img = [
            width,  // original width of image
            height   // original height of image
    ];
    var zoom = zoomLevel();
    function zoomLevel() {
        return Math.ceil(
                Math.log(
                        Math.max(width, height) /
                        256
                    ) / Math.log(2)
                );
    };

    // create the map
    var map = L.map('map', {
        minZoom: minZoom,
        maxZoom: maxZoom,
        crs: L.CRS.Simple,
    });

    function project(coords) {
		var point = map.project(coords, zoom);
		return L.point(point.x, height - point.y);
	}
    function unproject(coords) {
        var invertedY = height - coords["1"];
        var point = L.point(coords["0"], invertedY);
        return map.unproject(point, zoom);
    }



    //sets the max bounds on map
    var maxSouthWest = unproject([0, height]);
    var maxNorthEast = unproject([width, 0]);
    map.setMaxBounds(new L.LatLngBounds(maxSouthWest, maxNorthEast));
    
    map.setView(unproject([img[0] / 2, img[1] / 2]), maxZoom);

		var southWest = unproject([0, 0]);
    var northEast = unproject([width, height]);

    L.tileLayer('https://static.xam.nu/dayz/maps/deerisle/5.3/satellite/{z}/{x}/{y}.webp', {
        noWrap: true,
        bounds:  new L.LatLngBounds(southWest, northEast),
    }).addTo(map);
      // Отображаем координаты при клике на карту
  map.on('click', function(e) {
    console.log('Ваши координаты карты:', project(e.latlng));
  });
}
Но тут Y не совпадает в обще,а вот X близко но не совсем.

P.s по шагам:
Изображение
Выбрал место на карте,ставлю туда маркер:
Изображение
А он берет и уезжает на 10-15 метров.Что не очень хорошо...
Консоль в ответ на:

Код: Выделить всё

L.marker(unproject([6333, 14798])).addTo(map);
Выдает:

Код: Выделить всё

v {lat: -24.21875, lng: 98.953125}
То есть координаты совпадают с местом клика,но маркер почему-то уехал.

USide
Новоприбывший
Сообщения: 10
Зарегистрирован: 27 май 2024, 11:11
Репутация: 0
Откуда: СПБ

Re: Leaflet конвертирование координат

Сообщение USide » 27 май 2024, 19:41

Пока тестил,появилось ощущение что unproject и project сжирают знаки после запятой по этому маркер "убегает" не могу пока понять как решить.

AlexRomantsov
Завсегдатай
Сообщения: 328
Зарегистрирован: 24 мар 2022, 05:54
Репутация: 141
Ваше звание: хм, сам не знал
Откуда: Томск

Re: Leaflet конвертирование координат

Сообщение AlexRomantsov » 28 май 2024, 07:03

Кажется, этому (антигеодезическому костыльному :) ) методу не хватает точности. А вы можете применить коэффициент, или переделать игровые координаты проекта, например как 0 - 32696?
А для leaflet использовать var scale = 32696 / 256. Может подтянет маркер к месту клика

USide
Новоприбывший
Сообщения: 10
Зарегистрирован: 27 май 2024, 11:11
Репутация: 0
Откуда: СПБ

Re: Leaflet конвертирование координат

Сообщение USide » 28 май 2024, 10:49

AlexRomantsov писал(а):
28 май 2024, 07:03
Кажется, этому (антигеодезическому костыльному :) ) методу не хватает точности. А вы можете применить коэффициент, или переделать игровые координаты проекта, например как 0 - 32696?
А для leaflet использовать var scale = 32696 / 256. Может подтянет маркер к месту клика
Хм, в теории да...но карта игровая 16348 и если я сделаю 32696 то суть админки потеряю боюсь. Ибо мне нужно 100% совпадение чтобы я ставил маркер в админке и он в то же место ставился в игре...Вот в этом беда)Либо я вас не очень понял)
P.S в самой игре я ничего увы поменять не могу если что)

USide
Новоприбывший
Сообщения: 10
Зарегистрирован: 27 май 2024, 11:11
Репутация: 0
Откуда: СПБ

Re: Leaflet конвертирование координат

Сообщение USide » 28 май 2024, 11:25

Код: Выделить всё

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Leaflet Map Example</title>
  <!-- Подключаем стили Leaflet.js -->
  <link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
  <style>
	html,
	body {
		height: 100%;
		margin: 0;
		padding: 0;
	}
	
	#map {
		background-color: #242f3d;
		width: 100%;
		height: 100%;
		cursor: url('http://localhost/cursors/scope6.png') 16 16, auto;
	}
	
	#info {
		display: none;
		/* Скрываем блок по умолчанию */
		position: absolute;
		top: 20px;
		left: 50%;
		transform: translate(-50%);
		width: 50%;
		padding: 10px;
		border: none;
		border-radius: 3px;
		font-size: 12px;
		text-align: center;
		color: #222;
		background: #fff;
		z-index: 999;
	}
  </style>
</head>

<!-- Создаем контейнер для карты -->
	<div id="map"></div> <pre id="info"></pre>
<!-- Подключаем скрипты Leaflet.js -->
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>

<script>

    var width = 16348;
    var height = 16348;

    var minZoom = 2;
    var maxZoom = 6;
    var img = [
            width,  // original width of image
            height   // original height of image
    ];
    var zoom = zoomLevel();
    function zoomLevel() {
        return Math.ceil(
                Math.log(
                        Math.max(width, height) /
                        256
                    ) / Math.log(2)
                );
    };

    // create the map
    var map = L.map('map', {
        minZoom: minZoom,
        maxZoom: maxZoom,
        crs: L.CRS.Simple,
    });

    function project(coords) {
        var point = map.project(coords, zoom);
		console.log(point);
        return [point.x, (height - point.y)];
    }

    function unproject(coords) {
        var invertedY = height - coords[1];
        var point = L.point(coords[0], invertedY);
        var latLng = map.unproject(point, zoom);
        return [latLng.lat, latLng.lng];
    }

    //sets the max bounds on map
    var maxSouthWest = unproject([0, height]);
    var maxNorthEast = unproject([width, 0]);
    map.setMaxBounds(new L.LatLngBounds(maxSouthWest, maxNorthEast));
    
    map.setView(unproject([img[0] / 2, img[1] / 2]), maxZoom);

		var southWest = unproject([0, 0]);
    var northEast = unproject([width, height]);

    L.tileLayer('https://static.xam.nu/dayz/maps/deerisle/5.3/satellite/{z}/{x}/{y}.webp', {
        noWrap: true,
        bounds:  new L.LatLngBounds(southWest, northEast),
    }).addTo(map);
	function setPrecision(lat, lng, prec = 7) {
	  return {
		lat: Number(lat.toPrecision(prec)),
		lng: Number(lng.toPrecision(prec))
	  }
	}
	map.on('click', function(e) {
		var info = document.getElementById('info');
		info.innerHTML = `Координаты по карте:<br />${JSON.stringify(e.latlng)}<br />Игровые координаты:<br />${project(e.latlng)}`;
		info.style.display = 'block'; // Показываем блок при клике
	})
</script>
</html>
Вот текущий вариант мой.Но тут маркер чутка убегает(по игровой дистанции метров на 15-20),я пока в строну CRS и pro4js гуглил но не понял возможно ли через них сделать без project и unproject углы карты как мне надо...

AlexRomantsov
Завсегдатай
Сообщения: 328
Зарегистрирован: 24 мар 2022, 05:54
Репутация: 141
Ваше звание: хм, сам не знал
Откуда: Томск

Re: Leaflet конвертирование координат

Сообщение AlexRomantsov » 28 май 2024, 11:55

В теории, можно попробовать в proj сделать описание, если скажите градусные соответствия (широту и долготу) для ваших игровых координат углов карты. Есть еще аффинные трансформации.

AlexRomantsov
Завсегдатай
Сообщения: 328
Зарегистрирован: 24 мар 2022, 05:54
Репутация: 141
Ваше звание: хм, сам не знал
Откуда: Томск

Re: Leaflet конвертирование координат

Сообщение AlexRomantsov » 28 май 2024, 12:07

А вот не в этом ли проблема, в вашем первом сообщении какое значение верно, 16384 или 16348?
game1.jpg
game1.jpg (36.39 КБ) 815 просмотров
16384 больше похоже на бинарную истину. Попробуйте перепилить leaflet на 16384

USide
Новоприбывший
Сообщения: 10
Зарегистрирован: 27 май 2024, 11:11
Репутация: 0
Откуда: СПБ

Re: Leaflet конвертирование координат

Сообщение USide » 28 май 2024, 13:10

AlexRomantsov писал(а):
28 май 2024, 12:07
А вот не в этом ли проблема, в вашем первом сообщении какое значение верно, 16384 или 16348?game1.jpg
16384 больше похоже на бинарную истину. Попробуйте перепилить leaflet на 16384
Хммм...верный в обще 16348... ща попробую...

Вооо,а так норм вроде:

Код: Выделить всё

	map.on('click', function(e) {
		var info = document.getElementById('info');
		var scale = 16348 / 256;
		var x = (scale * e.latlng.lng).toFixed(4);
		var y = (scale * (256 + e.latlng.lat)).toFixed(4); // Инвертируем ось Y
		info.innerHTML = `Координаты по карте:<br />${JSON.stringify(e.latlng)}<br />Игровые координаты:<br />${x},${y}`;
		info.style.display = 'block'; // Показываем блок при клике
	})
Выдало:

Код: Выделить всё

Координаты по карте:
{"lat":-24.265625,"lng":99.03125}
Игровые координаты:
6324.0737,14798.4124
И через отладку в консоли прогнал обратно:

Код: Выделить всё

unproject([6324.0737,14798.4124])
(2) [-24.21230625000001, 98.8136515625]
Почти совпадает,но не большие отклонения все равно идут...
По этому маркер все равно чутка уезжает на 5-10 метров.

AlexRomantsov
Завсегдатай
Сообщения: 328
Зарегистрирован: 24 мар 2022, 05:54
Репутация: 141
Ваше звание: хм, сам не знал
Откуда: Томск

Re: Leaflet конвертирование координат

Сообщение AlexRomantsov » 28 май 2024, 13:22

Топлю за 16384! Может везде в проекте ошибка. 16348 - какая то несуразная цифирь, не логичная

USide
Новоприбывший
Сообщения: 10
Зарегистрирован: 27 май 2024, 11:11
Репутация: 0
Откуда: СПБ

Re: Leaflet конвертирование координат

Сообщение USide » 28 май 2024, 13:25

AlexRomantsov писал(а):
28 май 2024, 13:22
Топлю за 16384! Может везде в проекте ошибка. 16348 - какая то несуразная цифирь, не логичная
Я может и слепой,но вроде все норм :lol:
Ибо в карте оригинале эта же цифра.

Код: Выделить всё

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Leaflet Map Example</title>
  <!-- Подключаем стили Leaflet.js -->
  <link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
  <style>
	html,
	body {
		height: 100%;
		margin: 0;
		padding: 0;
	}
	
	#map {
		background-color: #242f3d;
		width: 100%;
		height: 100%;
		cursor: url('http://localhost/cursors/scope6.png') 16 16, auto;
	}
	
	#info {
		display: none;
		/* Скрываем блок по умолчанию */
		position: absolute;
		top: 20px;
		left: 50%;
		transform: translate(-50%);
		width: 50%;
		padding: 10px;
		border: none;
		border-radius: 3px;
		font-size: 12px;
		text-align: center;
		color: #222;
		background: #fff;
		z-index: 999;
	}
  </style>
</head>

<!-- Создаем контейнер для карты -->
	<div id="map"></div> <pre id="info"></pre>
<!-- Подключаем скрипты Leaflet.js -->
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>

<script>

    var width = 16348;
    var height = 16348;

    var minZoom = 2;
    var maxZoom = 6;
    var img = [
            width,  // original width of image
            height   // original height of image
    ];
    var zoom = zoomLevel();
    function zoomLevel() {
        return Math.ceil(
                Math.log(
                        Math.max(width, height) /
                        256
                    ) / Math.log(2)
                );
    };

    // create the map
    var map = L.map('map', {
        minZoom: minZoom,
        maxZoom: maxZoom,
        crs: L.CRS.Simple,
    });

    function project(coords) {
        var point = map.project(coords, zoom);
		console.log(point);
        return [point.x, (height - point.y)];
    }

    function unproject(coords) {
        var invertedY = height - coords[1];
        var point = L.point(coords[0], invertedY);
        var latLng = map.unproject(point, zoom);
        return [latLng.lat, latLng.lng];
    }

    //sets the max bounds on map
    var maxSouthWest = unproject([0, height]);
    var maxNorthEast = unproject([width, 0]);
    map.setMaxBounds(new L.LatLngBounds(maxSouthWest, maxNorthEast));
    
    map.setView(unproject([img[0] / 2, img[1] / 2]), maxZoom);

		var southWest = unproject([0, 0]);
    var northEast = unproject([width, height]);

    L.tileLayer('https://static.xam.nu/dayz/maps/deerisle/5.3/satellite/{z}/{x}/{y}.webp', {
        noWrap: true,
        bounds:  new L.LatLngBounds(southWest, northEast),
    }).addTo(map);
	function setPrecision(lat, lng, prec = 7) {
	  return {
		lat: Number(lat.toPrecision(prec)),
		lng: Number(lng.toPrecision(prec))
	  }
	}
	map.on('click', function(e) {
		var info = document.getElementById('info');
		var scale = 16348 / 256;
		var x = (scale * e.latlng.lng).toFixed(4);
		var y = (scale * (256 + e.latlng.lat)).toFixed(4); // Инвертируем ось Y
		info.innerHTML = `Координаты по карте:<br />${JSON.stringify(e.latlng)}<br />Игровые координаты:<br />${x},${y}`;
		info.style.display = 'block'; // Показываем блок при клике
	})
</script>
</html>

USide
Новоприбывший
Сообщения: 10
Зарегистрирован: 27 май 2024, 11:11
Репутация: 0
Откуда: СПБ

Re: Leaflet конвертирование координат

Сообщение USide » 28 май 2024, 13:25

Оййй блин...я точно слепой...
Проставил везде 16384 но все равно съезжает...магия

P.S а ща вроде совпало...спасибо позже дома буду проверю основательно...вот я слепой... :roll:

AlexRomantsov
Завсегдатай
Сообщения: 328
Зарегистрирован: 24 мар 2022, 05:54
Репутация: 141
Ваше звание: хм, сам не знал
Откуда: Томск

Re: Leaflet конвертирование координат

Сообщение AlexRomantsov » 28 май 2024, 14:01

Давайте пойдем простым логическим ходом. Все пирамиды тайловых сеток, что в картографии, что в играх, создаются удваиванием, от уровня к уровню. В т.ч. на источнике /dayz/maps/deerisle/5.3/satellite/{z}/{x}/{y}.webp.
В уровне {z}=0 - 1 тайл (весь глобус). В уровне {z}=1 - 2 ячейки сетки на каждой оси (по 2 тайла по {X} или по {Y}). В уровне n (видимо последнем, самом крупном игровой карты) - 16384 ячейки на оси (2 в степени 14).
Последний раз редактировалось AlexRomantsov 29 май 2024, 05:01, всего редактировалось 1 раз.

USide
Новоприбывший
Сообщения: 10
Зарегистрирован: 27 май 2024, 11:11
Репутация: 0
Откуда: СПБ

Re: Leaflet конвертирование координат

Сообщение USide » 28 май 2024, 15:26

AlexRomantsov писал(а):
28 май 2024, 14:01
Давайте пойдем простым логическим ходом. Все тайловые сетки, что в картографии, что в играх, создаются удваиванием, от уровня к уровню. В т.ч. на источнике /dayz/maps/deerisle/5.3/satellite/{z}/{x}/{y}.webp.
В уровне {z}=0 - 1 тайл (весь глобус). В уровне {z}=1 - 2 ячейки сетки на каждой оси (по 2 тайла по {X} или по {Y}). В уровне n (видимо последнем, самом крупном игровой карты) - 16384 ячейки на оси (2 в степени 14).
Хм примерно суть я понял,но не очень понял как это применить)Ща буду проверять правки)

Ответить

Вернуться в «Я новичок!»

Кто сейчас на конференции

Сейчас этот форум просматривают: Ahrefs [Bot] и 5 гостей