├── 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 |
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 |
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 |
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 |
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 |
25 |
Масштаб:
26 |
Центр:
27 |
Координаты:
28 |
Мышь:
29 |
Маркер:
30 |
31 |
32 |
33 |
34 |
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 |
59 |
60 |
61 |
446 |
447 |
469 |
484 |
485 |
486 |
487 |
488 |
489 |
490 |
491 |
492 |
--------------------------------------------------------------------------------