├── robots.txt ├── .gitignore ├── validator └── index.php ├── favicon.ico ├── latlon ├── geo.png ├── center.png ├── marker.png ├── yandex.png └── index.html ├── arch ├── favicon.ico ├── screenshot.png └── index.html ├── hazard ├── favicon.ico ├── screenshot.png └── index.html ├── levels ├── favicon.ico ├── screenshot.png └── index.html ├── mall ├── favicon.ico ├── screenshot.png └── index.html ├── place ├── favicon.ico └── index.html ├── routes ├── favicon.ico ├── update.php └── index.html ├── entrance ├── favicon.ico ├── screenshot.png └── index.html ├── fitness ├── favicon.ico ├── screenshot.png └── index.html ├── helipad ├── favicon.ico ├── screenshot.png └── index.html ├── navalny ├── favicon.ico ├── screenshot.png ├── script.js ├── map.php ├── table.html └── index.html ├── outpost ├── favicon.ico ├── screenshot.png ├── points.php └── index.html ├── allotments ├── favicon.ico ├── screenshot.png └── index.html ├── boundary ├── screenshot.png ├── update.php ├── favicon.ico ├── index.html └── osm.php ├── data_center ├── favicon.ico └── index.html ├── education ├── favicon.ico └── index.html ├── OSMvsNarod ├── screenshot.png └── index.html ├── russian_post ├── favicon.ico ├── screenshot.png ├── get.php ├── parse.php └── index.html ├── latlon.html ├── OSMvsNarod.html ├── i ├── ok.js ├── ajax.js ├── common.js ├── josm.js ├── map.js ├── lib.js └── osm.js ├── m ├── cache.class.php └── mysql.class.php ├── overpass └── index.php ├── coloured-addresses-ru.mapcss ├── index.html ├── geocoder └── index.php └── address └── index.html /robots.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | geojson 2 | -------------------------------------------------------------------------------- /validator/index.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |

Сайт переехал сюда.

8 | 9 | 10 | -------------------------------------------------------------------------------- /OSMvsNarod.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |

Сайт переехал сюда.

