Skip to content

Commit

Permalink
Create leaflet_great_circle2.html
Browse files Browse the repository at this point in the history
making new leaflet great circle with help from gemini
  • Loading branch information
danames authored Jan 26, 2025
1 parent 7dc6ced commit 54aee96
Showing 1 changed file with 222 additions and 0 deletions.
222 changes: 222 additions & 0 deletions leaflet/leaflet_great_circle2.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Draw the Great Circle Path</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin="" />
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
}
#map {
height: 400px;
width: 80%;
margin: 20px auto;
border: 1px solid #ccc;
}
.container {
width: 80%;
margin: 20px auto;
}
h1, h2 {
text-align: center;
}
h2 {
margin-top: 30px;
}
pre {
background-color: #f5f5f5;
padding: 15px;
border-radius: 5px;
overflow-x: auto;
}
code {
font-family: 'Courier New', Courier, monospace;
}
.subtitle {
text-align: center;
margin-bottom: 20px;
}
.form-container {
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 20px;
}
.form-group {
margin-right: 15px;
}
label {
display: block;
margin-bottom: 5px;
}
input[type="number"] {
width: 100px;
}
.leaflet-div-icon {
background: transparent;
border: none;
}

.triangle {
width: 0;
height: 0;
border-left: 8px solid transparent;
border-right: 8px solid transparent;
border-bottom: 16px solid purple;
}
</style>
</head>
<body>
<div class="container">
<h1>Drawing the Great Circle on a Leaflet Map</h1>
<p class="subtitle">By Dr. Dan Ames - Jan 23, 2025</p>

<div id="map"></div>

<h2>Enter the Start and End Coordinates</h2>
<div class="form-container">
<div class="form-group">
<label for="start_latitude">Start Latitude:</label>
<input type="number" id="start_latitude" name="start_latitude" value="40.0">
</div>
<div class="form-group">
<label for="start_longitude">Start Longitude:</label>
<input type="number" id="start_longitude" name="start_longitude" value="-111.0">
</div>
<div class="form-group">
<label for="end_latitude">End Latitude:</label>
<input type="number" id="end_latitude" name="end_latitude" value="39.0">
</div>
<div class="form-group">
<label for="end_longitude">End Longitude:</label>
<input type="number" id="end_longitude" name="end_longitude" value="1.0">
</div>

<button id="submit-button">Draw Points and Great Circle</button>
</div>
<div id="results">
Results:
</div>


<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin=""></script>
<script>
// Initialize the map
var map = L.map('map').setView([39.0, -45.0], 3); // Centered on Utah

// Add a tile layer (base map) from OpenStreetMap
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);

// Function to create a triangle marker
function createTriangleIcon() {
return L.divIcon({
className: 'triangle',
iconSize: [16, 16]
});
}

//Function to compute the distance between two points using the Haversine formula
function compute_distance(lat1,lng1,lat2,lng2){
//convert inputs to radians
const rad_lat1 = lat1 * Math.PI/180;
const rad_lng1 = lng1 * Math.PI/180;
const rad_lat2 = lat2 * Math.PI/180;
const rad_lng2 = lng2 * Math.PI/180;

//Differences in coordinates
const dLat = rad_lat2 - rad_lat1;
const dLon = rad_lng2 - rad_lng1;

//Earth's radius in km (estimated)
const R = 6371;

//Haversine formula
const a = (Math.sin(dLat/2))**2 + Math.cos(rad_lat1) * Math.cos(rad_lat2) * (Math.sin((dLon)/2))**2;
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
const distance = R * c;
//a = sin²(Δφ/2) + cos(φ₁) * cos(φ₂) * sin²(Δλ/2)
//c = 2 * atan2(√a, √(1-a))
//d = R * c

//Write the resulting distance
document.getElementById("results").innerHTML = "Distance = " + distance + " km";
}


// Function to draw a great circle line connecting the two points
function great_circle(lat1, lng1, lat2, lng2) {
// Convert inputs to radians
const rad_lat1 = lat1 * Math.PI / 180;
const rad_lng1 = lng1 * Math.PI / 180;
const rad_lat2 = lat2 * Math.PI / 180;
const rad_lng2 = lng2 * Math.PI / 180;

// Calculate the angular distance (δ) between the two points using the Haversine formula
const dLon = rad_lng2 - rad_lng1;
const dLat = rad_lat2 - rad_lat1;
const a = Math.sin(dLat / 2) ** 2 + Math.cos(rad_lat1) * Math.cos(rad_lat2) * Math.sin(dLon / 2) ** 2;
const angular_distance = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); // This is 'c' in your equations

// Divide the angular distance into 10 segments
const num_segments = 100; // Increased for smoother line
const segment_angle = angular_distance / num_segments;

// Generate points along the great circle
const points = [];
for (let i = 0; i <= num_segments; i++) {
const f = i / num_segments;

// Calculate intermediate latitude (φ) and longitude (λ)
const A = Math.sin((1 - f) * angular_distance) / Math.sin(angular_distance);
const B = Math.sin(f * angular_distance) / Math.sin(angular_distance);
const x = A * Math.cos(rad_lat1) * Math.cos(rad_lng1) + B * Math.cos(rad_lat2) * Math.cos(rad_lng2);
const y = A * Math.cos(rad_lat1) * Math.sin(rad_lng1) + B * Math.cos(rad_lat2) * Math.sin(rad_lng2);
const z = A * Math.sin(rad_lat1) + B * Math.sin(rad_lat2);
const new_lat = Math.atan2(z, Math.sqrt(x ** 2 + y ** 2));
const new_lng = Math.atan2(y, x);

points.push([new_lat * 180 / Math.PI, new_lng * 180 / Math.PI]);
}

// Draw the great circle line
const polyline = L.polyline(points, { color: 'red' }).addTo(map);
}


// Add marker on form submission
document.getElementById('submit-button').addEventListener('click', function() {
var start_lat = parseFloat(document.getElementById('start_latitude').value);
var start_lng = parseFloat(document.getElementById('start_longitude').value);
var end_lat = parseFloat(document.getElementById('end_latitude').value);
var end_lng = parseFloat(document.getElementById('end_longitude').value);

if (!isNaN(start_lat) && !isNaN(start_lng) && !isNaN(end_lat) && !isNaN(end_lng)) {
var startMarker = L.marker([start_lat, start_lng], {
icon: createTriangleIcon()
}).addTo(map);
startMarker.bindPopup("Start Point<br>[" + start_lat + ", " + start_lng + "]");

var endMarker = L.marker([end_lat, end_lng], {
icon: createTriangleIcon()
}).addTo(map);
endMarker.bindPopup("End Point<br>[" + end_lat + ", " + end_lng + "]");

//compute the distance between the two points
compute_distance(start_lat,start_lng,end_lat,end_lng);
great_circle(start_lat,start_lng,end_lat,end_lng);

} else {
alert('Please enter valid coordinates.');
}
});

</script>
</div>
</body>
</html>

0 comments on commit 54aee96

Please sign in to comment.