diff -r efd9c589177a -r c0b4a8b5a012 toolkit/javascript/d3/src/geo/circle.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/toolkit/javascript/d3/src/geo/circle.js Thu Apr 10 14:20:23 2014 +0200 @@ -0,0 +1,146 @@ +// TODO breakAtDateLine? + +d3.geo.circle = function() { + var origin = [0, 0], + degrees = 90 - 1e-2, + radians = degrees * d3_geo_radians, + arc = d3.geo.greatArc().target(Object); + + function circle() { + // TODO render a circle as a Polygon + } + + function visible(point) { + return arc.distance(point) < radians; + } + + circle.clip = function(d) { + arc.source(typeof origin === "function" ? origin.apply(this, arguments) : origin); + return clipType(d); + }; + + var clipType = d3_geo_type({ + + FeatureCollection: function(o) { + var features = o.features.map(clipType).filter(Object); + return features && (o = Object.create(o), o.features = features, o); + }, + + Feature: function(o) { + var geometry = clipType(o.geometry); + return geometry && (o = Object.create(o), o.geometry = geometry, o); + }, + + Point: function(o) { + return visible(o.coordinates) && o; + }, + + MultiPoint: function(o) { + var coordinates = o.coordinates.filter(visible); + return coordinates.length && { + type: o.type, + coordinates: coordinates + }; + }, + + LineString: function(o) { + var coordinates = clip(o.coordinates); + return coordinates.length && (o = Object.create(o), o.coordinates = coordinates, o); + }, + + MultiLineString: function(o) { + var coordinates = o.coordinates.map(clip).filter(function(d) { return d.length; }); + return coordinates.length && (o = Object.create(o), o.coordinates = coordinates, o); + }, + + Polygon: function(o) { + var coordinates = o.coordinates.map(clip); + return coordinates[0].length && (o = Object.create(o), o.coordinates = coordinates, o); + }, + + MultiPolygon: function(o) { + var coordinates = o.coordinates.map(function(d) { return d.map(clip); }).filter(function(d) { return d[0].length; }); + return coordinates.length && (o = Object.create(o), o.coordinates = coordinates, o); + }, + + GeometryCollection: function(o) { + var geometries = o.geometries.map(clipType).filter(Object); + return geometries.length && (o = Object.create(o), o.geometries = geometries, o); + } + + }); + + function clip(coordinates) { + var i = -1, + n = coordinates.length, + clipped = [], + p0, + p1, + p2, + d0, + d1; + + while (++i < n) { + d1 = arc.distance(p2 = coordinates[i]); + if (d1 < radians) { + if (p1) clipped.push(d3_geo_greatArcInterpolate(p1, p2)((d0 - radians) / (d0 - d1))); + clipped.push(p2); + p0 = p1 = null; + } else { + p1 = p2; + if (!p0 && clipped.length) { + clipped.push(d3_geo_greatArcInterpolate(clipped[clipped.length - 1], p1)((radians - d0) / (d1 - d0))); + p0 = p1; + } + } + d0 = d1; + } + + if (p1 && clipped.length) { + d1 = arc.distance(p2 = clipped[0]); + clipped.push(d3_geo_greatArcInterpolate(p1, p2)((d0 - radians) / (d0 - d1))); + } + + return resample(clipped); + } + + // Resample coordinates, creating great arcs between each. + function resample(coordinates) { + var i = 0, + n = coordinates.length, + j, + m, + resampled = n ? [coordinates[0]] : coordinates, + resamples, + origin = arc.source(); + + while (++i < n) { + resamples = arc.source(coordinates[i - 1])(coordinates[i]).coordinates; + for (j = 0, m = resamples.length; ++j < m;) resampled.push(resamples[j]); + } + + arc.source(origin); + return resampled; + } + + circle.origin = function(x) { + if (!arguments.length) return origin; + origin = x; + return circle; + }; + + circle.angle = function(x) { + if (!arguments.length) return degrees; + radians = (degrees = +x) * d3_geo_radians; + return circle; + }; + + // Precision is specified in degrees. + circle.precision = function(x) { + if (!arguments.length) return arc.precision(); + arc.precision(x); + return circle; + }; + + return circle; +}