8 | 9 | 10 | -------------------------------------------------------------------------------- /russian_post/get.php: -------------------------------------------------------------------------------- 1 | ?f AND lat < ?f AND lon > ?f AND lon < ?f', $a[1], $a[3], $a[0], $a[2]); 13 | 14 | $res = mysql::getList($sql); 15 | 16 | header('Content-type: application/json'); 17 | echo json_encode($res, JSON_UNESCAPED_UNICODE); 18 | -------------------------------------------------------------------------------- /i/ok.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Функция подстановки окончаний 3 | * @author CupIvan 4 | * @example n=12; st=n+' стул'+ok(n, '', 'а', 'ьев') 5 | * @example ok('12 стул(|а|ьев)') 6 | */ 7 | function ok(n, n1, n2, n5) 8 | { 9 | if (n1 == undefined) return ok_string(n) 10 | 11 | if (n5 == undefined) n5 = n2||'' 12 | res = n5; d = n % 10; dd = n % 100 13 | if (d < 5) res = n2||'' 14 | if (d < 2) res = n1||'' 15 | if (!d || (dd > 4 && dd < 21)) res = n5 16 | return res 17 | } 18 | 19 | function ok_string(st) 20 | { 21 | var n = /\d+/.exec(st)[0] 22 | st = st.replace(/\((.+?)\)/g, (_,a)=>{ 23 | var a = a.split('|') 24 | return ok(n, ...a) 25 | }) 26 | return st 27 | } 28 | -------------------------------------------------------------------------------- /i/ajax.js: -------------------------------------------------------------------------------- 1 | function ajax(url, handler, post) 2 | { 3 | var xhr = new XMLHttpRequest() 4 | if (!post) 5 | { 6 | xhr.open('GET', url, true) 7 | xhr.send() 8 | } 9 | else 10 | if (post.tagName == 'FORM') 11 | { 12 | xhr.open('POST', url, true) 13 | xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); 14 | var i, st = '' 15 | for (i = 0; i < post.elements.length; i++) 16 | if (post.elements[i].name) 17 | if (post.elements[i].value) 18 | st += '&'+post.elements[i].name+'='+encodeURIComponent(post.elements[i].value) 19 | xhr.send(st) 20 | } 21 | xhr.onreadystatechange = function(){ 22 | if (xhr.readyState != 4) return 23 | if (xhr.status == 200) 24 | handler(JSON.parse(xhr.responseText)) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /navalny/script.js: -------------------------------------------------------------------------------- 1 | function _hours(x) 2 | { 3 | x = x.toLowerCase() 4 | const a={'понедельник': 'пн', 'вторник': 'вт', 'среда': 'ср', 'четверг': 'чт', 'пятница': 'пт', 'суббота': 'сб', 'воскресенье': 'вс', 5 | 'птн': 'пт', 'c': '', 6 | 'пн':'Mo','вт':'Tu','ср':'We','чт':'Th','пт':'Fr','сб':'Sa','вс':'Su'} 7 | for (let day in a) x = x.replace(new RegExp(day, 'i'), a[day]) 8 | x = x.replace('открыт', '') 9 | x = x.replace('работает', '') 10 | x = x.replace('часы работы', '') 11 | x = x.replace(': ', ' ') 12 | x = x.replace(/–/g, '-') 13 | x = x.replace(/с /g, '') 14 | x = x.replace(/до/g, '-') 15 | x = x.replace(/\s+-\s+/g, '-') 16 | x = x.replace(/,/g, ';') 17 | x = x.replace(/\s+/g, ' ') 18 | x = x.replace(/^\s+|\s+$|\./g, '') 19 | return x 20 | } 21 | -------------------------------------------------------------------------------- /navalny/map.php: -------------------------------------------------------------------------------- 1 | $a['region'], 23 | 'addr:city' => $a['city'], 24 | 'address' => $a['address'], 25 | 'lat' => @$a['coordinates'][1], 26 | 'lon' => @$a['coordinates'][0], 27 | 'contact:website' => URL.'/hq/'.$a['slug'], 28 | 'contact:phone' => @$a['phone']?:'', 29 | 'contact:email' => @$a['contact_person_email']?:'', 30 | 'person' => @$a['contact_person']?:'', 31 | 'state' => @$a['state']?:'', 32 | 'opened' => true, 33 | ]; 34 | } 35 | } 36 | 37 | header('Content-type: application/json'); 38 | echo json_encode($res, JSON_UNESCAPED_UNICODE); 39 | -------------------------------------------------------------------------------- /m/cache.class.php: -------------------------------------------------------------------------------- 1 | 16) $key = md5($key); 37 | return '/tmp/cache/'.$key; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /boundary/update.php: -------------------------------------------------------------------------------- 1 | #!/bin/env php 2 | 2 | OpenStreetMap way element iconimage/svg+xmlOpenStreetMap way element icon2014-03-10https://wiki.openstreetmap.org/wiki/User:Moresby 3 | -------------------------------------------------------------------------------- /overpass/index.php: -------------------------------------------------------------------------------- 1 | time() - 2*3600) 20 | { 21 | $page = file_get_contents($fname); 22 | $log .= 'CACHE'; 23 | } 24 | 25 | if (empty($page)) 26 | { 27 | $servers = [ 28 | 'https://lz4.overpass-api.de/api/interpreter', 29 | 'https://z.overpass-api.de/api/interpreter', 30 | 'http://overpass.openstreetmap.fr/api/interpreter', 31 | 'https://overpass.kumi.systems/api/interpreter', 32 | ]; 33 | if (strpos($_SERVER['HTTP_HOST'], '_.osm') !== false) 34 | $servers = ['https://osm.cupivan.ru/overpass']; 35 | else 36 | @file_put_contents($fname, '{}'); 37 | $server = $servers[mt_rand(0, count($servers)-1)]; 38 | $url = "$server/?data=".urlencode($data); 39 | 40 | $page = @file_get_contents($url); 41 | if ($page) @file_put_contents($fname, $page); else { @unlink($fname); $page = '{"state": "error", "url": "'.$url.'"}'; } 42 | $log .= 'DOWNLOAD'; 43 | } 44 | 45 | $log .= "\t".round(strlen($page)/1024)."Kb\t$fname\t$data\n"; 46 | 47 | @file_put_contents(DIR.date('Y-m-d').'.log', $log, FILE_APPEND); 48 | 49 | echo $page; 50 | -------------------------------------------------------------------------------- /i/common.js: -------------------------------------------------------------------------------- 1 | $(function(){ 2 | const div = $('div') 3 | div.innerHTML = ` 4 | 7 | 8 | Открыть на GitHub 9 | 10 | 29 | ` 30 | document.body.appendChild(div) 31 | }) 32 | -------------------------------------------------------------------------------- /routes/update.php: -------------------------------------------------------------------------------- 1 | #!/bin/env php 2 | [], 'ways'=>[], 'relations'=>[]]; 5 | 6 | parse('56.2480951,43.9418364,56.2533404,43.9514494'); // Мызинский мост 7 | parse('56.2983246,43.9575005,56.2993485,43.9664698'); // Молитовский мост 8 | parse('56.3167747,43.9576292,56.3221772,43.9702034'); // Метромост 9 | parse('56.3255800,43.9676714,56.3304578,43.9775419'); // Канавинский мост 10 | 11 | function parse($coords) 12 | { 13 | global $data; 14 | $q = 'http://osm.cupivan.ru/overpass/?data='. 15 | urlencode('[out:json];(rel["type"="route"]('.$coords.'););(._;>;);out body;'); 16 | $a = file_get_contents($q); 17 | $a = json_decode($a, true); 18 | 19 | foreach ($a['elements'] as $a) 20 | { 21 | $id = $a['id']; $type = $a['type']; 22 | unset($a['type']); unset($a['id']); 23 | if ($type == 'node') $data['nodes'][$id] = $a; 24 | if ($type == 'way') $data['ways'][$id] = $a; 25 | if ($type == 'relation') $data['relations'][$id] = $a; 26 | } 27 | } 28 | 29 | $_ = $data; $routes=[]; 30 | foreach ($_['relations'] as $rid => $a) 31 | { 32 | $st = ''; 33 | $data = ['ref'=>$a['tags']['ref'],'stops'=>[]]; 34 | $ref = $a['tags']['ref']; 35 | $routes[$rid] = ['ref'=>$ref, 'stops'=>[]]; 36 | foreach ($a['members'] as $a) 37 | if ($a['role'] == 'stop') 38 | { 39 | $data['stops'][] = $a['ref']; 40 | $routes[$rid]['stops'][] = $a['ref']; 41 | } 42 | } 43 | 44 | $nodes = []; 45 | $st = "var routes={};\n"; 46 | foreach ($routes as $k => $v) 47 | { 48 | $st .= 'routes['.$k.'] = '.json_encode($v, JSON_UNESCAPED_UNICODE)."\n"; 49 | foreach ($v['stops'] as $id) 50 | if (!empty($_['nodes'][$id]['lat'])) 51 | { 52 | $a = $_['nodes'][$id]; 53 | $a = ['c'=>[$a['lat'],$a['lon']], 'n'=>$a['tags']['name']]; 54 | $nodes[$id] = $a; 55 | } 56 | } 57 | file_put_contents('routes.js', $st); 58 | 59 | $st = "var nodes={};\n"; 60 | foreach ($nodes as $k => $v) 61 | { 62 | $st .= 'nodes['.$k.'] = '.json_encode($v, JSON_UNESCAPED_UNICODE)."\n"; 63 | } 64 | file_put_contents('nodes.js', $st); 65 | -------------------------------------------------------------------------------- /i/josm.js: -------------------------------------------------------------------------------- 1 | // https://josm.openstreetmap.de/wiki/Help/RemoteControlCommands 2 | var josm = { 3 | version: false, // версия JOSM 4 | running: false, // запущен ли редактор 5 | 6 | /** иконка со ссылкой на объект */ 7 | icon: function(id) 8 | { 9 | var type = osm.getType(id) 10 | 11 | var url = 'http://www.openstreetmap.org/browse/'+type+'/'+id 12 | 13 | var pic = '' 14 | if (type == 'node') pic = 'b/b5/Mf_node' 15 | if (type == 'way') pic = '8/83/Mf_area' 16 | if (type == 'relation') pic = '5/59/Relation' 17 | 18 | return '' + 19 | ''+ 20 | '' 21 | }, 22 | /** ссылка на объект */ 23 | link: function(a = {}) 24 | { 25 | var type = osm.getType(a) 26 | if (!type) return null 27 | return 'http://127.0.0.1:8111/load_object?objects='+type[0]+a.id 28 | }, 29 | /** ссылка на изменение параметров */ 30 | link_edit: function(a, params) 31 | { 32 | var type = osm.getType(a) 33 | var i, tags = '' 34 | for (i in params) tags += (tags?'%7C':'')+i+'='+encodeURIComponent(params[i]) 35 | return 'http://127.0.0.1:8111/load_object?objects='+type[0]+a.id+'&addtags='+tags 36 | }, 37 | /** ссылка на создание точки */ 38 | link_node: function(params) 39 | { 40 | var i, tags = '' 41 | for (i in params) 42 | if (i != 'lat' && i != 'lon') 43 | tags += (tags?'%7C':'')+i+'='+encodeURIComponent(params[i]) 44 | return 'http://127.0.0.1:8111/add_node?lat='+params.lat+'&lon='+params.lon+'&addtags='+tags 45 | }, 46 | link_zoom: function(a, delta=0.00001) 47 | { 48 | if (!a.lat && a.center) 49 | [a.lat, a.lon] = a.center 50 | return 'http://127.0.0.1:8111/load_and_zoom?left='+(a.lon-delta)+'&right='+(a.lon-0+delta)+'&top='+(a.lat-0+delta)+'&bottom='+(a.lat-delta) 51 | }, 52 | } 53 | 54 | /** проверка запущен JOSM или нет */ 55 | setInterval(x=function(){ 56 | fetch('http://127.0.0.1:8111/version').then(_=>_.json()).then(a=>{ 57 | josm.running = false 58 | if (a.protocolversion) 59 | { 60 | josm.running = true 61 | josm.version = a.protocolversion.major+'.'+a.protocolversion.minor 62 | } 63 | }).catch(e=>{}) 64 | }, 10000) 65 | setTimeout(x, 2000) 66 | 67 | window.$(function() { 68 | var div = document.createElement('div') 69 | div.innerHTML = '' 70 | document.body.appendChild(div) 71 | }) 72 | -------------------------------------------------------------------------------- /outpost/points.php: -------------------------------------------------------------------------------- 1 | $coords[0], 17 | 'lon' => $coords[1], 18 | 'h' => $a['workTime'], 19 | ]; 20 | } 21 | 22 | return $res; 23 | }); 24 | break; 25 | case 'Labirint': 26 | echo get_points($_REQUEST[$x], function(){ 27 | $st = get_page('https://labirint.ru/maps/'); 28 | $n1 = strpos($st, 'var json = \'{"center'); 29 | $n2 = strpos($st, 'var yaMapsCity'); 30 | $st = substr($st, $n1+12, $n2-$n1-20); 31 | 32 | foreach (json_decode($st, true)['points'] as $a) 33 | if ($a['icontype'] == 'dl') 34 | { 35 | $coords = explode(',', $a['coordinates']); 36 | $res[] = [ 37 | 'lat' => $a['x'], 38 | 'lon' => $a['y'], 39 | ]; 40 | } 41 | 42 | return $res; 43 | }); 44 | break; 45 | case 'Onlinetrade': 46 | echo get_points($_REQUEST[$x], function(){ 47 | $st = get_page('https://www.onlinetrade.ru/shops/'); 48 | $n1 = strpos($st, 'var firstUse'); 49 | $n2 = strpos($st, 'YMapsID_shoplist'); 50 | $st = substr($st, $n1, $n2-$n1); 51 | if (preg_match_all('#Lon.+?(\d[\d.]+).+?Lat.+?(\d[\d.]+)#', $st, $m, PREG_SET_ORDER)) 52 | foreach ($m as $a) 53 | { 54 | $res[] = [ 55 | 'lat' => $a[2], 56 | 'lon' => $a[1], 57 | ]; 58 | } 59 | 60 | return $res; 61 | }); 62 | break; 63 | } 64 | 65 | function get_points($brand, $parser) 66 | { 67 | $cache = '/tmp/cache_osm/'.$_REQUEST['brand'].'.json'; 68 | $dir = dirname($cache); 69 | if (!file_exists($dir)) mkdir($dir, 0777, true); 70 | if (time() - @filemtime($cache) < 7*24*3600) return file_get_contents($cache); 71 | 72 | $res = $parser(); 73 | 74 | $st = json_encode($res, JSON_UNESCAPED_UNICODE); 75 | if ($st) file_put_contents($cache, $st); 76 | 77 | return $st; 78 | } 79 | 80 | function get_page($url) 81 | { 82 | $cache = '/tmp/cache_osm/'.md5($url).'.html'; 83 | if (time() - @filemtime($cache) < 24*3600) return file_get_contents($cache); 84 | $st = file_get_contents($url); 85 | if ($st) file_put_contents($cache, $st); 86 | return $st; 87 | } 88 | -------------------------------------------------------------------------------- /russian_post/parse.php: -------------------------------------------------------------------------------- 1 | $ref, 13 | 'limit' => 100, 14 | 'radius' => 1000, 15 | ]; 16 | $json = json_encode($json); 17 | $context = stream_context_create(['http' => [ 18 | 'method' => 'POST', 19 | 'header' => "Content-type: application/json\r\nContent-Length: ".strlen($json)."\r\n", 20 | 'content' => $json, 21 | ]]); 22 | $url = 'https://www.pochta.ru/suggestions/v2/postoffice.find-nearest-by-postalcode-raw-filters'; 23 | $st = file_get_contents($url, false, $context); 24 | $a = json_decode($st, true); 25 | 26 | require_once '../m/mysql.class.php'; 27 | mysql::$base = 'opendata'; 28 | mysql::$user = 'opendata'; 29 | mysql::$pass = 'opendata'; 30 | 31 | foreach ($a as $a) 32 | { 33 | mysql::insert_duplicate('russian_post', [ 34 | 'ref' => $a['postalCode'], 35 | 'lat' => $a['latitude'], 36 | 'lon' => $a['longitude'], 37 | 'json' => json_encode($a, JSON_UNESCAPED_UNICODE), 38 | 'timestamp' => date('Y-m-d H:i:s'), 39 | 'city' => @$a['address']['settlementOrCity'], 40 | 'address' => @$a['addressSource'], 41 | 'opening_hours' => _oh($a), 42 | ]); 43 | cache::set('pochta/'.$a['postalCode'], $a); 44 | } 45 | 46 | send($ref); 47 | 48 | 49 | function send($ref) 50 | { 51 | $a = cache::get('pochta/'.$ref, null, 'week'); 52 | if (is_null($a)) return false; 53 | header('Content-type: application/json'); 54 | echo json_encode($a, JSON_UNESCAPED_UNICODE); 55 | return true; 56 | } 57 | 58 | /** формирование opening_hours */ 59 | function _oh($a) 60 | { 61 | if (!empty($a['isClosed']) || !empty($a['isTemporaryClosed'])) return 'closed'; 62 | if (empty($a['workingHours'])) return ''; 63 | 64 | $_d = ['', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su']; 65 | $tmp = []; 66 | 67 | // объединяем дни с одинаковым режимом работы 68 | foreach ($a['workingHours'] as $h) 69 | if (!empty($h['beginWorkTime'])) 70 | { 71 | $time = $h['beginWorkTime'].'-'.$h['endWorkTime']; 72 | if (!empty($h['lunches'])) 73 | $time = str_replace('-', '-'.@$h['lunches'][0]['beginLunchTime'].','.@$h['lunches'][0]['endLunchTime'].'-', $time); 74 | $time = preg_replace('/(:\d{2}):00/', '$1', $time); 75 | @$tmp[$time][] = ($_d[$h['weekDayId']]); 76 | } 77 | 78 | // формируем строку opening_hours 79 | $hours = ''; 80 | foreach ($tmp as $time => $a) 81 | $hours .= ($hours?'; ':'') . implode(',', $a).' '.$time; 82 | 83 | // склеиваем смежные дни 84 | for ($i=2; $i 2 | 3 | 4 | 5 | 6 | Все штабы Алексея Навального в таблице 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /i/map.js: -------------------------------------------------------------------------------- 1 | if (!window.L) 2 | { 3 | document.write('' 4 | +'' 6 | +'' 8 | ) 9 | } 10 | 11 | var map = { 12 | init: function(params){ 13 | params = params || {}; 14 | var i, a, t = document.location.hash.replace(/.+?\?/, '').split('&'); 15 | for (i = 0; i < t.length; i++) { a = t[i].split('='); params[a[0]] = a[1]; } 16 | 17 | // или пробуем загрузить последние координаты 18 | if (!params[i='lat'] && (t=localStorage.getItem(i))) params[i] = t 19 | if (!params[i='lon'] && (t=localStorage.getItem(i))) params[i] = t 20 | if (!params[i='z'] && (t=localStorage.getItem(i))) params[i] = t 21 | if (!params[i='layer']&& (t=localStorage.getItem(i))) params[i] = t 22 | 23 | const maps = { 24 | 'Mapnik': 25 | L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', { 26 | attribution: '© OpenStreetMap', 27 | maxZoom: 20, 28 | maxNativeZoom: 18, 29 | }), 30 | 'Graystyle': 31 | L.tileLayer('https://tiles.wmflabs.org/bw-mapnik/{z}/{x}/{y}.png', { 32 | attribution: '© OpenStreetMap', 33 | maxZoom: 20, 34 | maxNativeZoom: 18, 35 | }), 36 | 'German': 37 | L.tileLayer('https://tile.openstreetmap.de/{z}/{x}/{y}.png', { 38 | attribution: '© OpenStreetMap', 39 | maxZoom: 20, 40 | maxNativeZoom: 18, 41 | }), 42 | 'France': 43 | L.tileLayer('https://{s}.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png', { 44 | attribution: '© OpenStreetMap', 45 | maxZoom: 20, 46 | maxNativeZoom: 18, 47 | }), 48 | } 49 | 50 | var map = L.map(params.id||'map', {zoomControl: false, layers: [maps[params.layer||'Mapnik']]}).setView([params.lat||55.74, params.lon||37.62], params.z||11) 51 | 52 | L.control.layers(maps, {}, {position: 'topleft'}).addTo(map) 53 | L.control.zoom().addTo(map); 54 | 55 | if (!params.lat && document.location.protocol == 'https:') map.locate() 56 | 57 | map.on('popupopen', function(e){ if (window.make_popup != undefined) e.popup.setContent(window.make_popup(e.popup.options.data, e.popup._source)) }) 58 | 59 | map.on('moveend', function(){ 60 | var hash = '?z='+map.getZoom() 61 | var a = map.getCenter() 62 | 63 | // коррекция долготы для углов > 360 градусов 64 | var lng = a.lng % 360 65 | if (lng > 180) lng -= 180 66 | a.lng = lng 67 | 68 | // обновляем хэш 69 | if (params.update_hash !== false) 70 | { 71 | hash += '&lat='+a.lat+'&lon='+a.lng 72 | hash = '#'+(Math.round(a.lat*a.lat/10+a.lng*a.lng/10))+'/'+hash 73 | history.replaceState(null, null, hash); 74 | } 75 | 76 | // сохраняем также в localStorage 77 | localStorage.setItem('lat', a.lat) 78 | localStorage.setItem('lon', a.lng) 79 | localStorage.setItem('z', map.getZoom()) 80 | }) 81 | 82 | map.on('baselayerchange', function(layer){ 83 | localStorage.setItem('layer', layer.name) 84 | }) 85 | 86 | return map 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /coloured-addresses-ru.mapcss: -------------------------------------------------------------------------------- 1 | meta { 2 | title: "Подсветка адресации"; 3 | description: "Подсветка домов на одной улице своим цветом"; 4 | version: "0.4_2012-08-21"; 5 | author: "CupIvan"; 6 | link: "https://osm.cupivan.ru/coloured-addresses-ru.mapcss"; 7 | watch-modified: true; 8 | } 9 | 10 | area[addr:street=~/(^|.+ )А/] { fill-color: #74A0C6; } 11 | area[addr:street=~/(^|.+ )Б/] { fill-color: #D9BF05; } 12 | area[addr:street=~/(^|.+ )В/] { fill-color: #D6987A; } 13 | area[addr:street=~/(^|.+ )Г/] { fill-color: #559B63; } 14 | area[addr:street=~/(^|.+ )Д/] { fill-color: #B2D8A2; } 15 | area[addr:street=~/(^|.+ )Е/] { fill-color: #D82BD6; } 16 | area[addr:street=~/(^|.+ )Ж/] { fill-color: #4328F6; } 17 | area[addr:street=~/(^|.+ )З/] { fill-color: #43DA2C; } 18 | area[addr:street=~/(^|.+ )И/] { fill-color: #26CEF5; } 19 | area[addr:street=~/(^|.+ )К/] { fill-color: #C05821; } 20 | area[addr:street=~/(^|.+ )Л/] { fill-color: #D20C44; } 21 | area[addr:street=~/(^|.+ )М/] { fill-color: #5A5381; } 22 | area[addr:street=~/(^|.+ )Н/] { fill-color: #4C55B2; } 23 | area[addr:street=~/(^|.+ )О/] { fill-color: #D5BCAB; } 24 | area[addr:street=~/(^|.+ )П/] { fill-color: #5C1150; } 25 | area[addr:street=~/(^|.+ )Р/] { fill-color: #40BA8F; } 26 | area[addr:street=~/(^|.+ )С/] { fill-color: #38FBC5; } 27 | area[addr:street=~/(^|.+ )Т/] { fill-color: #BCA75B; } 28 | area[addr:street=~/(^|.+ )У/] { fill-color: #A40A5F; } 29 | area[addr:street=~/(^|.+ )Ф/] { fill-color: #675E00; } 30 | area[addr:street=~/(^|.+ )Х/] { fill-color: #0E8481; } 31 | area[addr:street=~/(^|.+ )Ц/] { fill-color: #D8FBB0; } 32 | area[addr:street=~/(^|.+ )Ч/] { fill-color: #61843D; } 33 | area[addr:street=~/(^|.+ )Ш/] { fill-color: #F34177; } 34 | area[addr:street=~/(^|.+ )Щ/] { fill-color: #51FC40; } 35 | area[addr:street=~/(^|.+ )Э/] { fill-color: #12EA9A; } 36 | area[addr:street=~/(^|.+ )Ю/] { fill-color: #A4CB65; } 37 | area[addr:street=~/(^|.+ )Я/] { fill-color: #B2D3F0; } 38 | 39 | /* Жуковский: Гризодубовой - Грищенко */ 40 | area[addr:street=~/(^|.+ )Гриз/] { fill-color: #D4523B; } 41 | area[addr:street=~/(^|.+ )Грищ/] { fill-color: #C1F7C2; } 42 | 43 | /* Рощино: Садовая - Садовый - Советская - Солнечная */ 44 | area[addr:street=~/(^|.+ )Сад/] { fill-color: #B31101; } 45 | area[addr:street=~/(^|.+ )Сад.+ый/] { fill-color: #1F4586; } 46 | area[addr:street=~/(^|.+ )Сов/] { fill-color: #078FEC; } 47 | area[addr:street=~/(^|.+ )Сол/] { fill-color: #8DCBC8; } 48 | 49 | /* Рощино: Короткая - Короленко */ 50 | area[addr:street=~/(^|.+ )Корот/] { fill-color: #F9E4B3; } 51 | area[addr:street=~/(^|.+ )Корол/] { fill-color: #2C7123; } 52 | 53 | /* Крымск: Славы - Синёва - Славянская */ 54 | area[addr:street=~/(^|.+ )Слав/] { fill-color: #07059B; } 55 | area[addr:street=~/(^|.+ )Син/] { fill-color: #ACDE26; } 56 | area[addr:street=~/(^|.+ )Славя/] { fill-color: #BDD2CB; } 57 | 58 | /* Крымск: Крупской - Комсомольская */ 59 | area[addr:street=~/(^|.+ )Кр/] { fill-color: #6FC44A; } 60 | area[addr:street=~/(^|.+ )Ко/] { fill-color: #7B8B68; } 61 | 62 | /* 63 | FILE ARCHIVED ON 11:20:36 Apr 25, 2013 AND RETRIEVED FROM THE 64 | INTERNET ARCHIVE ON 19:07:51 May 01, 2020. 65 | JAVASCRIPT APPENDED BY WAYBACK MACHINE, COPYRIGHT INTERNET ARCHIVE. 66 | 67 | ALL OTHER CONTENT MAY ALSO BE PROTECTED BY COPYRIGHT (17 U.S.C. 68 | SECTION 108(a)(3)). 69 | */ 70 | /* 71 | playback timings (ms): 72 | PetaboxLoader3.datanode: 168.331 (4) 73 | exclusion.robots: 0.211 74 | exclusion.robots.policy: 0.197 75 | captures_list: 309.789 76 | esindex: 0.009 77 | LoadShardBlock: 197.521 (3) 78 | PetaboxLoader3.resolve: 199.26 (2) 79 | RedisCDXSource: 93.253 80 | CDXLines.iter: 15.107 (3) 81 | load_resource: 191.389 82 | */ -------------------------------------------------------------------------------- /helipad/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Вертолётные площадки на карте OSM 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 24 | 25 | 26 | 27 | 28 |
29 |
30 | 31 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /levels/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Этажность зданий на карте OSM 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 24 | 25 | 26 | 27 | 28 |
29 |
30 | 31 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /hazard/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | OSM карта опасных мест 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 24 | 25 | 26 | 27 | 28 |
29 |
30 | 31 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /routes/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Карта маршрутов общественного транспорта 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 21 | 22 | 23 | 24 | 25 |
26 |
27 |
28 |
29 |
30 | 31 | 32 | 33 | 34 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | -------------------------------------------------------------------------------- /boundary/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Границы районов на карте OSM 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 23 | 24 | 25 | 26 | 27 |
28 |
29 | 30 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CupIvan - мой вклад в OSM 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 22 | 23 |
24 |

