toolkit/exemples/couple/javascript/d3/src/geo/circle.js
changeset 47 c0b4a8b5a012
equal deleted inserted replaced
46:efd9c589177a 47:c0b4a8b5a012
       
     1 // TODO breakAtDateLine?
       
     2 
       
     3 d3.geo.circle = function() {
       
     4   var origin = [0, 0],
       
     5       degrees = 90 - 1e-2,
       
     6       radians = degrees * d3_geo_radians,
       
     7       arc = d3.geo.greatArc().target(Object);
       
     8 
       
     9   function circle() {
       
    10     // TODO render a circle as a Polygon
       
    11   }
       
    12 
       
    13   function visible(point) {
       
    14     return arc.distance(point) < radians;
       
    15   }
       
    16 
       
    17   circle.clip = function(d) {
       
    18     arc.source(typeof origin === "function" ? origin.apply(this, arguments) : origin);
       
    19     return clipType(d);
       
    20   };
       
    21 
       
    22   var clipType = d3_geo_type({
       
    23 
       
    24     FeatureCollection: function(o) {
       
    25       var features = o.features.map(clipType).filter(Object);
       
    26       return features && (o = Object.create(o), o.features = features, o);
       
    27     },
       
    28 
       
    29     Feature: function(o) {
       
    30       var geometry = clipType(o.geometry);
       
    31       return geometry && (o = Object.create(o), o.geometry = geometry, o);
       
    32     },
       
    33 
       
    34     Point: function(o) {
       
    35       return visible(o.coordinates) && o;
       
    36     },
       
    37 
       
    38     MultiPoint: function(o) {
       
    39       var coordinates = o.coordinates.filter(visible);
       
    40       return coordinates.length && {
       
    41         type: o.type,
       
    42         coordinates: coordinates
       
    43       };
       
    44     },
       
    45 
       
    46     LineString: function(o) {
       
    47       var coordinates = clip(o.coordinates);
       
    48       return coordinates.length && (o = Object.create(o), o.coordinates = coordinates, o);
       
    49     },
       
    50 
       
    51     MultiLineString: function(o) {
       
    52       var coordinates = o.coordinates.map(clip).filter(function(d) { return d.length; });
       
    53       return coordinates.length && (o = Object.create(o), o.coordinates = coordinates, o);
       
    54     },
       
    55 
       
    56     Polygon: function(o) {
       
    57       var coordinates = o.coordinates.map(clip);
       
    58       return coordinates[0].length && (o = Object.create(o), o.coordinates = coordinates, o);
       
    59     },
       
    60 
       
    61     MultiPolygon: function(o) {
       
    62       var coordinates = o.coordinates.map(function(d) { return d.map(clip); }).filter(function(d) { return d[0].length; });
       
    63       return coordinates.length && (o = Object.create(o), o.coordinates = coordinates, o);
       
    64     },
       
    65 
       
    66     GeometryCollection: function(o) {
       
    67       var geometries = o.geometries.map(clipType).filter(Object);
       
    68       return geometries.length && (o = Object.create(o), o.geometries = geometries, o);
       
    69     }
       
    70 
       
    71   });
       
    72 
       
    73   function clip(coordinates) {
       
    74     var i = -1,
       
    75         n = coordinates.length,
       
    76         clipped = [],
       
    77         p0,
       
    78         p1,
       
    79         p2,
       
    80         d0,
       
    81         d1;
       
    82 
       
    83     while (++i < n) {
       
    84       d1 = arc.distance(p2 = coordinates[i]);
       
    85       if (d1 < radians) {
       
    86         if (p1) clipped.push(d3_geo_greatArcInterpolate(p1, p2)((d0 - radians) / (d0 - d1)));
       
    87         clipped.push(p2);
       
    88         p0 = p1 = null;
       
    89       } else {
       
    90         p1 = p2;
       
    91         if (!p0 && clipped.length) {
       
    92           clipped.push(d3_geo_greatArcInterpolate(clipped[clipped.length - 1], p1)((radians - d0) / (d1 - d0)));
       
    93           p0 = p1;
       
    94         }
       
    95       }
       
    96       d0 = d1;
       
    97     }
       
    98 
       
    99     if (p1 && clipped.length) {
       
   100       d1 = arc.distance(p2 = clipped[0]);
       
   101       clipped.push(d3_geo_greatArcInterpolate(p1, p2)((d0 - radians) / (d0 - d1)));
       
   102     }
       
   103 
       
   104     return resample(clipped);
       
   105   }
       
   106 
       
   107   // Resample coordinates, creating great arcs between each.
       
   108   function resample(coordinates) {
       
   109     var i = 0,
       
   110         n = coordinates.length,
       
   111         j,
       
   112         m,
       
   113         resampled = n ? [coordinates[0]] : coordinates,
       
   114         resamples,
       
   115         origin = arc.source();
       
   116 
       
   117     while (++i < n) {
       
   118       resamples = arc.source(coordinates[i - 1])(coordinates[i]).coordinates;
       
   119       for (j = 0, m = resamples.length; ++j < m;) resampled.push(resamples[j]);
       
   120     }
       
   121 
       
   122     arc.source(origin);
       
   123     return resampled;
       
   124   }
       
   125 
       
   126   circle.origin = function(x) {
       
   127     if (!arguments.length) return origin;
       
   128     origin = x;
       
   129     return circle;
       
   130   };
       
   131 
       
   132   circle.angle = function(x) {
       
   133     if (!arguments.length) return degrees;
       
   134     radians = (degrees = +x) * d3_geo_radians;
       
   135     return circle;
       
   136   };
       
   137 
       
   138   // Precision is specified in degrees.
       
   139   circle.precision = function(x) {
       
   140     if (!arguments.length) return arc.precision();
       
   141     arc.precision(x);
       
   142     return circle;
       
   143   };
       
   144 
       
   145   return circle;
       
   146 }