From 0bb4cf4e1b96a89da1020baf85201c8c9805009f Mon Sep 17 00:00:00 2001 From: H9 Date: Sun, 8 Mar 2026 21:32:40 +0530 Subject: [PATCH] 7012, updted ths --- templates/earth.html | 3266 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 3156 insertions(+), 110 deletions(-) diff --git a/templates/earth.html b/templates/earth.html index 28bc28d..6c0cfdb 100644 --- a/templates/earth.html +++ b/templates/earth.html @@ -146,15 +146,40 @@ + + + + - - - + + + + + + + + + + + + + + + + + + + + + + - - + /* Cyber Popup Styles */ + .cyber-popup { + min-width: 280px; + font-family: 'Share Tech Mono', monospace; + text-transform: uppercase; + background: rgba(5, 5, 5, 0.95); + border: 1px solid var(--primary-color); + padding: 0; + position: relative; + overflow: hidden; + } + + .cyber-header { + background: rgba(0, 255, 209, 0.1); + padding: 10px; + border-bottom: 1px solid var(--primary-color); + display: flex; + justify-content: space-between; + align-items: center; + } + + .cyber-content { + padding: 12px; + display: grid; + grid-template-columns: 1fr 1fr; + gap: 8px; + font-size: 10px; + } + + .typewriter { + overflow: hidden; + border-right: .15em solid var(--primary-color); + white-space: nowrap; + letter-spacing: .05em; + max-width: fit-content; + } + + /* End Cyber Popup Styles */ + +
@@ -1636,14 +1829,29 @@ @@ -1735,6 +1943,12 @@
+ + +
×
+ style="cursor: pointer; color: #00FFD1; font-size: 18px; opacity: 0.8;"> + ×
@@ -1773,7 +1988,8 @@
-
TARGET_SOURCES +
+ TARGET_SOURCES [AGGRESSIVE_MODE]
× @@ -1918,19 +2138,22 @@ UPLINK_LEGEND
MILITARY + class="fas fa-fighter-jet" style="color:var(--flight-mil)">
+ MILITARY
-
COMMERCIAL +
+ COMMERCIAL
-
PRIVATE +
+ + PRIVATE
-
EMERGENCY +
+ + EMERGENCY
@@ -1940,7 +2163,7 @@
- +
+ GLOBAL ANALYSIS
@@ -2010,11 +2262,12 @@ + CELL TOWER UPLINK
@@ -4042,12 +6345,14 @@ -
×
+
+ ×
-
LOADING_VECTORS...
+
+ LOADING_VECTORS...
@@ -4248,6 +6553,7 @@ message: userMessage, web_search: webSearchToggle.checked, engine: engineSelect.value, + model_id: document.getElementById('ai-model-select').value, human_mode: humanModeToggle.checked, context: contextToggle.checked ? getMapContext() : {} }; @@ -4267,7 +6573,7 @@ const flightMatch = reply.match(/\[TRACK_FLIGHT:\s*(\w+)\]/i); if (flightMatch) { const icao = flightMatch[1].toLowerCase(); - addMessage(`COMMAND_DETECTED: TRACKING_FLIGHT_${icao.toUpperCase()}`, 'system'); + addMessage(`COMMAND_DETECTED: TRACKING_FLIGHT_${icao.toUpperCase()} `, 'system'); if (typeof flightMarkers !== 'undefined' && flightMarkers[icao]) { map.setView(flightMarkers[icao].getLatLng(), 10); flightMarkers[icao].openPopup(); @@ -4278,7 +6584,7 @@ const vesselMatch = reply.match(/\[TRACK_VESSEL:\s*(\d+)\]/i); if (vesselMatch) { const mmsi = vesselMatch[1]; - addMessage(`COMMAND_DETECTED: TRACKING_VESSEL_${mmsi}`, 'system'); + addMessage(`COMMAND_DETECTED: TRACKING_VESSEL_${mmsi} `, 'system'); if (typeof vesselMarkers !== 'undefined' && vesselMarkers[mmsi]) { map.setView(vesselMarkers[mmsi].getLatLng(), 10); vesselMarkers[mmsi].openPopup(); @@ -4335,10 +6641,10 @@ } } else { const error = await response.json(); - addMessage(`ERROR: ${error.reply || error.error || 'Unknown error'}`, 'system'); + addMessage(`ERROR: ${error.reply || error.error || 'Unknown error'} `, 'system'); } } catch (e) { - addMessage(`CONNECTION ERROR: ${e.message}`, 'system'); + addMessage(`CONNECTION ERROR: ${e.message} `, 'system'); } finally { sendBtn.disabled = false; sendBtn.textContent = 'SEND'; @@ -4381,10 +6687,10 @@ const content = mem.content.replace(/\n/g, '
'); item.innerHTML = ` -
+ < div style = "font-size: 10px; color: rgba(0, 255, 209, 0.5); display: flex; justify-content: space-between;" > ID: ${mem.id} ${new Date(mem.timestamp).toLocaleString()} -
+
${content}
@@ -4392,21 +6698,21 @@ - `; + `; memoryList.appendChild(item); }); } else { memoryList.innerHTML = '
ARCHIVE_EMPTY
'; } } catch (e) { - memoryList.innerHTML = `
CONNECTION_ERROR: ${e.message}
`; + memoryList.innerHTML = `< div style = "text-align: center; color: #FF0055; margin-top: 50px;" > CONNECTION_ERROR: ${e.message} `; } } window.deleteMemory = async (id) => { if (!confirm('DELETE_MEMORY_VECTOR? This cannot be undone.')) return; try { - await fetch(`/api/geosentialai/memory/${id}`, { method: 'DELETE' }); + await fetch(`/ api / geosentialai / memory / ${id} `, { method: 'DELETE' }); loadMemories(); // Refresh } catch (e) { alert('Deletion failed: ' + e.message); @@ -4427,7 +6733,7 @@ const newContent = prompt("EDIT_MEMORY_VECTOR:"); if (newContent) { try { - await fetch(`/api/geosentialai/memory/${id}`, { + await fetch(`/ api / geosentialai / memory / ${id} `, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ content: newContent }) @@ -4483,11 +6789,11 @@ lastScrapeResults = data.results; renderOmniResults(data.results); } else { - omniList.innerHTML = `
ERROR: ${data.error}
`; + omniList.innerHTML = `< div style = "color: #FF0055;" > ERROR: ${data.error} `; } } catch (e) { - omniList.innerHTML = `
CONNECTION_FAIL: ${e.message}
`; + omniList.innerHTML = `< div style = "color: #FF0055;" > CONNECTION_FAIL: ${e.message} `; } finally { scrapeBtn.textContent = 'SCAN'; scrapeBtn.disabled = false; @@ -4506,32 +6812,32 @@ const el = document.createElement('div'); el.style.cssText = "background: rgba(0, 255, 209, 0.05); padding: 8px; border: 1px solid rgba(0, 255, 209, 0.1);"; - let content = `
- ${item.title} -
`; + let content = `< div style = "font-weight: bold; color: #00FFD1; margin-bottom: 4px;" > + ${item.title} + `; if (item.snippet) { - content += `
${item.snippet}
`; + content += `< div style = "font-size: 11px; color: #ccc; margin-bottom: 4px;" > ${item.snippet} `; } if (item.full_text) { - content += `
- [FULL_TEXT_EXTRACT] ${item.full_text} -
`; + content += `< div style = "font-size: 10px; color: #fff; background: rgba(0,0,0,0.3); padding: 4px; margin-top: 4px; border-left: 2px solid #00FFD1;" > + [FULL_TEXT_EXTRACT] ${item.full_text} + `; } if (scrapeType.value === 'images' && item.link.match(/\.(jpeg|jpg|gif|png)$/) != null) { - content += ``; + content += `< img src = "${item.link}" style = "max-width: 100%; margin-top: 5px; border: 1px solid #333;" > `; } if (scrapeType.value === 'videos') { if (item.thumbnail) { - content += `
- -
- -
-
`; + content += `< div style = "position: relative; margin-top: 5px;" > + +
+ +
+ `; } } @@ -4565,7 +6871,7 @@ // Format for AI let summary = "ANALYZED SCAN DATA:\n"; lastScrapeResults.slice(0, 5).forEach(item => { - summary += `- ${item.title}: ${item.snippet}\n`; + summary += `- ${item.title}: ${item.snippet} \n`; if (item.full_text) summary += ` EXTRACT: ${item.full_text.substring(0, 200)}...\n`; }); @@ -4575,7 +6881,7 @@ const input = document.getElementById('geosentialai-input'); // Auto-fill logic - input.value = `Analyze this scan data:\n${summary}`; + input.value = `Analyze this scan data: \n${summary}`; input.focus(); }); } @@ -4665,8 +6971,748 @@ // Initial Status Check checkOllamaStatus(); + + // ========================================== + // 3D GLOBE MAPBOX INTEGRATION + // ========================================== + let mapboxMap = null; + let is3DGlobeActive = false; + + // Ensure mapbox popup styling fits cyberpunk theme + const mapboxCustomCSS = document.createElement('style'); + mapboxCustomCSS.innerHTML = ` + .mapboxgl-popup-content { + background: #050505 !important; + border: 1px solid var(--popup-accent, #00FFD1) !important; + color: #EEE !important; + font-family: 'Share Tech Mono', monospace !important; + font-size: 11px !important; + box-shadow: 0 0 15px rgba(0, 255, 209, 0.2) !important; + padding: 10px !important; + } + .mapboxgl-popup-close-button { + color: var(--popup-accent, #00FFD1) !important; + font-size: 16px !important; + } + .mapboxgl-popup-tip { + border-top-color: var(--popup-accent, #00FFD1) !important; + border-bottom-color: var(--popup-accent, #00FFD1) !important; + } + .mapbox-custom-marker { + width: 8px; + height: 8px; + border-radius: 50%; + cursor: pointer; + } + `; + document.head.appendChild(mapboxCustomCSS); + + function initMapbox() { + if (mapboxMap) return; // Already initialized + mapboxgl.accessToken = ''; + mapboxMap = new mapboxgl.Map({ + container: 'mapbox-container', + style: 'mapbox://styles/mapbox/satellite-streets-v12', + projection: 'globe', // Display as a 3D globe + zoom: map.getZoom() - 1, // Mapbox zoom is roughly leaflet zoom - 1 + center: [map.getCenter().lng, map.getCenter().lat], + pitch: 45 // Add some pitch for 3D effect + }); + + mapboxMap.on('style.load', () => { + // Add atmosphere for 3D feel + mapboxMap.setFog({ + 'color': 'rgb(186, 210, 235)', // Lower atmosphere + 'high-color': 'rgb(36, 92, 223)', // Upper atmosphere + 'horizon-blend': 0.02, // Atmosphere thickness + 'space-color': 'rgb(11, 11, 25)', // Background color + 'star-intensity': 0.6 // Stars + }); + + // Source for flights + mapboxMap.addSource('flights', { + type: 'geojson', + data: { + type: 'FeatureCollection', + features: [] + }, + cluster: false + }); + + // Layer for flight icons (changed to circle since custom raster style has no sprites) + mapboxMap.addLayer({ + id: 'flights-layer', + type: 'circle', + source: 'flights', + paint: { + 'circle-radius': 5, + 'circle-color': [ + 'match', + ['get', 'type'], + 'military', '#FF4400', + 'private', '#FF00FF', + 'emergency', '#FFFFFF', + '#00FFD1' // default commercial + ], + 'circle-stroke-width': 1, + 'circle-stroke-color': '#000000' + } + }); + + // Source for active flight path + mapboxMap.addSource('flight-path', { + type: 'geojson', + data: { + type: 'FeatureCollection', + features: [] + } + }); + + // Layer for active flight path + mapboxMap.addLayer({ + id: 'flight-path-layer', + type: 'line', + source: 'flight-path', + layout: { + 'line-join': 'round', + 'line-cap': 'round' + }, + paint: { + 'line-color': '#00A3FF', + 'line-width': 3, + 'line-opacity': 0.8, + 'line-dasharray': [2, 2] + } + }); + + // Vessel Path Layer + mapboxMap.addSource('vessel-path', { + type: 'geojson', + data: { type: 'FeatureCollection', features: [] } + }); + mapboxMap.addLayer({ + id: 'vessel-path-layer', + type: 'line', + source: 'vessel-path', + layout: { 'line-join': 'round', 'line-cap': 'round' }, + paint: { 'line-color': '#00FF88', 'line-width': 2, 'line-dasharray': [2, 2] } + }); + + // Interaction + mapboxMap.on('click', 'flights-layer', (e) => { + if (!e.features.length) return; + const f = e.features[0].properties; + renderEntityIntel('flight', f); + + // Draw flight path in Mapbox + const icao = f.icao24; + if (typeof flightHistory !== 'undefined' && flightHistory[icao] && flightHistory[icao].length > 1) { + const lineCoords = flightHistory[icao].map(pos => [pos[1], pos[0]]); // [lat, lng] to [lng, lat] + mapboxMap.getSource('flight-path').setData({ + type: 'FeatureCollection', + features: [{ + type: 'Feature', + geometry: { + type: 'LineString', + coordinates: lineCoords + } + }] + }); + } else { + mapboxMap.getSource('flight-path').setData({ type: 'FeatureCollection', features: [] }); + } + }); + + // Clear flight path when clicking elsewhere on the map + mapboxMap.on('click', (e) => { + const features = mapboxMap.queryRenderedFeatures(e.point, { layers: ['flights-layer'] }); + if (!features.length && mapboxMap.getSource('flight-path')) { + mapboxMap.getSource('flight-path').setData({ type: 'FeatureCollection', features: [] }); + } + }); + + // Change cursor on hover + mapboxMap.on('mouseenter', 'flights-layer', () => { + mapboxMap.getCanvas().style.cursor = 'pointer'; + }); + mapboxMap.on('mouseleave', 'flights-layer', () => { + mapboxMap.getCanvas().style.cursor = ''; + }); + + // Setup click handlers for coordinate/sentiment/tower on the 3D globe + setupMapboxClickHandlers(); + + // Hook for traffic particles in 3D + if (mapboxMap) { + mapboxMap.on('moveend', () => { + if (trafficEnabled && is3DGlobeActive && typeof trafficEngine !== 'undefined') { + trafficEngine.fetchRoads(); + } + }); + } + }); + } + + function updateMapboxFlights() { + // Mapbox flight rendering is now handled by HTML Markers in syncAllSensorsTo3D + } + + // Hook into original renderFlights to auto-sync mapbox + const originalRenderFlights = renderFlights; + renderFlights = function () { + originalRenderFlights.apply(this, arguments); + updateMapboxFlights(); + }; + + const globeToggleBtn = document.getElementById('globe-toggle'); + if (globeToggleBtn) { + globeToggleBtn.addEventListener('click', () => { + is3DGlobeActive = !is3DGlobeActive; + + const leafletContainer = document.getElementById('map'); + const mapboxContainer = document.getElementById('mapbox-container'); + + if (is3DGlobeActive) { + // Switch to 3D Mapbox + leafletContainer.style.display = 'none'; + mapboxContainer.style.display = 'block'; + globeToggleBtn.style.background = 'rgba(0, 255, 209, 0.2)'; + globeToggleBtn.style.color = '#fff'; + globeToggleBtn.innerHTML = ' 2D MAP'; + + initMapbox(); + + // Sync view from leaflet to mapbox + const center = map.getCenter(); + let zoom = map.getZoom() - 1; + if (zoom < 0) zoom = 0; + + mapboxMap.jumpTo({ + center: [center.lng, center.lat], + zoom: zoom + }); + + // Refresh flight data to mapbox immediately + setTimeout(updateMapboxFlights, 500); + + // Sync Traffic Particles + if (trafficEnabled && typeof trafficEngine !== 'undefined') { + trafficEngine.fetchRoads(); + } + + } else { + // Switch back to 2D Leaflet + mapboxContainer.style.display = 'none'; + leafletContainer.style.display = 'block'; + globeToggleBtn.style.background = 'transparent'; + globeToggleBtn.style.color = '#00FFD1'; + globeToggleBtn.innerHTML = ' 3D GLOBE'; + + // Sync view from mapbox back to leaflet + if (mapboxMap) { + const center = mapboxMap.getCenter(); + const zoom = mapboxMap.getZoom() + 1; + map.setView([center.lat, center.lng], zoom, { animate: false }); + } + + // Sync Traffic Particles back to Leaflet + if (trafficEnabled && typeof trafficEngine !== 'undefined') { + trafficEngine.fetchRoads(); + } + } + }); + } + // ========================================== + // 3D GLOBE MARKER HELPERS + // ========================================== + var mapboxExtraMarkers = { + flights: {}, + vessels: {}, + cameras: [], + wigleCams: [], + coords: [], + traffic: [], + sentiment: [], + towers: [], + satellites: {} + }; + + function createMapboxMarker(lat, lng, color, onClick, iconClass) { + if (!mapboxMap) return null; + var el = document.createElement('div'); + el.style.cssText = 'width:14px;height:14px;border-radius:50%;cursor:pointer;border:2px solid ' + color + ';background:' + color + '40;display:flex;align-items:center;justify-content:center;'; + if (iconClass) { + var icon = document.createElement('i'); + icon.className = iconClass; + icon.style.cssText = 'font-size:8px;color:' + color + ';'; + el.appendChild(icon); + } + if (onClick) { + el.addEventListener('click', function (e) { + if (mapboxMap) { + mapboxMap.flyTo({ + center: [lng, lat], + zoom: 15, + pitch: 60, + speed: 1.2, + curve: 1.4, + essential: true + }); + } + onClick(e); + }); + } + var marker = new mapboxgl.Marker({ element: el }) + .setLngLat([lng, lat]) + .addTo(mapboxMap); + return marker; + } + + function clearMapboxMarkers(type) { + if (!mapboxExtraMarkers[type]) return; + if (Array.isArray(mapboxExtraMarkers[type])) { + mapboxExtraMarkers[type].forEach(function (m) { if (m && m.remove) m.remove(); }); + mapboxExtraMarkers[type] = []; + } else { + for (var id in mapboxExtraMarkers[type]) { + if (mapboxExtraMarkers[type][id] && mapboxExtraMarkers[type][id].remove) { + mapboxExtraMarkers[type][id].remove(); + } + delete mapboxExtraMarkers[type][id]; + } + } + } + + function syncAllSensorsTo3D() { + if (!is3DGlobeActive) return; + + // ===== FLIGHTS ===== + if (flightEnabled && typeof lastFlightData !== 'undefined') { + const list = lastFlightData || []; + const currentBatch = list.slice(0, 1500); // 1500 for global coverage + const currentIds = new Set(currentBatch.map(f => f.icao24)); + + if (is3DGlobeActive) { + currentBatch.forEach(f => { + const id = f.icao24; + let color = '#00FFD1'; + if (f.type === 'military') color = '#FF4400'; + else if (f.type === 'private') color = '#FF00FF'; + else if (f.type === 'emergency') color = '#FFFFFF'; + + if (mapboxExtraMarkers.flights[id]) { + mapboxExtraMarkers.flights[id].setLngLat([f.long, f.lat]); + const el = mapboxExtraMarkers.flights[id].getElement(); + el.style.transform = 'rotate(' + (f.heading || 0) + 'deg)'; + } else { + const m = createMapboxMarker(f.lat, f.long, color, (e) => { + if (e) e.stopPropagation(); + renderEntityIntel('flight', f); + const icao = f.icao24; + if (typeof flightHistory !== 'undefined' && flightHistory[icao] && flightHistory[icao].length > 1) { + const lineCoords = flightHistory[icao].map(pos => [pos[1], pos[0]]); + if (mapboxMap.getSource('flight-path')) { + mapboxMap.getSource('flight-path').setData({ + type: 'FeatureCollection', + features: [{ type: 'Feature', geometry: { type: 'LineString', coordinates: lineCoords } }] + }); + } + } + }, 'fas fa-plane'); + if (m) { + m.getElement().style.transform = 'rotate(' + (f.heading || 0) + 'deg)'; + mapboxExtraMarkers.flights[id] = m; + } + } + }); + for (let id in mapboxExtraMarkers.flights) { + if (!currentIds.has(id)) { + mapboxExtraMarkers.flights[id].remove(); + delete mapboxExtraMarkers.flights[id]; + } + } + } + + } else { + clearMapboxMarkers('flights'); + } + + // ===== VESSELS ===== + if (vesselEnabled && typeof lastVesselData !== 'undefined') { + const list = lastVesselData || []; + const currentBatch = list.slice(0, 500); // 500 for global coverage + const currentIds = new Set(currentBatch.map(v => v.mmsi)); + + if (is3DGlobeActive) { + currentBatch.forEach(v => { + const id = v.mmsi; + let color = '#FFCC00'; + if (v.type === 'cargo') color = '#00CCFF'; + else if (v.type === 'tanker') color = '#FF4444'; + else if (v.type === 'passenger') color = '#00FF88'; + else if (v.type === 'fishing') color = '#FFAA00'; + else if (v.type === 'military' || v.type === 'milt') color = '#FF4400'; + + if (mapboxExtraMarkers.vessels[id]) { + mapboxExtraMarkers.vessels[id].setLngLat([v.lon, v.lat]); + const el = mapboxExtraMarkers.vessels[id].getElement(); + el.style.transform = `rotate(${v.heading || 0}deg)`; + } else { + const m = createMapboxMarker(v.lat, v.lon, color, (e) => { + if (e) e.stopPropagation(); + renderEntityIntel('vessel', v); + // Show 3D path + try { + const pathId = v.uid || v.mmsi; + axios.get(`/api/geo/vessel/path/${pathId}`).then(res => { + if (res.data && res.data.length > 0) { + const lineCoords = res.data.map(p => [p[1], p[0]]); + if (mapboxMap.getSource('vessel-path')) { + mapboxMap.getSource('vessel-path').setData({ + type: 'FeatureCollection', + features: [{ type: 'Feature', geometry: { type: 'LineString', coordinates: lineCoords } }] + }); + } + } + }); + } catch (e) { console.error(e); } + }, 'fas fa-ship'); + if (m) { + m.getElement().style.transform = `rotate(${v.heading || 0}deg)`; + mapboxExtraMarkers.vessels[id] = m; + } + } + }); + for (let id in mapboxExtraMarkers.vessels) { + if (!currentIds.has(id)) { + mapboxExtraMarkers.vessels[id].remove(); + delete mapboxExtraMarkers.vessels[id]; + } + } + } + + } else { + clearMapboxMarkers('vessels'); + } + + // ===== CAMERAS ===== + if (cameraEnabled && typeof cameraMarkers !== 'undefined') { + if (is3DGlobeActive) { + clearMapboxMarkers('cameras'); + Object.entries(cameraMarkers).forEach(function (pair) { + var camId = pair[0]; + var leafletMarker = pair[1]; + var ll = leafletMarker.getLatLng(); + var cam = leafletMarker.camData; // Retrieve data from 2D marker + + var m = createMapboxMarker(ll.lat, ll.lng, '#FF0055', function (e) { + if (e) e.stopPropagation(); + if (!cam) return; + + const videoId = `mapbox-cam-vid-${camId}`; + let mediaContent = ''; + + if (cam.type === 'image') { + mediaContent = ` +
+ +
LIVE_SNAPSHOT
+
`; + } else if (cam.type === 'hls') { + mediaContent = ``; + } else if (cam.type === 'youtube' || cam.type === 'iframe') { + mediaContent = ``; + } else { + mediaContent = ` +
+ +
LIVE_FEED_AVAILABLE
+ + OPEN_STREAM + +
`; + } + + const popupHtml = ` +
+
+ ${cam.name || 'TRAFFIC_CAMERA'} + ${cam.region || ''} +
+
+ ${mediaContent} +
+
+ ID: ${camId} + ${ll.lat.toFixed(4)}, ${ll.lng.toFixed(4)} +
+
+ Open Full Stream +
+
`; + + new mapboxgl.Popup({ maxWidth: '400px', className: 'camera-popup' }) + .setLngLat([ll.lng, ll.lat]) + .setHTML(popupHtml) + .addTo(mapboxMap); + + // Init HLS after popup renders + if (cam.type === 'hls') { + setTimeout(() => { + const videoEl = document.getElementById(videoId); + if (videoEl && typeof Hls !== 'undefined' && Hls.isSupported()) { + const hls = new Hls({ enableWorker: true, lowLatencyMode: true }); + hls.loadSource(cam.stream); + hls.attachMedia(videoEl); + hls.on(Hls.Events.MANIFEST_PARSED, () => { videoEl.play().catch(() => { }); }); + hls.on(Hls.Events.ERROR, (ev, data) => { + if (data.fatal) { + videoEl.style.display = 'none'; + videoEl.parentElement.innerHTML += `
STREAM_OFFLINE — Open in player
`; + } + }); + } else if (videoEl && videoEl.canPlayType('application/vnd.apple.mpegurl')) { + videoEl.src = cam.stream; + videoEl.play().catch(() => { }); + } + }, 250); + } + }, 'fas fa-video'); + if (m) mapboxExtraMarkers.cameras.push(m); + }); + } + } else { + clearMapboxMarkers('cameras'); + } + + // ===== WIGLE CAMERAS ===== + if (wigleCamEnabled && lastWigleCamData && lastWigleCamData.length > 0) { + if (is3DGlobeActive) { + clearMapboxMarkers('wigleCams'); + lastWigleCamData.forEach(function (cam) { + var color = '#FFCC00'; + if (cam.type === 'flock') color = '#FF0033'; + else if (cam.type === 'dashcam') color = '#00A3FF'; + + var m = createMapboxMarker(cam.lat, cam.lon, color, function (e) { + if (e) e.stopPropagation(); + renderEntityIntel('network', cam); + }, 'fas fa-eye'); + if (m) mapboxExtraMarkers.wigleCams.push(m); + }); + } + } else { + clearMapboxMarkers('wigleCams'); + } + + // ===== SATELLITES ===== + if (satelliteEnabled && satelliteData.length > 0) { + if (is3DGlobeActive) { + const currentIds = new Set(satelliteData.slice(0, 2000).map(s => s.name)); + + // Orbit Paths (3D) + if (orbitPathEnabled && mapboxMap && selectedSatelliteName) { + const sat = satelliteData.find(s => s.name === selectedSatelliteName); + if (sat && sat.path) { + const orbitFeature = { + type: 'Feature', + properties: { color: SAT_COLORS[sat.type] || SAT_COLORS.other }, + geometry: { + type: 'LineString', + coordinates: sat.path.map(p => [p[1], p[0]]) + } + }; + + if (!mapboxMap.getSource('satellite-orbits')) { + mapboxMap.addSource('satellite-orbits', { + type: 'geojson', + data: { type: 'FeatureCollection', features: [orbitFeature] } + }); + mapboxMap.addLayer({ + id: 'satellite-orbits-layer', + type: 'line', + source: 'satellite-orbits', + paint: { + 'line-color': ['get', 'color'], + 'line-width': 1.5, + 'line-opacity': 0.8, + 'line-dasharray': [2, 2] + } + }); + } else { + mapboxMap.getSource('satellite-orbits').setData({ + type: 'FeatureCollection', + features: [orbitFeature] + }); + } + } else { + if (mapboxMap.getSource('satellite-orbits')) { + mapboxMap.getSource('satellite-orbits').setData({ type: 'FeatureCollection', features: [] }); + } + } + } else if (mapboxMap && mapboxMap.getSource('satellite-orbits')) { + mapboxMap.getSource('satellite-orbits').setData({ type: 'FeatureCollection', features: [] }); + } + + satelliteData.slice(0, 2000).forEach(sat => { + const id = sat.name; + const color = SAT_COLORS[sat.type] || SAT_COLORS.other; + + if (mapboxExtraMarkers.satellites[id]) { + mapboxExtraMarkers.satellites[id].setLngLat([sat.lng, sat.lat]); + } else { + const noradId = sat.tle2.split(/\s+/)[1]; + const iconClass = SAT_ICONS[sat.type] || SAT_ICONS.other; + const m = createMapboxMarker(sat.lat, sat.lng, color, (e) => { + if (e) e.stopPropagation(); + selectedSatelliteName = sat.name; + const iconClass = SAT_ICONS[sat.type] || SAT_ICONS.other; + + // Re-sync to show orbit + syncAllSensorsTo3D(); + renderEntityIntel('satellite', sat); + }, iconClass); + if (m) { + const el = m.getElement(); + el.style.borderRadius = '0'; + el.style.transform = 'rotate(45deg)'; + el.style.width = '12px'; + el.style.height = '12px'; + el.style.border = '1.5px solid ' + color; + el.style.background = 'rgba(0,0,0,0.8)'; + el.style.boxShadow = '0 0 10px ' + color + '60'; + + mapboxExtraMarkers.satellites[id] = m; + } + } + }); + + for (let id in mapboxExtraMarkers.satellites) { + if (!currentIds.has(id)) { + mapboxExtraMarkers.satellites[id].remove(); + delete mapboxExtraMarkers.satellites[id]; + } + } + } + } else { + clearMapboxMarkers('satellites'); + if (mapboxMap && mapboxMap.getSource('satellite-orbits')) { + mapboxMap.getSource('satellite-orbits').setData({ type: 'FeatureCollection', features: [] }); + } + } + + // ===== COORDINATES ===== + if (coordEnabled && typeof savedCoords !== 'undefined') { + if (is3DGlobeActive) { + clearMapboxMarkers('coords'); + savedCoords.forEach(function (ll) { + var m = createMapboxMarker(ll.lat, ll.lng, '#FFFF00', function (e) { + if (e) e.stopPropagation(); + var popupHtml = '
' + + '
COORDINATE_UPLINK
' + + '
' + + '
LAT: ' + ll.lat.toFixed(6) + '
' + + '
LNG: ' + ll.lng.toFixed(6) + '
' + + '
'; + new mapboxgl.Popup({ maxWidth: '250px' }).setLngLat([ll.lng, ll.lat]).setHTML(popupHtml).addTo(mapboxMap); + }, 'fas fa-crosshairs'); + if (m) mapboxExtraMarkers.coords.push(m); + }); + } + } else { + clearMapboxMarkers('coords'); + } + + // ===== TRAFFIC ===== + if (trafficEnabled) { + if (is3DGlobeActive) { + clearMapboxMarkers('traffic'); + var tc = map.getCenter(); + var tm = createMapboxMarker(tc.lat, tc.lng, '#FFA600', function (e) { + if (e) e.stopPropagation(); + var popupHtml = '
' + + '
TOMTOM_TRAFFIC_UPLINK
' + + '
' + + '
STATUS: MONITORING
' + + '
LAT: ' + tc.lat.toFixed(4) + '
' + + '
LNG: ' + tc.lng.toFixed(4) + '
' + + '
LIVE FLOW DATA IN SIDEBAR
' + + '
'; + new mapboxgl.Popup({ maxWidth: '280px' }).setLngLat([tc.lng, tc.lat]).setHTML(popupHtml).addTo(mapboxMap); + }, 'fas fa-road'); + if (tm) mapboxExtraMarkers.traffic.push(tm); + } + } else { + clearMapboxMarkers('traffic'); + } + + // ===== SENTIMENT ===== + if (sentimentEnabled) { + if (is3DGlobeActive) { + clearMapboxMarkers('sentiment'); + var sc = map.getCenter(); + var sm = createMapboxMarker(sc.lat, sc.lng, '#00FFD1', function (e) { + if (e) e.stopPropagation(); + fetchSentimentData(sc.lat, sc.lng); + }, 'fas fa-satellite-dish'); + if (sm) mapboxExtraMarkers.sentiment.push(sm); + } + } else { + clearMapboxMarkers('sentiment'); + } + + // ===== CELL TOWERS ===== + if (towerEnabled && typeof lastTowerData !== 'undefined' && Array.isArray(lastTowerData)) { + if (is3DGlobeActive) { + clearMapboxMarkers('towers'); + lastTowerData.slice(0, 50).forEach(function (t) { + var m = createMapboxMarker(t.lat, t.lon, '#BC13FE', function (e) { + if (e) e.stopPropagation(); + renderEntityIntel('tower', t); + }, 'fas fa-broadcast-tower'); + if (m) mapboxExtraMarkers.towers.push(m); + }); + } + } else { + clearMapboxMarkers('towers'); + } + } + + // Mapbox globe click handler for coordinate, sentiment, tower + var _mapboxClickSetup = false; + function setupMapboxClickHandlers() { + if (!mapboxMap || _mapboxClickSetup) return; + _mapboxClickSetup = true; + mapboxMap.on('click', function (e) { + if (coordEnabled && !sentimentEnabled && !towerEnabled && !earthNetworksEnabled && !wigleCamEnabled) { + var popupHtml = '
' + + '
COORDINATE_UPLINK
' + + '
' + + '
LAT: ' + e.lngLat.lat.toFixed(6) + '
' + + '
LNG: ' + e.lngLat.lng.toFixed(6) + '
' + + '
'; + new mapboxgl.Popup({ maxWidth: '250px' }).setLngLat([e.lngLat.lng, + e.lngLat.lat]).setHTML(popupHtml).addTo(mapboxMap); + } + if (sentimentEnabled) { + fetchSentimentData(e.lngLat.lat, e.lngLat.lng); + } + if (towerEnabled) { + updateTowerTracker(e.lngLat.lat, e.lngLat.lng); + } + if (earthNetworksEnabled) { + updateEarthNetworks(e.lngLat.lat, e.lngLat.lng); + } + if (wigleCamEnabled) { + updateWigleCamLayer(e.lngLat.lat, e.lngLat.lng); + } + }); + } + + setInterval(syncAllSensorsTo3D, 5000); + - +