Мой небольшой вклад в OSM: карты и валидаторы

25 | 26 |
27 |

Валидатор подъездов

28 | 29 |
На данной карте можно посмотреть в каких подъездах не проставлены
номера квартир, а также этажность и адрес на здании.
30 |
31 | 32 |
33 |

Этажность зданий

34 | 35 |
Раскраска зданий по количеству этажей.
Удобно смотреть где ещё не указаны этажи.
36 |
37 | 38 |
39 |

Архитектурные стили

40 | 41 |
Раскраска зданий по направлениям в архитектуре.
Быстрый переход в JOSM для редактирования.
42 |
43 | 44 |
45 |

Сравнение с картой Яндекса

46 | 47 |
Двойная карта OSM / Яндекс. Поиск населённых пунктов
и координаты городов в формате Википедии.
48 |
49 | 50 |
51 |

Карта садовых участков

52 | 53 |
На этой карте удобно смотреть где нужно исправить название:
в поле name не должно быть всяких СНТ, ДНП и др.
54 |
55 | 56 |
57 |

Карта торговых центров

58 | 59 |
На карте обозначены крупные торговые центры. Красным помечены мелкие супермаркеты, у которых нужно поменять теги. 60 |
61 | 62 |
63 |

Все штабы Алексея Навального

64 | 65 |
Название, время работы, ссылки на группу вКонтакте и телефоны.
Вся информация берётся online из базы OSM.
66 |
67 | 68 |
69 |

