mirror of
https://github.com/FoggedLens/iD.git
synced 2026-03-07 03:41:33 +00:00
17
css/app.css
17
css/app.css
@@ -1433,6 +1433,14 @@ div.combobox {
|
||||
height:18px;
|
||||
}
|
||||
|
||||
.background-control .layer-toggle-gpx .layer-extent {
|
||||
display:none;
|
||||
}
|
||||
|
||||
.background-control .layer-toggle-gpx.selected .layer-extent {
|
||||
display:inline-block;
|
||||
}
|
||||
|
||||
/* Geocoder */
|
||||
|
||||
.geocode-control, .geocode-control form {
|
||||
@@ -1489,9 +1497,12 @@ div.combobox {
|
||||
background:#000;
|
||||
}
|
||||
|
||||
#surface, #tile-g {
|
||||
#surface, #layer-g, .layer-layer {
|
||||
position:absolute;
|
||||
top:0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
transform-origin:0 0;
|
||||
-ms-transform-origin:0 0;
|
||||
-webkit-transform-origin:0 0;
|
||||
@@ -1507,10 +1518,6 @@ div.combobox {
|
||||
position: static;
|
||||
}
|
||||
|
||||
#tile-g {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
/* About Section
|
||||
------------------------------------------------------- */
|
||||
|
||||
|
||||
@@ -886,6 +886,14 @@ text.point {
|
||||
pointer-events: visibleStroke;
|
||||
}
|
||||
|
||||
/* GPX Paths */
|
||||
path.gpx {
|
||||
stroke:#6AFF25;
|
||||
stroke-width:2;
|
||||
fill:transparent;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Modes */
|
||||
|
||||
.mode-draw-line .vertex.active,
|
||||
|
||||
@@ -184,3 +184,6 @@ en:
|
||||
out: Zoom Out
|
||||
imagery:
|
||||
provided_by: "Imagery provided by {source}"
|
||||
gpx:
|
||||
local_layer: "Local GPX file"
|
||||
drag_drop: "Drag and drop a .gpx file on the page"
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
<script src='js/lib/d3-compat.js'></script>
|
||||
<script src='js/lib/bootstrap-tooltip.js'></script>
|
||||
<script src='js/lib/rtree.js'></script>
|
||||
<script src='js/lib/togeojson.js'></script>
|
||||
|
||||
<script src='js/id/id.js'></script>
|
||||
<script src='js/id/util.js'></script>
|
||||
@@ -41,6 +42,7 @@
|
||||
|
||||
<script src='js/id/renderer/background.js'></script>
|
||||
<script src='js/id/renderer/background_source.js'></script>
|
||||
<script src='js/id/renderer/localgpx.js'></script>
|
||||
<script src='js/id/renderer/map.js'></script>
|
||||
|
||||
<script src="js/id/svg.js"></script>
|
||||
|
||||
@@ -91,7 +91,8 @@ window.iD = function () {
|
||||
};
|
||||
|
||||
/* Map */
|
||||
context.background = function() { return map.background; };
|
||||
context.layers = function() { return map.layers; };
|
||||
context.background = function() { return map.layers[0]; };
|
||||
context.surface = function() { return map.surface; };
|
||||
context.projection = map.projection;
|
||||
context.tail = map.tail;
|
||||
@@ -124,7 +125,7 @@ window.iD = function () {
|
||||
|
||||
var q = iD.util.stringQs(location.hash.substring(1)), detected = false;
|
||||
if (q.layer) {
|
||||
context.background()
|
||||
context.layers()[0]
|
||||
.source(_.find(backgroundSources, function(l) {
|
||||
if (l.data.sourcetag === q.layer) {
|
||||
detected = true;
|
||||
@@ -163,6 +164,8 @@ iD.detect = function() {
|
||||
|
||||
browser.locale = navigator.language;
|
||||
|
||||
browser.filedrop = (window.FileReader && 'ondrop' in window);
|
||||
|
||||
function nav(x) {
|
||||
return navigator.userAgent.indexOf(x) !== -1;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,8 @@ iD.BackgroundSource = {};
|
||||
|
||||
// derive the url of a 'quadkey' style tile from a coordinate object
|
||||
iD.BackgroundSource.template = function(data) {
|
||||
var generator = function(coord) {
|
||||
|
||||
function generator(coord) {
|
||||
var u = '';
|
||||
for (var zoom = coord[2]; zoom > 0; zoom--) {
|
||||
var b = 0;
|
||||
@@ -25,7 +26,7 @@ iD.BackgroundSource.template = function(data) {
|
||||
var subdomains = r.split(':')[1].split(',');
|
||||
return subdomains[coord[2] % subdomains.length];
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
generator.data = data;
|
||||
|
||||
|
||||
94
js/id/renderer/localgpx.js
Normal file
94
js/id/renderer/localgpx.js
Normal file
@@ -0,0 +1,94 @@
|
||||
iD.LocalGpx = function(context) {
|
||||
var tileSize = 256,
|
||||
projection,
|
||||
gj = {},
|
||||
enable = true,
|
||||
size = [0, 0],
|
||||
transformProp = iD.util.prefixCSSProperty('Transform'),
|
||||
path = d3.geo.path().projection(projection),
|
||||
source = d3.functor('');
|
||||
|
||||
function render(selection) {
|
||||
|
||||
path.projection(projection);
|
||||
|
||||
var surf = selection.selectAll('svg')
|
||||
.data(enable ? [gj] : []);
|
||||
|
||||
surf.exit().remove();
|
||||
|
||||
surf.enter()
|
||||
.append('svg')
|
||||
.style('position', 'absolute');
|
||||
|
||||
var paths = surf
|
||||
.selectAll('path')
|
||||
.data(function(d) { return [d]; });
|
||||
|
||||
paths
|
||||
.enter()
|
||||
.append('path')
|
||||
.attr('class', 'gpx');
|
||||
|
||||
paths
|
||||
.attr('d', path);
|
||||
}
|
||||
|
||||
function toDom(x) {
|
||||
return (new DOMParser()).parseFromString(x, 'text/xml');
|
||||
}
|
||||
|
||||
render.projection = function(_) {
|
||||
if (!arguments.length) return projection;
|
||||
projection = _;
|
||||
return render;
|
||||
};
|
||||
|
||||
render.enable = function(_) {
|
||||
if (!arguments.length) return enable;
|
||||
enable = _;
|
||||
return render;
|
||||
};
|
||||
|
||||
render.geojson = function(_) {
|
||||
if (!arguments.length) return gj;
|
||||
gj = _;
|
||||
return render;
|
||||
};
|
||||
|
||||
render.size = function(_) {
|
||||
if (!arguments.length) return size;
|
||||
size = _;
|
||||
return render;
|
||||
};
|
||||
|
||||
render.id = 'layer-gpx';
|
||||
|
||||
function over() {
|
||||
d3.event.stopPropagation();
|
||||
d3.event.preventDefault();
|
||||
d3.event.dataTransfer.dropEffect = 'copy';
|
||||
}
|
||||
|
||||
d3.select('body')
|
||||
.attr('dropzone', 'copy')
|
||||
.on('drop.localgpx', function() {
|
||||
d3.event.stopPropagation();
|
||||
d3.event.preventDefault();
|
||||
var f = d3.event.dataTransfer.files[0],
|
||||
reader = new FileReader();
|
||||
|
||||
reader.onload = function(e) {
|
||||
render.geojson(toGeoJSON.gpx(toDom(e.target.result)));
|
||||
context.redraw();
|
||||
context.map().pan([0, 0]);
|
||||
};
|
||||
|
||||
reader.readAsText(f);
|
||||
})
|
||||
.on('dragenter.localgpx', over)
|
||||
.on('dragexit.localgpx', over)
|
||||
.on('dragover.localgpx', over);
|
||||
|
||||
return render;
|
||||
};
|
||||
@@ -11,8 +11,9 @@ iD.Map = function(context) {
|
||||
dblclickEnabled = true,
|
||||
transformStart,
|
||||
minzoom = 0,
|
||||
background = iD.Background()
|
||||
.projection(projection),
|
||||
layers = [
|
||||
iD.Background().projection(projection),
|
||||
iD.LocalGpx(context).projection(projection)],
|
||||
transformProp = iD.util.prefixCSSProperty('Transform'),
|
||||
points = iD.svg.Points(roundedProjection, context),
|
||||
vertices = iD.svg.Vertices(roundedProjection, context),
|
||||
@@ -21,7 +22,7 @@ iD.Map = function(context) {
|
||||
midpoints = iD.svg.Midpoints(roundedProjection),
|
||||
labels = iD.svg.Labels(roundedProjection, context),
|
||||
tail = iD.ui.Tail(),
|
||||
surface, tilegroup;
|
||||
surface, layergroup;
|
||||
|
||||
function map(selection) {
|
||||
context.history()
|
||||
@@ -29,8 +30,8 @@ iD.Map = function(context) {
|
||||
|
||||
selection.call(zoom);
|
||||
|
||||
tilegroup = selection.append('div')
|
||||
.attr('id', 'tile-g');
|
||||
layergroup = selection.append('div')
|
||||
.attr('id', 'layer-g');
|
||||
|
||||
var supersurface = selection.append('div')
|
||||
.style('position', 'absolute');
|
||||
@@ -47,10 +48,9 @@ iD.Map = function(context) {
|
||||
.attr('id', 'surface')
|
||||
.call(iD.svg.Surface());
|
||||
|
||||
|
||||
map.size(selection.size());
|
||||
map.surface = surface;
|
||||
map.tilesurface = tilegroup;
|
||||
map.layersurface = layergroup;
|
||||
|
||||
supersurface
|
||||
.call(tail);
|
||||
@@ -131,7 +131,7 @@ iD.Map = function(context) {
|
||||
'scale(' + scale + ')' +
|
||||
'translate(' + tX + 'px,' + tY + 'px) ';
|
||||
|
||||
tilegroup.style(transformProp, transform);
|
||||
layergroup.style(transformProp, transform);
|
||||
surface.style(transformProp, transform);
|
||||
queueRedraw();
|
||||
|
||||
@@ -142,7 +142,7 @@ iD.Map = function(context) {
|
||||
var prop = surface.node().style[transformProp];
|
||||
if (!prop || prop === 'none') return false;
|
||||
surface.node().style[transformProp] = '';
|
||||
tilegroup.node().style[transformProp] = '';
|
||||
layergroup.node().style[transformProp] = '';
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -165,7 +165,18 @@ iD.Map = function(context) {
|
||||
}
|
||||
|
||||
if (!difference) {
|
||||
tilegroup.call(background);
|
||||
var sel = layergroup
|
||||
.selectAll('.layer-layer')
|
||||
.data(layers);
|
||||
|
||||
sel.exit().remove();
|
||||
|
||||
sel.enter().append('div')
|
||||
.attr('class', 'layer-layer');
|
||||
|
||||
sel.each(function(layer) {
|
||||
d3.select(this).call(layer);
|
||||
});
|
||||
}
|
||||
|
||||
if (map.editable()) {
|
||||
@@ -260,7 +271,9 @@ iD.Map = function(context) {
|
||||
var center = map.center();
|
||||
dimensions = _;
|
||||
surface.size(dimensions);
|
||||
background.size(dimensions);
|
||||
layers.map(function(l) {
|
||||
l.size(dimensions);
|
||||
});
|
||||
projection.clipExtent([[0, 0], dimensions]);
|
||||
setCenter(center);
|
||||
return redraw();
|
||||
@@ -371,7 +384,7 @@ iD.Map = function(context) {
|
||||
return map;
|
||||
};
|
||||
|
||||
map.background = background;
|
||||
map.layers = layers;
|
||||
map.projection = projection;
|
||||
map.redraw = redraw;
|
||||
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
iD.ui.Background = function(context) {
|
||||
var event = d3.dispatch('cancel', 'save'),
|
||||
key = 'b',
|
||||
opacities = [1, 0.5, 0];
|
||||
|
||||
var layers = context.backgroundSources();
|
||||
opacities = [1, 0.5, 0],
|
||||
directions = [
|
||||
['left', [1, 0]],
|
||||
['top', [0, -1]],
|
||||
['right', [-1, 0]],
|
||||
['bottom', [0, 1]]],
|
||||
layers = context.backgroundSources();
|
||||
|
||||
function getSources() {
|
||||
var ext = context.map().extent();
|
||||
@@ -15,24 +19,6 @@ iD.ui.Background = function(context) {
|
||||
|
||||
function background(selection) {
|
||||
|
||||
var content = selection.append('div')
|
||||
.attr('class', 'content fillD map-overlay hide'),
|
||||
shown = false;
|
||||
|
||||
var tooltip = bootstrap.tooltip()
|
||||
.placement('right')
|
||||
.html(true)
|
||||
.title(iD.ui.tooltipHtml(t('background.description'), key));
|
||||
|
||||
var button = selection.append('button')
|
||||
.attr('tabindex', -1)
|
||||
.attr('class', 'fillD')
|
||||
.on('click.background-toggle', toggle)
|
||||
.call(tooltip);
|
||||
|
||||
button.append('span')
|
||||
.attr('class', 'layers icon');
|
||||
|
||||
function toggle() {
|
||||
tooltip.hide(button);
|
||||
setVisible(content.classed('hide'));
|
||||
@@ -55,56 +41,23 @@ iD.ui.Background = function(context) {
|
||||
}
|
||||
}
|
||||
|
||||
context.surface().on('mousedown.background-outside', function() {
|
||||
setVisible(false);
|
||||
});
|
||||
|
||||
context.container().on('mousedown.background-outside', function() {
|
||||
setVisible(false);
|
||||
});
|
||||
|
||||
var opa = content
|
||||
.append('div')
|
||||
.attr('class', 'opacity-options-wrapper');
|
||||
|
||||
opa.append('h4')
|
||||
.text(t('background.title'));
|
||||
|
||||
var opacityList = opa.append('ul')
|
||||
.attr('class', 'opacity-options');
|
||||
|
||||
function setOpacity(d) {
|
||||
context.map().tilesurface
|
||||
context.map().layersurface.selectAll('.layer-layer')
|
||||
.filter(function(d) { return d == context.map().layers[0]; })
|
||||
.transition()
|
||||
.style('opacity', d)
|
||||
.attr('data-opacity', d);
|
||||
|
||||
opacityList.selectAll('li')
|
||||
.classed('selected', false);
|
||||
d3.select(this)
|
||||
.classed('selected', true);
|
||||
|
||||
if (d3.event) {
|
||||
d3.select(this)
|
||||
.classed('selected', true);
|
||||
}
|
||||
}
|
||||
|
||||
opacityList.selectAll('div.opacity')
|
||||
.data(opacities)
|
||||
.enter()
|
||||
.append('li')
|
||||
.attr('data-original-title', function(d) {
|
||||
return t('background.percent_brightness', { opacity: (d * 100) });
|
||||
})
|
||||
.on('click.set-opacity', setOpacity)
|
||||
.html("<div class='select-box'></div>")
|
||||
.call(bootstrap.tooltip()
|
||||
.placement('top'))
|
||||
.append('div')
|
||||
.attr('class', 'opacity')
|
||||
.style('opacity', String);
|
||||
|
||||
// Make sure there is an active selection by default
|
||||
opa.select('.opacity-options li:nth-child(2)')
|
||||
.classed('selected', true);
|
||||
|
||||
function selectLayer(d) {
|
||||
|
||||
content.selectAll('a.layer')
|
||||
.classed('selected', function(d) {
|
||||
return d.data.name === context.background().source().data.name;
|
||||
@@ -135,9 +88,16 @@ iD.ui.Background = function(context) {
|
||||
selectLayer(d);
|
||||
}
|
||||
|
||||
var layerList = content
|
||||
.append('ul')
|
||||
.attr('class', 'toggle-list fillL');
|
||||
function clickGpx(d) {
|
||||
d3.event.preventDefault();
|
||||
if (!_.isEmpty(context.map().layers[1].geojson())) {
|
||||
context.map().layers[1]
|
||||
.enable(!context.map().layers[1].enable());
|
||||
d3.select(this)
|
||||
.classed('selected', context.map().layers[1].enable());
|
||||
context.redraw();
|
||||
}
|
||||
}
|
||||
|
||||
function update() {
|
||||
var layerLinks = layerList.selectAll('a.layer')
|
||||
@@ -169,26 +129,122 @@ iD.ui.Background = function(context) {
|
||||
return d.data.name;
|
||||
});
|
||||
|
||||
gpxLayerItem
|
||||
.classed('selected', function() {
|
||||
var gpxLayer = context.map().layers[1];
|
||||
return !_.isEmpty(gpxLayer.geojson()) &&
|
||||
gpxLayer.enable();
|
||||
});
|
||||
|
||||
layerLinks.exit()
|
||||
.remove();
|
||||
|
||||
selectLayer(context.background().source());
|
||||
}
|
||||
|
||||
context.map().on('move.background-update', _.debounce(update, 1000));
|
||||
function clickNudge(d) {
|
||||
var interval = window.setInterval(nudge, 100);
|
||||
|
||||
update();
|
||||
d3.select(this).on('mouseup', function() {
|
||||
window.clearInterval(interval);
|
||||
nudge();
|
||||
});
|
||||
|
||||
function nudge() {
|
||||
context.background().nudge(d[1], context.map().zoom());
|
||||
context.redraw();
|
||||
}
|
||||
}
|
||||
|
||||
var content = selection.append('div')
|
||||
.attr('class', 'content fillD map-overlay hide'),
|
||||
tooltip = bootstrap.tooltip()
|
||||
.placement('right')
|
||||
.html(true)
|
||||
.title(iD.ui.tooltipHtml(t('background.description'), key)),
|
||||
button = selection.append('button')
|
||||
.attr('tabindex', -1)
|
||||
.attr('class', 'fillD')
|
||||
.on('click.background-toggle', toggle)
|
||||
.call(tooltip),
|
||||
opa = content
|
||||
.append('div')
|
||||
.attr('class', 'opacity-options-wrapper'),
|
||||
shown = false;
|
||||
|
||||
button.append('span')
|
||||
.attr('class', 'layers icon');
|
||||
|
||||
opa.append('h4')
|
||||
.text(t('background.title'));
|
||||
|
||||
context.surface().on('mousedown.background-outside', function() {
|
||||
setVisible(false);
|
||||
});
|
||||
|
||||
context.container().on('mousedown.background-outside', function() {
|
||||
setVisible(false);
|
||||
});
|
||||
|
||||
var opacityList = opa.append('ul')
|
||||
.attr('class', 'opacity-options');
|
||||
|
||||
opacityList.selectAll('div.opacity')
|
||||
.data(opacities)
|
||||
.enter()
|
||||
.append('li')
|
||||
.attr('data-original-title', function(d) {
|
||||
return t('background.percent_brightness', { opacity: (d * 100) });
|
||||
})
|
||||
.on('click.set-opacity', setOpacity)
|
||||
.html("<div class='select-box'></div>")
|
||||
.call(bootstrap.tooltip()
|
||||
.placement('top'))
|
||||
.append('div')
|
||||
.attr('class', 'opacity')
|
||||
.style('opacity', String);
|
||||
|
||||
// Make sure there is an active selection by default
|
||||
opa.select('.opacity-options li:nth-child(2)')
|
||||
.classed('selected', true);
|
||||
|
||||
var layerList = content
|
||||
.append('ul')
|
||||
.attr('class', 'toggle-list fillL');
|
||||
|
||||
var gpxLayerItem = content
|
||||
.append('ul')
|
||||
.style('display', iD.detect().filedrop ? 'block' : 'none')
|
||||
.attr('class', 'toggle-list fillL')
|
||||
.append('li')
|
||||
.append('a')
|
||||
.classed('layer-toggle-gpx', true)
|
||||
.call(bootstrap.tooltip()
|
||||
.title(t('gpx.drag_drop'))
|
||||
.placement('right'))
|
||||
.on('click.set-gpx', clickGpx);
|
||||
|
||||
gpxLayerItem
|
||||
.append('span')
|
||||
.attr('class', 'icon toggle');
|
||||
|
||||
gpxLayerItem.append('span')
|
||||
.text(t('gpx.local_layer'));
|
||||
|
||||
gpxLayerItem
|
||||
.append('a')
|
||||
.attr('class', 'icon geocode layer-extent')
|
||||
.on('click', function() {
|
||||
d3.event.preventDefault();
|
||||
d3.event.stopPropagation();
|
||||
context.map()
|
||||
.extent(d3.geo.bounds(context.map().layers[1].geojson()));
|
||||
});
|
||||
|
||||
var adjustments = content
|
||||
.append('div')
|
||||
.attr('class', 'adjustments pad1');
|
||||
|
||||
var directions = [
|
||||
['left', [1, 0]],
|
||||
['top', [0, -1]],
|
||||
['right', [-1, 0]],
|
||||
['bottom', [0, 1]]];
|
||||
|
||||
adjustments.append('a')
|
||||
.text(t('background.fix_misalignment'))
|
||||
.attr('href', '#')
|
||||
@@ -197,8 +253,7 @@ iD.ui.Background = function(context) {
|
||||
.on('click', function() {
|
||||
var exp = d3.select(this).classed('expanded');
|
||||
nudge_container.style('display', exp ? 'none' : 'block');
|
||||
d3.select(this)
|
||||
.classed('expanded', !exp);
|
||||
d3.select(this).classed('expanded', !exp);
|
||||
d3.event.preventDefault();
|
||||
});
|
||||
|
||||
@@ -212,20 +267,7 @@ iD.ui.Background = function(context) {
|
||||
.append('button')
|
||||
.attr('class', function(d) { return d[0] + ' nudge'; })
|
||||
.text(function(d) { return d[0]; })
|
||||
.on('mousedown', function(d) {
|
||||
|
||||
var interval = window.setInterval(nudge, 100);
|
||||
|
||||
d3.select(this).on('mouseup', function() {
|
||||
window.clearInterval(interval);
|
||||
nudge();
|
||||
});
|
||||
|
||||
function nudge() {
|
||||
context.background().nudge(d[1], context.map().zoom());
|
||||
context.redraw();
|
||||
}
|
||||
});
|
||||
.on('mousedown', clickNudge);
|
||||
|
||||
nudge_container.append('button')
|
||||
.text(t('background.reset'))
|
||||
@@ -235,8 +277,12 @@ iD.ui.Background = function(context) {
|
||||
context.redraw();
|
||||
});
|
||||
|
||||
var keybinding = d3.keybinding('background');
|
||||
context.map()
|
||||
.on('move.background-update', _.debounce(update, 1000));
|
||||
update();
|
||||
setOpacity(0.5);
|
||||
|
||||
var keybinding = d3.keybinding('background');
|
||||
keybinding.on(key, toggle);
|
||||
|
||||
d3.select(document)
|
||||
|
||||
120
js/lib/togeojson.js
Normal file
120
js/lib/togeojson.js
Normal file
@@ -0,0 +1,120 @@
|
||||
toGeoJSON = (function() {
|
||||
var removeSpace = (/\s*/g), trimSpace = (/^\s*|\s*$/g), splitSpace = (/\s+/);
|
||||
function okhash(x) {
|
||||
if (!x || !x.length) return 0;
|
||||
for (var i = 0, h = 0; i < x.length; i++) {
|
||||
h = ((h << 5) - h) + x.charCodeAt(i) | 0;
|
||||
} return h;
|
||||
}
|
||||
function get(x, y) { return x.getElementsByTagName(y); }
|
||||
function attr(x, y) { return x.getAttribute(y); }
|
||||
function attrf(x, y) { return parseFloat(attr(x, y)); }
|
||||
function get1(x, y) { var n = get(x, y); return n.length ? n[0] : null; }
|
||||
function numarray(x) {
|
||||
for (var j = 0, o = []; j < x.length; j++) o[j] = parseFloat(x[j]);
|
||||
return o;
|
||||
}
|
||||
function nodeVal(x) { return x && x.firstChild && x.firstChild.nodeValue; }
|
||||
function coord1(v) { return numarray(v.replace(removeSpace, '').split(',')); }
|
||||
function coord(v) {
|
||||
var coords = v.replace(trimSpace, '').split(splitSpace), o = [];
|
||||
for (var i = 0; i < coords.length; i++) o.push(coord1(coords[i]));
|
||||
return o;
|
||||
}
|
||||
function fc() { return { type: 'FeatureCollection', features: [] }; }
|
||||
t = {
|
||||
kml: function(doc, o) {
|
||||
o = o || {};
|
||||
var gj = fc(), styleIndex = {},
|
||||
geotypes = ['Polygon', 'LineString', 'Point'],
|
||||
placemarks = get(doc, 'Placemark'), styles = get(doc, 'Style');
|
||||
|
||||
if (o.styles) for (var k = 0; k < styles.length; k++) {
|
||||
styleIndex['#' + styles[k].id] = okhash(styles[k].innerHTML).toString(16);
|
||||
}
|
||||
for (var j = 0; j < placemarks.length; j++) {
|
||||
gj.features = gj.features.concat(getPlacemark(placemarks[j]));
|
||||
}
|
||||
function getGeometry(root) {
|
||||
var geomNode, geomNodes, i, j, k, geoms = [];
|
||||
if (get1(root, 'MultiGeometry')) return getGeometry(get1(root, 'MultiGeometry'));
|
||||
for (i = 0; i < geotypes.length; i++) {
|
||||
geomNodes = get(root, geotypes[i]);
|
||||
if (geomNodes) {
|
||||
for (j = 0; j < geomNodes.length; j++) {
|
||||
geomNode = geomNodes[j];
|
||||
if (geotypes[i] == 'Point') {
|
||||
geoms.push({ type: 'Point',
|
||||
coordinates: coord1(nodeVal(get1(geomNode, 'coordinates')))
|
||||
});
|
||||
} else if (geotypes[i] == 'LineString') {
|
||||
geoms.push({ type: 'LineString',
|
||||
coordinates: coord(nodeVal(get1(geomNode, 'coordinates')))
|
||||
});
|
||||
} else if (geotypes[i] == 'Polygon') {
|
||||
var rings = get(geomNode, 'LinearRing'), coords = [];
|
||||
for (k = 0; k < rings.length; k++) {
|
||||
coords.push(coord(nodeVal(get1(rings[k], 'coordinates'))));
|
||||
}
|
||||
geoms.push({ type: 'Polygon', coordinates: coords });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return geoms;
|
||||
}
|
||||
function getPlacemark(root) {
|
||||
var geoms = getGeometry(root), i, properties = {},
|
||||
name = nodeVal(get1(root, 'name')),
|
||||
styleUrl = nodeVal(get1(root, 'styleUrl')),
|
||||
description = nodeVal(get1(root, 'description')),
|
||||
extendedData = get1(root, 'ExtendedData');
|
||||
|
||||
if (!geoms.length) return false;
|
||||
if (name) properties.name = name;
|
||||
if (styleUrl && styleIndex[styleUrl]) {
|
||||
properties.styleUrl = styleUrl;
|
||||
properties.styleHash = styleIndex[styleUrl];
|
||||
}
|
||||
if (description) properties.description = description;
|
||||
if (extendedData) {
|
||||
var datas = get(extendedData, 'Data'),
|
||||
simpleDatas = get(extendedData, 'SimpleData');
|
||||
|
||||
for (i = 0; i < datas.length; i++) {
|
||||
properties[datas[i].getAttribute('name')] = nodeVal(get1(datas[i], 'value'));
|
||||
}
|
||||
for (i = 0; i < simpleDatas.length; i++) {
|
||||
properties[simpleDatas[i].getAttribute('name')] = nodeVal(simpleDatas[i]);
|
||||
}
|
||||
}
|
||||
return [{ type: 'Feature', geometry: (geoms.length === 1) ? geoms[0] : {
|
||||
type: 'GeometryCollection',
|
||||
geometries: geoms }, properties: properties }];
|
||||
}
|
||||
return gj;
|
||||
},
|
||||
gpx: function(doc, o) {
|
||||
var i, j, tracks = get(doc, 'trk'), track, pt, gj = fc();
|
||||
for (i = 0; i < tracks.length; i++) {
|
||||
track = tracks[i];
|
||||
var name = nodeVal(get1(track, 'name'));
|
||||
var pts = get(track, 'trkpt'), line = [];
|
||||
for (j = 0; j < pts.length; j++) {
|
||||
line.push([attrf(pts[j], 'lon'), attrf(pts[j], 'lat')]);
|
||||
}
|
||||
gj.features.push({
|
||||
type: 'Feature',
|
||||
properties: {
|
||||
name: name || ''
|
||||
},
|
||||
geometry: { type: 'LineString', coordinates: line }
|
||||
});
|
||||
}
|
||||
return gj;
|
||||
}
|
||||
};
|
||||
return t;
|
||||
})();
|
||||
|
||||
if (typeof module !== 'undefined') module.exports = toGeoJSON;
|
||||
@@ -31,6 +31,7 @@
|
||||
<script src='../js/lib/d3-compat.js'></script>
|
||||
<script src='../js/lib/bootstrap-tooltip.js'></script>
|
||||
<script src='../js/lib/rtree.js'></script>
|
||||
<script src='../js/lib/togeojson.js'></script>
|
||||
|
||||
<script src='../js/id/id.js'></script>
|
||||
<script src='../js/id/util.js'></script>
|
||||
@@ -45,6 +46,7 @@
|
||||
<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/localgpx.js'></script>
|
||||
|
||||
<script src="../js/id/svg.js"></script>
|
||||
<script src="../js/id/svg/areas.js"></script>
|
||||
|
||||
Reference in New Issue
Block a user