block by renecnielsen a96a9e58c640ab78ed11

Sky

Full Screen

A map of the sky that uses an azimuthal equidistant projection with star data. Longitudes and latitudes for the geo projection are obtained from declination and right ascension respectively (longitude is also inverted, because, unlike the earth globe, the celestial sphere is seen from the inside).

The boreal (northern) sky is shown at left, while the austral (southern) at right. Because right ascension is given in hours, both maps are divided in 24 slices. A circle is shown every 10 degrees of declination.

Star size indicates magnitude. Bigger circles depict brighter stars.

forked from nitaku‘s block: Sky

index.js

(function() {
  var graticule, height, magnitude, map_austral, map_boreal, maps, path_generator_austral, path_generator_boreal, projection_austral, projection_boreal, svg, width, zoom;

  svg = d3.select('svg');

  width = svg[0][0].getBoundingClientRect().width;

  height = svg[0][0].getBoundingClientRect().height;

  projection_boreal = d3.geo.azimuthalEquidistant().scale(150).rotate([180, -90, 0]).center([0, 0]).translate([width / 4 + 4.35, height / 2]).precision(.1).clipAngle(90 + 1e-3);

  projection_austral = d3.geo.azimuthalEquidistant().scale(150).rotate([0, 90, 0]).center([0, 0]).translate([3 * width / 4 - 4.35, height / 2]).precision(.1).clipAngle(90 + 1e-3);

  graticule = d3.geo.graticule().minorStep([15, 10]).majorStep([90, 10]);

  path_generator_boreal = d3.geo.path().projection(projection_boreal);

  path_generator_austral = d3.geo.path().projection(projection_austral);

  /* create maps groups
  */

  maps = svg.append('g');

  map_boreal = maps.append('g').attr('id', 'map_boreal');

  map_austral = maps.append('g').attr('id', 'map_austral');

  /* draw the graticules
  */

  map_boreal.append('path').datum(graticule).attr('class', 'graticule').attr('d', path_generator_boreal);

  map_austral.append('path').datum(graticule).attr('class', 'graticule').attr('d', path_generator_austral);

  /* define a zoom behavior
  */

  zoom = d3.behavior.zoom().scaleExtent([1, 20]).on('zoom', function() {
    return maps.attr('transform', "translate(" + (zoom.translate()) + ")scale(" + (zoom.scale()) + ")");
  });

  /* bind the zoom behavior to the main SVG
  */

  svg.call(zoom);

  /* define a scale for magnitude
  */

  magnitude = d3.scale.quantize().domain([-1, 5]).range([7, 6, 5, 4, 3, 2, 1]);

  d3.csv('stars.csv', function(data) {
    map_boreal.selectAll('.star').data(data.filter(function(d) {
      return +d.dec_deg > 0;
    })).enter().append('circle').attr('class', 'star').attr('r', function(d) {
      return magnitude(+d.magnitude) / 2;
    }).attr('transform', function(d) {
      var lat, lon, x, y, _ref;
      lat = +d.dec_deg + +d.dec_min / 60 + +d.dec_sec / 3600;
      lon = (+d.RA_hour + +d.RA_min / 60 + +d.RA_sec / 3600) * (360 / 24);
      _ref = projection_boreal([-lon, lat]), x = _ref[0], y = _ref[1];
      return "translate(" + x + "," + y + ")";
    });
    return map_austral.selectAll('.star').data(data.filter(function(d) {
      return +d.dec_deg <= 0;
    })).enter().append('circle').attr('class', 'star').attr('r', function(d) {
      return magnitude(+d.magnitude) / 2;
    }).attr('transform', function(d) {
      var lat, lon, x, y, _ref;
      lat = +d.dec_deg + +d.dec_min / 60 + +d.dec_sec / 3600;
      lon = (+d.RA_hour + +d.RA_min / 60 + +d.RA_sec / 3600) * (360 / 24);
      _ref = projection_austral([-lon, lat]), x = _ref[0], y = _ref[1];
      return "translate(" + x + "," + y + ")";
    });
  });

}).call(this);