Карта вертолётных площадок

70 | 71 |
На карте обозначены вертолётные площадки.
Красным помечены площадки на крышах зданий.
72 |
73 | 74 |
75 |

Карта опасных мест

76 | 77 |
На карте обозначены опасные места: от опасных поворотов на дороге до скотомогильников сибирской язвы. 78 |
79 | 80 |
81 |

Пункты выдачи заказов

82 | 83 |
Пункты выдачи заказов интернет-магазинов
Лабиринт, Wildberries, Озон, Онлайн Трейд и др.
84 |
85 | 86 |
87 |

Фитнес и спортивные центры

88 | 89 |
Места где можно позаниматься фитнесом, спортом, плаванием.
В зале или на уличных тренажёрах.
90 |
91 | 92 |
93 |

Границы областей России

94 | 95 |
Визуальное отображение границ России на карте OSM
Возможность простой генерации GeoJSON.
96 |
97 | 98 |
99 |

Отделения Почты России

100 | 101 |
Отделения Почты России с дополнительной информацией на карте
и в виде таблицы для быстрого поиска невалидных данных.
102 |
103 |
104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /geocoder/index.php: -------------------------------------------------------------------------------- 1 | ;); 62 | out body;"; 63 | 64 | $json = file_get_contents('https://osm.cupivan.ru/overpass/?data='.urlencode($query)); 65 | $a = json_decode($json, true); 66 | 67 | if (empty($a['elements'])) die('{error: "empty result"}'); 68 | 69 | 70 | // перебираем все элементы и ищем центр полигона 71 | $nodes = []; $ways = []; 72 | foreach ($a['elements'] as $a) 73 | { 74 | if ($a['type'] == 'node') $nodes[$a['id']] = $a; 75 | if ($a['type'] == 'way') $ways[$a['id']] = array_map(function($nodeId) use($nodes) { return $nodes[$nodeId]; }, $a['nodes']); 76 | if (@$a['tags']['addr:street'] == $street) 77 | { 78 | $center = get_center($a, $flat); 79 | if (@$a['tags']['addr:housenumber'] == $house) 80 | { 81 | echo json_encode($center); 82 | exit; 83 | } 84 | } 85 | } 86 | 87 | // если попали сюда - значит номер дома не найден 88 | $center['type'] = 'street'; 89 | echo json_encode($center); 90 | exit; 91 | 92 | 93 | /** центральная точка полигона или координаты входа */ 94 | function get_center($a, $flat) 95 | { 96 | global $ways; 97 | 98 | $center = ['lat'=>0, 'lon'=>0, 'type'=>'building', 'id'=>$a['type'][0].$a['id']]; 99 | 100 | if ($a['type'] == 'node') return array_intersect_key($a, $center); 101 | 102 | $w = []; 103 | // список веев для обработки 104 | if ($a['type'] == 'way') $w[] = $a['id']; 105 | if ($a['type'] == 'relation') 106 | foreach ($a['members'] as $_) 107 | if ($_['type'] == 'way' && $_['role'] == 'outer') $w[] = $_['ref']; 108 | 109 | $n = 0; 110 | foreach ($w as $wayId) 111 | foreach ($ways[$wayId] as $node) 112 | { 113 | // нашли подъезд для этой квартиры 114 | if (!empty($node['tags']['addr:flats'])) 115 | { 116 | $x = explode('-', $node['tags']['addr:flats']); 117 | if ($flat >= $x[0] && $flat <= $x[1]) 118 | return ['type'=>'entrance'] + array_intersect_key($node, $center); 119 | } 120 | $center['lat'] += $node['lat']; 121 | $center['lon'] += $node['lon']; 122 | $n++; 123 | } 124 | $center['lat'] /= $n; 125 | $center['lon'] /= $n; 126 | 127 | return $center; 128 | } 129 | 130 | 131 | /** bbox города для поиска адреса */ 132 | function get_city_bounds($city) 133 | { 134 | $lat_min = $lot_min = $lat_max = $lon_max = NULL; 135 | if ($city == 'Нижний Новгород') 136 | return '(56.14478445312653,43.73313903808594,56.47235255844717,44.22271728515624)'; 137 | return "(0,0,0,0)"; 138 | return "($lat_min,$lon_min,$lat_max,$lon_max)"; 139 | } 140 | -------------------------------------------------------------------------------- /outpost/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Пункты выдачи заказов на карте OSM 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 24 | 25 | 26 | 27 | 28 |
29 |
30 | 31 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | -------------------------------------------------------------------------------- /i/lib.js: -------------------------------------------------------------------------------- 1 | // dollar.js 3.5 2 | window.$$=function(a,b,_){var i,j,k,h,l=document,m,e,n,o;if(typeof(a)!='string'){if(a)l=a;a=b;b=_};l=[l];a=a.split(' ');h=a.length;for(i=0;i=0)n[0]=n[2],n[2]='input';if(n[1]=='#')e=[l[j].getElementById(n[2])];else if(n[1]=='.')try{e=l[j].getElementsByClassName(n[2])}catch(e){e=_getElementsByClassName(l[j],n[2])}else try{e=l[j].getElementsByTagName(n[2])}catch(e){};o=e.length;if(i==h-1){var p=[];for(k=0;k12)m-=12,Y++;t.setTime(0);t.setUTCHours(H);t.setUTCMinutes(i);t.setUTCSeconds(s);t.setUTCFullYear(Y);t.setUTCDate(d);t.setUTCMonth(m-1);return t.getTime()?Math.round(t.getTime()/1000):0} 9 | -------------------------------------------------------------------------------- /place/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Карта населённых пунктов 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 23 | 24 | 25 | 26 | 27 |
28 |
29 | 30 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | -------------------------------------------------------------------------------- /data_center/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Датацентры и ЦОД на карте OSM 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 23 | 24 | 25 | 26 | 27 |
28 |
29 | 30 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | -------------------------------------------------------------------------------- /education/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Школы на карте OSM 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 23 | 24 | 25 | 26 | 27 |
28 |
29 | 30 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | -------------------------------------------------------------------------------- /address/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Адресный поиск по OSM с точностью до этажа 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 26 | 27 | 28 | 29 | 30 |

