v12: Nominatim first, Overpass districts, area fix
This commit is contained in:
parent
2dee3e51bc
commit
5928f7faad
101
index.html
101
index.html
@ -167,24 +167,77 @@ function onRegionChange(){
|
|||||||
if(!region){document.getElementById('locStatus').textContent='';return;}
|
if(!region){document.getElementById('locStatus').textContent='';return;}
|
||||||
map.setView(region.center,9);
|
map.setView(region.center,9);
|
||||||
const st=document.getElementById('locStatus');
|
const st=document.getElementById('locStatus');
|
||||||
st.textContent='⏳ поиск региона...';
|
st.textContent='⏳ '+name+'...';
|
||||||
// ШАГ 1: через Nominatim ищем ТОЛЬКО relation административной границы
|
// Пробуем найти регион через Nominatim (надёжнее всего)
|
||||||
const q='[out:json];(rel["name:ru"="'+name+' область"]["boundary"="administrative"];rel["name"="'+name+' область"]["boundary"="administrative"];);out tags id;';
|
fetch('https://nominatim.openstreetmap.org/search?format=json&q='+encodeURIComponent(name+' область')+'&countrycodes=kz&limit=3&type=administrative')
|
||||||
fetch('https://overpass-api.de/api/interpreter?data='+encodeURIComponent(q))
|
|
||||||
.then(r=>r.json())
|
.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=>{
|
.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='<option value="">— все —</option>';
|
||||||
|
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='<option value="">— все —</option>';
|
||||||
|
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];
|
const rel=data.elements[0];
|
||||||
regionRelId=rel.id;
|
regionRelId=rel.id;
|
||||||
st.textContent='⏳ районы...';
|
st.textContent='✅ регион: '+rel.id+', ищу районы...';
|
||||||
// ШАГ 2: ищем районы (admin_level=6,7) внутри региона
|
// ШАГ 2: районы (admin_level=6,7) внутри rel
|
||||||
const areaId=3600000000+rel.id;
|
const q2='[out:json][timeout:20];area('+rel.id+')->.a;(rel(area.a)["boundary"="administrative"]["admin_level"~"6|7"];);out tags id;';
|
||||||
const q2='[out:json];area('+areaId+')->.a;(rel(area.a)["boundary"="administrative"]["admin_level"~"6|7"];);out tags id;';
|
|
||||||
return fetch('https://overpass-api.de/api/interpreter?data='+encodeURIComponent(q2));
|
return fetch('https://overpass-api.de/api/interpreter?data='+encodeURIComponent(q2));
|
||||||
})
|
})
|
||||||
.then(r=>r.json())
|
.then(r=>r&&r.json())
|
||||||
.then(data=>{
|
.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();
|
const seen=new Map();
|
||||||
data.elements.forEach(el=>{
|
data.elements.forEach(el=>{
|
||||||
if(!el.tags||!el.tags.name)return;
|
if(!el.tags||!el.tags.name)return;
|
||||||
@ -202,34 +255,12 @@ function onRegionChange(){
|
|||||||
st.textContent='✅ '+sorted.length+' районов';
|
st.textContent='✅ '+sorted.length+' районов';
|
||||||
})
|
})
|
||||||
.catch(e=>{
|
.catch(e=>{
|
||||||
dsel.innerHTML='<option value="">— ошибка —</option>';
|
st.textContent='⚠ ошибка OSM: '+e.message+', fallback...';
|
||||||
st.textContent='⚠ районы: '+e.message;
|
|
||||||
// fallback: поищем через Nominatim
|
|
||||||
fetchNominatimDistricts(name);
|
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='<option value="">— все —</option>';
|
|
||||||
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(){
|
function onDistrictSelect(){
|
||||||
const dname=document.getElementById('districtSelect').value;
|
const dname=document.getElementById('districtSelect').value;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user