The following code is
very preliminary, but exhibits the principle of map creation, that I've chosen. The stream system that I spoke of previously is not the primary way to organize the drawing of images. Instead a human map drawer reasons with various layers and objects to draw in those layers. The layers have an order: the first drawn first, then next one – possibly overwriting features in the previous layers – and so on till all layers are drawn. In map making most objects are coordinate transformed zero times or more, and finally the object is projected onto a flat surface, i.e. "the paper". When a label is attached to an object, (f.ex. the string "Sirius" to the star Sirius) it is not transformed/projected quite the same way: a label should be placed
near the object that it labels, but "upright" from the perspective of the image spectator, so that the spectator needn't put the head on one side: the label has to take the paper position of the object and add a little offset so as to be written near but not on the object it refers to.
The programming system, and the code below, is not finally defined: it needs some fixes to become logical, and to reflect the stream system that I've speculated about earlier, but at last I got an idea of how to code maps in a generic way. The long term intention is of course not just star maps, but any map. The details of how to store databases in files and how they're loaded and processed is of course a remaining topic: I'm inclined towards relation algebras rather than the clumsy SQL thinking, but this is a matter of syntax, not semantics, since a well designed relation algebra should be mapable to SQL statements.
orion() {
## procedure for the heavenly hunter
border += load “ori_b.db”;
labels += [pos: [x: middle, y: bottom],
string: "Orion",
justify: middle];
projection [type: Lambert_conic, α: 5ʰ20ᵐ, δ: 10°, Δδ: 10°];
frame [height: 500px, width: 500px];
}
monoceros() {
## procedure for the heavenly unicorn
border += load "mon_b.db";
labels += [pos: [x: middle, y: bottom],
string: "Monoceros",
justify: middle];
projection [type: Lambert_conic, α: 7ʰ10ᵐ, δ: 10°, Δδ: 10°];
frame [height: 500px, width: 600px];
}
main() {
## ‘layer’ declares the layers wherein the program puts
## objects, when executing an ‘out’ all layers are drawn
## with stored objects one by one, background first, then
## border, aso. to at last map_labels. What layers that
## are to be used, is up to the programmer and the naming
## is free by programmer choice:
layer background(noproj); # background: no projections,
# just one frame
layer border; # border: given in αδ* as
# a loop → coorsys
# change, projection,
# frame
layer grid; # grid: given in αδ* as
# lines → coorsys
# change, projection,
# frame
layer nebulae; # nebulae: given in αδ →
# coorsys change,
# projection, frame
layer stars; # stars: given in αδ →
# coorsys change,
# projection, frame
layer labels(noproj); # labels: given in αδ →
# x₀y₀ + xy offset ???
# (MANUALLY!)
background += infinite [color: [r: x00, g: x00, b: x40]];
grid += grid [α: 1ʰ, δ: 10°];
stars += load "stars.db";
labels += align stars "stardesg.db";
nebulae += load "nebulae.db";
labels += align nebulae "nebdesg.db";
{ # a stacklike block for loading local data
orion; # run procedure ‘orion’
out "orion.svg";
}
{
monoceros; # run procedure ‘monoceros’
out "monoceros.svg";
}
}
Further notes on the layers:
layer border
is for
constellation borders,
layer labels
is for star and galaxy labels, and are intended for manually copying positions from the star and galaxy layers, then adding an offset to place the star and galaxy labels at proper positions: not colliding with each other, not overlapping the labelled object.