From 5928f7faad2b554df8a35340125dac32f1e0a099 Mon Sep 17 00:00:00 2001 From: Dauren777 Date: Fri, 19 Jun 2026 06:51:27 +0000 Subject: [PATCH] v12: Nominatim first, Overpass districts, area fix --- index.html | 101 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 66 insertions(+), 35 deletions(-) diff --git a/index.html b/index.html index 3ac3e44..6130360 100644 --- a/index.html +++ b/index.html @@ -167,24 +167,77 @@ function onRegionChange(){ if(!region){document.getElementById('locStatus').textContent='';return;} map.setView(region.center,9); const st=document.getElementById('locStatus'); - st.textContent='⏳ поиск региона...'; - // ШАГ 1: через Nominatim ищем ТОЛЬКО relation административной границы - const q='[out:json];(rel["name:ru"="'+name+' область"]["boundary"="administrative"];rel["name"="'+name+' область"]["boundary"="administrative"];);out tags id;'; - fetch('https://overpass-api.de/api/interpreter?data='+encodeURIComponent(q)) + st.textContent='⏳ '+name+'...'; + // Пробуем найти регион через Nominatim (надёжнее всего) + fetch('https://nominatim.openstreetmap.org/search?format=json&q='+encodeURIComponent(name+' область')+'&countrycodes=kz&limit=3&type=administrative') .then(r=>r.json()) + .then(list=>{ + if(!list.length)return fetch('https://nominatim.openstreetmap.org/search?format=json&q='+encodeURIComponent(name+' облысы')+'&countrycodes=kz&limit=3&type=administrative').then(r=>r.json()); + return list; + }) + .then(list=>{ + if(!list||!list.length||!list[0].osm_id){st.textContent='⚠ регион не найден в Nominatim';return;} + const item=list[0]; + regionRelId=item.osm_id; + st.textContent='⏳ районы '+name+'...'; + // Ищем районы через Overpass: area(3600000000+osm_id) + const q='[out:json][timeout:20];area('+(3600000000+item.osm_id)+')->.a;(rel(area.a)["boundary"="administrative"]["admin_level"~"6|7|8"];);out tags id;'; + return fetch('https://overpass-api.de/api/interpreter?data='+encodeURIComponent(q)); + }) + .then(r=>r&&r.json()) .then(data=>{ - if(!data||!data.elements||!data.elements.length)throw new Error('регион не найден в OSM'); + if(!data||!data.elements||!data.elements.length){ + st.textContent='⚠ районы не найдены через OSM'; + // fallback: через Nominatim + fetch('https://nominatim.openstreetmap.org/search?format=json&q='+encodeURIComponent('районы '+name+' области')+'&countrycodes=kz&limit=30') + .then(r=>r.json()).then(nom=>{ + dsel.innerHTML=''; + const seen=new Set(); + nom.forEach(item=>{ + let n=item.display_name.split(',')[0].trim(); + if(!n||seen.has(n)||n===name)return;seen.add(n); + const o=document.createElement('option'); + o.value=n;o.textContent=n; + dsel.appendChild(o); + districtList.push({name:n,osm_id:item.osm_id||0}); + }); + st.textContent='✅ Nominatim: '+seen.size; + }); + return; + } + const seen=new Map(); + data.elements.forEach(el=>{ + if(!el.tags||!el.tags.name)return; + let clean=el.tags.name.replace(/\s*ауданы$/i,'').replace(/\s*районы$/i,'').replace(/\s*район$/i,'').trim(); + if(clean&&!seen.has(clean))seen.set(clean,el.id); + }); + dsel.innerHTML=''; + const sorted=[...seen.keys()].sort(); + sorted.forEach(n=>{ + const o=document.createElement('option'); + o.value=n;o.textContent=n; + dsel.appendChild(o); + districtList.push({name:n,osm_id:seen.get(n)}); + }); + st.textContent='✅ '+sorted.length+' районов из OSM'; + }) + .catch(e=>{ + st.textContent='⚠ ошибка: '+e.message; + }); +} const rel=data.elements[0]; regionRelId=rel.id; - st.textContent='⏳ районы...'; - // ШАГ 2: ищем районы (admin_level=6,7) внутри региона - const areaId=3600000000+rel.id; - const q2='[out:json];area('+areaId+')->.a;(rel(area.a)["boundary"="administrative"]["admin_level"~"6|7"];);out tags id;'; + st.textContent='✅ регион: '+rel.id+', ищу районы...'; + // ШАГ 2: районы (admin_level=6,7) внутри rel + const q2='[out:json][timeout:20];area('+rel.id+')->.a;(rel(area.a)["boundary"="administrative"]["admin_level"~"6|7"];);out tags id;'; return fetch('https://overpass-api.de/api/interpreter?data='+encodeURIComponent(q2)); }) - .then(r=>r.json()) + .then(r=>r&&r.json()) .then(data=>{ - if(!data||!data.elements||!data.elements.length)throw new Error('районы не найдены'); + if(!data||!data.elements||!data.elements.length){ + st.textContent='⚠ районы не найдены через OSM, пробую Nominatim...'; + return fetchNominatimDistricts(name); + } const seen=new Map(); data.elements.forEach(el=>{ if(!el.tags||!el.tags.name)return; @@ -202,34 +255,12 @@ function onRegionChange(){ st.textContent='✅ '+sorted.length+' районов'; }) .catch(e=>{ - dsel.innerHTML=''; - st.textContent='⚠ районы: '+e.message; - // fallback: поищем через Nominatim + st.textContent='⚠ ошибка OSM: '+e.message+', fallback...'; fetchNominatimDistricts(name); }); } -function fetchNominatimDistricts(regionName){ - const st=document.getElementById('locStatus'); - st.textContent='⏳ районы через Nominatim...'; - fetch('https://nominatim.openstreetmap.org/search?format=json&q='+encodeURIComponent(regionName+' район')+'&countrycodes=kz&limit=25') - .then(r=>r.json()) - .then(data=>{ - const dsel=document.getElementById('districtSelect'); - dsel.innerHTML=''; - if(!data||!data.length){st.textContent='⚠ районы не найдены';return;} - const seen=new Set(); - data.forEach(item=>{ - let n=item.display_name.split(',')[0].trim(); - if(!n||seen.has(n))return;seen.add(n); - const o=document.createElement('option'); - o.value=n;o.textContent=n; - dsel.appendChild(o); - districtList.push({name:n,osm_id:item.osm_id}); - }); - st.textContent='✅ через Nominatim: '+seen.size; - }); -} + function onDistrictSelect(){ const dname=document.getElementById('districtSelect').value;