add a bunch of (false) information to the map

This commit is contained in:
2026-01-21 23:25:04 +01:00
parent 08fe8ebc7f
commit 9f591b1bdc
4 changed files with 955 additions and 74 deletions

View File

@@ -20,10 +20,24 @@
</div>
<div class="control-section">
<label>
<input type="checkbox" v-model="showOctagon" @change="toggleOctagon">
Show Octagon
<label class="section-header" @click="historicMarkersExpanded = !historicMarkersExpanded" style="cursor: pointer;">
{{ historicMarkersExpanded ? '▼' : '▶' }} Historic Markers
</label>
<div v-if="historicMarkersExpanded" class="subsection">
<button class="hide-all-btn" @click="hideAllHistoricMarkers">
{{ allHistoricMarkersHidden ? 'Show All' : 'Hide All' }}
</button>
<div v-for="site in KNOWN_SITES" :key="site.name" class="site-control">
<label>
<input type="checkbox" v-model="visibleSites[site.name]" @change="toggleSite(site.name)">
{{ site.name }}
</label>
<button class="jump-btn" @click="jumpToSite(site)" title="Jump to location">📍</button>
</div>
</div>
</div>
<div class="control-section">
<label>
<input type="checkbox" v-model="showLidar" @change="toggleLidar">
Show Lidar
@@ -111,6 +125,11 @@
<div>Bearing: {{ popup.feature.properties.bearing.toFixed(1) }}°</div>
<button @click="deleteFeature(popup.feature.id)" class="popup-btn danger">Delete</button>
</div>
<div v-else-if="popup.type === 'site'" class="site-popup">
<strong>{{ popup.feature.properties.name }}</strong>
<div class="site-type">{{ popup.feature.properties.type === 'road_confirmed' ? 'Confirmed Road Segment' : 'Earthwork' }}</div>
<div class="site-description">{{ popup.feature.properties.description }}</div>
</div>
</div>
<button @click="popup.visible = false" class="popup-close">×</button>
</div>
@@ -138,7 +157,9 @@ const sandboxRef = ref(null);
const sandboxVisible = ref(false);
const sandboxOffscreen = ref(false);
const baseLayer = ref('osm');
const showOctagon = ref(true);
const historicMarkersExpanded = ref(true);
const visibleSites = ref({});
const allHistoricMarkersHidden = ref(false);
const showLidar = ref(true);
const showGeometry = ref(true);
const imperialUnits = ref(false);
@@ -155,7 +176,7 @@ const nextFeatureId = ref(1);
// UI state
const contextMenu = ref({ visible: false, x: 0, y: 0, lngLat: null, hasTile: false });
const popup = ref({ visible: false, x: 0, y: 0, type: null, feature: null });
const popup = ref({ visible: false, x: 0, y: 0, type: null, feature: null, lngLat: null });
// Map instance
let map = null;
@@ -237,29 +258,16 @@ const KNOWN_SITES = [
"tiles":["BS18430458"]}
];
// Tile names to load
const TILE_NAMES = [
'BS19820747',
'BS19820748',
'BS19830747',
'BS19830748',
'BS19820746',
'BS19810747',
'BS19810746',
];
// Newark Octagon coordinates
const octagonCoords = [
[-82.44123, 40.05443],
[-82.44260, 40.05309],
[-82.44464, 40.05237],
[-82.44631, 40.05342],
[-82.44728, 40.05500],
[-82.44589, 40.05633],
[-82.44389, 40.05698],
[-82.44216, 40.05595],
[-82.44123, 40.05443],
];
// Tile names to load - merged from all KNOWN_SITES
const TILE_NAMES = (() => {
const allTiles = new Set();
KNOWN_SITES.forEach(site => {
if (site.tiles) {
site.tiles.forEach(tile => allTiles.add(tile));
}
});
return Array.from(allTiles);
})();
const octagonCenter = [-82.44383, 40.05469];
@@ -521,12 +529,64 @@ function updateBaseLayer() {
}
}
function toggleOctagon() {
function toggleGeometry() {
if (!map) return;
const visibility = showOctagon.value ? 'visible' : 'none';
map.setLayoutProperty('octagon-fill', 'visibility', visibility);
map.setLayoutProperty('octagon-outline', 'visibility', visibility);
const visibility = showGeometry.value ? 'visible' : 'none';
if (map.getLayer('geometry-pins')) {
map.setLayoutProperty('geometry-pins', 'visibility', visibility);
}
if (map.getLayer('geometry-lines')) {
map.setLayoutProperty('geometry-lines', 'visibility', visibility);
}
if (map.getLayer('geometry-labels')) {
map.setLayoutProperty('geometry-labels', 'visibility', visibility);
}
}
function toggleSite(siteName) {
if (!map) return;
const visible = visibleSites.value[siteName];
const visibility = visible ? 'visible' : 'none';
// Toggle marker
const markerLayerId = `site-marker-${siteName}`;
if (map.getLayer(markerLayerId)) {
map.setLayoutProperty(markerLayerId, 'visibility', visibility);
}
// Toggle overlay geometry
const overlayLayerId = `site-overlay-${siteName}`;
if (map.getLayer(overlayLayerId)) {
map.setLayoutProperty(overlayLayerId, 'visibility', visibility);
}
// Toggle polyline
const polylineLayerId = `site-polyline-${siteName}`;
if (map.getLayer(polylineLayerId)) {
map.setLayoutProperty(polylineLayerId, 'visibility', visibility);
}
}
function jumpToSite(site) {
if (!map) return;
const coords = site.coordinates[0];
map.flyTo({
center: coords,
zoom: 15,
duration: 1500
});
}
function hideAllHistoricMarkers() {
allHistoricMarkersHidden.value = !allHistoricMarkersHidden.value;
KNOWN_SITES.forEach(site => {
visibleSites.value[site.name] = !allHistoricMarkersHidden.value;
toggleSite(site.name);
});
}
function toggleLidar() {
@@ -553,21 +613,6 @@ function updateLidarOpacity() {
}
}
function toggleGeometry() {
if (!map) return;
const visibility = showGeometry.value ? 'visible' : 'none';
if (map.getLayer('geometry-pins')) {
map.setLayoutProperty('geometry-pins', 'visibility', visibility);
}
if (map.getLayer('geometry-lines')) {
map.setLayoutProperty('geometry-lines', 'visibility', visibility);
}
if (map.getLayer('geometry-labels')) {
map.setLayoutProperty('geometry-labels', 'visibility', visibility);
}
}
function openSandbox() {
if (Object.keys(tileCache.value).length > 0) {
sandboxVisible.value = true;
@@ -826,12 +871,17 @@ onMounted(() => {
const featureData = geometryFeatures.value.features.find(f => f.id === feature.properties.id);
if (featureData) {
const coords = featureData.geometry.type === 'Point'
? featureData.geometry.coordinates
: featureData.geometry.coordinates[0]; // Use first point of line
popup.value = {
visible: true,
x: e.point.x,
y: e.point.y,
type: featureData.properties.type,
feature: featureData
feature: featureData,
lngLat: coords
};
}
} else {
@@ -870,37 +920,144 @@ onMounted(() => {
});
map.on('load', async () => {
// Add octagon overlay
map.addSource('octagon', {
type: 'geojson',
data: {
type: 'Feature',
geometry: {
type: 'Polygon',
coordinates: [octagonCoords]
// Initialize visibility state for all sites
KNOWN_SITES.forEach(site => {
visibleSites.value[site.name] = true;
});
// Add historic site markers and overlays
KNOWN_SITES.forEach(site => {
// Add marker
const markerCoords = site.coordinates[0];
map.addSource(`site-marker-${site.name}`, {
type: 'geojson',
data: {
type: 'Feature',
geometry: {
type: 'Point',
coordinates: markerCoords
},
properties: {
name: site.name,
description: site.description,
type: site.type
}
}
});
map.addLayer({
id: `site-marker-${site.name}`,
type: 'circle',
source: `site-marker-${site.name}`,
paint: {
'circle-radius': 10,
'circle-color': site.type === 'road_confirmed' ? '#4A9EFF' : '#ff6b6b',
'circle-stroke-width': 3,
'circle-stroke-color': '#ffffff'
}
});
// Add overlay geometry if present
if (site.overlay) {
site.overlay.forEach((geom, idx) => {
map.addSource(`site-overlay-${site.name}-${idx}`, {
type: 'geojson',
data: {
type: 'Feature',
geometry: {
type: 'Polygon',
coordinates: [geom.coordinates]
}
}
});
map.addLayer({
id: `site-overlay-${site.name}-${idx}`,
type: 'fill',
source: `site-overlay-${site.name}-${idx}`,
paint: {
'fill-color': site.type === 'road_confirmed' ? '#4A9EFF' : '#ff6b6b',
'fill-opacity': 0.2
}
});
map.addLayer({
id: `site-overlay-outline-${site.name}-${idx}`,
type: 'line',
source: `site-overlay-${site.name}-${idx}`,
paint: {
'line-color': site.type === 'road_confirmed' ? '#4A9EFF' : '#ff6b6b',
'line-width': 2
}
});
});
}
});
map.addLayer({
id: 'octagon-fill',
type: 'fill',
source: 'octagon',
paint: {
'fill-color': '#ff0000',
'fill-opacity': 0.2
// Add polyline for multi-coordinate sites
if (site.coordinates.length > 1) {
map.addSource(`site-polyline-${site.name}`, {
type: 'geojson',
data: {
type: 'Feature',
geometry: {
type: 'LineString',
coordinates: site.coordinates
}
}
});
map.addLayer({
id: `site-polyline-${site.name}`,
type: 'line',
source: `site-polyline-${site.name}`,
paint: {
'line-color': '#4A9EFF',
'line-width': 3,
'line-dasharray': [2, 2]
}
});
}
// Add click handler for marker popups
map.on('click', `site-marker-${site.name}`, (e) => {
e.preventDefault();
popup.value = {
visible: true,
x: e.point.x,
y: e.point.y,
type: 'site',
feature: {
properties: {
name: site.name,
description: site.description,
type: site.type
}
},
lngLat: site.coordinates[0]
};
});
// Cursor pointer on hover
map.on('mouseenter', `site-marker-${site.name}`, () => {
map.getCanvas().style.cursor = 'pointer';
});
map.on('mouseleave', `site-marker-${site.name}`, () => {
map.getCanvas().style.cursor = '';
});
});
map.addLayer({
id: 'octagon-outline',
type: 'line',
source: 'octagon',
paint: {
'line-color': '#ff0000',
'line-width': 2
// Update popup position when map moves or zooms
const updatePopupPosition = () => {
if (popup.value.visible && popup.value.lngLat) {
const point = map.project(popup.value.lngLat);
popup.value.x = point.x;
popup.value.y = point.y;
}
});
};
map.on('move', updatePopupPosition);
map.on('zoom', updatePopupPosition);
// Add geometry source and layers
map.addSource('geometry', {
@@ -1023,6 +1180,69 @@ onUnmounted(() => {
cursor: default;
}
.control-section .section-header {
font-weight: bold;
margin-bottom: 8px;
user-select: none;
}
.subsection {
margin-left: 10px;
padding-left: 10px;
border-left: 2px solid #ddd;
}
.hide-all-btn {
width: 100%;
padding: 6px 10px;
margin: 8px 0;
background: #f5f5f5;
border: 1px solid #ddd;
border-radius: 3px;
font-size: 13px;
font-weight: 600;
cursor: pointer;
transition: all 0.2s;
}
.hide-all-btn:hover {
background: #e8e8e8;
border-color: #999;
}
.site-control {
display: flex;
align-items: center;
justify-content: space-between;
margin: 4px 0;
}
.site-control label {
flex: 1;
margin: 0 !important;
font-weight: normal !important;
}
.jump-btn {
padding: 4px 8px;
background: #4A9EFF;
color: white;
border: none;
border-radius: 3px;
font-size: 12px;
cursor: pointer;
transition: all 0.2s;
margin-left: 8px;
}
.jump-btn:hover {
background: #2E8FE3;
}
.jump-btn:active {
transform: scale(0.95);
}
.control-section input[type="radio"],
.control-section input[type="checkbox"] {
margin-right: 8px;
@@ -1153,6 +1373,7 @@ onUnmounted(() => {
box-shadow: 0 2px 12px rgba(0,0,0,0.4);
z-index: 1000;
min-width: 180px;
max-width: 350px;
overflow: hidden;
}
@@ -1173,6 +1394,24 @@ onUnmounted(() => {
color: #666;
}
.site-popup {
max-width: 320px;
}
.site-type {
font-size: 11px !important;
text-transform: uppercase;
letter-spacing: 0.5px;
color: #999 !important;
margin-bottom: 8px !important;
}
.site-description {
line-height: 1.5;
color: #333 !important;
font-size: 13px !important;
}
.popup-btn {
display: block;
width: 100%;