2023-08-24 18:26:16 +02:00
|
|
|
<!DOCTYPE html>
|
|
|
|
<html>
|
|
|
|
<head>
|
2023-08-30 02:02:16 +02:00
|
|
|
<meta charset="UTF-8">
|
2023-09-04 02:15:19 +02:00
|
|
|
<link rel="icon" type="image/x-icon" href="./favicon.ico">
|
2023-11-21 23:47:59 +01:00
|
|
|
<title>UPlanet Map View ! Please Zoom In.</title>
|
2023-08-24 18:26:16 +02:00
|
|
|
<link rel="stylesheet" href="leaflet.css" />
|
2023-08-30 02:02:16 +02:00
|
|
|
<style>
|
|
|
|
.clickable-area {
|
|
|
|
fill-opacity: 0.2; /* Adjust the opacity as needed */
|
|
|
|
fill: #0074d9; /* Adjust the color as needed */
|
|
|
|
stroke: #001f3f;
|
|
|
|
}
|
|
|
|
#coordinates-display {
|
|
|
|
position: absolute;
|
2023-09-01 19:41:43 +02:00
|
|
|
bottom: 20px; /* Adjust the bottom position as needed */
|
2023-08-30 02:02:16 +02:00
|
|
|
left: 10px; /* Adjust the left position as needed */
|
|
|
|
background-color: white;
|
|
|
|
padding: 5px;
|
|
|
|
border: 1px solid black;
|
|
|
|
z-index: 1000;
|
|
|
|
}
|
2023-09-01 19:41:43 +02:00
|
|
|
#map-container {
|
|
|
|
position: fixed;
|
|
|
|
top: 0;
|
|
|
|
left: 0;
|
|
|
|
width: 100%;
|
|
|
|
height: 100%;
|
|
|
|
}
|
2023-10-19 17:36:02 +02:00
|
|
|
.button {
|
|
|
|
background-color: #3498db;
|
|
|
|
color: #fff;
|
|
|
|
padding: 10px 20px;
|
|
|
|
border: none;
|
|
|
|
cursor: pointer;
|
|
|
|
}
|
2023-12-02 16:50:17 +01:00
|
|
|
.grid-number {
|
2023-12-03 22:15:12 +01:00
|
|
|
position: absolute;
|
|
|
|
font-size: 16px;
|
|
|
|
font-weight: bold;
|
|
|
|
color: #fff;
|
|
|
|
z-index: 1300;
|
|
|
|
|
2023-12-02 16:50:17 +01:00
|
|
|
}
|
2023-12-03 22:15:12 +01:00
|
|
|
|
2023-08-30 02:02:16 +02:00
|
|
|
</style>
|
2023-09-01 19:41:43 +02:00
|
|
|
|
2023-08-24 18:26:16 +02:00
|
|
|
</head>
|
|
|
|
<body>
|
2023-10-19 17:36:02 +02:00
|
|
|
<div id="map-container" style="position: relative;">
|
2023-08-30 02:02:16 +02:00
|
|
|
<div id="coordinates-display"></div> <!-- Coordinates display element -->
|
|
|
|
<div id="map" style="width: 100%; height: 100vh;"></div>
|
2023-10-19 17:36:02 +02:00
|
|
|
</div>
|
2023-08-24 18:26:16 +02:00
|
|
|
|
|
|
|
<script src="leaflet.js"></script>
|
2023-08-30 02:02:16 +02:00
|
|
|
|
2023-08-31 21:40:53 +02:00
|
|
|
<script>
|
2023-08-30 02:02:16 +02:00
|
|
|
|
2023-12-02 16:50:17 +01:00
|
|
|
// Function to extract URL parameters
|
|
|
|
function getUrlParameter(name) {
|
|
|
|
name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
|
|
|
|
const regex = new RegExp('[\\?&]' + name + '=([^&#]*)');
|
|
|
|
const results = regex.exec(location.search);
|
|
|
|
return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' '));
|
|
|
|
}
|
|
|
|
|
2023-08-24 18:26:16 +02:00
|
|
|
// const desiredImageWidthInKm = 11; // Now Is calculated from northEastLon - southWestLon
|
|
|
|
const tileSizeInPixels = 256;
|
|
|
|
|
|
|
|
function calculateZoomLevel(desiredImageWidthInKm, latitude) {
|
|
|
|
const earthEquatorialCircumference = 40075016.686; // Earth's equatorial circumference in meters
|
|
|
|
// Calculate the distance covered by one degree of longitude at the given latitude
|
|
|
|
const metersPerLongitudeDegree = earthEquatorialCircumference * Math.cos((Math.PI / 180) * latitude) / 360;
|
|
|
|
const metersPerPixel = metersPerLongitudeDegree * 360 / (tileSizeInPixels * Math.pow(2, 20));
|
|
|
|
// Calculate the number of pixels needed to achieve the desired width
|
|
|
|
const numberOfPixelsHorizontally = (desiredImageWidthInKm * 1000) / metersPerPixel;
|
|
|
|
// Calculate the appropriate zoom level
|
|
|
|
const zoomLevel = Math.log2(tileSizeInPixels * Math.pow(2, 20) / numberOfPixelsHorizontally);
|
|
|
|
return zoomLevel;
|
|
|
|
}
|
|
|
|
|
2023-12-02 16:50:17 +01:00
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Extract the hostname (e.g., "https://ipfs.domain.tld" or "http://ipfs.localhost:8080")
|
|
|
|
var currentURL = new URL(window.location.href);
|
|
|
|
var hostname = currentURL.hostname;
|
|
|
|
var port = currentURL.port;
|
|
|
|
var protocol = currentURL.protocol.split(":")[0];
|
|
|
|
// Check and replace the port if it's 8080
|
|
|
|
if (port === "8080") {
|
|
|
|
port = "1234";
|
|
|
|
}
|
|
|
|
var zHost = hostname.replace("ipfs", "astroport");
|
|
|
|
// Create the "station" variable with the specified format
|
|
|
|
var station = protocol + "://" + zHost + (port ? (":" + port) : "");
|
|
|
|
console.log(station)
|
|
|
|
//////////////////////////////////////////////////////////////// fetchAstroport
|
|
|
|
async function fetchAstroport(myURL) {
|
|
|
|
try {
|
|
|
|
let one = await fetch(myURL); // Gets a promise
|
|
|
|
var doc = await one.text();
|
|
|
|
var regex = /url='([^']+)/i; // Get response PORT
|
|
|
|
var redirectURL = doc.match(regex)[1];
|
|
|
|
|
|
|
|
console.log(redirectURL);
|
|
|
|
|
2023-12-03 22:15:12 +01:00
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
setTimeout(async function () {
|
|
|
|
try {
|
|
|
|
let two = await fetch(redirectURL);
|
|
|
|
const data = await two.json();
|
|
|
|
console.log(data);
|
|
|
|
resolve(data);
|
|
|
|
} catch (error) {
|
|
|
|
console.log('Fetch error (inside setTimeout):', error);
|
|
|
|
reject(error);
|
|
|
|
}
|
|
|
|
}, 3000);
|
|
|
|
});
|
2023-12-02 16:50:17 +01:00
|
|
|
} catch (err) {
|
|
|
|
console.log('Fetch error:', err);
|
2023-12-03 22:15:12 +01:00
|
|
|
return Promise.reject(err);
|
2023-12-02 16:50:17 +01:00
|
|
|
}
|
2023-08-24 18:26:16 +02:00
|
|
|
}
|
2023-12-02 16:50:17 +01:00
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2023-08-24 18:26:16 +02:00
|
|
|
|
2023-10-19 17:36:02 +02:00
|
|
|
const defaultIPNS = '';
|
|
|
|
const sectorIPNS = getUrlParameter('ipns') || defaultIPNS;
|
|
|
|
console.log('sectorIPNS: /ipns/', sectorIPNS);
|
2023-12-02 16:50:17 +01:00
|
|
|
|
2023-10-19 17:36:02 +02:00
|
|
|
if (sectorIPNS !== '') {
|
|
|
|
const buttonContainer = document.createElement('div');
|
|
|
|
buttonContainer.id = 'button-container'
|
|
|
|
buttonContainer.style.position = 'absolute';
|
|
|
|
buttonContainer.style.bottom = '10px';
|
|
|
|
buttonContainer.style.left = '10px';
|
|
|
|
buttonContainer.style.width = '200px';
|
|
|
|
buttonContainer.style.height = '150px';
|
|
|
|
buttonContainer.style.zIndex = '1001';
|
|
|
|
buttonContainer.style.display = 'flex';
|
|
|
|
buttonContainer.style.flexDirection = 'column';
|
|
|
|
buttonContainer.style.alignItems = 'center';
|
|
|
|
buttonContainer.style.justifyContent = 'center';
|
|
|
|
|
|
|
|
const button = document.createElement('button');
|
|
|
|
button.innerText = 'EXPLORE';
|
|
|
|
button.className = 'button';
|
|
|
|
|
|
|
|
// Add an event listener to the button
|
|
|
|
button.addEventListener('click', function() {
|
|
|
|
window.open( '/ipns/'+ sectorIPNS, "AstroTab");
|
|
|
|
});
|
|
|
|
|
|
|
|
// Append the button to the button container
|
|
|
|
buttonContainer.appendChild(button);
|
|
|
|
document.body.appendChild(buttonContainer);
|
|
|
|
}
|
|
|
|
|
2023-09-02 00:45:07 +02:00
|
|
|
const defaultSouthWestLat = 0.00;
|
|
|
|
const defaultSouthWestLon = 0.00;
|
|
|
|
const defaultOffsetDegrees = 10.00; // 10° offset
|
2023-08-24 18:26:16 +02:00
|
|
|
|
|
|
|
const southWestLat = parseFloat(getUrlParameter('southWestLat')) || defaultSouthWestLat;
|
|
|
|
console.log('Lat:', southWestLat);
|
|
|
|
const southWestLon = parseFloat(getUrlParameter('southWestLon')) || defaultSouthWestLon;
|
|
|
|
console.log('Lon:', southWestLon);
|
|
|
|
const deg = parseFloat(getUrlParameter('deg')) || defaultOffsetDegrees;
|
|
|
|
console.log('Offset:', deg);
|
|
|
|
|
|
|
|
// Calculate northEastLat and northEastLon with deg° offset only if parameters are empty
|
|
|
|
const northEastLatParam = getUrlParameter('northEastLat');
|
|
|
|
const northEastLonParam = getUrlParameter('northEastLon');
|
|
|
|
|
|
|
|
const northEastLat = northEastLatParam ? parseFloat(northEastLatParam) : southWestLat + deg;
|
|
|
|
const northEastLon = northEastLonParam ? parseFloat(northEastLonParam) : southWestLon + deg;
|
|
|
|
|
|
|
|
// Calculate the longitudinal distance in degrees
|
|
|
|
const lonDistanceInDegrees = Math.abs(northEastLon - southWestLon);
|
|
|
|
console.log('lonDistanceInDegrees:', lonDistanceInDegrees);
|
|
|
|
|
2023-08-30 02:02:16 +02:00
|
|
|
// Calculate the desired image width in kilometers
|
|
|
|
const earthEquatorialCircumference = 40075016.686; // Earth's equatorial circumference in meters
|
|
|
|
const metersPerLongitudeDegree = Math.abs(earthEquatorialCircumference * Math.cos((Math.PI / 180) * southWestLat) / 360);
|
|
|
|
const desiredImageWidthInMeters = lonDistanceInDegrees * metersPerLongitudeDegree;
|
|
|
|
const desiredImageWidthInKm = desiredImageWidthInMeters / 1000;
|
|
|
|
console.log('desiredImageWidthInKm:', desiredImageWidthInKm);
|
2023-08-24 18:26:16 +02:00
|
|
|
|
|
|
|
const centerLat = (southWestLat + northEastLat) / 2;
|
|
|
|
const centerLon = (southWestLon + northEastLon) / 2;
|
|
|
|
|
|
|
|
// Provide the latitude for adjustment
|
|
|
|
const latitude = centerLat;
|
|
|
|
const zoomLevel = calculateZoomLevel(desiredImageWidthInKm, latitude);
|
|
|
|
console.log('Recommended zoom level:', zoomLevel);
|
|
|
|
|
|
|
|
const map = L.map('map').setView([centerLat, centerLon], zoomLevel);
|
|
|
|
|
|
|
|
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
|
|
|
attribution: 'U Planet'
|
|
|
|
}).addTo(map);
|
|
|
|
|
2023-08-30 02:02:16 +02:00
|
|
|
const gridSize = 10; // Number of rows and columns in the grid
|
|
|
|
const NSize = deg / 10; // Size of each grid cell
|
|
|
|
|
|
|
|
// Create a HTML element for displaying coordinates
|
|
|
|
const coordinatesDisplay = document.getElementById('coordinates-display');
|
|
|
|
|
|
|
|
// Check if deg is less than or equal to 0.01
|
|
|
|
if (deg <= 0.01) {
|
|
|
|
const container = document.createElement('div');
|
|
|
|
container.style.position = 'fixed';
|
|
|
|
container.style.top = '0';
|
|
|
|
container.style.left = '0';
|
|
|
|
container.style.width = '100vw';
|
|
|
|
container.style.height = '100vh';
|
2023-08-31 18:57:27 +02:00
|
|
|
container.style.backgroundColor = 'rgba(255, 255, 255, 0.4)';
|
2023-08-30 02:02:16 +02:00
|
|
|
container.style.border = 'none';
|
2023-09-01 19:41:43 +02:00
|
|
|
container.style.zIndex = '999';
|
2023-08-30 02:02:16 +02:00
|
|
|
container.style.display = 'flex';
|
|
|
|
container.style.flexDirection = 'column';
|
|
|
|
container.style.alignItems = 'center';
|
|
|
|
container.style.justifyContent = 'center';
|
|
|
|
|
|
|
|
|
|
|
|
const button = document.createElement('button');
|
2023-11-24 03:40:51 +01:00
|
|
|
button.textContent = 'Activate ẐenCard';
|
2023-08-30 02:02:16 +02:00
|
|
|
button.style.width = '100%';
|
|
|
|
button.style.height = '100px'; // Customize the button height
|
|
|
|
button.style.backgroundColor = '#0074d9';
|
|
|
|
button.style.border = 'none';
|
|
|
|
button.style.fontFamily = 'Arial, sans-serif'; // Customize the font family
|
|
|
|
button.style.fontSize = '24px'; // Customize the font size
|
|
|
|
button.style.color = '#fff'; // Customize the font color
|
|
|
|
|
|
|
|
button.addEventListener('click', () => {
|
2023-12-01 02:31:07 +01:00
|
|
|
const url = `${station}/?uplanet=@&zlat=${southWestLat}&zlon=${southWestLon}`;
|
2023-08-30 02:02:16 +02:00
|
|
|
window.location.href = url;
|
|
|
|
});
|
|
|
|
|
|
|
|
container.appendChild(button);
|
|
|
|
|
|
|
|
document.body.appendChild(container);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
// Add a mousemove event listener to the map
|
|
|
|
map.on('mousemove', (event) => {
|
|
|
|
const latLng = event.latlng;
|
|
|
|
const lat = latLng.lat.toFixed(6);
|
|
|
|
const lng = latLng.lng.toFixed(6);
|
|
|
|
coordinatesDisplay.textContent = `Latitude: ${lat}, Longitude: ${lng}`;
|
|
|
|
});
|
|
|
|
|
2023-12-03 22:15:12 +01:00
|
|
|
///// UPPER THAN 0.01
|
2023-08-30 02:02:16 +02:00
|
|
|
}
|
|
|
|
|
2023-12-03 22:15:12 +01:00
|
|
|
// Add a click event listener to the map container
|
|
|
|
document.getElementById('map-container').addEventListener('click', (event) => {
|
|
|
|
const isInsideRectangle = event.target.classList.contains('clickable-area');
|
|
|
|
if (!isInsideRectangle) {
|
|
|
|
history.back(); // Trigger browser's back functionality
|
|
|
|
}
|
|
|
|
});
|
2023-08-30 02:02:16 +02:00
|
|
|
|
2023-10-19 17:36:02 +02:00
|
|
|
/////////////////
|
2023-12-08 14:10:47 +01:00
|
|
|
async function loadGridNumbers(myURL) {
|
|
|
|
try {
|
2023-12-02 16:50:17 +01:00
|
|
|
const data = await fetchAstroport(myURL);
|
|
|
|
return data.gridNumbers || [];
|
2023-12-08 14:10:47 +01:00
|
|
|
} catch (error) {
|
2023-12-02 16:50:17 +01:00
|
|
|
console.error('Error loading grid numbers:', error);
|
|
|
|
return [];
|
|
|
|
}
|
2023-12-08 14:10:47 +01:00
|
|
|
}
|
2023-12-02 16:50:17 +01:00
|
|
|
|
|
|
|
// Function to overlay grid numbers on the map
|
2023-12-03 22:15:12 +01:00
|
|
|
function overlayGridNumbers(rectangle, number) {
|
|
|
|
const latLng = rectangle.getBounds().getCenter();
|
|
|
|
const containerPoint = map.latLngToContainerPoint(latLng);
|
|
|
|
|
|
|
|
const numberElement = document.createElement('div');
|
|
|
|
numberElement.className = 'grid-number';
|
|
|
|
numberElement.textContent = number;
|
|
|
|
numberElement.style.position = 'absolute';
|
|
|
|
numberElement.style.fontSize = '16px';
|
|
|
|
numberElement.style.fontWeight = 'bold';
|
|
|
|
numberElement.style.color = 'red';
|
|
|
|
numberElement.style.top = `${containerPoint.y}px`;
|
|
|
|
numberElement.style.left = `${containerPoint.x}px`;
|
|
|
|
|
|
|
|
document.getElementById('map-container').appendChild(numberElement);
|
|
|
|
}
|
|
|
|
|
2023-12-02 16:50:17 +01:00
|
|
|
const zquery = 'zone='+NSize+'&ulat='+southWestLat+'&ulon='+southWestLon; // Replace with your actual query parameters
|
|
|
|
const zoneURL = station+'/?' + zquery;
|
|
|
|
|
|
|
|
console.log('ZONE URL:', zoneURL);
|
|
|
|
|
2023-12-03 22:15:12 +01:00
|
|
|
// Create a clickable rectangle for each grid cell
|
|
|
|
const rectangles = [];
|
|
|
|
for (let latIndex = 0; latIndex < gridSize; latIndex++) {
|
|
|
|
for (let lonIndex = 0; lonIndex < gridSize; lonIndex++) {
|
|
|
|
const lat = southWestLat + latIndex * NSize;
|
|
|
|
const lon = southWestLon + lonIndex * NSize;
|
|
|
|
|
|
|
|
// Create a clickable rectangle
|
|
|
|
const rectangle = L.rectangle(
|
|
|
|
[[lat, lon], [lat + NSize, lon + NSize]],
|
|
|
|
{ color: 'transparent', weight: 1, className: 'clickable-area' } // Add CSS class
|
|
|
|
);
|
|
|
|
|
|
|
|
// Add a click event to the rectangle
|
|
|
|
rectangle.on('click', () => {
|
|
|
|
// Calculate new northEastLat and northEastLon based on the clicked grid cell
|
|
|
|
const newNorthEastLat = lat.toFixed(2);
|
|
|
|
const newNorthEastLon = lon.toFixed(2);
|
|
|
|
|
|
|
|
// Update URL parameters with the new values
|
|
|
|
const url = `map_render.html?southWestLat=${newNorthEastLat}&southWestLon=${newNorthEastLon}°=${NSize}`;
|
|
|
|
window.location.href = url;
|
|
|
|
});
|
2023-08-30 02:02:16 +02:00
|
|
|
|
2023-12-03 22:15:12 +01:00
|
|
|
// Add the rectangle to the map and to the array
|
|
|
|
rectangle.addTo(map);
|
|
|
|
rectangles.push(rectangle);
|
|
|
|
}
|
|
|
|
}
|
2023-12-08 14:10:47 +01:00
|
|
|
|
|
|
|
// Load grid numbers and overlay them on the map
|
|
|
|
loadGridNumbers(zoneURL).then(gridNumbers => {
|
|
|
|
gridNumbers.forEach(({ lat, lon, number, ipns }) => {
|
|
|
|
// Calculate the center of the rectangle based on lat + NSize and lon + NSize
|
|
|
|
const latCenter = lat + (lat < 0 ? -NSize / 2 : NSize / 2);
|
|
|
|
const lonCenter = lon + (lon < 0 ? -NSize / 2 : NSize / 2);
|
|
|
|
|
|
|
|
const latLng = L.latLng(latCenter, lonCenter);
|
|
|
|
|
|
|
|
// Find the corresponding rectangle
|
|
|
|
const matchingRectangle = rectangles.find(rectangle =>
|
|
|
|
rectangle.getBounds().contains(latLng)
|
|
|
|
);
|
|
|
|
|
|
|
|
if (matchingRectangle) {
|
|
|
|
overlayGridNumbers(matchingRectangle, number);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ipns !== '') {
|
|
|
|
const buttonContainer = document.createElement('div');
|
|
|
|
buttonContainer.id = 'button-container'
|
|
|
|
buttonContainer.style.position = 'absolute';
|
|
|
|
buttonContainer.style.bottom = '10px';
|
|
|
|
buttonContainer.style.left = '10px';
|
|
|
|
buttonContainer.style.width = '200px';
|
|
|
|
buttonContainer.style.height = '150px';
|
|
|
|
buttonContainer.style.zIndex = '1001';
|
|
|
|
buttonContainer.style.display = 'flex';
|
|
|
|
buttonContainer.style.flexDirection = 'column';
|
|
|
|
buttonContainer.style.alignItems = 'center';
|
|
|
|
buttonContainer.style.justifyContent = 'center';
|
|
|
|
|
|
|
|
const button = document.createElement('button');
|
|
|
|
button.innerText = 'EXPLORE';
|
|
|
|
button.className = 'button';
|
|
|
|
|
|
|
|
// Add an event listener to the button
|
|
|
|
button.addEventListener('click', function() {
|
2023-12-15 18:31:06 +01:00
|
|
|
window.open( ipns , "_new");
|
2023-12-08 14:10:47 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
// Append the button to the button container
|
|
|
|
buttonContainer.appendChild(button);
|
|
|
|
document.body.appendChild(buttonContainer);
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
2023-08-24 18:26:16 +02:00
|
|
|
</script>
|
|
|
|
</body>
|
|
|
|
</html>
|