To be able to present constellations and star names from other cultures like the traditional Chinese ones(upcoming feature), I refactored the star-naming system so that it is possible to display different types of names. The feature is selectable in the form below with the Stars -> Show section. The select box has the star name options Beyer, Flamsteed, variables, Gliese and designation, which is a combination of all the previous options, and contains whichever applies first.
Try selecting a different constellation, dial up the display limits and select different star designations to see the effect.
To facilitate the extended naming capability, I extracted all the different names and designations from the stellar data files into a separate file unsurprisingly called 'starnames.json' that contains all the names apart from the Hipparcos number. That also reduces redundancy, since most names only need to appear once.
These are the relevant options in the configuration object, all renamed from previous versions to better represent the actual meaning:
{
stars: {
designation: true, // Show star names (Bayer, Flamsteed, Variable star, Gliese or designation,
// i.e. whichever of the previous applies first); may vary with culture setting
designationType: "desig", // Which kind of name is displayed as designation (fieldname in starnames.json)
designationStyle: { fill: "#ddddbb", font: "11px 'Palatino Linotype', Georgia, Times, 'Times Roman', serif",
align: "left", baseline: "top" },
designationLimit: 2.5, // Show only names for stars brighter than nameLimit
propername: false, // Show proper name (if present)
propernameType: "name", // Field in starnames.json that contains proper name; may vary with culture setting
propernameStyle: { fill: "#ddddbb", font: "13px 'Palatino Linotype', Georgia, Times, 'Times Roman', serif",
align: "right", baseline: "bottom" },
propernameLimit: 1.5, // Show proper names for stars brighter than propernameLimit
}}
The different parameter names in older versions are transformed automatically to preserve backward compatibility. Finally, I've also exposed an additional function, 'Celestial.showConstellation(id)', that zooms in and focuses on the selected constellation given with the three-letter-code ID (case-insensitive).
// Zoom in on the constellation Orion
Celestial.showConstellation('ori');
Something for the Holidays: Printable wall map of the universe with a d3-celestial sky map combined with a logarithmic chart of the whole universe from our Sun straight through to the big bang! Click on the images below to download large versions with 8000 px width, combined or in separate parts.
A new feature for my d3-celestial star map: A sky color gradient that shows the current sky state at the set time and date if the projection is hemispheric. No extra coding needed, just set daylight.show to true in the configuration of check "Daylight Sky" in the form. Time zone still needs to be set manually and horizontal refraction isn't considered yet, so the result need not be entirely accurate.
I was looking for a simple graphical location-selector, a globe that can be spun, zoomed in and clicked on to get an approximate location.
I found none so obviously I had to make my own. A good starting point was planetary.js which already takes care of the spinnable and zoomable globe and is pretty easy to extend with plugins. See my fork for details about the mouse-actions plugin.
All the work is done in a callback function for the mouse actions mousedown and mouseup. We could just use click, but that would also cause a positioning update on dragging actions on the globe. Only updating when the mouse coordinates don't change between down and up takes care of that. The rest is pretty straight forward, take mouse coordinates, calculate geographic position with the d3.js function projection.invert, and if that is valid (i.e. inside the globe) update the geolocation of the sky view.
globe.loadPlugin(mouse({
onMousedown: function() {
var x = d3.event.offsetX,
y = d3.event.offsetY;
position = [x, y];
},
onMouseup: function() {
var x = d3.event.offsetX,
y = d3.event.offsetY,
format = d3.format("-.3f");
if (position[0] !== x || position[1] !== y) return;
var pos = this.projection.invert([x,y]);
if (!isNaN(pos[0])) {
// latitude, longitude convention is the opposite for sky coordinates
Celestial.skyview({"location": [format(pos[1]), format(pos[0])]});
}
return pos;
}
}));
Time zones are not taken into account yet, so the result is not necessarily valid. That will be fixed later, as well as putting a position marker on the globe, showing the current terminator between day and night, and optionally also show the current sky state on the current view changing between blue and transparent.
Showing off some new features and howtos for d3.celstial. First setting the Color of DSOs. The new settings below allow to display alle the deep space objects in a uniform default color if the 'colors' setting is set to false in the configuration-section under 'dsos'. The colr is determined by the 'fill' and 'stroke' properties.
dsos: {
colors: false, // Show DSOs in symbol colors if true, use style settings below if false
style: { fill: "#cccccc", stroke: "#cccccc", width: 2, opacity: 1 }, // Default style for dsos
}
Second, how to convert cursor position to map coordinates. For this we need the function invert that is implemented for every map projection. If it gets valid x/y screen coordinates relative to the upper left corner of the map (that's why offsetLeft/Top are subtracted first [Correction: Turns out offsetX/Y does the trick]), it returns the sky position in decimal degrees. Caveat: A position outside of the projected map returns [NaN, NaN].
function getPosition(e) {
var p = document.getElementById ('celestial-map17').getBoundingClientRect(),
x = e.offsetX,
y = e.offsetY,
inv = Celestial.mapProjection.invert([x, y]);
return inv; // [right ascension -180...180 degrees, declination -90...90 degrees]
}
document.getElementById('celestial-map17').addEventListener('mousemove', getPosition, false);
If you want to pretty print the coordinates in hms and dms as above, here are the conversion functions for your convenience:
function deg2hms (deg) {
if (deg === null || isNaN(parseFloat(deg))) return;
var ra = deg < 0 ? (deg + 360) / 15 : deg / 15,
h = Math.floor (ra),
rest1 = (ra - h) * 60,
m = Math.floor(rest1),
rest2 = (rest1 - m) * 60;
s = Math.round(rest2);
return '' + pad(h) + 'ʰ ' + pad(m) + 'ᵐ ' + pad(s) + 'ˢ';
}
function deg2dms (deg) {
if (deg === null || isNaN(parseFloat(deg))) return;
var d = Math.floor (deg),
rest1 = (deg - d) * 60,
m = Math.floor(rest1),
rest2 = (rest1 - m) * 60;
s = Math.round(rest2);
return '' + pad(d) + '° ' + pad(m) + '′ ' + pad(s) + '″';
}
function pad(n) {
if (n < 0) return n > -10 ? '-0' + Math.abs(n) : n;
return n < 10 ? '0' + n : n;
}
And last a simple added functionality, a download link that saves the current canvas content as an image.
var button = document.getElementById('btnDownload');
// Set the file name to your liking, e.g. add the displayed date/time
button.setAttribute('download', 'd3-celestial.png');
button.addEventListener('click', function (e) {
var canvas = document.querySelector('#celestial-map canvas'),
// To get a download instead of image display, according to stack overflow
dataURL = canvas.toDataURL('image/png').replace('image/png', 'image/octet-stream');
button.href = dataURL;
});
I have added a simple example of how to add your own data to my interactive celestial map. Specifically, how to display the Summer Triangle at its proper position. It'll look like this:
First we need to add the proper libraries and stylesheet:
Whatever you add needs to be valid geoJSON. The various types of objects are described in the readme of the data folder in the GitHub repository. This can be a separate file or a JSON object filled at runtime or defined inline. Like so:
var jsonLine = {
"type":"FeatureCollection",
// this is an array, add as many objects as you want
"features":[
{"type":"Feature",
"id":"SummerTriangle",
"properties": {
// Name
"n":"Summer Triangle",
// Location of name text on the map
"loc": [-67.5, 52]
}, "geometry":{
// the line object as an array of point coordinates,
// always as [ra -180..180 degrees, dec -90..90 degrees]
"type":"MultiLineString",
"coordinates":[[
[-80.7653, 38.7837],
[-62.3042, 8.8683],
[-49.642, 45.2803],
[-80.7653, 38.7837]
]]
}
}
]
};
As you can see, this defines the Summer Triangle asterism, consisting of the bright stars Vega (Alpha Lyr), Deneb (Alpha Cyg) and Altair (Alpha Aql).
You also need to define how the triangle is going to look like with some styles (see documentation on GitHub):
The file argument is optional for providing an external geoJSON file, since we already defingd our data, we don't need it. Type is 'line', that leaves two function definiions, the first one gets called at loading, this is where we add our data to the d3-celestial data container, and redraw is called at every redraw event for the map. so here you need to define how to display the added object(s).
callback: function(error, json) {
if (error) return console.warn(error);
// Load the geoJSON file and transform to correct coordinate system, if necessary
var asterism = Celestial.getData(jsonLine, config.transform);
// Add to celestial objects container in d3
Celestial.container.selectAll(".asterisms")
.data(asterism.features)
.enter().append("path")
.attr("class", "ast");
// Trigger redraw to display changes
Celestial.redraw();
}
The callback funtion is pretty straight forward: Load the data with Celestial.getData, add to Celestial.container in te usual d3 manner, and redraw. It also provides a json parameter that contains the parsed JSON if a file property is given, but we already have defined jsonLine above, so we use that.
redraw: function() {
// Select the added objects by class name as given previously
Celestial.container.selectAll(".ast").each(function(d) {
// Set line styles
Celestial.setStyle(lineStyle);
// Project objects on map
Celestial.map(d);
// draw on canvas
Celestial.context.fill();
Celestial.context.stroke();
// If point is visible (this doesn't work automatically for points)
if (Celestial.clip(d.properties.loc)) {
// get point coordinates
pt = Celestial.mapProjection(d.properties.loc);
// Set text styles
Celestial.setTextStyle(textStyle);
// and draw text on canvas
Celestial.context.fillText(d.properties.n, pt[0], pt[1]);
}
})
}
And the redraw function with the actual display of the elements, contained in a d3.selectAll call on the previously set class property of the added objects. Celestial.setStyle applies the predefined canvas styles, Celestial.map projects each line on the map. However, that doesn't work for points, so that is done manually with Celestial.clip (true if point is currently visible) and Celestial.mapProjection. and the rest are standard canvas fill and stroke operations. The beginPath and closePath commands are done automatically.
Celestial.display(config);
Finally, the whole map is displayed. Check out the documentation or download/fork the D3-Celestial source in the GitHub repository. The complete sample code is in the file triangle.html in the demo folder.
As the IAU has recently approved a lot of official star names, so I updated d3-celestial to reflect these. Some are comletely new, others now have an officially approved spelling. I changed all those I previously spelled differently.
Here are those that have completely new names I didn't have before:
Name Designation ID Con # Vmag HIP# HD# RA(J2000) Dec(J2000)
Alkarab HR 8905 ups Peg - 4.42 115623 220657 351.344931 23.404100
Athebyne HR 6132 eta Dra A 2.73 80331 148387 245.997858 61.514214
Beemim HR 1393 ups03 Eri - 3.97 20535 28028 66.009239 -34.016848
Brachium HR 5603 sig Lib A 3.25 73714 133216 226.017567 -25.281961
Castula HR 265 ups02 Cas - 4.62 4422 5395 14.166271 59.181055
Chamukuy HR 1412 tet02 Tau Aa 3.73 20894 28319 67.165586 15.870882
Dalim HR 963 alf For A 3.86 14879 20010 48.018864 -28.987620
Fang HR 5944 pi Sco Aa 2.89 78265 143018 239.712972 -26.114108
Fulu HR 153 zet Cas - 3.69 2920 3360 9.242851 53.896908
Fuyue HR 6630 - Sco - 3.19 87261 161892 267.464503 -37.043305
Ginan HR 4700 eps Cru - 3.59 60260 107446 185.340039 -60.401147
Iklil HR 5928 rho Sco Aa 3.87 78104 142669 239.221151 -29.214073
Jishui HR 2930 omi Gem - 4.89 37265 61110 114.791387 34.584346
Kang HR 5315 kap Vir - 4.18 69427 124294 213.223939 -10.273704
Larawag HR 6241 eps Sco - 2.29 82396 151680 252.540878 -34.293232
Lilii Borea HR 824 39 Ari - 4.52 13061 17361 41.977256 29.247115
Mahasim HR 2095 tet Aur A 2.65 28380 40312 89.930292 37.212585
Nembus HR 464 51 And - 3.59 7607 9927 24.498154 48.628214
Pipirima HR 6252 mu02 Sco A 3.56 82545 151985 253.083939 -38.017535
Revati HR 361 zet Psc A 5.21 5737 7344 18.432864 7.575354
Saclateni HR 1612 zet Aur A 3.69 23453 32068 75.619531 41.075839
Taiyangshou HR 4518 chi UMa - 3.69 57399 102224 176.512559 47.779406
Tianguan HR 1910 zet Tau A 2.97 26451 37202 84.411189 21.142544
Tiaki HR 8636 bet Gru - 2.12 112122 214952 340.666876 -46.884576
Tianyi HR 4863 7 Dra - 5.43 62423 111335 191.893099 66.790305
Unurgunite HR 2646 sig CMa - 3.49 33856 52877 105.429782 -27.934830
Wurren HR 338 zet Phe Aa 4.02 5348 6882 17.096173 -55.245758
Xamidimura HR 6247 mu01 Sco Aa 3.00 82514 151890 252.967630 -38.047380
Xuange HR 5351 lam Boo - 4.18 69732 125162 214.095912 46.088306
Zhang HR 3903 ups01 Hya A 4.11 48356 85444 147.869558 -14.846603
See some more d3-celestial examples here, play with it here or check out the documentation and/or fork/download the source from the GitHub repository.
This is version 0.6 of my interactive celestial map, featuring the apparent position of solar system objects. By default it shows the major planets, the Sun and the Moon, butt it is configurable to show any solar system object with known orbital elements, as long as a specific date is given. Appearance can also be configured in the configuration settings
Some more new details: Day back/forward arrows on the date-time picker, and directly setting a geographic coordinate in the configuration.
This is the entire code for the above display (apart from including the necessary javascript libraries):
Celestial.display({
projection:"airy",
datapath: "http://ofrohn.github.io/data/",
location: true,
geopos: [38,110],
planets: {show: true}
});
See some more d3-celestial examples here, play with it here or check out the documentation and/or fork/download the source from the GitHub repository.
Star designations and proper names are now handled separately, so both can be displayed at once for those stars that have proper names, preferably at different locations relative to the stellar disk, which is settable in the configuration
It is now possible to display grid values at each line (so far only in the configuration), with the options to display them around the outline, in the center, or with an array of degree-values indicating the location where the line of values is crossing the respective other direction. So latitude-lines for longitude and vice-versa. And it works in quite a lot of cases. too.
Finally, the constellations are now ranked by prominence, with the possibility to assign a different font to each of the ranks, e.g. to display the names with different sizes. The ranks are assigned by the following criteria:
1. Rank: Large constellations with lots of bright stars. E.g. Orion, Ursa Major
2. Rank: Large constellations *or* with one or more really bright star(s). E.g. Monoceros, Crux
3. Rank: The rest, Circinus, Sagitta, the like.
And the reason for this? Well, to improve my giant wall map with all the features I'd like it to have. You can download the original by clicking on the image below, but be aware it is quite large, 3.7MB. As you can see, it also includes the log-scale universe I made last month.
Finally, I have made more parameters available interactively via the integrated form, the size formulae for stars and DSOs, as well as the Milky Way color and opacity. Next up are more style settings.
See some more d3-celestial examples here, play with it here or check out the documentation and/or fork/download the source from the GitHub repository.
The D3-Celstial interactive skymap now has a complete set of animated transitions, with zoom, rotation and projection change all going smoothly, as well as a way to automatize them (see documentation at the GitHub repository. To celebrate, here I present the Great Messier Show, showing all 110 Messier objects in order. Or select the ones you want to see with the select-box below. This automatically stops the animation after the current move finishes, so you may have to wait a bit. Stopping/starting can also be done manually with the button on the left. Finally, the checkbox "show object names" is pretty self-explanatory, I think.
Data for each object: Messier designation, NGC designation (if any), proper name (if any), object type, classification -
For globular clusters: Shapley–Sawyer classification, open clusters: Trumpler classification, planetary nebulae: Vorontsov-Velyaminov classification, galaxies: Galaxy morphology classification and activity class. Finally apparent visual magnitude and apparent dimensions in arcminutes.
Since I'm on to animated transitions for my interactive skymap, animating rotations is the logical next step. Here is a live demo showing the effect along with some of the weirder projections possible with d3.js as in the last post. Only this time not as a video but with the animated map itself.
Starting with the not-so-weird Aitoff via Bonne, Foucaut, Ginzburg IX, Hill Eucyclic, L'Arrivée back to Aitoff.
Check out the documentation or fork/download the D3-Celestial source in the GitHub repository.
I have implemented some animated transitions for my interactive skymap, enabling a smooth change of the selected projection. Here are some videos showing the effect. The first one goes from Hammer-projection to Equirectangular, Craster Parabolic, Eckert II, Focaut and finally back to Hammer.
The second video shows off some of the weirder projections possible with d3.js. Starting with the not-so-weird Aitoff via Bonne, Collignon, Ginzburg IX, Hill Eucyclic, L'Arrivée back to Aitoff.
A few neat features in addition to the recent location option added to my interactive celestial map. First, setting the map orientation, i.e. which way is up, in degrees clockwise from north. Also fixing the orientation is possible, preventing the zoom and pan interaction from spinning the map display every which way. The second setting concerns the location-dependent map display on 360° maps, it allows to darken the hemisphere currently below the horizon at the set location & time.
Here's the initial release of my latest project: a configurable, open source interactive celestial map. See details at the page and the readme on the GitHub repository. But before I go on any further, here's an example:
It should zoom and rotate with mouse-wheel/dragging or the equivalent gestures on touch devices. Some mobile browsers seem to be preempted by the OS from receiving touch gestures. Mobile Chrome works fine. Whereas desktop Chrome has a weird glitch where you have to hold the finger/mouse button down until the rotation happens while dragging. On all other browsers I tested a 'flick' will suffice, with a little patience, because it's pretty slow at the moment. It gets a lot faster if you set the limit magnitude for stars lower. Well, there's no way around it: there are a lot of stars in the sky!
How to get it on a web page? Easy: Include all the necessary scripts (sea readme), declare an empty div with id "map" and run the code, like so:
Check out the documentation for all the possible configuration parameters. The above linked blog page has a form with all the options to play around with. The repository also contains a page named viewer.html with the same function.
You may have seen the various sky maps on my blog, like half of the pages linked below the header, or this one. Those are all based on a homegrown non-interactive painfully slow sky map program. I've always wanted to make it interactive (and faster), but that would have been a lot of work I don't really have the time for. Well, until I found that d3.js already has all the functionality I needed. line drawing maps, interactions and so on. With some tweaking, like convert all the position from right ascension/declination to latitude/longitude as GeoJSON requires, and a lot more minor and major details that took a lot more time than expected, it's finally good enough to release, and well, here it is.
I have added an option to set the center coordinates for my interactive celestial map, so far only for equatorial coordinates. It is still interactive, so you can pan and zoom as well, but having a determined center should come in handy for showing the current sky over a location on earth, or other planets. Which is sure to come as a feature, eventually.
Leaving the fields blank is equivalent to 0h, 0°
Now, with D3.js it would be perfectly possible to update the center location (or any other viewing state, for thet matter) without reloading, I just haven't implementet it yet. That's also still to come.
Check out the documentation in the GitHub repository for all possible settings. The above linked blog page has an interactive form with all the options to play around with. The repository also contains a page named viewer.html with the same function.