index.html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Sky</title>
        <link type="text/css" href="index.css" rel="stylesheet"/>
        <script src="//d3js.org/d3.v3.min.js"></script>
    </head>
    <body>
        <svg width="960" height="500">
        </svg>
    </body>
    <script src="index.js"></script>
</html>

index.coffee

svg = d3.select('svg')

width = svg[0][0].getBoundingClientRect().width
height = svg[0][0].getBoundingClientRect().height

# projection = d3.geo.mercator()
    # .scale(2800)
    # .translate([50, 2620])
    # .precision(0.1)
    
# projection = d3.geo.albers()
    # .center([14, 34])
    # .rotate([-14, 0])
    # .parallels([38, 61])
    # .scale(2100)
    
projection_boreal = d3.geo.azimuthalEquidistant()
    .scale(150)
    .rotate([180,-90,0])
    .center([0, 0])
    .translate([width / 4 + 4.35, height / 2])
    .precision(.1)
    .clipAngle(90 + 1e-3)
    
projection_austral = d3.geo.azimuthalEquidistant()
    .scale(150)
    .rotate([0,90,0])
    .center([0, 0])
    .translate([3*width / 4 - 4.35, height / 2])
    .precision(.1)
    .clipAngle(90 + 1e-3)
    
# sky_projection = (lambda, phi) ->
    # [x, y] = geo_projection(lambda, phi)
    # return [x, -y]

graticule = d3.geo.graticule()
    .minorStep([15,10])
    .majorStep([90,10])

path_generator_boreal = d3.geo.path()
    .projection(projection_boreal)
    
path_generator_austral = d3.geo.path()
    .projection(projection_austral)
    
### create maps groups ###
maps = svg.append('g')

map_boreal = maps.append('g')
    .attr('id', 'map_boreal')
    
map_austral = maps.append('g')
    .attr('id', 'map_austral')
    
### draw the graticules ###
map_boreal.append('path')
    .datum(graticule)
    .attr('class', 'graticule')
    .attr('d', path_generator_boreal)
    
map_austral.append('path')
    .datum(graticule)
    .attr('class', 'graticule')
    .attr('d', path_generator_austral)
    
### define a zoom behavior ###
zoom = d3.behavior.zoom()
    .scaleExtent([1,20]) # min-max zoom
    .on 'zoom', () ->
      # whenever the user zooms,
      # modify translation and scale of the zoom group accordingly
      maps.attr('transform', "translate(#{zoom.translate()})scale(#{zoom.scale()})")
      
### bind the zoom behavior to the main SVG ###
svg.call(zoom)


### define a scale for magnitude ###
magnitude = d3.scale.quantize()
    .domain([-1,5])
    .range([7,6,5,4,3,2,1])
    
d3.csv 'stars.csv', (data) ->
    map_boreal.selectAll('.star')
        .data(data.filter((d) -> +d.dec_deg > 0))
      .enter().append('circle')
        .attr('class', 'star')
        .attr('r', (d) -> magnitude(+d.magnitude)/2)
        .attr 'transform', (d) ->
            lat = +d.dec_deg + +d.dec_min/60 + +d.dec_sec/3600
            lon = (+d.RA_hour + +d.RA_min/60 + +d.RA_sec/3600)*(360/24)
            [x, y] = projection_boreal([-lon, lat])
            return "translate(#{x},#{y})"
            
    map_austral.selectAll('.star')
        .data(data.filter((d) -> +d.dec_deg <= 0))
      .enter().append('circle')
        .attr('class', 'star')
        .attr('r', (d) -> magnitude(+d.magnitude)/2)
        .attr 'transform', (d) ->
            lat = +d.dec_deg + +d.dec_min/60 + +d.dec_sec/3600
            lon = (+d.RA_hour + +d.RA_min/60 + +d.RA_sec/3600)*(360/24)
            [x, y] = projection_austral([-lon, lat])
            return "translate(#{x},#{y})"
            

index.css

body {
  background: #1a055c;
}

.star {
  fill: white;
}

.graticule {
  fill: none;
  stroke: white;
  stroke-width: 0.2px;
  vector-effect: non-scaling-stroke;
}

index.sass

body
    background: #1A055C
    
.star
    fill: white
    
.graticule
    fill: none
    stroke: white
    stroke-width: .2px
    vector-effect: non-scaling-stroke