Поиск квартиры с точностью до этажа по базе OpenStreetMap

31 | 32 |
33 | 34 |
Поисковый запрос:
35 | 36 | 37 | 38 | 39 |
40 | 41 |
42 | 43 |
44 | 45 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | -------------------------------------------------------------------------------- /mall/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Валидатор торговых центров на карте OSM 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 24 | 25 | 26 | 27 | 28 |
29 |
30 | 31 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | -------------------------------------------------------------------------------- /fitness/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Спорт и фитнес на карте OSM 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 25 | 26 | 27 | 28 | 29 |
30 |
31 | 32 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | -------------------------------------------------------------------------------- /arch/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Архитектурные стили зданий на карте OSM 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 24 | 25 | 26 | 27 | 28 |
29 |
30 | 31 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | -------------------------------------------------------------------------------- /boundary/osm.php: -------------------------------------------------------------------------------- 1 | 'MultiPolygon', 'coordinates'=>[]]; 9 | $nodes = []; 10 | $ways = []; 11 | $nodeFrom = []; // хэш: точка => начало линии 12 | $nodeTo = []; // хэш: точка => конец линии 13 | 14 | foreach ($a['elements'] as $a) 15 | { 16 | if ($a['type'] == 'node') $nodes[$a['id']] = [$a['lon'], $a['lat']]; 17 | if ($a['type'] == 'way') 18 | { 19 | $ways[$a['id']] = $a['nodes']; 20 | $nodeFrom[$a['nodes'][0]][] = $a['id']; 21 | $nodeTo[$a['nodes'][count($a['nodes'])-1]][] = $a['id']; 22 | } 23 | 24 | if ($a['id'] == $id) 25 | { 26 | $geo['id'] = $a['type'][0].$id; 27 | $geo['properties'] = $a['tags']; 28 | $refs = []; 29 | // внешние границы 30 | foreach ($a['members'] as $_) 31 | if ($_['type'] == 'way' && $_['role'] == 'outer') 32 | $refs[] = $_['ref']; 33 | // добавляем полигоны-дырки 34 | foreach ($a['members'] as $_) 35 | if ($_['type'] == 'way' && $_['role'] == 'inner') 36 | $refs[] = $_['ref']; 37 | 38 | // сортировка линий 39 | $sort_refs = function($refs) use($ways, $nodeFrom, $nodeTo) 40 | { 41 | $sorted = []; $ck = -1; 42 | 43 | while (count($refs)) 44 | { 45 | $wayId = array_pop($refs); 46 | $sorted[++$ck] = [$wayId]; 47 | $node = $ways[$wayId][0]; 48 | 49 | // одна замкнутая линия? 50 | if ($node == $ways[$wayId][count($ways[$wayId])-1]) 51 | continue; 52 | 53 | while (count($refs)) 54 | { 55 | // ищем соседнюю 56 | foreach ($refs as $k => $id) 57 | { 58 | $last = count($ways[$id]) - 1; 59 | if ($ways[$id][0] == $node) $node = $ways[$id][$last]; 60 | else 61 | if ($ways[$id][$last] == $node) $node = $ways[$id][0]; 62 | else 63 | continue; 64 | $sorted[$ck][] = $id; 65 | unset($refs[$k]); 66 | continue 2; 67 | } 68 | 69 | // сначала проверим, не зациклились ли мы 70 | if ($node == $ways[$wayId][0]) 71 | { 72 | print_r($ways[$wayId]); 73 | exit; 74 | } 75 | 76 | // если мы здесь, то значит полигон замкнулся, 77 | // поэтому начинаем всё заново для следующего 78 | break; 79 | } 80 | } 81 | return $sorted; 82 | }; 83 | 84 | $lastNode = NULL; 85 | $refs = $sort_refs($refs); 86 | $geo['coordinates'] = osm_fill_coords($refs, $ways, $nodes, $is_simple); 87 | break; 88 | } 89 | } 90 | return $geo; 91 | } 92 | 93 | /** заполнение координат */ 94 | function osm_fill_coords($a, $ways, $nodes, $is_simple = true) 95 | { 96 | foreach ($a as $i => $_) 97 | $a[$i] = [osm_fill_way_coords($_, $ways, $nodes, $is_simple)]; 98 | return $a; 99 | } 100 | 101 | /** заполнение координат для массива линий */ 102 | function osm_fill_way_coords($a, $ways, $nodes, $is_simple = true) 103 | { 104 | $res = []; $lastNode = NULL; 105 | static $cache = []; 106 | for ($i=0; $i 1) continue; 194 | if (is_null($s_min) || $s < $s_min) { $s_min = $s; $s_i = $i; $s_n++; } 195 | } 196 | if (!$s_n) break; 197 | array_splice($a, $s_i, 1); // удаляем эту точку 198 | if (count($a) < 10) break; 199 | } 200 | 201 | return $a; 202 | } 203 | 204 | /** площадь треугольника по координатам x2 */ 205 | // https://m.fxyz.ru/4/279/280/302/904/ 206 | function osm_calc_square($x, $y, $z) 207 | { 208 | $x1 = $x[0]; $y1 = $x[1]; 209 | $x2 = $y[0]; $y2 = $y[1]; 210 | $x3 = $z[0]; $y3 = $z[1]; 211 | $s = ($x1-$x3)*($y2-$y3) - ($y1-$y3)*($x2-$x3); 212 | return abs($s); 213 | } 214 | -------------------------------------------------------------------------------- /navalny/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Все штабы Алексея Навального на online карте 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 23 | 24 | 25 | 26 | 27 |
28 |
29 | 30 | 31 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | -------------------------------------------------------------------------------- /i/osm.js: -------------------------------------------------------------------------------- 1 | var osm = { 2 | search_region: 60, // коэффициент округления координат (чем меньше - тем больший регион скачивается) 3 | debug: false, 4 | 5 | /** поиск объектов в OSM базе */ 6 | search: function(filter, handler){ 7 | var bounds = '', _bounds = [] 8 | if (filter.bounds) 9 | { 10 | filter.bounds, k = osm.search_region 11 | bounds = '' 12 | + '(' + (_bounds[0]=Math.floor(filter.bounds[1]*k)/k) 13 | + ',' + (_bounds[1]=Math.floor(filter.bounds[0]*k)/k) 14 | + ',' + (_bounds[2]=Math.ceil( filter.bounds[3]*k)/k) 15 | + ',' + (_bounds[3]=Math.ceil( filter.bounds[2]*k)/k) 16 | + ')'; 17 | delete filter.bounds 18 | } 19 | 20 | var type = {} 21 | if (filter[x='node']) { type[x]=1; delete filter[x] } 22 | if (filter[x='way']) { type[x]=1; delete filter[x] } 23 | if (filter[x='relation']) { type[x]=1; delete filter[x] } 24 | if (!type.node && !type.way && !type.relation) type = {nwr:1} 25 | 26 | var i, j, f='' 27 | for (i in filter) 28 | { 29 | if (i == 'id') { f = '(id:'+filter[i]+')'; break; } 30 | f += '["'+i+'"' 31 | if (filter[i] !== true) 32 | f += filter[i] ? '="'+filter[i]+'"' : '' 33 | f += ']' 34 | } 35 | 36 | var query = '' 37 | +'[out:json];(' 38 | +(type.node ?('node'+f+bounds+';'):'') 39 | +(type.way ?('way' +f+bounds+';'):'') 40 | +(type.relation?('rel' +f+bounds+';'):'') 41 | +(type.nwr ?('nwr' +f+bounds+';'):'') 42 | +');(._;>;);out body;'; 43 | 44 | var _bounds_coords = [] 45 | if (osm.debug) 46 | { 47 | console.log('BOUNDS: '+bounds) 48 | _bounds_coords.push([_bounds[1], _bounds[0]]) 49 | _bounds_coords.push([_bounds[1], _bounds[2]]) 50 | _bounds_coords.push([_bounds[3], _bounds[2]]) 51 | _bounds_coords.push([_bounds[3], _bounds[0]]) 52 | } 53 | 54 | fetch('/overpass/?data='+encodeURIComponent(query) 55 | +'&domain='+encodeURIComponent(window.location.hostname)).then(_=>_.json()).then(x=>{ 56 | var i, j, a, data = [] 57 | var nodes = {}, ways = {} 58 | 59 | if (osm.debug) 60 | data.push({type: 'bounds', id: JSON.stringify(_bounds_coords), coords: _bounds_coords}) 61 | 62 | if (!x.elements) return handler(data) 63 | 64 | for (i = 0; i < x.elements.length; i++) 65 | { 66 | a = x.elements[i] 67 | a.osm_id = a.type[0] + a.id 68 | if (a.tags) 69 | for (j in filter) 70 | if (j == 'id') 71 | { 72 | if (a.id == filter[j]) { data.push(a); break } 73 | } 74 | else 75 | if (a.tags[j]) 76 | if (filter[j] === true || (filter[j] && a.tags[j] == filter[j])) 77 | { 78 | data.push(a) 79 | break 80 | } 81 | 82 | if (a.type == 'node') nodes[a.id] = a; else 83 | if (a.type == 'way') ways [a.id] = a 84 | } 85 | 86 | var _coords = function(a){ 87 | var i, id, res = [] 88 | for (i=0; i 0) 177 | { 178 | data[i].center[0] /= x.length 179 | data[i].center[1] /= x.length 180 | } 181 | 182 | data[i].geo = _coords(data[i].nodes) 183 | data[i].nodes = x 184 | 185 | if (a.type == 'way') 186 | data[i].geoJSON.push(data[i].geo) 187 | } 188 | if (a.type == 'node') 189 | data[i].center = [a.lat, a.lon] 190 | 191 | if (a.type == 'bounds') 192 | data[i].geoJSON = [a.coords] 193 | 194 | if (a.type == 'node') 195 | data[i].geoJSON = {type: 'Point', coordinates: [a.lon, a.lat]} 196 | else 197 | data[i].geoJSON = {type: 'MultiPolygon', coordinates: [data[i].geoJSON]} 198 | } 199 | 200 | handler(data) 201 | }) 202 | }, 203 | 204 | /** ссылка на объект */ 205 | link: function(a) 206 | { 207 | const {type, id} = osm.parseId(a) 208 | return 'https://www.openstreetmap.org/'+type+'/'+id 209 | }, 210 | /** ссылка на объект в редакторе level0 */ 211 | link_level0: function(a) 212 | { 213 | const {type, id} = osm.parseId(a) 214 | return 'http://level0.osmz.ru/?url='+type+'/'+id 215 | }, 216 | /** тип и id объекта */ 217 | parseId: function(a) 218 | { 219 | return {type: osm.getType(a), id: (''+(typeof(a)=='object'?a.id:a)).replace(/\D/g, '')} 220 | }, 221 | /** тип объекта */ 222 | getType: function(a) 223 | { 224 | if (!a) return null 225 | 226 | if (a.type) return a.type 227 | 228 | const id = '' + (typeof(a) == 'object' ? a.id : a) 229 | 230 | var type = 'node' 231 | 232 | if (id[0] == 'n') type = 'node' 233 | if (id[0] == 'w') type = 'way' 234 | if (id[0] == 'r') type = 'relation' 235 | 236 | return type 237 | }, 238 | 239 | /** ссылки на редактирование */ 240 | editLinks: function(a, params) 241 | { 242 | const res = [] 243 | 244 | let url 245 | if (url = osm.link(a)) 246 | res.push('OSM') 247 | if (josm.running) 248 | { 249 | res.push('JOSM') 250 | if (url = josm.link(a)) 251 | res.push('Загрузить в JOSM') 252 | if (params) 253 | { 254 | if (params.onedit) 255 | this.onedit = params.onedit 256 | delete params.onedit 257 | if (url = josm.link_edit(a, params)) 258 | res.push(' (Правка)') 259 | } 260 | } 261 | if (url = osm.link_level0(a)) 262 | res.push('level0') 263 | return res.length ? '
'+res.join('   |   ') : '' 264 | }, 265 | onEdit: function() 266 | { 267 | this.onedit() 268 | }, 269 | 270 | } 271 | -------------------------------------------------------------------------------- /allotments/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Садовые участки на карте OSM 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 34 | 35 | 36 | 37 | 38 |
39 | 40 | 41 | 42 | 45 |
43 | 44 |
46 | 47 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | -------------------------------------------------------------------------------- /latlon/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | OSM: определитель координат и обратный геокодер 5 | 6 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 |
24 |

Параметры карты OpenLayers:

25 |

Масштаб:

26 |

Центр:

27 |

Координаты:

28 |

Мышь:

29 |

Маркер:

30 |

Геокодер Nominatim:

31 |

32 |

Геокодер Яндекс:

33 |

34 |

Геокодер openstreetmap.by:

35 |

36 |
37 | 38 | 39 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | -------------------------------------------------------------------------------- /OSMvsNarod/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Сравнение карты OSM с народной картой Яндекса 5 | 6 | 26 | 27 | 28 | 29 | 30 | 222 | 223 | 224 | 225 | 226 | 237 | 238 | 239 | 240 | 241 |
242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | -------------------------------------------------------------------------------- /entrance/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Карта подъездов и номера квартир OSM 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 24 | 25 | 26 | 27 | 28 |
29 |
30 | 31 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | -------------------------------------------------------------------------------- /m/mysql.class.php: -------------------------------------------------------------------------------- 1 | $name)) 80 | $GLOBALS['prepare_skip'] = true; 81 | } 82 | 83 | if ($GLOBALS['prepare_skip']) return ''; 84 | 85 | switch($x['type']) 86 | { 87 | case 'p': return $eq.$value; 88 | case 'i': return $eq.(int)$value; 89 | case 'f': return $eq.(float)$value; 90 | case 's': 91 | case 'S': 92 | // if ($value === '') $GLOBALS['prepare_skip'] = true; 93 | if ($x['type'] == 'S') { $value = "%$value%"; $eq = str_replace('=', 'LIKE', $eq); } 94 | return $eq.self::prepareString($value); 95 | case 'd': return date('"Y-m-d"', is_numeric($value) && $value > 3000 ? $value : strtotime($value)); 96 | case 'dt': return date('"Y-m-d H:i:s"', is_numeric($value) && $value > 3000 ? $value : strtotime($value)); 97 | case 'ai': case 'as': 98 | if (empty($value)) { $GLOBALS['prepare_skip'] = true; return ''; } 99 | $a = array(); 100 | if (is_scalar($value)) $value = explode(',', $value); 101 | foreach ($value as $v) 102 | if ($x['type'] == 'ai') 103 | { 104 | if (is_numeric($v)) $a[] = $v; 105 | } 106 | else 107 | if ($x['type'] == 'as') 108 | { 109 | $a[] = self::prepareString($v); 110 | } 111 | return str_replace('=', 'IN', $eq).implode(',', $a); 112 | case 'kv': case 'kvf': 113 | $st = ''; $glue = ($x['type'] == 'kvf') ? ' AND ' : ', '; 114 | if ($value instanceOf Model) $value = $value->getData(); 115 | else 116 | if ($data instanceOf Model) $value = $data->getData(); 117 | 118 | if (is_array($value)) 119 | foreach ($value as $k => $v) 120 | { 121 | $st .= ($st?$glue:''); 122 | if (is_array($v)) // задан диапазон значений 123 | { 124 | if (count($v) == 2 && is_numeric($v[0]) && is_numeric($v[1])) 125 | $st .= "`$k` >= ".self::prepareString($v[0])." AND `$k` < ".self::prepareString($v[1]); 126 | else 127 | $st .= self::prepare("`$k` IN(?as)", $v); 128 | } 129 | else 130 | { 131 | $st .= strpos($v, '%') !== false && $GLOBALS['prepare_is_select'] ? "`$k` LIKE " : "`$k` = "; 132 | if (is_bool($v)) $v = $v ? 1 : 0; 133 | if (strpos($v, '=') === 0) $st .= substr($v, 1); // COMMENT: например '= NOW()' 134 | else 135 | // if (is_numeric($v)) $st .= $v; 136 | // else 137 | if (is_null($v)) $st .= 'NULL'; 138 | else $st .= self::prepareString($v); 139 | } 140 | } 141 | if (!$st) $st = 1; 142 | return $st; 143 | default: 144 | return ''; 145 | } 146 | } 147 | static function prepareString($st) 148 | { 149 | return '"'.addslashes($st).'"'; 150 | } 151 | static function prepare($sql, $data='_stored', $d2='_stored', $d3=NULL, $d4=NULL, $d5=NULL, $d6=NULL) 152 | { 153 | $sql = "\n$sql "; 154 | if ($data === '_stored') $data = self::$data; 155 | 156 | if ($d2 !== '_stored') 157 | $data = array($data, $d2, $d3, $d4, $d5, $d6); 158 | 159 | self::$data = $data; 160 | 161 | // FIXME: убрать глобальные переменные 162 | $GLOBALS['prepare_is_select'] = stripos(" $sql", 'SELECT'); 163 | $GLOBALS['prepare_data'] = $data; 164 | $GLOBALS['prepare_index'] = 0; 165 | $GLOBALS['prepare_skip'] = false; 166 | 167 | $sql = preg_replace_callback('#((?[a-z0-9_]+)=)?\?(?s|S|i|f|dt|d|p|ai|as|kvf|kv):?(?[a-z0-9_]*)(?=?)#i', 168 | 'mysql::prepare_callback', $sql); 169 | if (@$GLOBALS['prepare_skip']) $sql = ''; 170 | 171 | unset($GLOBALS['prepare_is_select']); 172 | unset($GLOBALS['prepare_data']); 173 | unset($GLOBALS['prepare_index']); 174 | unset($GLOBALS['prepare_skip']); 175 | 176 | return $sql; 177 | } 178 | static function query($sql) 179 | { 180 | $t = microtime(true); 181 | $sql_dump = mb_strlen($sql) > 5*1024 ? mb_substr($sql, 0, 5*1024 - 3).'...' : $sql; 182 | self::connect(); 183 | $res = @mysqli_query(self::$connection, $sql); 184 | $errno = mysqli_errno(self::$connection); 185 | if ($errno) 186 | { 187 | array_push(self::$errors, self::$error = $errno."\n".mysqli_error(self::$connection)."\n".$sql_dump); 188 | //log::mysql('error', [$sql, self::$error]); 189 | } 190 | array_push(self::$history, $sql_dump.' -- '.$t.' + '.round(microtime(true)-$t, 4)); 191 | return $errno ? false : $res; 192 | } 193 | static function fetch($res) 194 | { 195 | return mysqli_fetch_assoc($res); 196 | } 197 | static function getList($sql) 198 | { 199 | $is_sql_count = false; 200 | if (strpos($sql, 'SELECT') !== false && strpos($sql, 'LIMIT') !== false) 201 | { 202 | $sql = preg_replace('/SELECT /', 'SELECT SQL_CALC_FOUND_ROWS ', $sql, 1); 203 | $is_sql_count = true; 204 | } 205 | 206 | $res = self::query($sql); 207 | if (!$res) return array(); 208 | $ret = array(); 209 | while ($row = mysqli_fetch_assoc($res)) 210 | $ret[] = $row; 211 | self::$count = $is_sql_count ? (int)self::getValue('SELECT FOUND_ROWS()') : count($ret); 212 | return $ret; 213 | } 214 | static function getItem($sql) 215 | { 216 | if (self::$cache && isset($cache_sql[$sql])) return $cache_sql[$sql]; 217 | $res = self::query($sql); 218 | if ($res === false) return array(); 219 | $res = mysqli_fetch_assoc($res); if (is_null($res)) $res = array(); 220 | if (self::$cache) $cache_sql[$sql] = $res; 221 | return $res; 222 | } 223 | static function getValue($sql) 224 | { 225 | if (self::$cache && isset($cache_sql[$sql])) return $cache_sql[$sql]; 226 | $res = self::query($sql); 227 | if (!is_object($res)) return NULL; 228 | $res = mysqli_fetch_array($res); 229 | if (empty($res)) return NULL; 230 | $res = $res[0]; 231 | if (self::$cache) $cache_sql[$sql] = $res; 232 | return $res; 233 | } 234 | static function getValues($sql, $field = null) 235 | { 236 | $res = self::getList($sql); 237 | if (is_null($field)) $field = array_keys($res[0])[0]; 238 | foreach ($res as $i => $a) 239 | $res[$i] = $a[$field]; 240 | return $res; 241 | } 242 | static function getListCount() 243 | { 244 | return self::$count; 245 | } 246 | static function get($table, $id, $fields = NULL) 247 | { 248 | if (empty($fields)) $fields = '*'; 249 | $p = is_numeric($id) ? '`id` = ?i' : '?p'; 250 | $sql = mysql::prepare("SELECT $fields FROM `$table` WHERE $p LIMIT 1", $id); 251 | return mysql::getItem($sql); 252 | } 253 | static function search($table, $a, $fields = NULL, $orderBy = NULL) 254 | { 255 | if ( empty($fields)) $fields = '*'; 256 | if (!empty($orderBy)) $orderBy = "ORDER BY $orderBy"; 257 | $sql = mysql::prepare("SELECT $fields FROM `$table` WHERE ?kvf $orderBy", $a); 258 | return mysql::getList($sql); 259 | } 260 | static function insert($table, $a) 261 | { 262 | $sql = self::prepare("INSERT INTO `$table` SET ?kv", $a); 263 | $res = mysql::query($sql); 264 | return mysqli_errno(self::$connection) ? false : mysql::getLastInsertId(); 265 | } 266 | static function insert_values($table, $a) 267 | { 268 | if (empty($a)) return false; 269 | $values = []; 270 | foreach ($a as $a) $values[] = mysql::prepare('(?as)', $a); 271 | $sql = self::prepare("INSERT INTO `$table` VALUES ".implode(',', $values)); 272 | $res = mysql::query($sql); 273 | return mysqli_errno(self::$connection) ? false : mysql::getLastInsertId(); 274 | } 275 | static function getLastInsertId() { return mysqli_insert_id(self::$connection); } 276 | static function insert_duplicate($table, $a) 277 | { 278 | $sql = self::prepare("INSERT INTO `$table` SET ?kv ON DUPLICATE KEY UPDATE ?kv", $a, $a); 279 | $res = mysql::query($sql); 280 | return mysqli_errno(self::$connection) ? false : self::getRowsCount(); 281 | } 282 | static function replace($table, $a) 283 | { 284 | $sql = self::prepare("REPLACE INTO `$table` SET ?kv", $a); 285 | $res = mysql::query($sql); 286 | return mysqli_errno(self::$connection) ? false : true; 287 | } 288 | static function update($table, $a, $where = NULL) 289 | { 290 | // передали id записи, которую нужно изменить 291 | if (is_numeric($where)) 292 | { 293 | $a['id'] = $where; 294 | $where = NULL; 295 | } 296 | // передали условие выборки записей на изменение 297 | if (is_null($where)) 298 | { 299 | if (empty($a['id'])) return NULL; 300 | $where = self::prepare("`id` = ?i", $a['id']); 301 | unset($a['id']); 302 | } 303 | // $where в качестве хеша 304 | if (is_array($where)) 305 | { 306 | $where = mysql::prepare('?kvf', $where); 307 | } 308 | if (empty($a)) return 0; 309 | $sql = self::prepare("UPDATE `$table` SET ?kv WHERE ?p", $a, $where); 310 | $res = self::query($sql); 311 | if ($res === false) return false; 312 | return self::getRowsCount(); 313 | } 314 | static function delete($table, $sql) 315 | { 316 | if (empty($sql)) return false; 317 | if (is_array($sql)) $sql = mysql::prepare('?kvf', $sql); 318 | if (is_numeric($sql)) $sql = mysql::prepare("`id` = ?i", $sql); // передали число 319 | $sql = self::prepare("DELETE FROM `$table` WHERE ?p", $sql); 320 | return self::query($sql); 321 | } 322 | /** кол-во изменённых рядов */ 323 | static function getRowsCount() 324 | { 325 | return mysqli_affected_rows(self::$connection); 326 | } 327 | static function getLastError() 328 | { 329 | $errno = mysqli_errno(self::$connection); 330 | return $errno ? array('errno' => $errno) : array(); 331 | } 332 | static function setDefault($value, &$a, $fields='') 333 | { 334 | $x = $a; 335 | if (!empty($fields)) $x = array_intersect_key($a, array_fill_keys(explode(',', $fields), 1)); 336 | foreach ($x as $k => $v) 337 | { 338 | if (empty($v)) $a[$k] = $value; 339 | } 340 | } 341 | } 342 | -------------------------------------------------------------------------------- /russian_post/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Отделения Почты России на карте OSM 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 41 | 53 | 54 | 55 | 58 |
56 | 57 |
59 | 60 | 61 | 446 | 447 | 469 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | --------------------------------------------------------------------------------