mirror of
https://github.com/FoggedLens/iD.git
synced 2026-02-13 17:23:02 +00:00
Local GPX file support, first push towards multilayer support.
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
78
js/id/renderer/localgpx.js
Normal file
78
js/id/renderer/localgpx.js
Normal file
@@ -0,0 +1,78 @@
|
||||
iD.LocalGpx = function() {
|
||||
var tileSize = 256,
|
||||
projection,
|
||||
gj = {},
|
||||
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([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.size = function(_) {
|
||||
if (!arguments.length) return size;
|
||||
size = _;
|
||||
return render;
|
||||
};
|
||||
|
||||
function over() {
|
||||
d3.event.stopPropagation();
|
||||
d3.event.preventDefault();
|
||||
d3.event.dataTransfer.dropEffect = 'copy';
|
||||
console.log('here');
|
||||
}
|
||||
|
||||
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) {
|
||||
gj = toGeoJSON.gpx(toDom(e.target.result));
|
||||
};
|
||||
|
||||
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().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', 'layers-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('.tile-layer-group')
|
||||
.data(layers);
|
||||
|
||||
sel.exit().remove();
|
||||
|
||||
sel.enter().append('div')
|
||||
.attr('class', 'tile-layer-group');
|
||||
|
||||
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;
|
||||
|
||||
|
||||
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;
|
||||
Reference in New Issue
Block a user