Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save chaosifier/ced25440e582a1970fd469bfb82b524f to your computer and use it in GitHub Desktop.

Select an option

Save chaosifier/ced25440e582a1970fd469bfb82b524f to your computer and use it in GitHub Desktop.
Geocode Bounding Box Visualizer
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Geocode Bounding Box Visualizer</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
background-color: #f4f4f9;
}
.container {
max-width: 1000px;
margin: 0 auto;
}
.form-panel {
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
margin-bottom: 20px;
}
.input-group {
display: grid;
grid-template-columns: 2fr 1fr 1fr 1fr;
gap: 10px;
margin-bottom: 15px;
}
@media (max-width: 600px) {
.input-group {
grid-template-columns: 1fr;
}
}
input,
button {
padding: 10px;
border: 1px solid #ccc;
border-radius: 4px;
font-size: 14px;
}
button {
background-color: #1a73e8;
color: white;
border: none;
cursor: pointer;
font-weight: bold;
}
button:hover {
background-color: #1557b0;
}
#map {
width: 100%;
height: 500px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.stats-panel {
margin-top: 15px;
background: #e8f0fe;
padding: 15px;
border-radius: 4px;
display: none;
}
</style>
</head>
<body>
<div class="container">
<h2>Geocode Bounding Box Visualizer</h2>
<div class="form-panel">
<div class="input-group">
<input
type="text"
id="street"
placeholder="Street Address"
value="1201 Hidden Ridge Dr"
/>
<input type="text" id="city" placeholder="City" value="Irving" />
<input
type="text"
id="state"
placeholder="State (e.g. TX)"
value="TX"
/>
<input type="text" id="zip" placeholder="ZIP Code" value="75038" />
</div>
<button onclick="geocodeAddress()">Geocode & Map Bounds</button>
</div>
<div id="stats" class="stats-panel"></div>
<div id="map"></div>
</div>
<script>
let map;
let geocoder;
let currentMarker = null;
let currentRectangle = null;
let currentCircle = null;
// Initialize the Map
function initMap() {
geocoder = new google.maps.Geocoder();
// Default map center (Dallas/Fort Worth area)
map = new google.maps.Map(document.getElementById("map"), {
zoom: 12,
center: { lat: 32.848, lng: -97.241 },
});
}
function geocodeAddress() {
// 1. Check if the SDK is actually ready
if (typeof google === "undefined" || !google.maps) {
alert(
"Google Maps SDK is still loading. Please wait a moment and try again.",
);
return;
}
// 2. Instantly initialize the geocoder if it's missing
if (!geocoder) {
geocoder = new google.maps.Geocoder();
}
const street = document.getElementById("street").value;
const city = document.getElementById("city").value;
const state = document.getElementById("state").value;
const zip = document.getElementById("zip").value;
const fullAddress = `${street}, ${city}, ${state} ${zip}`;
// 3. Safe to call now!
geocoder.geocode({ address: fullAddress }, (results, status) => {
if (status === "OK" && results[0]) {
const result = results[0];
const location = result.geometry.location;
const viewport = result.geometry.viewport;
const locType = result.geometry.location_type;
const isPartial = result.partial_match ? "TRUE" : "FALSE";
// Clear previous drawings
if (currentMarker) currentMarker.setMap(null);
if (currentRectangle) currentRectangle.setMap(null);
if (currentCircle) currentCircle.setMap(null);
// 1. Center map and drop marker on the coordinates
map.setCenter(location);
currentMarker = new google.maps.Marker({
map: map,
position: location,
title: "Returned Coordinate",
});
// 2. Draw the exact Viewport Bounding Box (Red Rectangle)
currentRectangle = new google.maps.Rectangle({
strokeColor: "#FF0000",
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: "#FF0000",
fillOpacity: 0.1,
map: map,
bounds: viewport,
});
// 3. Compute dynamic uncertainty radius (using previous math module)
const radiusMeters = calculatePredictiveRadius(result);
// 4. Draw predicted certainty radius (Blue Circle)
currentCircle = new google.maps.Circle({
strokeColor: "#1A73E8",
strokeOpacity: 0.7,
strokeWeight: 1,
fillColor: "#1A73E8",
fillOpacity: 0.15,
map: map,
center: location,
radius: radiusMeters,
});
// 5. Fit map view to fully contain the bounding box bounds
map.fitBounds(viewport);
// Display tracking data panels
const statsDiv = document.getElementById("stats");
statsDiv.style.display = "block";
statsDiv.innerHTML = `
<strong>Formatted Address Returned:</strong> ${result.formatted_address}<br>
<strong>Location Type:</strong> <span style="color:#d93025; font-weight:bold;">${locType}</span><br>
<strong>Partial Match Flag:</strong> ${isPartial}<br>
<strong>Calculated Uncertainty Radius:</strong> ${radiusMeters.toFixed(2)} meters
`;
} else {
alert("Geocode failed due to: " + status);
}
});
}
// Helper math calculation module
function calculatePredictiveRadius(result) {
const lat1 = result.geometry.location.lat();
const lng1 = result.geometry.location.lng();
const lat2 = result.geometry.viewport.getNorthEast().lat();
const lng2 = result.geometry.viewport.getNorthEast().lng();
const R = 6371000;
const dLat = ((lat2 - lat1) * Math.PI) / 180;
const dLng = ((lng2 - lng1) * Math.PI) / 180;
const a =
Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos((lat1 * Math.PI) / 180) *
Math.cos((lat2 * Math.PI) / 180) *
Math.sin(dLng / 2) *
Math.sin(dLng / 2);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
let baseRadius = R * c;
const locType = result.geometry.location_type;
const isPartial = result.partial_match || false;
if (locType === "ROOFTOP") {
return isPartial ? 75 : 20;
} else if (locType === "RANGE_INTERPOLATED") {
return baseRadius;
} else if (locType === "GEOMETRIC_CENTER") {
return baseRadius * 1.5;
} else if (locType === "APPROXIMATE") {
return Math.max(baseRadius, 5000);
}
return baseRadius;
}
</script>
<!-- Replace YOUR_API_KEY with your actual Google Maps API key -->
<script
src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap"
async
defer
></script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment