mirror of
https://github.com/FoggedLens/iD.git
synced 2026-02-13 01:02:58 +00:00
Merge branch 'master' into discard-tags
Inline discardTags Conflicts: index.html
This commit is contained in:
7
Makefile
7
Makefile
@@ -30,6 +30,9 @@ all: \
|
||||
js/id/connection.js \
|
||||
js/id/oauth.js \
|
||||
js/id/services/*.js \
|
||||
data/data.js \
|
||||
data/imagery.js \
|
||||
data/deprecated.js \
|
||||
js/id/util.js \
|
||||
js/id/geo.js \
|
||||
js/id/geo/*.js \
|
||||
@@ -50,9 +53,7 @@ all: \
|
||||
js/id/validate.js \
|
||||
js/id/end.js \
|
||||
locale/locale.js \
|
||||
locale/en.js \
|
||||
data/data.js \
|
||||
data/deprecated.js
|
||||
locale/en.js
|
||||
|
||||
iD.js: Makefile
|
||||
@rm -f $@
|
||||
|
||||
18
css/app.css
18
css/app.css
@@ -93,7 +93,6 @@ a:hover {
|
||||
color:#597be7;
|
||||
}
|
||||
|
||||
|
||||
textarea,
|
||||
input[type=text] {
|
||||
background-color: white;
|
||||
@@ -186,6 +185,8 @@ ul.toggle-list li a {
|
||||
border-top: 1px solid white;
|
||||
display:block;
|
||||
border-top: 1px solid rgba(0, 0, 0, .5);
|
||||
text-wrap:no-wrap;
|
||||
overflow:hidden;
|
||||
}
|
||||
ul.toggle-list li a:hover { background-color: #ececec;}
|
||||
|
||||
@@ -687,6 +688,10 @@ a.selected:hover .toggle.icon { background-position: -40px -180px;}
|
||||
top:190px;
|
||||
}
|
||||
|
||||
.layerswitcher-control .map-overlay {
|
||||
width:250px;
|
||||
}
|
||||
|
||||
.nudge-container {
|
||||
margin-top: 10px;
|
||||
}
|
||||
@@ -1393,6 +1398,13 @@ a.success-action {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.lasso-box {
|
||||
fill-opacity:0.2;
|
||||
fill: #bde5aa;
|
||||
stroke: #000;
|
||||
stroke-width: 1;
|
||||
}
|
||||
|
||||
/* Media Queries
|
||||
------------------------------------------------------- */
|
||||
|
||||
@@ -1403,10 +1415,6 @@ a.success-action {
|
||||
.save .label, .apply .label, .cancel .label { display: block;}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
div.combobox {
|
||||
width:155px;
|
||||
z-index: 9999;
|
||||
|
||||
602
data/imagery.js
Normal file
602
data/imagery.js
Normal file
@@ -0,0 +1,602 @@
|
||||
iD.data.imagery = [
|
||||
{
|
||||
"name": "Bing aerial imagery",
|
||||
"template": "http://ecn.t0.tiles.virtualearth.net/tiles/a{u}.jpeg?g=587&mkt=en-gb&n=z",
|
||||
"description": "Satellite imagery.",
|
||||
"scaleExtent": [
|
||||
0,
|
||||
20
|
||||
],
|
||||
"default": "yes",
|
||||
"sourcetag": "Bing",
|
||||
"logo": "bing_maps.png",
|
||||
"logo_url": "http://www.bing.com/maps",
|
||||
"terms_url": "http://opengeodata.org/microsoft-imagery-details"
|
||||
},
|
||||
{
|
||||
"name": "MapBox Satellite",
|
||||
"template": "http://{t}.tiles.mapbox.com/v3/openstreetmap.map-4wvf9l0l/{z}/{x}/{y}.png",
|
||||
"description": "Satellite and aerial imagery",
|
||||
"scaleExtent": [
|
||||
0,
|
||||
16
|
||||
],
|
||||
"subdomains": [
|
||||
"a",
|
||||
"b",
|
||||
"c"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "OpenStreetMap",
|
||||
"template": "http://{t}.tile.openstreetmap.org/{z}/{x}/{y}.png",
|
||||
"description": "The default OpenStreetMap layer.",
|
||||
"scaleExtent": [
|
||||
0,
|
||||
18
|
||||
],
|
||||
"subdomains": [
|
||||
"a",
|
||||
"b",
|
||||
"c"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": " TIGER 2012 Roads Overlay",
|
||||
"template": "http://{t}.tile.openstreetmap.us/tiger2012_roads_expanded/{z}/{x}/{y}.png",
|
||||
"subdomains": [
|
||||
"a",
|
||||
"b",
|
||||
"c"
|
||||
],
|
||||
"extent": [
|
||||
[
|
||||
-124.81,
|
||||
24.055
|
||||
],
|
||||
[
|
||||
-66.865,
|
||||
49.386
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": " TIGER 2012 Roads Overlay",
|
||||
"template": "http://{t}.tile.openstreetmap.us/tiger2012_roads_expanded/{z}/{x}/{y}.png",
|
||||
"subdomains": [
|
||||
"a",
|
||||
"b",
|
||||
"c"
|
||||
],
|
||||
"extent": [
|
||||
[
|
||||
-179.754,
|
||||
50.858
|
||||
],
|
||||
[
|
||||
-129.899,
|
||||
71.463
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": " TIGER 2012 Roads Overlay",
|
||||
"template": "http://{t}.tile.openstreetmap.us/tiger2012_roads_expanded/{z}/{x}/{y}.png",
|
||||
"subdomains": [
|
||||
"a",
|
||||
"b",
|
||||
"c"
|
||||
],
|
||||
"extent": [
|
||||
[
|
||||
-174.46,
|
||||
18.702
|
||||
],
|
||||
[
|
||||
-154.516,
|
||||
26.501
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": " USGS Topographic Maps",
|
||||
"template": "http://{t}.tile.openstreetmap.us/usgs_scanned_topos/{z}/{x}/{y}.png",
|
||||
"subdomains": [
|
||||
"a",
|
||||
"b",
|
||||
"c"
|
||||
],
|
||||
"extent": [
|
||||
[
|
||||
-125.991,
|
||||
24.005
|
||||
],
|
||||
[
|
||||
-65.988,
|
||||
50.009
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": " USGS Topographic Maps",
|
||||
"template": "http://{t}.tile.openstreetmap.us/usgs_scanned_topos/{z}/{x}/{y}.png",
|
||||
"subdomains": [
|
||||
"a",
|
||||
"b",
|
||||
"c"
|
||||
],
|
||||
"extent": [
|
||||
[
|
||||
-160.579,
|
||||
18.902
|
||||
],
|
||||
[
|
||||
-154.793,
|
||||
22.508
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": " USGS Topographic Maps",
|
||||
"template": "http://{t}.tile.openstreetmap.us/usgs_scanned_topos/{z}/{x}/{y}.png",
|
||||
"subdomains": [
|
||||
"a",
|
||||
"b",
|
||||
"c"
|
||||
],
|
||||
"extent": [
|
||||
[
|
||||
-178.001,
|
||||
51.255
|
||||
],
|
||||
[
|
||||
-130.004,
|
||||
71.999
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": " USGS Large Scale Aerial Imagery",
|
||||
"template": "http://{t}.tile.openstreetmap.us/usgs_large_scale/{z}/{x}/{y}.jpg",
|
||||
"subdomains": [
|
||||
"a",
|
||||
"b",
|
||||
"c"
|
||||
],
|
||||
"extent": [
|
||||
[
|
||||
-124.819,
|
||||
24.496
|
||||
],
|
||||
[
|
||||
-66.931,
|
||||
49.443
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "British Columbia bc_mosaic",
|
||||
"template": "http://{t}.imagery.paulnorman.ca/tiles/bc_mosaic/{z}/{x}/{y}.png",
|
||||
"subdomains": [
|
||||
"a",
|
||||
"b",
|
||||
"c",
|
||||
"d"
|
||||
],
|
||||
"extent": [
|
||||
[
|
||||
-123.441,
|
||||
48.995
|
||||
],
|
||||
[
|
||||
-121.346,
|
||||
50.426
|
||||
]
|
||||
],
|
||||
"sourcetag": "bc_mosaic",
|
||||
"terms_url": "http://imagery.paulnorman.ca/tiles/about.html"
|
||||
},
|
||||
{
|
||||
"name": "OS OpenData Streetview",
|
||||
"template": "http://os.openstreetmap.org/sv/{z}/{x}/{y}.png",
|
||||
"extent": [
|
||||
[
|
||||
-8.72,
|
||||
49.86
|
||||
],
|
||||
[
|
||||
1.84,
|
||||
60.92
|
||||
]
|
||||
],
|
||||
"sourcetag": "OS_OpenData_StreetView"
|
||||
},
|
||||
{
|
||||
"name": "OS OpenData Locator",
|
||||
"template": "http://tiles.itoworld.com/os_locator/{z}/{x}/{y}.png",
|
||||
"extent": [
|
||||
[
|
||||
-9,
|
||||
49.8
|
||||
],
|
||||
[
|
||||
1.9,
|
||||
61.1
|
||||
]
|
||||
],
|
||||
"sourcetag": "OS_OpenData_Locator"
|
||||
},
|
||||
{
|
||||
"name": "OS 1:25k historic (OSM)",
|
||||
"template": "http://ooc.openstreetmap.org/os1/{z}/{x}/{y}.jpg",
|
||||
"extent": [
|
||||
[
|
||||
-9,
|
||||
49.8
|
||||
],
|
||||
[
|
||||
1.9,
|
||||
61.1
|
||||
]
|
||||
],
|
||||
"sourcetag": "OS 1:25k"
|
||||
},
|
||||
{
|
||||
"name": "OS 1:25k historic (NLS)",
|
||||
"template": "http://geo.nls.uk/mapdata2/os/25000/{z}/{x}/{y}.png",
|
||||
"extent": [
|
||||
[
|
||||
-9,
|
||||
49.8
|
||||
],
|
||||
[
|
||||
1.9,
|
||||
61.1
|
||||
]
|
||||
],
|
||||
"sourcetag": "OS 1:25k",
|
||||
"logo": "icons/logo_nls70-nq8.png",
|
||||
"logo_url": "http://geo.nls.uk/maps/"
|
||||
},
|
||||
{
|
||||
"name": "OS 7th Series historic (OSM)",
|
||||
"template": "http://ooc.openstreetmap.org/os7/{z}/{x}/{y}.jpg",
|
||||
"extent": [
|
||||
[
|
||||
-9,
|
||||
49.8
|
||||
],
|
||||
[
|
||||
1.9,
|
||||
61.1
|
||||
]
|
||||
],
|
||||
"sourcetag": "OS7"
|
||||
},
|
||||
{
|
||||
"name": "OS 7th Series historic (NLS)",
|
||||
"template": "http://geo.nls.uk/mapdata2/os/seventh/{z}/{x}/{y}.png",
|
||||
"extent": [
|
||||
[
|
||||
-9,
|
||||
49.8
|
||||
],
|
||||
[
|
||||
1.9,
|
||||
61.1
|
||||
]
|
||||
],
|
||||
"sourcetag": "OS7",
|
||||
"logo": "icons/logo_nls70-nq8.png",
|
||||
"logo_url": "http://geo.nls.uk/maps/"
|
||||
},
|
||||
{
|
||||
"name": "OS New Popular Edition historic",
|
||||
"template": "http://ooc.openstreetmap.org/npe/{z}/{x}/{y}.png",
|
||||
"extent": [
|
||||
[
|
||||
-5.8,
|
||||
49.8
|
||||
],
|
||||
[
|
||||
1.9,
|
||||
55.8
|
||||
]
|
||||
],
|
||||
"sourcetag": "NPE"
|
||||
},
|
||||
{
|
||||
"name": "OS Scottish Popular historic",
|
||||
"template": "http://ooc.openstreetmap.org/npescotland/tiles/{z}/{x}/{y}.jpg",
|
||||
"extent": [
|
||||
[
|
||||
-7.8,
|
||||
54.5
|
||||
],
|
||||
[
|
||||
-1.1,
|
||||
61.1
|
||||
]
|
||||
],
|
||||
"sourcetag": "NPE"
|
||||
},
|
||||
{
|
||||
"name": "Surrey aerial",
|
||||
"template": "http://gravitystorm.dev.openstreetmap.org/surrey/{z}/{x}/{y}.png",
|
||||
"extent": [
|
||||
[
|
||||
-0.856,
|
||||
51.071
|
||||
],
|
||||
[
|
||||
0.062,
|
||||
51.473
|
||||
]
|
||||
],
|
||||
"sourcetag": "Surrey aerial"
|
||||
},
|
||||
{
|
||||
"name": "Haiti - GeoEye Jan 13",
|
||||
"template": "http://gravitystorm.dev.openstreetmap.org/imagery/haiti/{z}/{x}/{y}.jpg",
|
||||
"extent": [
|
||||
[
|
||||
-74.5,
|
||||
17.95
|
||||
],
|
||||
[
|
||||
-71.58,
|
||||
20.12
|
||||
]
|
||||
],
|
||||
"sourcetag": "Haiti GeoEye"
|
||||
},
|
||||
{
|
||||
"name": "Haiti - GeoEye Jan 13+",
|
||||
"template": "http://maps.nypl.org/tilecache/1/geoeye/{z}/{x}/{y}.jpg",
|
||||
"extent": [
|
||||
[
|
||||
-74.5,
|
||||
17.95
|
||||
],
|
||||
[
|
||||
-71.58,
|
||||
20.12
|
||||
]
|
||||
],
|
||||
"sourcetag": "Haiti GeoEye"
|
||||
},
|
||||
{
|
||||
"name": "Haiti - DigitalGlobe",
|
||||
"template": "http://maps.nypl.org/tilecache/1/dg_crisis/{z}/{x}/{y}.jpg",
|
||||
"extent": [
|
||||
[
|
||||
-74.5,
|
||||
17.95
|
||||
],
|
||||
[
|
||||
-71.58,
|
||||
20.12
|
||||
]
|
||||
],
|
||||
"sourcetag": "Haiti DigitalGlobe"
|
||||
},
|
||||
{
|
||||
"name": "Haiti - Street names",
|
||||
"template": "http://hypercube.telascience.org/tiles/1.0.0/haiti-city/{z}/{x}/{y}.jpg",
|
||||
"extent": [
|
||||
[
|
||||
-74.5,
|
||||
17.95
|
||||
],
|
||||
[
|
||||
-71.58,
|
||||
20.12
|
||||
]
|
||||
],
|
||||
"sourcetag": "Haiti streetnames"
|
||||
},
|
||||
{
|
||||
"name": "NAIP",
|
||||
"template": "http://cube.telascience.org/tilecache/tilecache.py/NAIP_ALL/{z}/{x}/{y}.png",
|
||||
"description": "National Agriculture Imagery Program",
|
||||
"extent": [
|
||||
[
|
||||
-125.8,
|
||||
24.2
|
||||
],
|
||||
[
|
||||
-62.3,
|
||||
49.5
|
||||
]
|
||||
],
|
||||
"sourcetag": "NAIP"
|
||||
},
|
||||
{
|
||||
"name": "NAIP",
|
||||
"template": "http://cube.telascience.org/tilecache/tilecache.py/NAIP_ALL/{z}/{x}/{y}.png",
|
||||
"description": "National Agriculture Imagery Program",
|
||||
"extent": [
|
||||
[
|
||||
-168.5,
|
||||
55.3
|
||||
],
|
||||
[
|
||||
-140,
|
||||
71.5
|
||||
]
|
||||
],
|
||||
"sourcetag": "NAIP"
|
||||
},
|
||||
{
|
||||
"name": "Ireland - NLS Historic Maps",
|
||||
"template": "http://geo.nls.uk/maps/ireland/gsgs4136/{z}/{x}/{y}.png",
|
||||
"extent": [
|
||||
[
|
||||
-10.71,
|
||||
51.32
|
||||
],
|
||||
[
|
||||
-5.37,
|
||||
55.46
|
||||
]
|
||||
],
|
||||
"sourcetag": "NLS Historic Maps",
|
||||
"logo": "icons/logo_nls70-nq8.png",
|
||||
"logo_url": "http://geo.nls.uk/maps/"
|
||||
},
|
||||
{
|
||||
"name": "Denmark - Fugro Aerial Imagery",
|
||||
"template": "http://tile.openstreetmap.dk/fugro2005/{z}/{x}/{y}.jpg",
|
||||
"extent": [
|
||||
[
|
||||
7.81,
|
||||
54.44
|
||||
],
|
||||
[
|
||||
15.49,
|
||||
57.86
|
||||
]
|
||||
],
|
||||
"sourcetag": "Fugro (2005)"
|
||||
},
|
||||
{
|
||||
"name": "Denmark - Stevns Kommune",
|
||||
"template": "http://tile.openstreetmap.dk/stevns/2009/{z}/{x}/{y}.jpg",
|
||||
"extent": [
|
||||
[
|
||||
12.09144,
|
||||
55.23403
|
||||
],
|
||||
[
|
||||
12.47712,
|
||||
55.43647
|
||||
]
|
||||
],
|
||||
"sourcetag": "Stevns Kommune (2009)"
|
||||
},
|
||||
{
|
||||
"name": "Austria - geoimage.at",
|
||||
"template": "http://geoimage.openstreetmap.at/4d80de696cd562a63ce463a58a61488d/{z}/{x}/{y}.jpg",
|
||||
"extent": [
|
||||
[
|
||||
9.36,
|
||||
46.33
|
||||
],
|
||||
[
|
||||
17.28,
|
||||
49.09
|
||||
]
|
||||
],
|
||||
"sourcetag": "geoimage.at"
|
||||
},
|
||||
{
|
||||
"name": "Russia - Kosmosnimki.ru IRS Satellite",
|
||||
"template": "http://irs.gis-lab.info/?layers=irs&request=GetTile&z={z}&x={x}&y={y}",
|
||||
"extent": [
|
||||
[
|
||||
19.02,
|
||||
40.96
|
||||
],
|
||||
[
|
||||
77.34,
|
||||
70.48
|
||||
]
|
||||
],
|
||||
"sourcetag": "Kosmosnimki.ru IRS"
|
||||
},
|
||||
{
|
||||
"name": "Belarus - Kosmosnimki.ru SPOT4 Satellite",
|
||||
"template": "http://irs.gis-lab.info/?layers=spot&request=GetTile&z={z}&x={x}&y={y}",
|
||||
"extent": [
|
||||
[
|
||||
23.16,
|
||||
51.25
|
||||
],
|
||||
[
|
||||
32.83,
|
||||
56.19
|
||||
]
|
||||
],
|
||||
"sourcetag": "Kosmosnimki.ru SPOT4"
|
||||
},
|
||||
{
|
||||
"name": "Australia - Geographic Reference Image",
|
||||
"template": "http://agri.openstreetmap.org/{z}/{x}/{y}.png",
|
||||
"extent": [
|
||||
[
|
||||
96,
|
||||
-44
|
||||
],
|
||||
[
|
||||
168,
|
||||
-9
|
||||
]
|
||||
],
|
||||
"sourcetag": "AGRI"
|
||||
},
|
||||
{
|
||||
"name": "Switzerland - Canton Aargau - AGIS 25cm 2011",
|
||||
"template": "http://tiles.poole.ch/AGIS/OF2011/{z}/{x}/{y}.png",
|
||||
"extent": [
|
||||
[
|
||||
7.69,
|
||||
47.13
|
||||
],
|
||||
[
|
||||
8.48,
|
||||
47.63
|
||||
]
|
||||
],
|
||||
"sourcetag": "AGIS OF2011"
|
||||
},
|
||||
{
|
||||
"name": "Switzerland - Canton Solothurn - SOGIS 2007",
|
||||
"template": "http://mapproxy.sosm.ch:8080/tiles/sogis2007/EPSG900913/{z}/{x}/{y}.png?origin=nw",
|
||||
"extent": [
|
||||
[
|
||||
7.33,
|
||||
47.06
|
||||
],
|
||||
[
|
||||
8.04,
|
||||
47.5
|
||||
]
|
||||
],
|
||||
"sourcetag": "Orthofoto 2007 WMS Solothurn"
|
||||
},
|
||||
{
|
||||
"name": "Poland - Media-Lab fleet GPS masstracks",
|
||||
"template": "http://masstracks.media-lab.com.pl/{z}/{x}/{y}.png",
|
||||
"extent": [
|
||||
[
|
||||
14,
|
||||
48.9
|
||||
],
|
||||
[
|
||||
24.2,
|
||||
55
|
||||
]
|
||||
],
|
||||
"sourcetag": "masstracks"
|
||||
},
|
||||
{
|
||||
"name": "South Africa - CD:NGI Aerial",
|
||||
"template": "http://{t}.aerial.openstreetmap.org.za/ngi-aerial/{z}/{x}/{y}.jpg",
|
||||
"subdomains": [
|
||||
"a",
|
||||
"b",
|
||||
"c"
|
||||
],
|
||||
"extent": [
|
||||
[
|
||||
17.64,
|
||||
-34.95
|
||||
],
|
||||
[
|
||||
32.87,
|
||||
-22.05
|
||||
]
|
||||
],
|
||||
"sourcetag": "ngi-aerial"
|
||||
}
|
||||
];
|
||||
@@ -1,7 +1,13 @@
|
||||
[
|
||||
{
|
||||
"name": "Bing aerial imagery",
|
||||
"url": "http://ecn.t0.tiles.virtualearth.net/tiles/a{q}uadkey.jpeg?g=587&mkt=en-gb&n=z",
|
||||
"template": "http://ecn.t0.tiles.virtualearth.net/tiles/a{u}.jpeg?g=587&mkt=en-gb&n=z",
|
||||
"description": "Satellite imagery.",
|
||||
"scaleExtent": [
|
||||
0,
|
||||
20
|
||||
],
|
||||
"default": "yes",
|
||||
"sourcetag": "Bing",
|
||||
"logo": "bing_maps.png",
|
||||
"logo_url": "http://www.bing.com/maps",
|
||||
@@ -9,7 +15,12 @@
|
||||
},
|
||||
{
|
||||
"name": "MapBox Satellite",
|
||||
"url": "http://{t}.tiles.mapbox.com/v3/openstreetmap.map-4wvf9l0l/{z}/{x}/{y}.png",
|
||||
"template": "http://{t}.tiles.mapbox.com/v3/openstreetmap.map-4wvf9l0l/{z}/{x}/{y}.png",
|
||||
"description": "Satellite and aerial imagery",
|
||||
"scaleExtent": [
|
||||
0,
|
||||
16
|
||||
],
|
||||
"subdomains": [
|
||||
"a",
|
||||
"b",
|
||||
@@ -17,12 +28,13 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "MapQuest Open Aerial",
|
||||
"url": "http://oatile1.mqcdn.com/tiles/1.0.0/sat/{z}/{x}/{y}.jpg"
|
||||
},
|
||||
{
|
||||
"name": "OSM - Mapnik",
|
||||
"url": "http://{t}.tile.openstreetmap.org/{z}/{x}/{y}.png",
|
||||
"name": "OpenStreetMap",
|
||||
"template": "http://{t}.tile.openstreetmap.org/{z}/{x}/{y}.png",
|
||||
"description": "The default OpenStreetMap layer.",
|
||||
"scaleExtent": [
|
||||
0,
|
||||
18
|
||||
],
|
||||
"subdomains": [
|
||||
"a",
|
||||
"b",
|
||||
@@ -30,151 +42,141 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "OSM - OpenCycleMap",
|
||||
"url": "http://tile.opencyclemap.org/cycle/{z}/{x}/{y}.png"
|
||||
},
|
||||
{
|
||||
"name": "OSM - MapQuest",
|
||||
"url": "http://otile1.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.jpg"
|
||||
},
|
||||
{
|
||||
"name": "OSM - Tiger Edited Map",
|
||||
"url": "http://tiger-osm.mapquest.com/tiles/1.0.0/tiger/{z}/{x}/{y}.png",
|
||||
"extent": [
|
||||
24.055,
|
||||
-124.81,
|
||||
49.386,
|
||||
-66.865
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "OSM - Tiger Edited Map",
|
||||
"url": "http://tiger-osm.mapquest.com/tiles/1.0.0/tiger/{z}/{x}/{y}.png",
|
||||
"extent": [
|
||||
50.858,
|
||||
-179.754,
|
||||
71.463,
|
||||
-129.899
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "OSM - Tiger Edited Map",
|
||||
"url": "http://tiger-osm.mapquest.com/tiles/1.0.0/tiger/{z}/{x}/{y}.png",
|
||||
"extent": [
|
||||
18.702,
|
||||
-174.46,
|
||||
26.501,
|
||||
-154.516
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "OSM US TIGER 2012 Roads Overlay",
|
||||
"url": "http://{t}.tile.openstreetmap.us/tiger2012_roads_expanded/{z}/{x}/{y}.png",
|
||||
"name": " TIGER 2012 Roads Overlay",
|
||||
"template": "http://{t}.tile.openstreetmap.us/tiger2012_roads_expanded/{z}/{x}/{y}.png",
|
||||
"subdomains": [
|
||||
"a",
|
||||
"b",
|
||||
"c"
|
||||
],
|
||||
"extent": [
|
||||
24.055,
|
||||
-124.81,
|
||||
49.386,
|
||||
-66.865
|
||||
[
|
||||
-124.81,
|
||||
24.055
|
||||
],
|
||||
[
|
||||
-66.865,
|
||||
49.386
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "OSM US TIGER 2012 Roads Overlay",
|
||||
"url": "http://{t}.tile.openstreetmap.us/tiger2012_roads_expanded/{z}/{x}/{y}.png",
|
||||
"name": " TIGER 2012 Roads Overlay",
|
||||
"template": "http://{t}.tile.openstreetmap.us/tiger2012_roads_expanded/{z}/{x}/{y}.png",
|
||||
"subdomains": [
|
||||
"a",
|
||||
"b",
|
||||
"c"
|
||||
],
|
||||
"extent": [
|
||||
50.858,
|
||||
-179.754,
|
||||
71.463,
|
||||
-129.899
|
||||
[
|
||||
-179.754,
|
||||
50.858
|
||||
],
|
||||
[
|
||||
-129.899,
|
||||
71.463
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "OSM US TIGER 2012 Roads Overlay",
|
||||
"url": "http://{t}.tile.openstreetmap.us/tiger2012_roads_expanded/{z}/{x}/{y}.png",
|
||||
"name": " TIGER 2012 Roads Overlay",
|
||||
"template": "http://{t}.tile.openstreetmap.us/tiger2012_roads_expanded/{z}/{x}/{y}.png",
|
||||
"subdomains": [
|
||||
"a",
|
||||
"b",
|
||||
"c"
|
||||
],
|
||||
"extent": [
|
||||
18.702,
|
||||
-174.46,
|
||||
26.501,
|
||||
-154.516
|
||||
[
|
||||
-174.46,
|
||||
18.702
|
||||
],
|
||||
[
|
||||
-154.516,
|
||||
26.501
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "OSM US USGS Topographic Maps",
|
||||
"url": "http://{t}.tile.openstreetmap.us/usgs_scanned_topos/{z}/{x}/{y}.png",
|
||||
"name": " USGS Topographic Maps",
|
||||
"template": "http://{t}.tile.openstreetmap.us/usgs_scanned_topos/{z}/{x}/{y}.png",
|
||||
"subdomains": [
|
||||
"a",
|
||||
"b",
|
||||
"c"
|
||||
],
|
||||
"extent": [
|
||||
24.005,
|
||||
-125.991,
|
||||
50.009,
|
||||
-65.988
|
||||
[
|
||||
-125.991,
|
||||
24.005
|
||||
],
|
||||
[
|
||||
-65.988,
|
||||
50.009
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "OSM US USGS Topographic Maps",
|
||||
"url": "http://{t}.tile.openstreetmap.us/usgs_scanned_topos/{z}/{x}/{y}.png",
|
||||
"name": " USGS Topographic Maps",
|
||||
"template": "http://{t}.tile.openstreetmap.us/usgs_scanned_topos/{z}/{x}/{y}.png",
|
||||
"subdomains": [
|
||||
"a",
|
||||
"b",
|
||||
"c"
|
||||
],
|
||||
"extent": [
|
||||
18.902,
|
||||
-160.579,
|
||||
22.508,
|
||||
-154.793
|
||||
[
|
||||
-160.579,
|
||||
18.902
|
||||
],
|
||||
[
|
||||
-154.793,
|
||||
22.508
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "OSM US USGS Topographic Maps",
|
||||
"url": "http://{t}.tile.openstreetmap.us/usgs_scanned_topos/{z}/{x}/{y}.png",
|
||||
"name": " USGS Topographic Maps",
|
||||
"template": "http://{t}.tile.openstreetmap.us/usgs_scanned_topos/{z}/{x}/{y}.png",
|
||||
"subdomains": [
|
||||
"a",
|
||||
"b",
|
||||
"c"
|
||||
],
|
||||
"extent": [
|
||||
51.255,
|
||||
-178.001,
|
||||
71.999,
|
||||
-130.004
|
||||
[
|
||||
-178.001,
|
||||
51.255
|
||||
],
|
||||
[
|
||||
-130.004,
|
||||
71.999
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "OSM US USGS Large Scale Aerial Imagery",
|
||||
"url": "http://{t}.tile.openstreetmap.us/usgs_large_scale/{z}/{x}/{y}.jpg",
|
||||
"name": " USGS Large Scale Aerial Imagery",
|
||||
"template": "http://{t}.tile.openstreetmap.us/usgs_large_scale/{z}/{x}/{y}.jpg",
|
||||
"subdomains": [
|
||||
"a",
|
||||
"b",
|
||||
"c"
|
||||
],
|
||||
"extent": [
|
||||
24.496,
|
||||
-124.819,
|
||||
49.443,
|
||||
-66.931
|
||||
[
|
||||
-124.819,
|
||||
24.496
|
||||
],
|
||||
[
|
||||
-66.931,
|
||||
49.443
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "British Columbia bc_mosaic",
|
||||
"url": "http://{t}.imagery.paulnorman.ca/tiles/bc_mosaic/{z}/{x}/{y}.png",
|
||||
"template": "http://{t}.imagery.paulnorman.ca/tiles/bc_mosaic/{z}/{x}/{y}.png",
|
||||
"subdomains": [
|
||||
"a",
|
||||
"b",
|
||||
@@ -182,55 +184,75 @@
|
||||
"d"
|
||||
],
|
||||
"extent": [
|
||||
48.995,
|
||||
-123.441,
|
||||
50.426,
|
||||
-121.346
|
||||
[
|
||||
-123.441,
|
||||
48.995
|
||||
],
|
||||
[
|
||||
-121.346,
|
||||
50.426
|
||||
]
|
||||
],
|
||||
"sourcetag": "bc_mosaic",
|
||||
"terms_url": "http://imagery.paulnorman.ca/tiles/about.html"
|
||||
},
|
||||
{
|
||||
"name": "OS OpenData Streetview",
|
||||
"url": "http://os.openstreetmap.org/sv/{z}/{x}/{y}.png",
|
||||
"template": "http://os.openstreetmap.org/sv/{z}/{x}/{y}.png",
|
||||
"extent": [
|
||||
49.86,
|
||||
-8.72,
|
||||
60.92,
|
||||
1.84
|
||||
[
|
||||
-8.72,
|
||||
49.86
|
||||
],
|
||||
[
|
||||
1.84,
|
||||
60.92
|
||||
]
|
||||
],
|
||||
"sourcetag": "OS_OpenData_StreetView"
|
||||
},
|
||||
{
|
||||
"name": "OS OpenData Locator",
|
||||
"url": "http://tiles.itoworld.com/os_locator/{z}/{x}/{y}.png",
|
||||
"template": "http://tiles.itoworld.com/os_locator/{z}/{x}/{y}.png",
|
||||
"extent": [
|
||||
49.8,
|
||||
-9,
|
||||
61.1,
|
||||
1.9
|
||||
[
|
||||
-9,
|
||||
49.8
|
||||
],
|
||||
[
|
||||
1.9,
|
||||
61.1
|
||||
]
|
||||
],
|
||||
"sourcetag": "OS_OpenData_Locator"
|
||||
},
|
||||
{
|
||||
"name": "OS 1:25k historic (OSM)",
|
||||
"url": "http://ooc.openstreetmap.org/os1/{z}/{x}/{y}.jpg",
|
||||
"template": "http://ooc.openstreetmap.org/os1/{z}/{x}/{y}.jpg",
|
||||
"extent": [
|
||||
49.8,
|
||||
-9,
|
||||
61.1,
|
||||
1.9
|
||||
[
|
||||
-9,
|
||||
49.8
|
||||
],
|
||||
[
|
||||
1.9,
|
||||
61.1
|
||||
]
|
||||
],
|
||||
"sourcetag": "OS 1:25k"
|
||||
},
|
||||
{
|
||||
"name": "OS 1:25k historic (NLS)",
|
||||
"url": "http://geo.nls.uk/mapdata2/os/25000/{z}/{x}/{y}.png",
|
||||
"template": "http://geo.nls.uk/mapdata2/os/25000/{z}/{x}/{y}.png",
|
||||
"extent": [
|
||||
49.8,
|
||||
-9,
|
||||
61.1,
|
||||
1.9
|
||||
[
|
||||
-9,
|
||||
49.8
|
||||
],
|
||||
[
|
||||
1.9,
|
||||
61.1
|
||||
]
|
||||
],
|
||||
"sourcetag": "OS 1:25k",
|
||||
"logo": "icons/logo_nls70-nq8.png",
|
||||
@@ -238,23 +260,31 @@
|
||||
},
|
||||
{
|
||||
"name": "OS 7th Series historic (OSM)",
|
||||
"url": "http://ooc.openstreetmap.org/os7/{z}/{x}/{y}.jpg",
|
||||
"template": "http://ooc.openstreetmap.org/os7/{z}/{x}/{y}.jpg",
|
||||
"extent": [
|
||||
49.8,
|
||||
-9,
|
||||
61.1,
|
||||
1.9
|
||||
[
|
||||
-9,
|
||||
49.8
|
||||
],
|
||||
[
|
||||
1.9,
|
||||
61.1
|
||||
]
|
||||
],
|
||||
"sourcetag": "OS7"
|
||||
},
|
||||
{
|
||||
"name": "OS 7th Series historic (NLS)",
|
||||
"url": "http://geo.nls.uk/mapdata2/os/seventh/{z}/{x}/{y}.png",
|
||||
"template": "http://geo.nls.uk/mapdata2/os/seventh/{z}/{x}/{y}.png",
|
||||
"extent": [
|
||||
49.8,
|
||||
-9,
|
||||
61.1,
|
||||
1.9
|
||||
[
|
||||
-9,
|
||||
49.8
|
||||
],
|
||||
[
|
||||
1.9,
|
||||
61.1
|
||||
]
|
||||
],
|
||||
"sourcetag": "OS7",
|
||||
"logo": "icons/logo_nls70-nq8.png",
|
||||
@@ -262,111 +292,153 @@
|
||||
},
|
||||
{
|
||||
"name": "OS New Popular Edition historic",
|
||||
"url": "http://ooc.openstreetmap.org/npe/{z}/{x}/{y}.png",
|
||||
"template": "http://ooc.openstreetmap.org/npe/{z}/{x}/{y}.png",
|
||||
"extent": [
|
||||
49.8,
|
||||
-5.8,
|
||||
55.8,
|
||||
1.9
|
||||
[
|
||||
-5.8,
|
||||
49.8
|
||||
],
|
||||
[
|
||||
1.9,
|
||||
55.8
|
||||
]
|
||||
],
|
||||
"sourcetag": "NPE"
|
||||
},
|
||||
{
|
||||
"name": "OS Scottish Popular historic",
|
||||
"url": "http://ooc.openstreetmap.org/npescotland/tiles/{z}/{x}/{y}.jpg",
|
||||
"template": "http://ooc.openstreetmap.org/npescotland/tiles/{z}/{x}/{y}.jpg",
|
||||
"extent": [
|
||||
54.5,
|
||||
-7.8,
|
||||
61.1,
|
||||
-1.1
|
||||
[
|
||||
-7.8,
|
||||
54.5
|
||||
],
|
||||
[
|
||||
-1.1,
|
||||
61.1
|
||||
]
|
||||
],
|
||||
"sourcetag": "NPE"
|
||||
},
|
||||
{
|
||||
"name": "Surrey aerial",
|
||||
"url": "http://gravitystorm.dev.openstreetmap.org/surrey/{z}/{x}/{y}.png",
|
||||
"template": "http://gravitystorm.dev.openstreetmap.org/surrey/{z}/{x}/{y}.png",
|
||||
"extent": [
|
||||
51.071,
|
||||
-0.856,
|
||||
51.473,
|
||||
0.062
|
||||
[
|
||||
-0.856,
|
||||
51.071
|
||||
],
|
||||
[
|
||||
0.062,
|
||||
51.473
|
||||
]
|
||||
],
|
||||
"sourcetag": "Surrey aerial"
|
||||
},
|
||||
{
|
||||
"name": "Haiti - GeoEye Jan 13",
|
||||
"url": "http://gravitystorm.dev.openstreetmap.org/imagery/haiti/{z}/{x}/{y}.jpg",
|
||||
"template": "http://gravitystorm.dev.openstreetmap.org/imagery/haiti/{z}/{x}/{y}.jpg",
|
||||
"extent": [
|
||||
17.95,
|
||||
-74.5,
|
||||
20.12,
|
||||
-71.58
|
||||
[
|
||||
-74.5,
|
||||
17.95
|
||||
],
|
||||
[
|
||||
-71.58,
|
||||
20.12
|
||||
]
|
||||
],
|
||||
"sourcetag": "Haiti GeoEye"
|
||||
},
|
||||
{
|
||||
"name": "Haiti - GeoEye Jan 13+",
|
||||
"url": "http://maps.nypl.org/tilecache/1/geoeye/{z}/{x}/{y}.jpg",
|
||||
"template": "http://maps.nypl.org/tilecache/1/geoeye/{z}/{x}/{y}.jpg",
|
||||
"extent": [
|
||||
17.95,
|
||||
-74.5,
|
||||
20.12,
|
||||
-71.58
|
||||
[
|
||||
-74.5,
|
||||
17.95
|
||||
],
|
||||
[
|
||||
-71.58,
|
||||
20.12
|
||||
]
|
||||
],
|
||||
"sourcetag": "Haiti GeoEye"
|
||||
},
|
||||
{
|
||||
"name": "Haiti - DigitalGlobe",
|
||||
"url": "http://maps.nypl.org/tilecache/1/dg_crisis/{z}/{x}/{y}.jpg",
|
||||
"template": "http://maps.nypl.org/tilecache/1/dg_crisis/{z}/{x}/{y}.jpg",
|
||||
"extent": [
|
||||
17.95,
|
||||
-74.5,
|
||||
20.12,
|
||||
-71.58
|
||||
[
|
||||
-74.5,
|
||||
17.95
|
||||
],
|
||||
[
|
||||
-71.58,
|
||||
20.12
|
||||
]
|
||||
],
|
||||
"sourcetag": "Haiti DigitalGlobe"
|
||||
},
|
||||
{
|
||||
"name": "Haiti - Street names",
|
||||
"url": "http://hypercube.telascience.org/tiles/1.0.0/haiti-city/{z}/{x}/{y}.jpg",
|
||||
"template": "http://hypercube.telascience.org/tiles/1.0.0/haiti-city/{z}/{x}/{y}.jpg",
|
||||
"extent": [
|
||||
17.95,
|
||||
-74.5,
|
||||
20.12,
|
||||
-71.58
|
||||
[
|
||||
-74.5,
|
||||
17.95
|
||||
],
|
||||
[
|
||||
-71.58,
|
||||
20.12
|
||||
]
|
||||
],
|
||||
"sourcetag": "Haiti streetnames"
|
||||
},
|
||||
{
|
||||
"name": "National Agriculture Imagery Program",
|
||||
"url": "http://cube.telascience.org/tilecache/tilecache.py/NAIP_ALL/{z}/{x}/{y}.png",
|
||||
"name": "NAIP",
|
||||
"template": "http://cube.telascience.org/tilecache/tilecache.py/NAIP_ALL/{z}/{x}/{y}.png",
|
||||
"description": "National Agriculture Imagery Program",
|
||||
"extent": [
|
||||
24.2,
|
||||
-125.8,
|
||||
49.5,
|
||||
-62.3
|
||||
[
|
||||
-125.8,
|
||||
24.2
|
||||
],
|
||||
[
|
||||
-62.3,
|
||||
49.5
|
||||
]
|
||||
],
|
||||
"sourcetag": "NAIP"
|
||||
},
|
||||
{
|
||||
"name": "National Agriculture Imagery Program",
|
||||
"url": "http://cube.telascience.org/tilecache/tilecache.py/NAIP_ALL/{z}/{x}/{y}.png",
|
||||
"name": "NAIP",
|
||||
"template": "http://cube.telascience.org/tilecache/tilecache.py/NAIP_ALL/{z}/{x}/{y}.png",
|
||||
"description": "National Agriculture Imagery Program",
|
||||
"extent": [
|
||||
55.3,
|
||||
-168.5,
|
||||
71.5,
|
||||
-140
|
||||
[
|
||||
-168.5,
|
||||
55.3
|
||||
],
|
||||
[
|
||||
-140,
|
||||
71.5
|
||||
]
|
||||
],
|
||||
"sourcetag": "NAIP"
|
||||
},
|
||||
{
|
||||
"name": "Ireland - NLS Historic Maps",
|
||||
"url": "http://geo.nls.uk/maps/ireland/gsgs4136/{z}/{x}/{y}.png",
|
||||
"template": "http://geo.nls.uk/maps/ireland/gsgs4136/{z}/{x}/{y}.png",
|
||||
"extent": [
|
||||
51.32,
|
||||
-10.71,
|
||||
55.46,
|
||||
-5.37
|
||||
[
|
||||
-10.71,
|
||||
51.32
|
||||
],
|
||||
[
|
||||
-5.37,
|
||||
55.46
|
||||
]
|
||||
],
|
||||
"sourcetag": "NLS Historic Maps",
|
||||
"logo": "icons/logo_nls70-nq8.png",
|
||||
@@ -374,116 +446,156 @@
|
||||
},
|
||||
{
|
||||
"name": "Denmark - Fugro Aerial Imagery",
|
||||
"url": "http://tile.openstreetmap.dk/fugro2005/{z}/{x}/{y}.jpg",
|
||||
"template": "http://tile.openstreetmap.dk/fugro2005/{z}/{x}/{y}.jpg",
|
||||
"extent": [
|
||||
54.44,
|
||||
7.81,
|
||||
57.86,
|
||||
15.49
|
||||
[
|
||||
7.81,
|
||||
54.44
|
||||
],
|
||||
[
|
||||
15.49,
|
||||
57.86
|
||||
]
|
||||
],
|
||||
"sourcetag": "Fugro (2005)"
|
||||
},
|
||||
{
|
||||
"name": "Denmark - Stevns Kommune",
|
||||
"url": "http://tile.openstreetmap.dk/stevns/2009/{z}/{x}/{y}.jpg",
|
||||
"template": "http://tile.openstreetmap.dk/stevns/2009/{z}/{x}/{y}.jpg",
|
||||
"extent": [
|
||||
55.23403,
|
||||
12.09144,
|
||||
55.43647,
|
||||
12.47712
|
||||
[
|
||||
12.09144,
|
||||
55.23403
|
||||
],
|
||||
[
|
||||
12.47712,
|
||||
55.43647
|
||||
]
|
||||
],
|
||||
"sourcetag": "Stevns Kommune (2009)"
|
||||
},
|
||||
{
|
||||
"name": "Austria - geoimage.at",
|
||||
"url": "http://geoimage.openstreetmap.at/4d80de696cd562a63ce463a58a61488d/{z}/{x}/{y}.jpg",
|
||||
"template": "http://geoimage.openstreetmap.at/4d80de696cd562a63ce463a58a61488d/{z}/{x}/{y}.jpg",
|
||||
"extent": [
|
||||
46.33,
|
||||
9.36,
|
||||
49.09,
|
||||
17.28
|
||||
[
|
||||
9.36,
|
||||
46.33
|
||||
],
|
||||
[
|
||||
17.28,
|
||||
49.09
|
||||
]
|
||||
],
|
||||
"sourcetag": "geoimage.at"
|
||||
},
|
||||
{
|
||||
"name": "Russia - Kosmosnimki.ru IRS Satellite",
|
||||
"url": "http://irs.gis-lab.info/?layers=irs&request=GetTile&z={z}&x={x}&y={y}",
|
||||
"template": "http://irs.gis-lab.info/?layers=irs&request=GetTile&z={z}&x={x}&y={y}",
|
||||
"extent": [
|
||||
40.96,
|
||||
19.02,
|
||||
70.48,
|
||||
77.34
|
||||
[
|
||||
19.02,
|
||||
40.96
|
||||
],
|
||||
[
|
||||
77.34,
|
||||
70.48
|
||||
]
|
||||
],
|
||||
"sourcetag": "Kosmosnimki.ru IRS"
|
||||
},
|
||||
{
|
||||
"name": "Belarus - Kosmosnimki.ru SPOT4 Satellite",
|
||||
"url": "http://irs.gis-lab.info/?layers=spot&request=GetTile&z={z}&x={x}&y={y}",
|
||||
"template": "http://irs.gis-lab.info/?layers=spot&request=GetTile&z={z}&x={x}&y={y}",
|
||||
"extent": [
|
||||
51.25,
|
||||
23.16,
|
||||
56.19,
|
||||
32.83
|
||||
[
|
||||
23.16,
|
||||
51.25
|
||||
],
|
||||
[
|
||||
32.83,
|
||||
56.19
|
||||
]
|
||||
],
|
||||
"sourcetag": "Kosmosnimki.ru SPOT4"
|
||||
},
|
||||
{
|
||||
"name": "Australia - Geographic Reference Image",
|
||||
"url": "http://agri.openstreetmap.org/{z}/{x}/{y}.png",
|
||||
"template": "http://agri.openstreetmap.org/{z}/{x}/{y}.png",
|
||||
"extent": [
|
||||
-44,
|
||||
96,
|
||||
-9,
|
||||
168
|
||||
[
|
||||
96,
|
||||
-44
|
||||
],
|
||||
[
|
||||
168,
|
||||
-9
|
||||
]
|
||||
],
|
||||
"sourcetag": "AGRI"
|
||||
},
|
||||
{
|
||||
"name": "Switzerland - Canton Aargau - AGIS 25cm 2011",
|
||||
"url": "http://tiles.poole.ch/AGIS/OF2011/{z}/{x}/{y}.png",
|
||||
"template": "http://tiles.poole.ch/AGIS/OF2011/{z}/{x}/{y}.png",
|
||||
"extent": [
|
||||
47.13,
|
||||
7.69,
|
||||
47.63,
|
||||
8.48
|
||||
[
|
||||
7.69,
|
||||
47.13
|
||||
],
|
||||
[
|
||||
8.48,
|
||||
47.63
|
||||
]
|
||||
],
|
||||
"sourcetag": "AGIS OF2011"
|
||||
},
|
||||
{
|
||||
"name": "Switzerland - Canton Solothurn - SOGIS 2007",
|
||||
"url": "http://mapproxy.sosm.ch:8080/tiles/sogis2007/EPSG900913/{z}/{x}/{y}.png?origin=nw",
|
||||
"template": "http://mapproxy.sosm.ch:8080/tiles/sogis2007/EPSG900913/{z}/{x}/{y}.png?origin=nw",
|
||||
"extent": [
|
||||
47.06,
|
||||
7.33,
|
||||
47.5,
|
||||
8.04
|
||||
[
|
||||
7.33,
|
||||
47.06
|
||||
],
|
||||
[
|
||||
8.04,
|
||||
47.5
|
||||
]
|
||||
],
|
||||
"sourcetag": "Orthofoto 2007 WMS Solothurn"
|
||||
},
|
||||
{
|
||||
"name": "Poland - Media-Lab fleet GPS masstracks",
|
||||
"url": "http://masstracks.media-lab.com.pl/{z}/{x}/{y}.png",
|
||||
"template": "http://masstracks.media-lab.com.pl/{z}/{x}/{y}.png",
|
||||
"extent": [
|
||||
48.9,
|
||||
14,
|
||||
55,
|
||||
24.2
|
||||
[
|
||||
14,
|
||||
48.9
|
||||
],
|
||||
[
|
||||
24.2,
|
||||
55
|
||||
]
|
||||
],
|
||||
"sourcetag": "masstracks"
|
||||
},
|
||||
{
|
||||
"name": "South Africa - CD:NGI Aerial",
|
||||
"url": "http://{t}.aerial.openstreetmap.org.za/ngi-aerial/{z}/{x}/{y}.jpg",
|
||||
"template": "http://{t}.aerial.openstreetmap.org.za/ngi-aerial/{z}/{x}/{y}.jpg",
|
||||
"subdomains": [
|
||||
"a",
|
||||
"b",
|
||||
"c"
|
||||
],
|
||||
"extent": [
|
||||
-34.95,
|
||||
17.64,
|
||||
-22.05,
|
||||
32.87
|
||||
[
|
||||
17.64,
|
||||
-34.95
|
||||
],
|
||||
[
|
||||
32.87,
|
||||
-22.05
|
||||
]
|
||||
],
|
||||
"sourcetag": "ngi-aerial"
|
||||
}
|
||||
|
||||
@@ -5,17 +5,58 @@ $ = cheerio.load(fs.readFileSync('imagery.xml'));
|
||||
|
||||
var imagery = [];
|
||||
|
||||
// CENSORSHIP! No, these are just layers that essentially duplicate other layers
|
||||
// or which have no clear use case.
|
||||
var censor = {
|
||||
'MapQuest Open Aerial': true,
|
||||
'OSM - OpenCycleMap': true,
|
||||
'OSM - MapQuest': true
|
||||
};
|
||||
|
||||
var replace = {
|
||||
'OSM - Mapnik': 'OpenStreetMap',
|
||||
'National Agriculture Imagery Program': 'NAIP'
|
||||
};
|
||||
|
||||
var description = {
|
||||
'MapBox Satellite': 'Satellite and aerial imagery',
|
||||
'OpenStreetMap': 'The default OpenStreetMap layer.',
|
||||
'OSM US TIGER 2012 Roads Overlay': 'Public domain road data from the US Government.',
|
||||
'Bing aerial imagery': 'Satellite imagery.',
|
||||
'NAIP': 'National Agriculture Imagery Program'
|
||||
};
|
||||
|
||||
var scaleExtent = {
|
||||
'MapBox Satellite': [0, 16],
|
||||
'OpenStreetMap': [0, 18],
|
||||
'OSM US TIGER 2012 Roads Overlay': [0, 17],
|
||||
'Bing aerial imagery': [0, 20]
|
||||
};
|
||||
|
||||
$('set').each(function(i) {
|
||||
var elem = $(this);
|
||||
|
||||
var im = {
|
||||
name: $(this).find('name').first().text(),
|
||||
url: $(this).find('url').first().text()
|
||||
template: $(this).find('url').first().text()
|
||||
};
|
||||
|
||||
// no luck with mapquest servers currently...
|
||||
if (im.template.match(/mapquest/g)) return;
|
||||
if (censor[im.name]) return;
|
||||
|
||||
im.name = im.name.replace('OSM US', '');
|
||||
|
||||
if (replace[im.name]) im.name = replace[im.name];
|
||||
|
||||
if (description[im.name]) im.description = description[im.name];
|
||||
|
||||
if (scaleExtent[im.name]) im.scaleExtent = scaleExtent[im.name];
|
||||
|
||||
var subdomains = [];
|
||||
|
||||
im.url = im.url
|
||||
im.template = im.template
|
||||
.replace('$quadkey', '{u}')
|
||||
.replace(/\$(\w)/g, function(m) {
|
||||
return '{' + m[1] + '}';
|
||||
})
|
||||
@@ -28,13 +69,13 @@ $('set').each(function(i) {
|
||||
|
||||
if (elem.attr('minlat')) {
|
||||
im.extent = [
|
||||
+elem.attr('minlat'),
|
||||
+elem.attr('minlon'),
|
||||
+elem.attr('maxlat'),
|
||||
+elem.attr('maxlon')];
|
||||
[+elem.attr('minlon'),
|
||||
+elem.attr('minlat')],
|
||||
[+elem.attr('maxlon'),
|
||||
+elem.attr('maxlat')]];
|
||||
}
|
||||
|
||||
['sourcetag', 'logo', 'logo_url', 'terms_url'].forEach(function(a) {
|
||||
['default', 'sourcetag', 'logo', 'logo_url', 'terms_url'].forEach(function(a) {
|
||||
if (elem.find(a).length) {
|
||||
im[a] = elem.find(a).first().text();
|
||||
}
|
||||
@@ -43,3 +84,4 @@ $('set').each(function(i) {
|
||||
});
|
||||
|
||||
fs.writeFileSync('imagery.json', JSON.stringify(imagery, null, 4));
|
||||
fs.writeFileSync('imagery.js', 'iD.data.imagery = ' + JSON.stringify(imagery, null, 4) + ';');
|
||||
|
||||
12
index.html
12
index.html
@@ -32,12 +32,18 @@
|
||||
<script src='js/id/oauth.js'></script>
|
||||
<script src='js/id/services/taginfo.js'></script>
|
||||
|
||||
<script src='data/data.js'></script>
|
||||
<script src='data/deprecated.js'></script>
|
||||
<script src='data/imagery.js'></script>
|
||||
<script src='data/discarded.js'></script>
|
||||
|
||||
<script src="js/id/geo.js"></script>
|
||||
<script src="js/id/geo/extent.js"></script>
|
||||
|
||||
<script src='js/id/renderer/background.js'></script>
|
||||
<script src='js/id/renderer/background_source.js'></script>
|
||||
<script src='js/id/renderer/map.js'></script>
|
||||
<script src='js/id/renderer/layers.js'></script>
|
||||
|
||||
<script src="js/id/svg.js"></script>
|
||||
<script src="js/id/svg/areas.js"></script>
|
||||
@@ -70,6 +76,7 @@
|
||||
<script src='js/id/ui/restore.js'></script>
|
||||
<script src='js/id/ui/tag_reference.js'></script>
|
||||
<script src='js/id/ui/key_reference.js'></script>
|
||||
<script src='js/id/ui/lasso.js'></script>
|
||||
|
||||
<script src='js/id/actions.js'></script>
|
||||
<script src="js/id/actions/add_midpoint.js"></script>
|
||||
@@ -83,6 +90,7 @@
|
||||
<script src="js/id/actions/delete_way.js"></script>
|
||||
<script src='js/id/actions/disconnect.js'></script>
|
||||
<script src='js/id/actions/join.js'></script>
|
||||
<script src='js/id/actions/merge.js'></script>
|
||||
<script src='js/id/actions/move_node.js'></script>
|
||||
<script src='js/id/actions/move_way.js'></script>
|
||||
<script src='js/id/actions/circularize.js'></script>
|
||||
@@ -97,6 +105,7 @@
|
||||
<script src='js/id/behavior/drag.js'></script>
|
||||
<script src='js/id/behavior/drag_node.js'></script>
|
||||
<script src='js/id/behavior/draw.js'></script>
|
||||
<script src='js/id/behavior/lasso.js'></script>
|
||||
<script src='js/id/behavior/draw_way.js'></script>
|
||||
<script src='js/id/behavior/hash.js'></script>
|
||||
<script src='js/id/behavior/hover.js'></script>
|
||||
@@ -136,9 +145,6 @@
|
||||
<script src='locale/locale.js'></script>
|
||||
<script src='locale/en.js'></script>
|
||||
|
||||
<script src='data/data.js'></script>
|
||||
<script src='data/deprecated.js'></script>
|
||||
<script src='data/discarded.js'></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id='iD'></div><script>
|
||||
|
||||
@@ -30,11 +30,7 @@ iD.actions.Connect = function(nodeIds) {
|
||||
});
|
||||
|
||||
graph.parentRelations(node).forEach(function (parent) {
|
||||
var memberA = parent.memberById(survivor.id),
|
||||
memberB = parent.memberById(node.id);
|
||||
if (!memberA) {
|
||||
graph = graph.replace(parent.addMember({id: survivor.id, role: memberB.role, type: 'node'}));
|
||||
}
|
||||
graph = graph.replace(parent.replaceMember(node, survivor));
|
||||
});
|
||||
|
||||
survivor = survivor.mergeTags(node.tags);
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
iD.actions.DiscardTags = function(entity) {
|
||||
return entity.update({
|
||||
tags: _.omit(entity.tags, iD.data.discarded)
|
||||
});
|
||||
};
|
||||
@@ -6,17 +6,26 @@
|
||||
// https://github.com/systemed/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MergeWaysAction.as
|
||||
// https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/CombineWayAction.java
|
||||
//
|
||||
iD.actions.Join = function(idA, idB) {
|
||||
iD.actions.Join = function(ids) {
|
||||
var idA = ids[0],
|
||||
idB = ids[1];
|
||||
|
||||
function groupEntitiesByGeometry(graph) {
|
||||
var entities = ids.map(function(id) { return graph.entity(id); });
|
||||
return _.extend({line: []}, _.groupBy(entities, function(entity) { return entity.geometry(graph); }));
|
||||
}
|
||||
|
||||
var action = function(graph) {
|
||||
var a = graph.entity(idA),
|
||||
b = graph.entity(idB),
|
||||
nodes, tags;
|
||||
nodes;
|
||||
|
||||
if (a.first() === b.first()) {
|
||||
// a <-- b ==> c
|
||||
// Expected result:
|
||||
// a <-- b <-- c
|
||||
nodes = b.nodes.slice().reverse().concat(a.nodes.slice(1));
|
||||
b = iD.actions.Reverse(idB)(graph).entity(idB);
|
||||
nodes = b.nodes.slice().concat(a.nodes.slice(1));
|
||||
|
||||
} else if (a.first() === b.last()) {
|
||||
// a <-- b <== c
|
||||
@@ -34,17 +43,13 @@ iD.actions.Join = function(idA, idB) {
|
||||
// a --> b <== c
|
||||
// Expected result:
|
||||
// a --> b --> c
|
||||
nodes = a.nodes.concat(b.nodes.slice().reverse().slice(1));
|
||||
b = iD.actions.Reverse(idB)(graph).entity(idB);
|
||||
nodes = a.nodes.concat(b.nodes.slice().slice(1));
|
||||
}
|
||||
|
||||
graph.parentRelations(b)
|
||||
.forEach(function (parent) {
|
||||
var memberA = parent.memberById(idA),
|
||||
memberB = parent.memberById(idB);
|
||||
if (!memberA) {
|
||||
graph = graph.replace(parent.addMember({id: idA, role: memberB.role, type: 'way'}));
|
||||
}
|
||||
});
|
||||
graph.parentRelations(b).forEach(function (parent) {
|
||||
graph = graph.replace(parent.replaceMember(b, a));
|
||||
});
|
||||
|
||||
graph = graph.replace(a.mergeTags(b.tags).update({nodes: nodes}));
|
||||
graph = iD.actions.DeleteWay(idB)(graph);
|
||||
@@ -53,8 +58,14 @@ iD.actions.Join = function(idA, idB) {
|
||||
};
|
||||
|
||||
action.enabled = function(graph) {
|
||||
var geometries = groupEntitiesByGeometry(graph);
|
||||
|
||||
if (ids.length !== 2 || ids.length !== geometries['line'].length)
|
||||
return false;
|
||||
|
||||
var a = graph.entity(idA),
|
||||
b = graph.entity(idB);
|
||||
|
||||
return a.first() === b.first() ||
|
||||
a.first() === b.last() ||
|
||||
a.last() === b.first() ||
|
||||
|
||||
35
js/id/actions/merge.js
Normal file
35
js/id/actions/merge.js
Normal file
@@ -0,0 +1,35 @@
|
||||
iD.actions.Merge = function(ids) {
|
||||
function groupEntitiesByGeometry(graph) {
|
||||
var entities = ids.map(function(id) { return graph.entity(id); });
|
||||
return _.extend({point: [], area: []}, _.groupBy(entities, function(entity) { return entity.geometry(graph); }));
|
||||
}
|
||||
|
||||
var action = function(graph) {
|
||||
var geometries = groupEntitiesByGeometry(graph),
|
||||
area = geometries.area[0],
|
||||
points = geometries.point;
|
||||
|
||||
points.forEach(function (point) {
|
||||
area = area.mergeTags(point.tags);
|
||||
|
||||
graph.parentRelations(point).forEach(function (parent) {
|
||||
graph = graph.replace(parent.replaceMember(point, area));
|
||||
});
|
||||
|
||||
graph = graph.remove(point);
|
||||
});
|
||||
|
||||
graph = graph.replace(area);
|
||||
|
||||
return graph;
|
||||
};
|
||||
|
||||
action.enabled = function(graph) {
|
||||
var geometries = groupEntitiesByGeometry(graph);
|
||||
return geometries.area.length === 1 &&
|
||||
geometries.point.length > 0 &&
|
||||
(geometries.area.length + geometries.point.length) === ids.length;
|
||||
};
|
||||
|
||||
return action;
|
||||
};
|
||||
@@ -1,9 +1,14 @@
|
||||
/*
|
||||
* Based on https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/potlatch2/tools/Quadrilateralise.as
|
||||
*/
|
||||
|
||||
iD.actions.Orthogonalize = function(wayId, projection) {
|
||||
var action = function(graph) {
|
||||
var way = graph.entity(wayId),
|
||||
nodes = graph.childNodes(way),
|
||||
points = nodes.map(function(n) { return projection(n.loc); }),
|
||||
quad_nodes = [], i, j;
|
||||
quad_nodes = [],
|
||||
best, i, j;
|
||||
|
||||
var score = squareness();
|
||||
for (i = 0; i < 1000; i++) {
|
||||
@@ -12,46 +17,18 @@ iD.actions.Orthogonalize = function(wayId, projection) {
|
||||
points[j] = addPoints(points[j],motions[j]);
|
||||
}
|
||||
var newScore = squareness();
|
||||
if (newScore > score) {
|
||||
return graph;
|
||||
if (newScore < score) {
|
||||
best = _.clone(points);
|
||||
score = newScore;
|
||||
}
|
||||
score = newScore;
|
||||
if (score < 1.0e-8) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
points = best;
|
||||
|
||||
for (i = 0; i < points.length - 1; i++) {
|
||||
quad_nodes.push(iD.Node({ loc: projection.invert(points[i]) }));
|
||||
}
|
||||
|
||||
for (i = 0; i < nodes.length; i++) {
|
||||
if (graph.parentWays(nodes[i]).length > 1) {
|
||||
var closest, closest_dist = Infinity, dist;
|
||||
for (j = 0; j < quad_nodes.length; j++) {
|
||||
dist = iD.geo.dist(quad_nodes[j].loc, nodes[i].loc);
|
||||
if (dist < closest_dist) {
|
||||
closest_dist = dist;
|
||||
closest = j;
|
||||
}
|
||||
}
|
||||
quad_nodes.splice(closest, 1, nodes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < quad_nodes.length; i++) {
|
||||
graph = graph.replace(quad_nodes[i]);
|
||||
}
|
||||
|
||||
var ids = _.pluck(quad_nodes, 'id'),
|
||||
difference = _.difference(_.uniq(way.nodes), ids);
|
||||
|
||||
ids.push(ids[0]);
|
||||
|
||||
graph = graph.replace(way.update({nodes: ids}));
|
||||
|
||||
for (i = 0; i < difference.length; i++) {
|
||||
graph = iD.actions.DeleteNode(difference[i])(graph);
|
||||
graph = graph.replace(graph.entity(nodes[i].id).move(projection.invert(points[i])));
|
||||
}
|
||||
|
||||
return graph;
|
||||
@@ -62,7 +39,7 @@ iD.actions.Orthogonalize = function(wayId, projection) {
|
||||
p = subtractPoints(a, b),
|
||||
q = subtractPoints(c, b);
|
||||
|
||||
var scale = p.length + q.length;
|
||||
var scale = iD.geo.dist(p, [0, 0]) + iD.geo.dist(q, [0, 0]);
|
||||
p = normalizePoint(p, 1.0);
|
||||
q = normalizePoint(q, 1.0);
|
||||
|
||||
|
||||
@@ -15,37 +15,55 @@ iD.actions.Split = function(nodeId, newWayId) {
|
||||
parents = graph.parentWays(node);
|
||||
|
||||
return parents.filter(function (parent) {
|
||||
return parent.first() !== nodeId &&
|
||||
parent.last() !== nodeId;
|
||||
return parent.isClosed() ||
|
||||
(parent.first() !== nodeId &&
|
||||
parent.last() !== nodeId);
|
||||
});
|
||||
}
|
||||
|
||||
var action = function(graph) {
|
||||
if (!action.enabled(graph))
|
||||
return graph;
|
||||
var wayA = candidateWays(graph)[0],
|
||||
wayB = iD.Way({id: newWayId, tags: wayA.tags}),
|
||||
nodesA,
|
||||
nodesB,
|
||||
isArea = wayA.isArea();
|
||||
|
||||
var way = candidateWays(graph)[0],
|
||||
idx = _.indexOf(way.nodes, nodeId);
|
||||
if (wayA.isClosed()) {
|
||||
var nodes = wayA.nodes.slice(0, -1),
|
||||
idxA = _.indexOf(nodes, nodeId),
|
||||
idxB = idxA + Math.floor(nodes.length / 2);
|
||||
|
||||
// Create a 'b' way that contains all of the tags in the second
|
||||
// half of this way
|
||||
var newWay = iD.Way({id: newWayId, tags: way.tags, nodes: way.nodes.slice(idx)});
|
||||
graph = graph.replace(newWay);
|
||||
if (idxB >= nodes.length) {
|
||||
idxB %= nodes.length;
|
||||
nodesA = nodes.slice(idxA).concat(nodes.slice(0, idxB + 1));
|
||||
nodesB = nodes.slice(idxB, idxA + 1);
|
||||
} else {
|
||||
nodesA = nodes.slice(idxA, idxB + 1);
|
||||
nodesB = nodes.slice(idxB).concat(nodes.slice(0, idxA + 1));
|
||||
}
|
||||
} else {
|
||||
var idx = _.indexOf(wayA.nodes, nodeId);
|
||||
nodesA = wayA.nodes.slice(0, idx + 1);
|
||||
nodesB = wayA.nodes.slice(idx);
|
||||
}
|
||||
|
||||
// Reduce the original way to only contain the first set of nodes
|
||||
graph = graph.replace(way.update({nodes: way.nodes.slice(0, idx + 1)}));
|
||||
wayA = wayA.update({nodes: nodesA});
|
||||
wayB = wayB.update({nodes: nodesB});
|
||||
|
||||
graph.parentRelations(way).forEach(function(relation) {
|
||||
graph = graph.replace(wayA);
|
||||
graph = graph.replace(wayB);
|
||||
|
||||
graph.parentRelations(wayA).forEach(function(relation) {
|
||||
if (relation.isRestriction()) {
|
||||
var via = relation.memberByRole('via');
|
||||
if (via && newWay.contains(via.id)) {
|
||||
relation = relation.updateMember({id: newWay.id}, relation.memberById(way.id).index);
|
||||
if (via && wayB.contains(via.id)) {
|
||||
relation = relation.updateMember({id: wayB.id}, relation.memberById(wayA.id).index);
|
||||
graph = graph.replace(relation);
|
||||
}
|
||||
} else {
|
||||
var role = relation.memberById(way.id).role,
|
||||
last = newWay.last(),
|
||||
i = relation.memberById(way.id).index,
|
||||
var role = relation.memberById(wayA.id).role,
|
||||
last = wayB.last(),
|
||||
i = relation.memberById(wayA.id).index,
|
||||
j;
|
||||
|
||||
for (j = 0; j < relation.members.length; j++) {
|
||||
@@ -55,11 +73,24 @@ iD.actions.Split = function(nodeId, newWayId) {
|
||||
}
|
||||
}
|
||||
|
||||
relation = relation.addMember({id: newWay.id, type: 'way', role: role}, i <= j ? i + 1 : i);
|
||||
relation = relation.addMember({id: wayB.id, type: 'wayA', role: role}, i <= j ? i + 1 : i);
|
||||
graph = graph.replace(relation);
|
||||
}
|
||||
});
|
||||
|
||||
if (isArea) {
|
||||
var multipolygon = iD.Relation({
|
||||
tags: _.extend({}, wayA.tags, {type: 'multipolygon'}),
|
||||
members: [
|
||||
{id: wayA.id, role: 'outer', type: 'way'},
|
||||
{id: wayB.id, role: 'outer', type: 'way'}
|
||||
]});
|
||||
|
||||
graph = graph.replace(multipolygon);
|
||||
graph = graph.replace(wayA.update({tags: {}}));
|
||||
graph = graph.replace(wayB.update({tags: {}}));
|
||||
}
|
||||
|
||||
return graph;
|
||||
};
|
||||
|
||||
|
||||
@@ -84,7 +84,11 @@ iD.behavior.DragNode = function(context) {
|
||||
if (d.type === 'node' && d.id !== entity.id) {
|
||||
loc = d.loc;
|
||||
} else if (d.type === 'way') {
|
||||
loc = iD.geo.chooseIndex(d, d3.mouse(context.surface().node()), context).loc;
|
||||
var point = d3.mouse(context.surface().node()),
|
||||
index = iD.geo.chooseIndex(d, point, context);
|
||||
if (iD.geo.dist(point, context.projection(index.loc)) < 10) {
|
||||
loc = index.loc;
|
||||
}
|
||||
}
|
||||
|
||||
context.replace(iD.actions.MoveNode(entity.id, loc));
|
||||
@@ -100,13 +104,18 @@ iD.behavior.DragNode = function(context) {
|
||||
|
||||
var d = datum();
|
||||
if (d.type === 'way') {
|
||||
var choice = iD.geo.chooseIndex(d, d3.mouse(context.surface().node()), context);
|
||||
context.replace(
|
||||
iD.actions.MoveNode(entity.id, choice.loc),
|
||||
iD.actions.AddVertex(d.id, entity.id, choice.index),
|
||||
connectAnnotation(d));
|
||||
var point = d3.mouse(context.surface().node()),
|
||||
choice = iD.geo.chooseIndex(d, point, context);
|
||||
if (iD.geo.dist(point, context.projection(choice.loc)) < 10) {
|
||||
context.replace(
|
||||
iD.actions.MoveNode(entity.id, choice.loc),
|
||||
iD.actions.AddVertex(d.id, entity.id, choice.index),
|
||||
connectAnnotation(d));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
} else if (d.type === 'node' && d.id !== entity.id) {
|
||||
if (d.type === 'node' && d.id !== entity.id) {
|
||||
context.replace(
|
||||
iD.actions.Connect([entity.id, d.id]),
|
||||
connectAnnotation(d));
|
||||
|
||||
@@ -27,13 +27,19 @@ iD.behavior.Draw = function(context) {
|
||||
|
||||
target.on('mousemove.draw', null);
|
||||
|
||||
d3.select(window).on('click.draw', function() {
|
||||
d3.select(window).on('mouseup.draw', function() {
|
||||
target.on('mousemove.draw', mousemove);
|
||||
if (iD.geo.dist(pos, point()) < closeTolerance ||
|
||||
(iD.geo.dist(pos, point()) < tolerance &&
|
||||
(+new Date() - time) < 500)) {
|
||||
click();
|
||||
}
|
||||
if (target.node() === d3.event.target) {
|
||||
d3.select(window).on('click.draw', function() {
|
||||
d3.select(window).on('click.draw', null);
|
||||
d3.event.stopPropagation();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -110,7 +116,7 @@ iD.behavior.Draw = function(context) {
|
||||
.on('mousedown.draw', null)
|
||||
.on('mousemove.draw', null);
|
||||
|
||||
d3.select(window).on('click.draw', null);
|
||||
d3.select(window).on('mouseup.draw', null);
|
||||
|
||||
d3.select(document)
|
||||
.call(keybinding.off)
|
||||
|
||||
64
js/id/behavior/lasso.js
Normal file
64
js/id/behavior/lasso.js
Normal file
@@ -0,0 +1,64 @@
|
||||
iD.behavior.Lasso = function(context) {
|
||||
|
||||
var behavior = function(selection) {
|
||||
|
||||
var timeout = null,
|
||||
// the position of the first mousedown
|
||||
pos = null,
|
||||
lasso;
|
||||
|
||||
function mousedown() {
|
||||
if (d3.event.shiftKey === true) {
|
||||
|
||||
lasso = iD.ui.lasso().a(d3.mouse(context.surface().node()));
|
||||
|
||||
context.surface().call(lasso);
|
||||
|
||||
selection
|
||||
.on('mousemove.lasso', mousemove)
|
||||
.on('mouseup.lasso', mouseup);
|
||||
|
||||
d3.event.stopPropagation();
|
||||
d3.event.preventDefault();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function mousemove() {
|
||||
lasso.b(d3.mouse(context.surface().node()));
|
||||
}
|
||||
|
||||
function normalize(a, b) {
|
||||
return [
|
||||
[Math.min(a[0], b[0]), Math.min(a[1], b[1])],
|
||||
[Math.max(a[0], b[0]), Math.max(a[1], b[1])]];
|
||||
}
|
||||
|
||||
function mouseup() {
|
||||
var extent = iD.geo.Extent(
|
||||
normalize(context.projection.invert(lasso.a()),
|
||||
context.projection.invert(lasso.b())));
|
||||
|
||||
lasso.close();
|
||||
|
||||
var selected = context.graph().intersects(extent);
|
||||
|
||||
selection
|
||||
.on('mousemove.lasso', null)
|
||||
.on('mouseup.lasso', null);
|
||||
|
||||
if (selected.length) {
|
||||
context.enter(iD.modes.Select(context, _.pluck(selected, 'id')));
|
||||
}
|
||||
}
|
||||
|
||||
selection
|
||||
.on('mousedown.lasso', mousedown);
|
||||
};
|
||||
|
||||
behavior.off = function(selection) {
|
||||
selection.on('mousedown.lasso', null);
|
||||
};
|
||||
|
||||
return behavior;
|
||||
};
|
||||
@@ -189,6 +189,9 @@ iD.Graph.prototype = {
|
||||
},
|
||||
|
||||
replace: function(entity) {
|
||||
if (this.entities[entity.id] === entity)
|
||||
return this;
|
||||
|
||||
return this.update(function () {
|
||||
this._updateCalculated(this.entities[entity.id], entity);
|
||||
this.entities[entity.id] = entity;
|
||||
|
||||
@@ -132,9 +132,16 @@ iD.History = function(context) {
|
||||
|
||||
changes: function() {
|
||||
var difference = history.difference();
|
||||
|
||||
function discardTags(entity) {
|
||||
return entity.update({
|
||||
tags: _.omit(entity.tags, iD.data.discarded)
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
modified: difference.modified().map(iD.actions.DiscardTags),
|
||||
created: difference.created().map(iD.actions.DiscardTags),
|
||||
modified: difference.modified().map(discardTags),
|
||||
created: difference.created().map(discardTags),
|
||||
deleted: difference.deleted()
|
||||
};
|
||||
},
|
||||
|
||||
@@ -49,6 +49,16 @@ _.extend(iD.Relation.prototype, {
|
||||
}
|
||||
},
|
||||
|
||||
// Return the first member with the given id and role. A copy of the member object
|
||||
// is returned, extended with an 'index' property whose value is the member index.
|
||||
memberByIdAndRole: function(id, role) {
|
||||
for (var i = 0; i < this.members.length; i++) {
|
||||
if (this.members[i].id === id && this.members[i].role === role) {
|
||||
return _.extend({}, this.members[i], {index: i});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
addMember: function(member, index) {
|
||||
var members = this.members.slice();
|
||||
members.splice(index === undefined ? members.length : index, 0, member);
|
||||
@@ -66,6 +76,28 @@ _.extend(iD.Relation.prototype, {
|
||||
return this.update({members: members});
|
||||
},
|
||||
|
||||
// Wherever a member appears with id `needle.id`, replace it with a member
|
||||
// with id `replacement.id`, type `replacement.type`, and the original role,
|
||||
// unless a member already exists with that id and role. Return an updated
|
||||
// relation.
|
||||
replaceMember: function(needle, replacement) {
|
||||
if (!this.memberById(needle.id))
|
||||
return this;
|
||||
|
||||
var members = [];
|
||||
|
||||
for (var i = 0; i < this.members.length; i++) {
|
||||
var member = this.members[i];
|
||||
if (member.id !== needle.id) {
|
||||
members.push(member);
|
||||
} else if (!this.memberByIdAndRole(replacement.id, member.role)) {
|
||||
members.push({id: replacement.id, type: replacement.type, role: member.role});
|
||||
}
|
||||
}
|
||||
|
||||
return this.update({members: members});
|
||||
},
|
||||
|
||||
asJXON: function(changeset_id) {
|
||||
var r = {
|
||||
relation: {
|
||||
|
||||
@@ -93,7 +93,9 @@ window.iD = function () {
|
||||
};
|
||||
|
||||
context.background()
|
||||
.source(iD.BackgroundSource.Bing);
|
||||
.source(_.find(iD.layers, function(l) {
|
||||
return l.data.name === 'Bing aerial imagery';
|
||||
}));
|
||||
|
||||
return d3.rebind(context, dispatch, 'on');
|
||||
};
|
||||
|
||||
@@ -10,6 +10,7 @@ iD.modes.Browse = function(context) {
|
||||
var behaviors = [
|
||||
iD.behavior.Hover(),
|
||||
iD.behavior.Select(context),
|
||||
iD.behavior.Lasso(context),
|
||||
iD.behavior.DragNode(context)];
|
||||
|
||||
mode.enter = function() {
|
||||
|
||||
@@ -42,6 +42,10 @@ iD.modes.Select = function(context, selection, initial) {
|
||||
.filter(function(o) { return o.available(); });
|
||||
operations.unshift(iD.operations.Delete(selection, context));
|
||||
|
||||
keybinding.on('⎋', function() {
|
||||
context.enter(iD.modes.Browse(context));
|
||||
});
|
||||
|
||||
operations.forEach(function(operation) {
|
||||
keybinding.on(operation.key, function() {
|
||||
if (operation.enabled()) {
|
||||
|
||||
@@ -1,21 +1,28 @@
|
||||
iD.operations.Merge = function(selection, context) {
|
||||
var action = iD.actions.Join(selection[0], selection[1]);
|
||||
var join = iD.actions.Join(selection),
|
||||
merge = iD.actions.Merge(selection);
|
||||
|
||||
var operation = function() {
|
||||
var annotation = t('operations.merge.annotation', {n: selection.length}),
|
||||
difference = context.perform(action, annotation);
|
||||
action;
|
||||
|
||||
if (join.enabled(context.graph())) {
|
||||
action = join;
|
||||
} else {
|
||||
action = merge;
|
||||
}
|
||||
|
||||
var difference = context.perform(action, annotation);
|
||||
context.enter(iD.modes.Select(context, difference.extantIDs()));
|
||||
};
|
||||
|
||||
operation.available = function() {
|
||||
return selection.length === 2 &&
|
||||
_.all(selection, function (id) {
|
||||
return context.geometry(id) === 'line';
|
||||
});
|
||||
return selection.length >= 2;
|
||||
};
|
||||
|
||||
operation.enabled = function() {
|
||||
return action.enabled(context.graph());
|
||||
return join.enabled(context.graph()) ||
|
||||
merge.enabled(context.graph());
|
||||
};
|
||||
|
||||
operation.id = "merge";
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
iD.BackgroundSource = {};
|
||||
|
||||
// derive the url of a 'quadkey' style tile from a coordinate object
|
||||
iD.BackgroundSource.template = function(template, subdomains, scaleExtent) {
|
||||
scaleExtent = scaleExtent || [0, 18];
|
||||
iD.BackgroundSource.template = function(data) {
|
||||
var generator = function(coord) {
|
||||
var u = '';
|
||||
for (var zoom = coord[2]; zoom > 0; zoom--) {
|
||||
@@ -12,19 +11,17 @@ iD.BackgroundSource.template = function(template, subdomains, scaleExtent) {
|
||||
if ((coord[1] & mask) !== 0) byte += 2;
|
||||
u += byte.toString();
|
||||
}
|
||||
// distribute requests against multiple domains
|
||||
var t = subdomains ?
|
||||
subdomains[coord[2] % subdomains.length] : '';
|
||||
return template
|
||||
.replace('{t}', t)
|
||||
|
||||
return data.template
|
||||
.replace('{t}', data.subdomains ?
|
||||
data.subdomains[coord[2] % data.subdomains.length] : '')
|
||||
.replace('{u}', u)
|
||||
.replace('{x}', coord[0])
|
||||
.replace('{y}', coord[1])
|
||||
.replace('{z}', coord[2]);
|
||||
};
|
||||
|
||||
generator.scaleExtent = scaleExtent;
|
||||
generator.template = template;
|
||||
generator.data = data;
|
||||
|
||||
return generator;
|
||||
};
|
||||
@@ -32,21 +29,9 @@ iD.BackgroundSource.template = function(template, subdomains, scaleExtent) {
|
||||
iD.BackgroundSource.Custom = function() {
|
||||
var template = window.prompt('Enter a tile template. Valid tokens are {z}, {x}, {y} for Z/X/Y scheme and {u} for quadtile scheme.');
|
||||
if (!template) return null;
|
||||
return iD.BackgroundSource.template(template, null, [0, 20]);
|
||||
return iD.BackgroundSource.template({
|
||||
template: template,
|
||||
name: 'Custom (customized)'
|
||||
});
|
||||
};
|
||||
|
||||
iD.BackgroundSource.Bing = iD.BackgroundSource.template(
|
||||
'http://ecn.t{t}.tiles.virtualearth.net/tiles/a{u}.jpeg?g=587&mkt=en-gb&n=z',
|
||||
[0, 1, 2, 3], [0, 20]);
|
||||
|
||||
iD.BackgroundSource.Tiger2012 = iD.BackgroundSource.template(
|
||||
'http://{t}.tile.openstreetmap.us/tiger2012_roads_expanded/{z}/{x}/{y}.png',
|
||||
['a', 'b', 'c'], [0, 17]);
|
||||
|
||||
iD.BackgroundSource.OSM = iD.BackgroundSource.template(
|
||||
'http://{t}.tile.openstreetmap.org/{z}/{x}/{y}.png',
|
||||
['a', 'b', 'c'], [0, 18]);
|
||||
|
||||
iD.BackgroundSource.MapBox = iD.BackgroundSource.template(
|
||||
'http://{t}.tiles.mapbox.com/v3/openstreetmap.map-4wvf9l0l/{z}/{x}/{y}.jpg70',
|
||||
['a', 'b', 'c'], [0, 16]);
|
||||
iD.BackgroundSource.Custom.data = { 'name': 'Custom' };
|
||||
|
||||
15
js/id/renderer/layers.js
Normal file
15
js/id/renderer/layers.js
Normal file
@@ -0,0 +1,15 @@
|
||||
iD.layers = iD.data.imagery.map(iD.BackgroundSource.template);
|
||||
|
||||
iD.layers.push((function() {
|
||||
function custom() {
|
||||
var template = window.prompt('Enter a tile template. Valid tokens are {z}, {x}, {y} for Z/X/Y scheme and {u} for quadtile scheme.');
|
||||
if (!template) return null;
|
||||
if (template.match(/google/g)) return null;
|
||||
return iD.BackgroundSource.template({
|
||||
template: template,
|
||||
name: 'Custom (customized)'
|
||||
});
|
||||
}
|
||||
custom.data = { name: 'Custom' };
|
||||
return custom;
|
||||
})());
|
||||
@@ -106,7 +106,7 @@ iD.Map = function(context) {
|
||||
}
|
||||
|
||||
if (Math.log(d3.event.scale / Math.LN2 - 8) < minzoom + 1) {
|
||||
iD.ui.flash()
|
||||
iD.ui.flash(context.container())
|
||||
.select('.content')
|
||||
.text('Cannot zoom out further in current mode.');
|
||||
return map.zoom(16);
|
||||
|
||||
@@ -161,8 +161,9 @@ iD.ui = function(context) {
|
||||
|
||||
var imagery = linkList.append('li').attr('id', 'attribution');
|
||||
imagery.append('span').text('imagery');
|
||||
imagery.append('a').attr('target', '_blank')
|
||||
.attr('href', 'http://opengeodata.org/microsoft-imagery-details').text(' provided by bing');
|
||||
imagery
|
||||
.append('span')
|
||||
.attr('class', 'provided-by');
|
||||
|
||||
linkList.append('li').attr('class', 'source-switch').append('a').attr('href', '#')
|
||||
.text('dev')
|
||||
|
||||
@@ -12,7 +12,7 @@ iD.ui.geocoder = function() {
|
||||
if (err) return hide();
|
||||
hide();
|
||||
if (!resp.length) {
|
||||
return iD.ui.flash()
|
||||
return iD.ui.flash(context.container())
|
||||
.select('.content')
|
||||
.append('h3')
|
||||
.text('No location found for "' + searchVal + '"');
|
||||
|
||||
@@ -163,7 +163,7 @@ iD.ui.inspector = function() {
|
||||
})
|
||||
.call(iD.keyReference(context));
|
||||
} else {
|
||||
iD.ui.flash()
|
||||
iD.ui.flash(context.container())
|
||||
.select('.content')
|
||||
.append('h3')
|
||||
.text(t('inspector.no_documentation_key'));
|
||||
|
||||
63
js/id/ui/lasso.js
Normal file
63
js/id/ui/lasso.js
Normal file
@@ -0,0 +1,63 @@
|
||||
iD.ui.lasso = function() {
|
||||
|
||||
var center, box,
|
||||
group,
|
||||
a = [0, 0],
|
||||
b = [0, 0];
|
||||
|
||||
function lasso(selection) {
|
||||
|
||||
group = selection.append('g')
|
||||
.attr('class', 'lasso')
|
||||
.attr('opacity', 0);
|
||||
|
||||
box = group.append('rect')
|
||||
.attr('class', 'lasso-box');
|
||||
|
||||
group.transition()
|
||||
.style('opacity', 1);
|
||||
|
||||
}
|
||||
|
||||
// top-left
|
||||
function topLeft(d) {
|
||||
return 'translate(' +
|
||||
[Math.min(d[0][0], d[1][0]), Math.min(d[0][1], d[1][1])] + ')';
|
||||
}
|
||||
|
||||
function width(d) { return Math.abs(d[0][0] - d[1][0]); }
|
||||
function height(d) { return Math.abs(d[0][1] - d[1][1]); }
|
||||
|
||||
function draw() {
|
||||
if (box) {
|
||||
box.data([[a, b]])
|
||||
.attr('transform', topLeft)
|
||||
.attr('width', width)
|
||||
.attr('height', height);
|
||||
}
|
||||
}
|
||||
|
||||
lasso.a = function(_) {
|
||||
if (!arguments.length) return a;
|
||||
a = _;
|
||||
draw();
|
||||
return lasso;
|
||||
};
|
||||
|
||||
lasso.b = function(_) {
|
||||
if (!arguments.length) return b;
|
||||
b = _;
|
||||
draw();
|
||||
return lasso;
|
||||
};
|
||||
|
||||
lasso.close = function(selection) {
|
||||
if (group) {
|
||||
group.transition()
|
||||
.attr('opacity', 0)
|
||||
.remove();
|
||||
}
|
||||
};
|
||||
|
||||
return lasso;
|
||||
};
|
||||
@@ -1,31 +1,17 @@
|
||||
iD.ui.layerswitcher = function(context) {
|
||||
var event = d3.dispatch('cancel', 'save'),
|
||||
sources = [{
|
||||
name: 'Bing',
|
||||
source: iD.BackgroundSource.Bing,
|
||||
description: 'Satellite imagery.',
|
||||
link: 'http://opengeodata.org/microsoft-imagery-details'
|
||||
}, {
|
||||
name: 'TIGER 2012',
|
||||
source: iD.BackgroundSource.Tiger2012,
|
||||
description: 'Public domain road data from the US Government.'
|
||||
}, {
|
||||
name: 'OSM',
|
||||
source: iD.BackgroundSource.OSM,
|
||||
description: 'The default OpenStreetMap layer.',
|
||||
link: 'http://www.openstreetmap.org/'
|
||||
}, {
|
||||
name: 'MapBox',
|
||||
source: iD.BackgroundSource.MapBox,
|
||||
description: 'Satellite and aerial imagery.',
|
||||
link: 'http://mapbox.com'
|
||||
}, {
|
||||
name: 'Custom',
|
||||
source: iD.BackgroundSource.Custom,
|
||||
description: 'A custom layer (requires configuration).'
|
||||
}],
|
||||
opacities = [1, 0.5, 0];
|
||||
|
||||
var layers = iD.layers;
|
||||
|
||||
function getSources() {
|
||||
var ext = context.map().extent();
|
||||
return layers.filter(function(layer) {
|
||||
return !layer.data.extent ||
|
||||
iD.geo.Extent(layer.data.extent).intersects(ext);
|
||||
});
|
||||
}
|
||||
|
||||
function layerswitcher(selection) {
|
||||
|
||||
var content = selection
|
||||
@@ -52,7 +38,7 @@ iD.ui.layerswitcher = function(context) {
|
||||
selection.on('click.layerswitcher-inside', function() {
|
||||
return d3.event.stopPropagation();
|
||||
});
|
||||
d3.select('body').on('click.layerswitcher-outside', hide);
|
||||
context.container().on('click.layerswitcher-outside', hide);
|
||||
}
|
||||
|
||||
var opa = content
|
||||
@@ -64,6 +50,17 @@ iD.ui.layerswitcher = function(context) {
|
||||
var opacityList = opa.append('ul')
|
||||
.attr('class', 'opacity-options');
|
||||
|
||||
function setOpacity(d) {
|
||||
context.map().tilesurface
|
||||
.transition()
|
||||
.style('opacity', d)
|
||||
.attr('data-opacity', d);
|
||||
opacityList.selectAll('li')
|
||||
.classed('selected', false);
|
||||
d3.select(this)
|
||||
.classed('selected', true);
|
||||
}
|
||||
|
||||
opacityList.selectAll('div.opacity')
|
||||
.data(opacities)
|
||||
.enter()
|
||||
@@ -71,69 +68,91 @@ iD.ui.layerswitcher = function(context) {
|
||||
.attr('data-original-title', function(d) {
|
||||
return t('layerswitcher.percent_brightness', { opacity: (d * 100) });
|
||||
})
|
||||
.on('click.set-opacity', function(d) {
|
||||
context.map().tilesurface
|
||||
.transition()
|
||||
.style('opacity', d)
|
||||
.attr('data-opacity', d);
|
||||
opacityList.selectAll('li')
|
||||
.classed('selected', false);
|
||||
d3.select(this)
|
||||
.classed('selected', true);
|
||||
})
|
||||
.on('click.set-opacity', setOpacity)
|
||||
.html("<div class='select-box'></div>")
|
||||
.call(bootstrap.tooltip().placement('top'))
|
||||
.append('div')
|
||||
.attr('class', 'opacity')
|
||||
.style('opacity', function(d) {
|
||||
return d;
|
||||
});
|
||||
.style('opacity', String);
|
||||
|
||||
// Make sure there is an active selection by default
|
||||
d3.select('.opacity-options li:nth-child(2)').classed('selected', true);
|
||||
opa.select('.opacity-options li:nth-child(2)').classed('selected', true);
|
||||
|
||||
function selectLayer(d) {
|
||||
|
||||
content.selectAll('a.layer')
|
||||
.classed('selected', function(d) {
|
||||
return d.source === context.background().source();
|
||||
return d === context.background().source();
|
||||
});
|
||||
d3.select('#attribution a')
|
||||
.attr('href', d.link)
|
||||
.text('provided by ' + d.name);
|
||||
|
||||
var provided_by = context.container().select('#attribution .provided-by')
|
||||
.html('');
|
||||
|
||||
if (d.data.terms_url) {
|
||||
provided_by.append('a')
|
||||
.attr('href', (d.data.terms_url || ''))
|
||||
.classed('disabled', !d.data.terms_url)
|
||||
.text(' provided by ' + (d.data.sourcetag || d.data.name));
|
||||
} else {
|
||||
provided_by
|
||||
.text(' provided by ' + (d.data.sourcetag || d.data.name));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
content
|
||||
function clickSetSource(d) {
|
||||
d3.event.preventDefault();
|
||||
if (d.data.name === 'Custom') {
|
||||
var configured = d();
|
||||
if (!configured) return;
|
||||
d = configured;
|
||||
}
|
||||
context.background().source(d);
|
||||
if (d.data.name === 'Custom (customized)') {
|
||||
context.history()
|
||||
.imagery_used('Custom (' + d.data.template + ')');
|
||||
} else {
|
||||
context.history()
|
||||
.imagery_used(d.data.sourcetag || d.data.name);
|
||||
}
|
||||
context.redraw();
|
||||
selectLayer(d);
|
||||
}
|
||||
|
||||
var layerList = content
|
||||
.append('ul')
|
||||
.attr('class', 'toggle-list fillL')
|
||||
.selectAll('a.layer')
|
||||
.data(sources)
|
||||
.enter()
|
||||
.attr('class', 'toggle-list fillL');
|
||||
|
||||
function update() {
|
||||
var layerLinks = layerList.selectAll('a.layer')
|
||||
.data(getSources(), function(d) {
|
||||
return d.data.name;
|
||||
});
|
||||
layerLinks.exit().remove();
|
||||
layerLinks.enter()
|
||||
.append('li')
|
||||
.append('a')
|
||||
.attr('data-original-title', function(d) {
|
||||
return d.description;
|
||||
return d.data.description || '';
|
||||
})
|
||||
.attr('href', '#')
|
||||
.attr('class', 'layer')
|
||||
.text(function(d) {
|
||||
return d.name;
|
||||
return d.data.name;
|
||||
})
|
||||
.call(bootstrap.tooltip().placement('right'))
|
||||
.on('click.set-source', function(d) {
|
||||
d3.event.preventDefault();
|
||||
if (d.name === 'Custom') {
|
||||
var configured = d.source();
|
||||
if (!configured) return;
|
||||
d.source = configured;
|
||||
d.name = 'Custom (' + d.source.template + ')';
|
||||
.each(function(d) {
|
||||
// only set tooltips for layers with tooltips
|
||||
if (d.data.description) {
|
||||
d3.select(this).call(bootstrap.tooltip().placement('right'));
|
||||
}
|
||||
context.background().source(d.source);
|
||||
context.history().imagery_used(d.name);
|
||||
context.redraw();
|
||||
selectLayer(d);
|
||||
})
|
||||
.on('click.set-source', clickSetSource)
|
||||
.insert('span')
|
||||
.attr('class','icon toggle');
|
||||
selectLayer(context.background().source());
|
||||
}
|
||||
|
||||
context.map().on('move.layerswitcher-update', _.debounce(update, 1000));
|
||||
|
||||
var adjustments = content
|
||||
.append('div')
|
||||
|
||||
@@ -30,7 +30,7 @@ iD.ui.save = function(context) {
|
||||
function click() {
|
||||
|
||||
function commit(e) {
|
||||
d3.select('.shaded').remove();
|
||||
context.container().select('.shaded').remove();
|
||||
var l = iD.ui.loading(context.container(), t('uploading_changes'), true);
|
||||
|
||||
connection.putChangeset(history.changes(),
|
||||
|
||||
@@ -35,12 +35,17 @@
|
||||
<script src='../js/id/oauth.js'></script>
|
||||
<script src='../js/id/services/taginfo.js'></script>
|
||||
|
||||
<script src='../data/data.js'></script>
|
||||
<script src='../data/deprecated.js'></script>
|
||||
<script src='../data/imagery.js'></script>
|
||||
|
||||
<script src="../js/id/geo.js"></script>
|
||||
<script src="../js/id/geo/extent.js"></script>
|
||||
|
||||
<script src='../js/id/renderer/background.js'></script>
|
||||
<script src='../js/id/renderer/background_source.js'></script>
|
||||
<script src='../js/id/renderer/map.js'></script>
|
||||
<script src='../js/id/renderer/layers.js'></script>
|
||||
|
||||
<script src="../js/id/svg.js"></script>
|
||||
<script src="../js/id/svg/areas.js"></script>
|
||||
@@ -62,6 +67,7 @@
|
||||
<script src='../js/id/ui/geocoder.js'></script>
|
||||
<script src='../js/id/ui/notice.js'></script>
|
||||
<script src='../js/id/ui/modal.js'></script>
|
||||
<script src='../js/id/ui/lasso.js'></script>
|
||||
<script src='../js/id/ui/flash.js'></script>
|
||||
<script src='../js/id/ui/confirm.js'></script>
|
||||
<script src='../js/id/ui/splash.js'></script>
|
||||
@@ -80,6 +86,7 @@
|
||||
<script src="../js/id/actions/delete_way.js"></script>
|
||||
<script src='../js/id/actions/disconnect.js'></script>
|
||||
<script src='../js/id/actions/join.js'></script>
|
||||
<script src='../js/id/actions/merge.js'></script>
|
||||
<script src='../js/id/actions/move_node.js'></script>
|
||||
<script src='../js/id/actions/move_way.js'></script>
|
||||
<script src='../js/id/actions/noop.js'></script>
|
||||
@@ -95,6 +102,7 @@
|
||||
<script src='../js/id/behavior/draw_way.js'></script>
|
||||
<script src='../js/id/behavior/hash.js'></script>
|
||||
<script src='../js/id/behavior/hover.js'></script>
|
||||
<script src='../js/id/behavior/lasso.js'></script>
|
||||
<script src='../js/id/behavior/select.js'></script>
|
||||
|
||||
<script src='../js/id/modes.js'></script>
|
||||
@@ -130,17 +138,6 @@
|
||||
<script src='../locale/locale.js'></script>
|
||||
<script src='../locale/en.js'></script>
|
||||
|
||||
<script src='../data/data.js'></script>
|
||||
<script src='../data/deprecated.js'></script>
|
||||
|
||||
<script>
|
||||
iD.debug = true;
|
||||
mocha.setup({
|
||||
ui: 'bdd',
|
||||
globals: ['__onresize.tail-size', '__onmousemove.zoom', '__onmouseup.zoom', '__onclick.draw']
|
||||
});
|
||||
var expect = chai.expect;
|
||||
</script>
|
||||
|
||||
<script src="spec/spec_helpers.js"></script>
|
||||
|
||||
@@ -157,6 +154,7 @@
|
||||
<script src="spec/actions/delete_way.js"></script>
|
||||
<script src='spec/actions/disconnect.js'></script>
|
||||
<script src="spec/actions/join.js"></script>
|
||||
<script src='spec/actions/merge.js'></script>
|
||||
<script src="spec/actions/move_node.js"></script>
|
||||
<script src="spec/actions/move_way.js"></script>
|
||||
<script src="spec/actions/noop.js"></script>
|
||||
|
||||
@@ -18,15 +18,6 @@
|
||||
<!-- include source files here... -->
|
||||
<script src='../iD.min.js'></script>
|
||||
|
||||
<script>
|
||||
iD.debug = true;
|
||||
mocha.setup({
|
||||
ui: 'bdd',
|
||||
globals: ['__onresize.tail-size']
|
||||
});
|
||||
var expect = chai.expect;
|
||||
</script>
|
||||
|
||||
<script src="spec/spec_helpers.js"></script>
|
||||
|
||||
<!-- include spec files here... -->
|
||||
@@ -42,6 +33,7 @@
|
||||
<script src="spec/actions/delete_way.js"></script>
|
||||
<script src='spec/actions/disconnect.js'></script>
|
||||
<script src="spec/actions/join.js"></script>
|
||||
<script src='spec/actions/merge.js'></script>
|
||||
<script src="spec/actions/move_node.js"></script>
|
||||
<script src="spec/actions/move_way.js"></script>
|
||||
<script src="spec/actions/noop.js"></script>
|
||||
|
||||
@@ -99,7 +99,7 @@ describe("iD.actions.Connect", function() {
|
||||
'-': iD.Way({id: '-', nodes: ['a', 'b']}),
|
||||
'=': iD.Way({id: '=', nodes: ['c', 'd']}),
|
||||
'r1': iD.Relation({id: 'r1', members: [{id: 'b', role: 'r1', type: 'node'}]}),
|
||||
'r2': iD.Relation({id: 'r2', members: [{id: 'b', role: 'r1', type: 'node'}, {id: 'c', role: 'r2', type: 'node'}]})
|
||||
'r2': iD.Relation({id: 'r2', members: [{id: 'b', role: 'r2', type: 'node'}, {id: 'c', role: 'r2', type: 'node'}]})
|
||||
});
|
||||
|
||||
graph = iD.actions.Connect(['b', 'c'])(graph);
|
||||
|
||||
@@ -10,7 +10,7 @@ describe("iD.actions.Join", function () {
|
||||
'=': iD.Way({id: '=', nodes: ['b', 'c']})
|
||||
});
|
||||
|
||||
expect(iD.actions.Join('-', '=').enabled(graph)).to.be.true;
|
||||
expect(iD.actions.Join(['-', '=']).enabled(graph)).to.be.true;
|
||||
});
|
||||
|
||||
it("returns true for ways that share a start/end node", function () {
|
||||
@@ -23,7 +23,7 @@ describe("iD.actions.Join", function () {
|
||||
'=': iD.Way({id: '=', nodes: ['c', 'b']})
|
||||
});
|
||||
|
||||
expect(iD.actions.Join('-', '=').enabled(graph)).to.be.true;
|
||||
expect(iD.actions.Join(['-', '=']).enabled(graph)).to.be.true;
|
||||
});
|
||||
|
||||
it("returns true for ways that share a start/start node", function () {
|
||||
@@ -36,7 +36,7 @@ describe("iD.actions.Join", function () {
|
||||
'=': iD.Way({id: '=', nodes: ['b', 'c']})
|
||||
});
|
||||
|
||||
expect(iD.actions.Join('-', '=').enabled(graph)).to.be.true;
|
||||
expect(iD.actions.Join(['-', '=']).enabled(graph)).to.be.true;
|
||||
});
|
||||
|
||||
it("returns true for ways that share an end/end node", function () {
|
||||
@@ -49,7 +49,7 @@ describe("iD.actions.Join", function () {
|
||||
'=': iD.Way({id: '=', nodes: ['c', 'b']})
|
||||
});
|
||||
|
||||
expect(iD.actions.Join('-', '=').enabled(graph)).to.be.true;
|
||||
expect(iD.actions.Join(['-', '=']).enabled(graph)).to.be.true;
|
||||
});
|
||||
|
||||
it("returns false for ways that don't share the necessary nodes", function () {
|
||||
@@ -65,7 +65,7 @@ describe("iD.actions.Join", function () {
|
||||
'=': iD.Way({id: '=', nodes: ['b', 'd']})
|
||||
});
|
||||
|
||||
expect(iD.actions.Join('-', '=').enabled(graph)).to.be.false;
|
||||
expect(iD.actions.Join(['-', '=']).enabled(graph)).to.be.false;
|
||||
});
|
||||
});
|
||||
|
||||
@@ -80,7 +80,7 @@ describe("iD.actions.Join", function () {
|
||||
'=': iD.Way({id: '=', nodes: ['b', 'c']})
|
||||
});
|
||||
|
||||
graph = iD.actions.Join('-', '=')(graph);
|
||||
graph = iD.actions.Join(['-', '='])(graph);
|
||||
|
||||
expect(graph.entity('-').nodes).to.eql(['a', 'b', 'c']);
|
||||
expect(graph.entity('=')).to.be.undefined;
|
||||
@@ -97,7 +97,7 @@ describe("iD.actions.Join", function () {
|
||||
'=': iD.Way({id: '=', nodes: ['c', 'b']})
|
||||
});
|
||||
|
||||
graph = iD.actions.Join('-', '=')(graph);
|
||||
graph = iD.actions.Join(['-', '='])(graph);
|
||||
|
||||
expect(graph.entity('-').nodes).to.eql(['c', 'b', 'a']);
|
||||
expect(graph.entity('=')).to.be.undefined;
|
||||
@@ -112,13 +112,14 @@ describe("iD.actions.Join", function () {
|
||||
'b': iD.Node({id: 'b'}),
|
||||
'c': iD.Node({id: 'c'}),
|
||||
'-': iD.Way({id: '-', nodes: ['b', 'a']}),
|
||||
'=': iD.Way({id: '=', nodes: ['b', 'c']})
|
||||
'=': iD.Way({id: '=', nodes: ['b', 'c'], tags: {'lanes:forward': 2}})
|
||||
});
|
||||
|
||||
graph = iD.actions.Join('-', '=')(graph);
|
||||
graph = iD.actions.Join(['-', '='])(graph);
|
||||
|
||||
expect(graph.entity('-').nodes).to.eql(['c', 'b', 'a']);
|
||||
expect(graph.entity('=')).to.be.undefined;
|
||||
expect(graph.entity('-').tags).to.eql({'lanes:backward': 2});
|
||||
});
|
||||
|
||||
it("joins a --> b <== c", function () {
|
||||
@@ -130,13 +131,14 @@ describe("iD.actions.Join", function () {
|
||||
'b': iD.Node({id: 'b'}),
|
||||
'c': iD.Node({id: 'c'}),
|
||||
'-': iD.Way({id: '-', nodes: ['a', 'b']}),
|
||||
'=': iD.Way({id: '=', nodes: ['c', 'b']})
|
||||
'=': iD.Way({id: '=', nodes: ['c', 'b'], tags: {'lanes:forward': 2}})
|
||||
});
|
||||
|
||||
graph = iD.actions.Join('-', '=')(graph);
|
||||
graph = iD.actions.Join(['-', '='])(graph);
|
||||
|
||||
expect(graph.entity('-').nodes).to.eql(['a', 'b', 'c']);
|
||||
expect(graph.entity('=')).to.be.undefined;
|
||||
expect(graph.entity('-').tags).to.eql({'lanes:backward': 2});
|
||||
});
|
||||
|
||||
it("merges tags", function () {
|
||||
@@ -148,7 +150,7 @@ describe("iD.actions.Join", function () {
|
||||
'=': iD.Way({id: '=', nodes: ['b', 'c'], tags: {a: 'a', b: '=', d: 'd'}})
|
||||
});
|
||||
|
||||
graph = iD.actions.Join('-', '=')(graph);
|
||||
graph = iD.actions.Join(['-', '='])(graph);
|
||||
|
||||
expect(graph.entity('-').tags).to.eql({a: 'a', b: '-; =', c: 'c', d: 'd'});
|
||||
});
|
||||
@@ -161,10 +163,10 @@ describe("iD.actions.Join", function () {
|
||||
'-': iD.Way({id: '-', nodes: ['a', 'b']}),
|
||||
'=': iD.Way({id: '=', nodes: ['b', 'c']}),
|
||||
'r1': iD.Relation({id: 'r1', members: [{id: '=', role: 'r1', type: 'way'}]}),
|
||||
'r2': iD.Relation({id: 'r2', members: [{id: '=', role: 'r1', type: 'way'}, {id: '-', role: 'r2', type: 'way'}]})
|
||||
'r2': iD.Relation({id: 'r2', members: [{id: '=', role: 'r2', type: 'way'}, {id: '-', role: 'r2', type: 'way'}]})
|
||||
});
|
||||
|
||||
graph = iD.actions.Join('-', '=')(graph);
|
||||
graph = iD.actions.Join(['-', '='])(graph);
|
||||
|
||||
expect(graph.entity('r1').members).to.eql([{id: '-', role: 'r1', type: 'way'}]);
|
||||
expect(graph.entity('r2').members).to.eql([{id: '-', role: 'r2', type: 'way'}]);
|
||||
|
||||
20
test/spec/actions/merge.js
Normal file
20
test/spec/actions/merge.js
Normal file
@@ -0,0 +1,20 @@
|
||||
describe("iD.actions.Merge", function () {
|
||||
it("merges multiple points to an area", function () {
|
||||
var graph = iD.Graph({
|
||||
'a': iD.Node({id: 'a', tags: {a: 'a'}}),
|
||||
'b': iD.Node({id: 'b', tags: {b: 'b'}}),
|
||||
'w': iD.Way({id: 'w', tags: {area: 'yes'}}),
|
||||
'r': iD.Relation({id: 'r', members: [{id: 'a', role: 'r', type: 'node'}]})
|
||||
}),
|
||||
action = iD.actions.Merge(['a', 'b', 'w']);
|
||||
|
||||
expect(action.enabled(graph)).to.be.true;
|
||||
|
||||
graph = action(graph);
|
||||
|
||||
expect(graph.entity('a')).to.be.undefined;
|
||||
expect(graph.entity('b')).to.be.undefined;
|
||||
expect(graph.entity('w').tags).to.eql({a: 'a', b: 'b', area: 'yes'});
|
||||
expect(graph.entity('r').members).to.eql([{id: 'w', role: 'r', type: 'way'}]);
|
||||
});
|
||||
});
|
||||
@@ -99,6 +99,66 @@ describe("iD.actions.Split", function () {
|
||||
expect(graph.entity('|').nodes).to.eql(['d', 'b']);
|
||||
});
|
||||
|
||||
it("splits a closed way at the given point and its antipode", function () {
|
||||
// Situation:
|
||||
// a ---- b
|
||||
// | |
|
||||
// d ---- c
|
||||
//
|
||||
// Split at a.
|
||||
//
|
||||
// Expected result:
|
||||
// a ---- b
|
||||
// || |
|
||||
// d ==== c
|
||||
//
|
||||
var graph = iD.Graph({
|
||||
'a': iD.Node({id: 'a'}),
|
||||
'b': iD.Node({id: 'b'}),
|
||||
'c': iD.Node({id: 'c'}),
|
||||
'd': iD.Node({id: 'd'}),
|
||||
'-': iD.Way({id: '-', nodes: ['a', 'b', 'c', 'd', 'a']})
|
||||
});
|
||||
|
||||
var g1 = iD.actions.Split('a', '=')(graph);
|
||||
expect(g1.entity('-').nodes).to.eql(['a', 'b', 'c']);
|
||||
expect(g1.entity('=').nodes).to.eql(['c', 'd', 'a']);
|
||||
|
||||
var g2 = iD.actions.Split('b', '=')(graph);
|
||||
expect(g2.entity('-').nodes).to.eql(['b', 'c', 'd']);
|
||||
expect(g2.entity('=').nodes).to.eql(['d', 'a', 'b']);
|
||||
|
||||
var g3 = iD.actions.Split('c', '=')(graph);
|
||||
expect(g3.entity('-').nodes).to.eql(['c', 'd', 'a']);
|
||||
expect(g3.entity('=').nodes).to.eql(['a', 'b', 'c']);
|
||||
|
||||
var g4 = iD.actions.Split('d', '=')(graph);
|
||||
expect(g4.entity('-').nodes).to.eql(['d', 'a', 'b']);
|
||||
expect(g4.entity('=').nodes).to.eql(['b', 'c', 'd']);
|
||||
});
|
||||
|
||||
it("splits an area by converting it to a multipolygon", function () {
|
||||
var graph = iD.Graph({
|
||||
'a': iD.Node({id: 'a'}),
|
||||
'b': iD.Node({id: 'b'}),
|
||||
'c': iD.Node({id: 'c'}),
|
||||
'd': iD.Node({id: 'd'}),
|
||||
'-': iD.Way({id: '-', tags: {building: 'yes'}, nodes: ['a', 'b', 'c', 'd', 'a']})
|
||||
});
|
||||
|
||||
graph = iD.actions.Split('a', '=')(graph);
|
||||
expect(graph.entity('-').tags).to.eql({});
|
||||
expect(graph.entity('=').tags).to.eql({});
|
||||
expect(graph.parentRelations(graph.entity('-'))).to.have.length(1);
|
||||
|
||||
var relation = graph.parentRelations(graph.entity('-'))[0];
|
||||
expect(relation.tags).to.eql({type: 'multipolygon', building: 'yes'});
|
||||
expect(relation.members).to.eql([
|
||||
{id: '-', role: 'outer', type: 'way'},
|
||||
{id: '=', role: 'outer', type: 'way'}
|
||||
]);
|
||||
});
|
||||
|
||||
it("adds the new way to parent relations (no connections)", function () {
|
||||
// Situation:
|
||||
// a ---- b ---- c
|
||||
|
||||
@@ -196,10 +196,16 @@ describe('iD.Graph', function() {
|
||||
});
|
||||
|
||||
describe("#replace", function () {
|
||||
it("is a no-op if the replacement is identical to the existing entity", function () {
|
||||
var node = iD.Node(),
|
||||
graph = iD.Graph([node]);
|
||||
expect(graph.replace(node)).to.equal(graph);
|
||||
});
|
||||
|
||||
it("returns a new graph", function () {
|
||||
var node = iD.Node(),
|
||||
graph = iD.Graph([node]);
|
||||
expect(graph.replace(node)).not.to.equal(graph);
|
||||
expect(graph.replace(node.update())).not.to.equal(graph);
|
||||
});
|
||||
|
||||
it("doesn't modify the receiver", function () {
|
||||
@@ -257,7 +263,6 @@ describe('iD.Graph', function() {
|
||||
graph = iD.Graph([node, r1]);
|
||||
expect(graph.replace(r1).parentRelations(node)).to.eql([r1]);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe("#update", function () {
|
||||
|
||||
@@ -131,6 +131,35 @@ describe('iD.Relation', function () {
|
||||
});
|
||||
});
|
||||
|
||||
describe("#replaceMember", function () {
|
||||
it("returns self if self does not contain needle", function () {
|
||||
var r = iD.Relation({members: []});
|
||||
expect(r.replaceMember({id: 'a'}, {id: 'b'})).to.equal(r);
|
||||
});
|
||||
|
||||
it("replaces a member which doesn't already exist", function () {
|
||||
var r = iD.Relation({members: [{id: 'a', role: 'a'}]});
|
||||
expect(r.replaceMember({id: 'a'}, {id: 'b', type: 'node'}).members).to.eql([{id: 'b', role: 'a', type: 'node'}]);
|
||||
});
|
||||
|
||||
it("preserves the existing role", function () {
|
||||
var r = iD.Relation({members: [{id: 'a', role: 'a', type: 'node'}]});
|
||||
expect(r.replaceMember({id: 'a'}, {id: 'b', type: 'node'}).members).to.eql([{id: 'b', role: 'a', type: 'node'}]);
|
||||
});
|
||||
|
||||
it("uses the replacement type", function () {
|
||||
var r = iD.Relation({members: [{id: 'a', role: 'a', type: 'node'}]});
|
||||
expect(r.replaceMember({id: 'a'}, {id: 'b', type: 'way'}).members).to.eql([{id: 'b', role: 'a', type: 'way'}]);
|
||||
});
|
||||
|
||||
it("removes members if replacing them would produce duplicates", function () {
|
||||
var r = iD.Relation({members: [
|
||||
{id: 'a', role: 'b', type: 'node'},
|
||||
{id: 'b', role: 'b', type: 'node'}]});
|
||||
expect(r.replaceMember({id: 'a'}, {id: 'b', type: 'node'}).members).to.eql([{id: 'b', role: 'b', type: 'node'}]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#asJXON", function () {
|
||||
it('converts a relation to jxon', function() {
|
||||
var relation = iD.Relation({id: 'r-1', members: [{id: 'w1', role: 'forward', type: 'way'}], tags: {type: 'route'}});
|
||||
|
||||
@@ -17,13 +17,13 @@ describe("iD.modes.AddPoint", function() {
|
||||
describe("clicking the map", function () {
|
||||
it("adds a node", function() {
|
||||
happen.mousedown(context.surface().node(), {});
|
||||
happen.click(window, {});
|
||||
happen.mouseup(window, {});
|
||||
expect(context.changes().created).to.have.length(1);
|
||||
});
|
||||
|
||||
it("selects the node", function() {
|
||||
happen.mousedown(context.surface().node(), {});
|
||||
happen.click(window, {});
|
||||
happen.mouseup(window, {});
|
||||
expect(context.mode().id).to.equal('select');
|
||||
expect(context.mode().selection()).to.eql([context.changes().created[0].id]);
|
||||
});
|
||||
|
||||
@@ -27,27 +27,21 @@ describe('iD.Background', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('iD.BackgroundSource.Bing', function() {
|
||||
it('generates tiles', function() {
|
||||
expect(iD.BackgroundSource.Bing([0,0,0])).to.equal('http://ecn.t0.tiles.virtualearth.net/tiles/a.jpeg?g=587&mkt=en-gb&n=z');
|
||||
});
|
||||
});
|
||||
|
||||
describe('iD.BackgroundSource.Template', function() {
|
||||
it('does not error with blank template', function() {
|
||||
var source = iD.BackgroundSource.template('');
|
||||
var source = iD.BackgroundSource.template({ template: '' });
|
||||
expect(source([0,1,2])).to.equal('');
|
||||
});
|
||||
it('generates a tile-generating source', function() {
|
||||
var source = iD.BackgroundSource.template('{z}/{x}/{y}');
|
||||
var source = iD.BackgroundSource.template({ template: '{z}/{x}/{y}' });
|
||||
expect(source([0,1,2])).to.equal('2/0/1');
|
||||
});
|
||||
it('supports subdomains', function() {
|
||||
var source = iD.BackgroundSource.template('{t}/{z}/{x}/{y}', ['apples', 'oranges']);
|
||||
var source = iD.BackgroundSource.template({ template: '{t}/{z}/{x}/{y}', subdomains: ['apples', 'oranges'] });
|
||||
expect(source([0,1,2])).to.equal('apples/2/0/1');
|
||||
});
|
||||
it('distributes requests between subdomains', function() {
|
||||
var source = iD.BackgroundSource.template('{t}/{z}/{x}/{y}', ['apples', 'oranges']);
|
||||
var source = iD.BackgroundSource.template({ template: '{t}/{z}/{x}/{y}', subdomains: ['apples', 'oranges'] });
|
||||
expect(source([0,1,1])).to.equal('oranges/1/0/1');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,3 +1,12 @@
|
||||
iD.debug = true;
|
||||
|
||||
mocha.setup({
|
||||
ui: 'bdd',
|
||||
globals: ['__onresize.tail-size', '__onmousemove.zoom', '__onmouseup.zoom', '__onclick.draw']
|
||||
});
|
||||
|
||||
var expect = chai.expect;
|
||||
|
||||
chai.use(function (chai, utils) {
|
||||
var flag = utils.flag;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user