hoàn thành chức năng phân lô trên ảnh predict

This commit is contained in:
2026-02-18 16:22:18 +07:00
committed by Victor Phan
parent eacc6f9b96
commit ae4d8cbbc9
5 changed files with 785 additions and 2 deletions
+177
View File
@@ -0,0 +1,177 @@
<!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="UTF-8">
<title>Test Shapefile Selection</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
<style>
body { font-family: Arial, sans-serif; padding: 20px; }
#map { height: 400px; border: 2px solid #ccc; margin: 20px 0; }
.info-box { background: #f0f0f0; padding: 15px; margin: 10px 0; border-radius: 5px; }
</style>
</head>
<body>
<h1>🧪 Test Shapefile Auto-Select Bbox</h1>
<div class="info-box">
<h3>Chọn Shapefile:</h3>
<select id="shapefileOverlay" onchange="onShapefileSelected(event)" style="width: 100%; padding: 10px; font-size: 14px;">
<option value="">-- Chọn shapefile --</option>
</select>
</div>
<div id="map"></div>
<div class="info-box">
<h3>Current Bbox:</h3>
<pre id="bboxInfo">Chưa chọn shapefile</pre>
</div>
<div class="info-box">
<h3>Console Logs:</h3>
<pre id="console" style="max-height: 200px; overflow-y: auto; background: #000; color: #0f0; padding: 10px;"></pre>
</div>
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
<script>
// Global variables
let map, drawnItems, selectedBbox = null;
// Custom console.log to display in page
const originalLog = console.log;
console.log = function(...args) {
originalLog.apply(console, args);
const consoleEl = document.getElementById('console');
consoleEl.textContent += args.join(' ') + '\n';
consoleEl.scrollTop = consoleEl.scrollHeight;
};
// Initialize map
function initMap() {
map = L.map('map').setView([10.0, 105.8], 10);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(map);
drawnItems = new L.FeatureGroup();
map.addLayer(drawnItems);
console.log('✅ Map initialized');
}
// Load shapefiles from API
async function loadShapefiles() {
try {
console.log('📡 Fetching shapefiles from API...');
const response = await fetch('http://localhost:8000/api/overlay/shapefiles');
const data = await response.json();
const select = document.getElementById('shapefileOverlay');
select.innerHTML = '<option value="">-- Chọn shapefile --</option>';
if (data.shapefiles && data.shapefiles.length > 0) {
data.shapefiles.forEach(shp => {
const option = document.createElement('option');
option.value = shp.path;
let label = `${shp.filename} - ${shp.feature_count} features`;
if (shp.crs) {
const crsCode = shp.crs.split(':').pop();
label += ` | CRS: ${crsCode}`;
}
if (shp.bbox && shp.bbox.length === 4) {
const [minLon, minLat, maxLon, maxLat] = shp.bbox;
label += ` | [${minLon.toFixed(2)}, ${minLat.toFixed(2)}, ${maxLon.toFixed(2)}, ${maxLat.toFixed(2)}]`;
}
option.textContent = label;
option.dataset.crs = shp.crs || '';
option.dataset.bbox = JSON.stringify(shp.bbox || []);
option.dataset.featureCount = shp.feature_count;
select.appendChild(option);
});
console.log(`✅ Loaded ${data.shapefiles.length} shapefiles`);
} else {
console.log('⚠️ No shapefiles found');
}
} catch (error) {
console.error('❌ Error loading shapefiles:', error);
}
}
// Handle shapefile selection
function onShapefileSelected(event) {
console.log('🔔 Shapefile selection changed');
const selectedOption = event.target.selectedOptions[0];
if (!selectedOption || !selectedOption.value) {
console.log('️ No shapefile selected');
document.getElementById('bboxInfo').textContent = 'Chưa chọn shapefile';
return;
}
const bboxData = selectedOption.dataset.bbox;
console.log('📦 Bbox data from option:', bboxData);
if (!bboxData || bboxData === '[]') {
console.log('⚠️ No bbox data in selected option');
return;
}
try {
const bbox = JSON.parse(bboxData);
console.log('📊 Parsed bbox:', bbox);
if (bbox.length !== 4) {
console.log('❌ Invalid bbox length:', bbox.length);
return;
}
const [minLon, minLat, maxLon, maxLat] = bbox;
// Validate bbox
if (minLon < -180 || maxLon > 180 || minLat < -90 || maxLat > 90) {
console.log('❌ Bbox out of valid range');
return;
}
console.log('✅ Valid bbox:', {minLon, minLat, maxLon, maxLat});
// Update map
const bounds = [[minLat, minLon], [maxLat, maxLon]];
const rectangle = L.rectangle(bounds, {
color: '#667eea',
weight: 3,
fillOpacity: 0.2
});
drawnItems.clearLayers();
drawnItems.addLayer(rectangle);
map.fitBounds(bounds, { padding: [50, 50] });
selectedBbox = {min_lon: minLon, min_lat: minLat, max_lon: maxLon, max_lat: maxLat};
console.log('🗺️ Map updated with new bbox');
// Update bbox info display
document.getElementById('bboxInfo').textContent = JSON.stringify(selectedBbox, null, 2);
alert(`✅ Bbox updated!\n\nmin_lon: ${minLon.toFixed(4)}\nmin_lat: ${minLat.toFixed(4)}\nmax_lon: ${maxLon.toFixed(4)}\nmax_lat: ${maxLat.toFixed(4)}`);
} catch (e) {
console.error('❌ Error:', e);
}
}
// Initialize on load
window.onload = function() {
console.log('🚀 Page loaded, initializing...');
initMap();
loadShapefiles();
};
</script>
</body>
</html>