diff --git a/.gitignore b/.gitignore index e84ac77..ecc85c6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,8 @@ *.pyc +#chart configurations I use to debug +test/ + # Distribution / packaging develop-eggs/ dist/ diff --git a/README.md b/README.md index 0cc7a85..c97ce26 100644 --- a/README.md +++ b/README.md @@ -209,6 +209,7 @@ The following settings can be included in a `StarCharter` configuration file: * `grid_col` - Colour to use when drawing grid of RA/Dec lines * `label_ecliptic` - Boolean (0 or 1) indicating whether to label the months along the ecliptic, showing the Sun's annual progress * `label_font_size_scaling` - Scaling factor to be applied to the font size of all star and DSO labels (default 1.0) +* `label_meridian` Boolean (0 or 1) indicating whether to label declination lines multiple of 10 degrees along the vernal meridian * `language` - The language used for the constellation names. Either "english" or "french". * `mag_alpha` - The multiplicative scaling factor to apply to the radii of stars differing in magnitude by one * `mag_max` - Used to regulate the size of stars. A star of this magnitude is drawn with size mag_size_norm. Also, this is the brightest magnitude of star which is shown in the magnitude key below the chart. @@ -220,6 +221,7 @@ The following settings can be included in a `StarCharter` configuration file: * `maximum_dso_label_count` - The maximum number of deep sky objects which may be labelled * `maximum_star_count` - The maximum number of stars to draw. If this is exceeded, only the brightest stars are shown. * `maximum_star_label_count` - The maximum number of stars which may be labelled +* `meridian_col` - Colour to use when drawing a line along the vernal meridian * `messier_only` - Boolean (0 or 1) indicating whether we plot only Messier objects, and no other deep sky objects * `must_show_all_ephemeris_labels` - Boolean (0 or 1) indicating whether we show all ephemeris text labels, even if they collide with other text. * `output_filename` - The target filename for the star chart. The file type (svg, png, eps or pdf) is inferred from the file extension. @@ -229,6 +231,7 @@ The following settings can be included in a `StarCharter` configuration file: * `plot_equator` - Boolean (0 or 1) indicating whether to draw a line along the equator * `plot_galactic_plane` - Boolean (0 or 1) indicating whether to draw a line along the galactic plane * `plot_galaxy_map` - Boolean (0 or 1) indicating whether to draw a shaded map of the Milky Way behind the star chart +* `plot_meridian` - Boolean (0 or 1) indicating whether we plot the vernal meridian * `plot_stars` - Boolean (0 or 1) indicating whether we plot any stars * `position_angle` - The position angle of the plot - i.e. the tilt of north, counter-clockwise from up, at the centre of the plot * `projection` - Select projection to use. Set to either flat, peters, gnomonic, sphere or alt_az @@ -244,8 +247,26 @@ The following settings can be included in a `StarCharter` configuration file: * `star_mag_labels` - Boolean (0 or 1) indicating whether we label the magnitudes of stars * `star_names` - Boolean (0 or 1) indicating whether we label the English names of stars * `star_variable_labels` - Boolean (0 or 1) indicating whether we label the variable-star designations of stars, e.g. V337_Car +* `dec_ticks_on_round_edge` - Boolean (o or 1) indicating whether lines of constant declination (or galactic latitude) put a tick on the round edge of an Alt_Az chart +* `ra_ticks_on_round_edge` - Boolean (o or 1) indicating whether lines of constant right ascension (or galactic longitude) put a tick on the round edge of an Alt_Az chart * `title` - The heading to write at the top of the star chart * `width` - The width of the star chart, in cm * `x_label_slant` - A slant to apply to all labels on the horizontal axes * `y_label_slant` - A slant to apply to all labels on the vertical axes * `zodiacal_only` - Boolean (0 or 1) indicating whether we plot only the zodiacal constellations + +# Changelog + +## Functionalities + +* Extended `alt_az` plotting to draw charts of arbitrary (<360°) angular width. E.G., this is useful to plot a chart of all stars you can see throughout the year +* Implemented ticks on round edge of the chart in `alt_az` mode, with the possibility to choose whether RA, Dec or both lines put ticks on it +* Possibility to plot the vernal meridian, with the option to put a tick on it every 10° of declination + +## New configuration parameters + +* `label_meridian` +* `meridian_col` +* `plot_meridian` +* `dec_ticks_on_round_edge` +* `ra_ticks_on_round_edge` diff --git a/src/astroGraphics/constellations.c b/src/astroGraphics/constellations.c index 0d81988..28820c3 100644 --- a/src/astroGraphics/constellations.c +++ b/src/astroGraphics/constellations.c @@ -66,7 +66,7 @@ void plot_constellation_boundaries(chart_config *s, line_drawer *ld) { // Set up line-drawing class ld_pen_up(ld, GSL_NAN, GSL_NAN, NULL, 1); - ld_label(ld, NULL, 1, 1); + ld_label(ld, NULL, 1, 1, 1); // Open file defining the celestial coordinates of the constellation boundaries file = fopen(SRCDIR "../data/constellations/downloads/boundaries.dat", "r"); diff --git a/src/astroGraphics/ephemeris.c b/src/astroGraphics/ephemeris.c index 3133888..b5ed046 100644 --- a/src/astroGraphics/ephemeris.c +++ b/src/astroGraphics/ephemeris.c @@ -518,7 +518,7 @@ void plot_ephemeris(chart_config *s, line_drawer *ld, cairo_page *page, int trac // Set line colour ld_pen_up(ld, GSL_NAN, GSL_NAN, NULL, 1); cairo_set_source_rgb(s->cairo_draw, s->ephemeris_col.red, s->ephemeris_col.grn, s->ephemeris_col.blu); - ld_label(ld, NULL, 1, 1); + ld_label(ld, NULL, 1, 1, 1); // Loop over the points in the ephemeris, and draw a line across the star chart const ephemeris *e = &s->ephemeris_data[trace_num]; @@ -591,7 +591,7 @@ void plot_ephemeris(chart_config *s, line_drawer *ld, cairo_page *page, int trac // Draw tick mark ld_pen_up(ld, GSL_NAN, GSL_NAN, NULL, 1); - ld_label(ld, NULL, 1, 1); + ld_label(ld, NULL, 1, 1, 1); ld_point(ld, x + graph_coords_tick_len * sin(theta), y - graph_coords_tick_len * cos(theta), NULL); ld_point(ld, x - graph_coords_tick_len * sin(theta), y + graph_coords_tick_len * cos(theta), NULL); ld_pen_up(ld, GSL_NAN, GSL_NAN, NULL, 1); @@ -894,4 +894,4 @@ double draw_ephemeris_table(chart_config *s, double legend_y_pos, int draw_outpu } return legend_y_pos; -} \ No newline at end of file +} diff --git a/src/astroGraphics/greatCircles.c b/src/astroGraphics/greatCircles.c index 60e87e4..6b7949f 100644 --- a/src/astroGraphics/greatCircles.c +++ b/src/astroGraphics/greatCircles.c @@ -61,7 +61,7 @@ static void plot_great_circle(double ra0, double dec0, chart_config *s, line_dra dec0 = dec0 * M_PI / 180; ld_pen_up(ld, GSL_NAN, GSL_NAN, NULL, 1); for (i = 0; i <= N_SAMPLES; i++) { - const double l = 2 * M_PI * ((double) i) / N_SAMPLES; + const double l = 2 * M_PI * ((double) i) / (N_SAMPLES-1); double a[3] = {cos(l), sin(l), 0.}; double ra, dec, x, y; @@ -97,6 +97,56 @@ static void plot_great_circle(double ra0, double dec0, chart_config *s, line_dra } } +//small modification to print half circle, useful for meridians. + +static void plot_great_half_circle(double ra0, double dec0, chart_config *s, line_drawer *ld, + cairo_page *page, int n_labels, gc_label *labels, colour colour) { + int i; + ra0 = ra0 * M_PI / 180; + dec0 = dec0 * M_PI / 180; + ld_pen_up(ld, GSL_NAN, GSL_NAN, NULL, 1); + for (i = 0; i <= N_SAMPLES; i++) { + const double l = M_PI * ((double) i) / (N_SAMPLES-1); + double a[3] = {cos(l), sin(l), 0.}; + double ra, dec, x, y; + + rotate_xz(a, a, dec0 - (M_PI / 2)); + rotate_xy(a, a, ra0); + + dec = asin(a[2]); + ra = atan2(a[1], a[0]); + plane_project(&x, &y, s, ra, dec, 0); + ld_point(ld, x, y, NULL); + } + ld_pen_up(ld, GSL_NAN, GSL_NAN, NULL, 1); + + if (n_labels) + for (i = 0; i < n_labels; i++) { + const double l = M_PI*(labels[i].xpos) / 180; + double a[3] = {cos(l), sin(l), 0.}; + double ra, dec, x, y, xtemp, ytemp; + + rotate_xz(a, a, dec0 - (M_PI / 2)); + rotate_xy(a, a, ra0); + + dec = asin(a[2]); + ra = atan2(a[1], a[0]); + plane_project(&x, &y, s, ra, dec, 0); + plane_project(&xtemp, &ytemp, s, ra-0.0000000001/(dec-M_PI/2), dec, 0); + //very, VERY brutal 1st order approximation + ld_point(ld, x+(xtemp-x)/sqrt((x-xtemp)*(x-xtemp)+(y-ytemp)*(y-ytemp))/50, y+(ytemp-y)/sqrt(((x-xtemp)*(x-xtemp))+((y-ytemp)*(y-ytemp)))/50, NULL); + ld_point(ld, x, y, NULL); + plane_project(&xtemp, &ytemp, s, ra+0.000000001/(dec-M_PI/2), dec, 0); + ld_point(ld, x+(xtemp-x)/sqrt((x-xtemp)*(x-xtemp)+(y-ytemp)*(y-ytemp))/50, y+(ytemp-y)/sqrt(((x-xtemp)*(x-xtemp))+((y-ytemp)*(y-ytemp)))/50, NULL); + ld_pen_up(ld, GSL_NAN, GSL_NAN, NULL, 1); + plane_project(&xtemp, &ytemp, s, ra+0.1/(dec-M_PI/2), dec, 0); + + chart_label_buffer(page, s, colour, labels[i].label, + &(label_position) {x+(xtemp-x)/sqrt(((x-xtemp)*(x-xtemp))+((y-ytemp)*(y-ytemp)))/25, y+(ytemp-y)/sqrt(((x-xtemp)*(x-xtemp))+((y-ytemp)*(y-ytemp)))/25, 0, 0, -1}, 1, + 0, 1, 2.0, 1, 0, 0, -0.5); + } +} + //! plot_equator - Draw a line along the celestial equator //! \param s - A structure defining the properties of the star chart to be drawn. //! \param ld - A structure used to draw lines on a cairo surface. @@ -110,6 +160,34 @@ void plot_equator(chart_config *s, line_drawer *ld, cairo_page *page) { plot_great_circle(0, 90, s, ld, page, 0, NULL, s->equator_col); } +// plots RA=0 meridian +void plot_meridian(chart_config *s, line_drawer *ld, cairo_page *page) { + gc_label labels[17] = {{"-80", 10}, + {"-70", 20}, + {"-60", 30}, + {"-50", 40}, + {"-40", 50}, + {"-30", 60}, + {"-20", 70}, + {"-10", 80}, + {"0", 90}, + {"10", 100}, + {"20", 110}, + {"30", 120}, + {"40", 130}, + {"50", 140}, + {"60", 150}, + {"70", 160}, + {"80", 170}, + }; + // Set line colour + ld_pen_up(ld, GSL_NAN, GSL_NAN, NULL, 1); + cairo_set_source_rgb(s->cairo_draw, s->meridian_col.red, s->meridian_col.grn, s->meridian_col.blu); + cairo_set_line_width(s->cairo_draw, s->great_circle_line_width); + + plot_great_half_circle(-90, 0, s, ld, page, s->label_meridian ? 17 : 0, labels, + s->meridian_col); +} //! plot_galactic_plane - Draw a line along the plane of the Milky Way //! \param s - A structure defining the properties of the star chart to be drawn. @@ -161,7 +239,7 @@ void plot_ecliptic(chart_config *s, line_drawer *ld, cairo_page *page) { //! \param legend_y_pos - The vertical pixel position of the top of the next legend to go under the star chart. double draw_great_circle_key(chart_config *s, double legend_y_pos) { - const int N = (s->plot_equator != 0) + (s->plot_ecliptic != 0) + (s->plot_galactic_plane != 0); + const int N = (s->plot_meridian != 0) + (s->plot_equator != 0) + (s->plot_ecliptic != 0) + (s->plot_galactic_plane != 0); const double w_left = 0.4; // The left margin const double w_item = 4.2 * s->font_size; // The width of each legend item (cm) @@ -188,12 +266,12 @@ double draw_great_circle_key(chart_config *s, double legend_y_pos) { // Reset font weight cairo_select_font_face(s->cairo_draw, s->font_family, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); - // Draw item on legend showing the colour of the equator + // Draw item on legend showing the colour of the meridian if (s->plot_equator != 0) { - const char *label = "The Equator"; + const char *label = "Vernal Meridian"; // Draw a line in the right colour - cairo_set_source_rgb(s->cairo_draw, s->equator_col.red, s->equator_col.grn, s->equator_col.blu); + cairo_set_source_rgb(s->cairo_draw, s->meridian_col.red, s->meridian_col.grn, s->meridian_col.blu); cairo_new_path(s->cairo_draw); cairo_move_to(s->cairo_draw, x * s->cm, y1 * s->cm); cairo_line_to(s->cairo_draw, (x + size) * s->cm, y1 * s->cm); @@ -216,6 +294,30 @@ double draw_great_circle_key(chart_config *s, double legend_y_pos) { if (s->plot_ecliptic != 0) { const char *label = "Ecliptic Plane"; + // Draw item on legend showing the colour of the equator + if (s->plot_equator != 0) { + const char *label = "The Equator"; + + // Draw a line in the right colour + cairo_set_source_rgb(s->cairo_draw, s->equator_col.red, s->equator_col.grn, s->equator_col.blu); + cairo_new_path(s->cairo_draw); + cairo_move_to(s->cairo_draw, x * s->cm, y1 * s->cm); + cairo_line_to(s->cairo_draw, (x + size) * s->cm, y1 * s->cm); + cairo_stroke(s->cairo_draw); + + // Write a text label next to it + cairo_set_source_rgb(s->cairo_draw, 0, 0, 0); + cairo_text_extents(s->cairo_draw, label, &extents); + cairo_move_to(s->cairo_draw, + (x + 0.1 + size * 1.25) * s->cm - extents.x_bearing, + y1 * s->cm - extents.height / 2 - extents.y_bearing + ); + cairo_show_text(s->cairo_draw, label); + + // Advance horizontally to draw the next item in the legend + x += w_item; + } + // Draw a line in the right colour cairo_set_source_rgb(s->cairo_draw, s->ecliptic_col.red, s->ecliptic_col.grn, s->ecliptic_col.blu); cairo_new_path(s->cairo_draw); diff --git a/src/astroGraphics/greatCircles.h b/src/astroGraphics/greatCircles.h index 48b7a78..95e637d 100644 --- a/src/astroGraphics/greatCircles.h +++ b/src/astroGraphics/greatCircles.h @@ -31,6 +31,8 @@ void plot_equator(chart_config *s, line_drawer *ld, cairo_page *page); +void plot_meridian(chart_config *s, line_drawer *ld, cairo_page *page); + void plot_galactic_plane(chart_config *s, line_drawer *ld, cairo_page *page); void plot_ecliptic(chart_config *s, line_drawer *ld, cairo_page *page); diff --git a/src/astroGraphics/raDecLines.c b/src/astroGraphics/raDecLines.c index 6669ce2..e9f4f5e 100644 --- a/src/astroGraphics/raDecLines.c +++ b/src/astroGraphics/raDecLines.c @@ -144,7 +144,8 @@ void plot_ra_dec_lines(chart_config *s, line_drawer *ld) { // Tell the line drawing class what label should be placed on the edge of the star chart when we cross it // Lines of constant RA only create tick labels on the horizontal axes, not the vertical axes - ld_label(ld, label, 1, 0); + // Lines of constant declination create a tick on the round edge of the chart in Alt_Az mode if and only if ordered to do so + ld_label(ld, label, 1, 0, s->ra_ticks_on_round_edge); // Trace the path of this line across chart for (j = 0; j < N_POINTS; j++) { @@ -214,7 +215,8 @@ void plot_ra_dec_lines(chart_config *s, line_drawer *ld) { // Tell the line drawing class what label should be placed on the edge of the star chart when we cross it // Lines of constant declination only create tick labels on the vertical axes, not the horizontal axes - ld_label(ld, label, 0, 1); + // Lines of constant declination create a tick on the round edge of the chart in Alt_Az mode if and only if ordered to do so + ld_label(ld, label, 0, 1, s->dec_ticks_on_round_edge); // Trace the path of this line across chart for (j = 0; j < N_POINTS; j++) { diff --git a/src/main.c b/src/main.c index 347c002..42b7fdc 100644 --- a/src/main.c +++ b/src/main.c @@ -80,11 +80,14 @@ void render_chart(chart_config *s) { plot_background_image(s); // Initialise module for tracing lines on the star chart - ld_init(&ld, s, page.x_labels, page.x2_labels, page.y_labels, page.y2_labels); + ld_init(&ld, s, page.x_labels, page.x2_labels, page.y_labels, page.y2_labels, page.r_labels); // Draw the line of the equator if (s->plot_equator) plot_equator(s, &ld, &page); + // Draw the line of the vernal meridian + if (s->plot_meridian) plot_meridian(s, &ld, &page); + // Draw the line of the galactic plane if (s->plot_galactic_plane) plot_galactic_plane(s, &ld, &page); @@ -350,7 +353,19 @@ int main(int argc, char **argv) { CHECK_KEYVALNUM("axis_ticks_value_only") settings_destination->axis_ticks_value_only = (int) key_val_num; continue; - } else if (strcmp(key, "axis_label") == 0) { + } else if (strcmp(key, "ra_ticks_on_round_edge") == 0) { + //! ra_ticks_on_round_edge - If 1, constant RA labels will place ticks on the round edge in Alt_Az mode. + //! If 0, they won't + CHECK_KEYVALNUM("ra_ticks_on_round_edge") + settings_destination->ra_ticks_on_round_edge = (int) key_val_num; + continue; + } else if (strcmp(key, "dec_ticks_on_round_edge") == 0) { +//! dec_ticks_on_round_edge - If 1, constant Dec labels will place ticks on the round edge in Alt_Az mode. + //! If 0, they won't + CHECK_KEYVALNUM("dec_ticks_on_round_edge") + settings_destination->dec_ticks_on_round_edge = (int) key_val_num; + continue; + } else if (strcmp(key, "axis_label") == 0) { //! axis_label - Boolean (0 or 1) indicating whether to write "Right ascension" and "Declination" on the //! vertical/horizontal axes CHECK_KEYVALNUM("axis_label") @@ -476,7 +491,7 @@ int main(int argc, char **argv) { } else if (strcmp(key_val, "alt_az") == 0) { settings_destination->projection = SW_PROJECTION_ALTAZ; settings_destination->aspect = 1.; - settings_destination->angular_width = 180.; + //settings_destination->angular_width = 180.; } else { snprintf(temp_err_string, FNAME_LENGTH, "Bad input file. projection should equal 'flat', 'gnomonic', 'sphere' or 'alt_az'."); @@ -720,7 +735,18 @@ int main(int argc, char **argv) { CHECK_KEYVALNUM("plot_equator") settings_destination->plot_equator = (int) key_val_num; continue; - } else if (strcmp(key, "ecliptic_col") == 0) { + }else if (strcmp(key, "plot_meridian") == 0) { + //! plot_meridian - Boolean (0 or 1) indicating whether to draw a line along the vernal meridian + CHECK_KEYVALNUM("plot_meridian") + settings_destination->plot_meridian = (int) key_val_num; + continue; + } else if (strcmp(key, "label_meridian") == 0) { + //! label_meridian - Boolean (0 or 1) indicating whether to label Dec degrees along the + //! vernal meridian, useful to label Dec lines in Alt_Az charts + CHECK_KEYVALNUM("label_meridian") + settings_destination->label_meridian = (int) key_val_num; + continue; + } else if (strcmp(key, "ecliptic_col") == 0) { //! ecliptic_col - Colour to use when drawing a line along the ecliptic settings_destination->ecliptic_col = colour_from_string(key_val); continue; @@ -732,6 +758,10 @@ int main(int argc, char **argv) { //! equator_col - Colour to use when drawing a line along the equator settings_destination->equator_col = colour_from_string(key_val); continue; + } else if (strcmp(key, "meridian_col") == 0) { + //! meridian_col - Colour to use when drawing a line along the equator + settings_destination->meridian_col = colour_from_string(key_val); + continue; } else if (strcmp(key, "plot_galaxy_map") == 0) { //! plot_galaxy_map - Boolean (0 or 1) indicating whether to draw a shaded map of the Milky Way behind //! the star chart diff --git a/src/mathsTools/projection.c b/src/mathsTools/projection.c index 70b4bc0..5465933 100644 --- a/src/mathsTools/projection.c +++ b/src/mathsTools/projection.c @@ -67,7 +67,14 @@ void galactic_project(double ra, double dec, double *l_out, double *b_out) { //! to be converted into galactic coordinates. void plane_project(double *x, double *y, chart_config *s, double lng, double lat, int grid_line) { - double azimuth, radius = 0, zenith_angle; + double azimuth, radius = 0, zenith_angle/*, cap_angle*/; + + /*cap_angle=M_PI/2; + if (s->angular_width/2>cap_angle) { + cap_angle=(s->angular_width)/2; + }*/ + //cap_angle=(s->angular_width)/2; + //printf("angular_width = %f", s->angular_width); if ((s->coords == SW_COORDS_GAL) && (!grid_line)) { @@ -97,15 +104,27 @@ void plane_project(double *x, double *y, chart_config *s, double lng, double lat } make_zenithal(&zenith_angle, &azimuth, lng, lat, s->ra0, s->dec0); azimuth -= s->position_angle * M_PI / 180; - if (zenith_angle > M_PI / 2) { - // Opposite side of sphere! - *x = *y = GSL_NAN; - return; + //if (zenith_angle > M_PI / alpha) { + if(s->projection == SW_PROJECTION_ALTAZ){ + //if (zenith_angle > s->angular_width/2) { //does this make intersections happen? + if (zenith_angle>M_PI){ + // Opposite side of sphere! + *x = *y = GSL_NAN; + return; + } + } else{ + if (zenith_angle > M_PI/2) { + // Opposite side of sphere! + *x = *y = GSL_NAN; + return; + } } if (s->projection == SW_PROJECTION_GNOM) radius = tan(zenith_angle); else if (s->projection == SW_PROJECTION_SPH) radius = sin(zenith_angle); - else if (s->projection == SW_PROJECTION_ALTAZ) radius = zenith_angle / (M_PI / 2); + //else if (s->projection == SW_PROJECTION_ALTAZ) radius = zenith_angle /(M_PI/alpha); + else if (s->projection == SW_PROJECTION_ALTAZ) radius = 2*zenith_angle /s->angular_width; + *y = radius * cos(azimuth); *x = radius * -sin(azimuth); @@ -120,10 +139,15 @@ void plane_project(double *x, double *y, chart_config *s, double lng, double lat void inv_plane_project(double *ra, double *dec, chart_config *s, double x, double y) { double za = 0.0; + double cap_angle=M_PI/2; + if (s->angular_width/2>cap_angle) { + cap_angle=(s->angular_width)/2; + } if (s->projection == SW_PROJECTION_GNOM) za = atan(hypot(x, y)); else if (s->projection == SW_PROJECTION_SPH) za = asin(hypot(x, y)); - else if (s->projection == SW_PROJECTION_ALTAZ) za = hypot(x, y) * (M_PI / 2); + //else if (s->projection == SW_PROJECTION_ALTAZ) za = hypot(x, y) * (M_PI / 2); + else if (s->projection == SW_PROJECTION_ALTAZ) za = hypot(x, y) * s->angular_width/2; if (s->projection == SW_PROJECTION_FLAT) { double pa = s->position_angle * M_PI / 180.; @@ -141,13 +165,22 @@ void inv_plane_project(double *ra, double *dec, chart_config *s, double x, doubl double az = atan2(-x, y) + s->position_angle * M_PI / 180.; double altitude = M_PI / 2 - za; + //double altitude = cap_angle - za; double a[3] = {cos(altitude) * cos(az), cos(altitude) * sin(az), sin(altitude)}; - if (altitude < 0) { - *ra = *dec = GSL_NAN; - return; - } - + //if (altitude < 0) { + //! Voglio disegnare solo le cose sopra la soglia che imposto, non sopra l'orizzonte + //!if (altitude < 1.4) { + if(s->projection == SW_PROJECTION_ALTAZ){ + if(altitudedec0); rotate_xy(a, a, s->ra0); diff --git a/src/settings/chart_config.c b/src/settings/chart_config.c index 571ebb1..543c1b3 100644 --- a/src/settings/chart_config.c +++ b/src/settings/chart_config.c @@ -41,6 +41,8 @@ void default_config(chart_config *i) { i->position_angle = 0.0; i->font_size = 1.0; i->axis_ticks_value_only = 1; + i->ra_ticks_on_round_edge = 1; + i->dec_ticks_on_round_edge = 1; i->ra_dec_lines = 1; i->x_label_slant = 0; i->y_label_slant = 0; @@ -94,9 +96,11 @@ void default_config(chart_config *i) { i->label_ecliptic = 0; i->plot_galactic_plane = 1; i->plot_equator = 1; + i->plot_meridian = 0; i->ecliptic_col = (colour) {0.8, 0.65, 0}; i->galactic_plane_col = (colour) {0, 0, 0.75}; i->equator_col = (colour) {0.65, 0, 0.65}; + i->meridian_col = (colour) {0.1, 0.8, 1}; i->constellation_stick_col = (colour) {0, 0.6, 0}; i->grid_col = (colour) {0.7, 0.7, 0.7}; i->constellation_boundary_col = (colour) {0.5, 0.5, 0.5}; @@ -118,7 +122,7 @@ void default_config(chart_config *i) { strcpy(i->galaxy_map_filename, SRCDIR "../data/milkyWay/process/output/galaxymap.dat"); strcpy(i->photo_filename, ""); strcpy(i->output_filename, "chart"); - strcpy(i->copyright, "Produced with StarCharter. https://github.com/dcf21/star-charter"); + strcpy(i->copyright, ""); strcpy(i->title, ""); // ---------------------------------------- @@ -134,6 +138,7 @@ void default_config(chart_config *i) { } void config_init(chart_config *i) { + i->marg=1.12; //margin specified here if (i->coords == SW_COORDS_GAL) i->ra0 *= M_PI / 180; // Specify galactic longitude in degrees else i->ra0 *= M_PI / 12; // Specify RA in hours i->dec0 *= M_PI / 180; // Specify declination and galactic latitude in degrees @@ -142,9 +147,11 @@ void config_init(chart_config *i) { else if (i->projection == SW_PROJECTION_PETERS) i->wlin = i->angular_width; else if (i->projection == SW_PROJECTION_GNOM) i->wlin = 2 * tan(i->angular_width / 2); else if (i->projection == SW_PROJECTION_SPH) - i->wlin = 2 * sin(i->angular_width / 2) * 1.12; // margin specified here + i->wlin = 2 * sin(i->angular_width / 2) * i->marg; else if (i->projection == SW_PROJECTION_ALTAZ) - i->wlin = i->angular_width / (M_PI / 2) * 1.12; // margin specified here + i->wlin = 2*i->marg; + //i->wlin = i->angular_width / (M_PI / 2) * i->marg; + //i->wlin = M_PI / (M_PI / 2) * 1.12; // margin specified here i->x_min = -i->wlin / 2; i->x_max = i->wlin / 2; i->y_min = -i->wlin / 2 * i->aspect; diff --git a/src/settings/chart_config.h b/src/settings/chart_config.h index bdeb9f5..357ebfc 100644 --- a/src/settings/chart_config.h +++ b/src/settings/chart_config.h @@ -115,6 +115,12 @@ typedef struct chart_config { //! If true, axis labels appear as "5h" or "30 deg". If false, preceded by alpha= or delta= int axis_ticks_value_only; + //! If true, constant RA lines make ticks on round edge in alt_az mode + int ra_ticks_on_round_edge; + + //! If true, constant Dec lines make ticks on round edge in alt_az mode + int dec_ticks_on_round_edge; + //! Boolean indicating whether we draw a grid of RA/Dec lines in the background of the star chart int ra_dec_lines; @@ -322,6 +328,9 @@ typedef struct chart_config { //! Colour to use when drawing a line along the equator colour equator_col; + //! Colour to use when drawing a line along the vernal meridian + colour meridian_col; + //! Boolean indicating whether to draw a line along the ecliptic int plot_ecliptic; @@ -331,6 +340,12 @@ typedef struct chart_config { //! Boolean indicating whether to draw a line along the equator int plot_equator; + //! Boolean indicating whether to draw a line along the vernal meridian + int plot_meridian; + + //! Boolean indicating whether to label Dec lines along the vernal meridian + int label_meridian; + //! Boolean indicating whether to label the months along the ecliptic, showing the Sun's annual progress int label_ecliptic; @@ -400,7 +415,7 @@ typedef struct chart_config { int output_format; double canvas_width, canvas_height, canvas_offset_x, canvas_offset_y, dpi, pt, cm, mm, line_width_base; - double wlin, x_min, x_max, y_min, y_max; + double wlin, marg, x_min, x_max, y_min, y_max; //! Width of the right-hand column of the legend under the finder chart double legend_right_column_width; diff --git a/src/vectorGraphics/cairo_page.c b/src/vectorGraphics/cairo_page.c index 74c268d..9fe119c 100644 --- a/src/vectorGraphics/cairo_page.c +++ b/src/vectorGraphics/cairo_page.c @@ -177,6 +177,7 @@ void cairo_init(cairo_page *p, chart_config *s) { p->x2_labels = listInit(); p->y_labels = listInit(); p->y2_labels = listInit(); + p->r_labels = listInit(); // Create a buffer into which we write all the text labels we are to write // We buffer them in order that we can plot them in order of priority, not the order in which they are added to @@ -202,6 +203,7 @@ void cairo_init(cairo_page *p, chart_config *s) { (s->canvas_offset_x + s->width / 2) * s->cm, (s->canvas_offset_y + s->width / 2 * s->aspect) * s->cm, s->width * s->cm / s->wlin, + //s->width * s-> cm /2/s->marg, 0, 2 * M_PI); } else { @@ -280,6 +282,7 @@ void draw_chart_edging(cairo_page *p, chart_config *s) { (s->canvas_offset_x + s->width / 2) * s->cm, (s->canvas_offset_y + s->width / 2 * s->aspect) * s->cm, s->width * s->cm / s->wlin, + //s->width * s->cm /2/s->marg, 0, 2 * M_PI); cairo_stroke(s->cairo_draw); @@ -665,7 +668,7 @@ int chart_label(cairo_page *p, chart_config *s, colour colour, const char *label //! \param p - A structure describing the status of the drawing surface //! \param s - Settings for the star chart we are drawing //! \param labels - The list of labels to write along this edge of the star chart -//! \param axis - One of ("x", "y", "x2", "y2") indicating whether this is the (bottom, left, top, right) edge +//! \param axis - One of ("x", "y", "x2", "y2", "r") indicating whether this is the (bottom, left, top, right, or round) edge void chart_ticks_draw(cairo_page *p, chart_config *s, list *labels, char *axis) { int N = listLen(labels); @@ -774,7 +777,27 @@ void chart_ticks_draw(cairo_page *p, chart_config *s, list *labels, char *axis) cairo_move_to(s->cairo_draw, -extents.x_bearing, -extents.height / 2 - extents.y_bearing); cairo_show_text(s->cairo_draw, tic_text); cairo_restore(s->cairo_draw); - } + } else if (strcmp(axis, "r") == 0) { + // Calculate coordinates of this label + x_canvas = (s-> canvas_offset_x + (s-> width*(1+cos(tic_pos)/s->marg))/2) *s->cm; + y_canvas = (s-> canvas_offset_y + (s-> width*(1+sin(tic_pos)/s->marg))/2) *s->cm; + + // Check that this label does not collide with previous labels + const double x_min = x_canvas-extents.width / 2; + const double x_max = x_canvas+extents.width / 2; + const double y_min = y_canvas-extents.height/2; + const double y_max = y_canvas+extents.height/2; + if (chart_check_label_exclusion(p, x_min, x_max, y_min, y_max)) continue; + chart_add_label_exclusion(p, s, x_min, x_max, y_min, y_max); + + // Write a label on the round edge of the chart + cairo_save(s->cairo_draw); + cairo_translate(s->cairo_draw, x_canvas, y_canvas); + cairo_move_to(s->cairo_draw, -extents.width / 2 -extents.x_bearing +(extents.width+0.5*s->cm)/2*cos(tic_pos), + -extents.height/2 -extents.y_bearing +(extents.height+0.5*s->cm)/2*sin(tic_pos)); //radial align with 0.5cm margin on each side + cairo_show_text(s->cairo_draw, tic_text); + cairo_restore(s->cairo_draw); + } } } @@ -808,6 +831,9 @@ int chart_finish(cairo_page *p, chart_config *s) { chart_ticks_draw(p, s, p->y_labels, "y"); chart_ticks_draw(p, s, p->x2_labels, "x2"); chart_ticks_draw(p, s, p->y2_labels, "y2"); + if (s->projection == SW_PROJECTION_ALTAZ) { + chart_ticks_draw(p, s, p->r_labels, "r"); + } // Close cairo drawing context cairo_destroy(s->cairo_draw); diff --git a/src/vectorGraphics/cairo_page.h b/src/vectorGraphics/cairo_page.h index 0c7dc7f..605bd15 100644 --- a/src/vectorGraphics/cairo_page.h +++ b/src/vectorGraphics/cairo_page.h @@ -64,7 +64,7 @@ typedef struct { } exclusion_region; typedef struct { - list *x_labels, *x2_labels, *y_labels, *y2_labels; + list *x_labels, *x2_labels, *y_labels, *y2_labels, *r_labels; label_buffer_item *labels_buffer; int labels_buffer_counter; diff --git a/src/vectorGraphics/lineDraw.c b/src/vectorGraphics/lineDraw.c index 3a99bd9..9578ec6 100644 --- a/src/vectorGraphics/lineDraw.c +++ b/src/vectorGraphics/lineDraw.c @@ -48,6 +48,19 @@ static void list_add_tick(list *l, double x, const char *label) { listAppendPtr(l, buff, FNAME_LENGTH, 0, DATATYPE_VOID); } +//Solve second degree equation +void solve2deg(double *sol1, double *sol2, double a, double b, double c){ + double delta= b*b-4*a*c; + if(delta >= 0){ + *sol1=(-b+sqrt(delta))/(2*a); + *sol2=(-b-sqrt(delta))/(2*a); + } + else{ + *sol1=*sol2=GSL_NAN; + } + +} + //! truncate_at_axis - Take a line segment which passes outside the boundary of the star chart, and truncate it at the //! edge of the chart. Also, if this line has a text label associated with it, then place a label on the axis where //! this line meets it, typically denoting the RA or the Dec being traced by this line. @@ -125,6 +138,49 @@ void truncate_at_axis(double *xout, double *yout, double x0, double y0, double x *yout = y0; } +//truncate_at_round_edge: looks for intersection with the edge of the chart in Alt_Az charts + +void truncate_at_round_edge(double *xout, double *yout, double x0, double y0, double x1, + double y1, char *label, list *rlabels) { + double x=GSL_NAN, y=GSL_NAN, s1, s2, theta=GSL_NAN; + + if (x1 != x0) { + // Look for intersection with round edge of chart + double m = (y1 - y0) / (x1 - x0); + solve2deg(&s1, &s2, 1+m*m, 2*m*(y0-m*x0), m*m*x0*x0+y0*y0-2*m*x0*y0-1); + if ((s1 <= gsl_max(x0, x1)) && (s1 >= gsl_min(x0, x1))){ + x=s1; + } else if ((s2 <= gsl_max(x0, x1)) && (s2 >= gsl_min(x0, x1))){ + x=s2; + } + y=m*(x-x0)+y0; + } else if (y1 != y0) { + x=x0; + if (sqrt(1-x0*x0)>gsl_min(y0, y1)&& sqrt(1-x0*x0)gsl_min(y0, y1)&& -sqrt(1-x0*x0)= 0) { + theta=asin(y); + } else if (y>=0){ + theta=acos(x); + } else if (x<0 && y<0) { + theta=M_PI+acos(-x); + } + if (theta != GSL_NAN){ + list_add_tick(rlabels, theta, label); + *xout = x; + *yout = y; + return; + } + // If no intersection found, then simply return the position of the start of the line + *xout = x0; + *yout = y0; +} + + //! ld_init - Initialise this module for drawing lines on star charts //! \param self - The structure used to hold data about this line drawing module instance. //! \param s - A structure defining the properties of the star chart to be drawn. @@ -132,11 +188,13 @@ void truncate_at_axis(double *xout, double *yout, double x0, double y0, double x //! \param x2labels - The list of labels to place on the top edge of the chart //! \param ylabels - The list of labels to place on the left edge of the chart //! \param y2labels - The list of labels to place on the right edge of the chart +//! \param rlabels - The list of labels to place on the round edge of the chart -void ld_init(line_drawer *self, chart_config *s, list *xlabels, list *x2labels, list *ylabels, list *y2labels) { +void ld_init(line_drawer *self, chart_config *s, list *xlabels, list *x2labels, list *ylabels, list *y2labels, list *rlabels) { self->label = NULL; self->label_on_x = 1; self->label_on_y = 1; + self->label_on_r =1; self->penup = 1; self->haddata = 0; self->xmin = s->x_min; @@ -147,6 +205,7 @@ void ld_init(line_drawer *self, chart_config *s, list *xlabels, list *x2labels, self->x2labels = x2labels; self->ylabels = ylabels; self->y2labels = y2labels; + self->rlabels = rlabels; self->s = s; self->wlin = s->wlin; self->xold = GSL_NAN; @@ -160,11 +219,14 @@ void ld_init(line_drawer *self, chart_config *s, list *xlabels, list *x2labels, //! \param l - The text label to be associated with the next line we draw //! \param label_on_x - Boolean indicating whether this label is allowed to be written on horizontal axes //! \param label_on_y - Boolean indicating whether this label is allowed to be written on vertical axes +//! \param label_on_r - Boolean indicating whether this label is allowed to be written on round edge -void ld_label(line_drawer *self, char *l, int label_on_x, int label_on_y) { +void ld_label(line_drawer *self, char *l, int label_on_x, int label_on_y, int label_on_r) { self->label = l; self->label_on_x = label_on_x; self->label_on_y = label_on_y; + self->label_on_r = label_on_r; + } //! ld_pen_up - Lift the pen and start drawing a new line @@ -227,9 +289,16 @@ void ld_point(line_drawer *self, double x, double y, const char *name) { yp[0] = y; Nitems = 1; } - for (i = 0; i < Nitems; i++) { - if (!gsl_finite(xp[i])) ld_pen_up(self, GSL_NAN, GSL_NAN, NULL, 1); - else ld_point_plot(self, xp[i], yp[i], name); + if (self->s->projection == SW_PROJECTION_ALTAZ) { + for (i = 0; i < Nitems; i++) { + if (!gsl_finite(xp[i])) ld_pen_up(self, GSL_NAN, GSL_NAN, NULL, 1); + else ld_point_plot_round(self, xp[i], yp[i], name); + } + } else { + for (i = 0; i < Nitems; i++) { + if (!gsl_finite(xp[i])) ld_pen_up(self, GSL_NAN, GSL_NAN, NULL, 1); + else ld_point_plot(self, xp[i], yp[i], name); + } } } @@ -287,3 +356,48 @@ void ld_point_plot(line_drawer *self, double x, double y, const char *name) { self->xold = x; self->yold = y; } + +//variant for round edge + +void ld_point_plot_round(line_drawer *self, double x, double y, const char *name) { + double x_canvas, y_canvas; + if(x*x+y*y<1){ + if ((gsl_finite(self->xold)) && self->penup) { + double xo, yo; + truncate_at_round_edge(&xo, &yo, self->xold, self->yold, x, y, + self->label, + self->label_on_r ? self->rlabels : NULL); + + fetch_canvas_coordinates(&x_canvas, &y_canvas, xo, yo, self->s); + if (!self->haddata) { + cairo_new_path(self->s->cairo_draw); + cairo_move_to(self->s->cairo_draw, x_canvas, y_canvas); + } else cairo_line_to(self->s->cairo_draw, x_canvas, y_canvas); + self->haddata = 1; + } + fetch_canvas_coordinates(&x_canvas, &y_canvas, x, y, self->s); + if (!self->haddata) { + cairo_new_path(self->s->cairo_draw); + cairo_move_to(self->s->cairo_draw, x_canvas, y_canvas); + } else cairo_line_to(self->s->cairo_draw, x_canvas, y_canvas); + self->haddata = 1; + self->penup = 0; + } else { + if ((gsl_finite(self->xold)) && (!self->penup)) { + double xo, yo; + truncate_at_round_edge(&xo, &yo, self->xold, self->yold, x, y, + self->label, + self->label_on_r ? self->rlabels : NULL); + + fetch_canvas_coordinates(&x_canvas, &y_canvas, xo, yo, self->s); + if (!self->haddata) { + cairo_new_path(self->s->cairo_draw); + cairo_move_to(self->s->cairo_draw, x_canvas, y_canvas); + } else cairo_line_to(self->s->cairo_draw, x_canvas, y_canvas); + self->haddata = 1; + } + ld_pen_up(self, GSL_NAN, GSL_NAN, NULL, 0); + } + self->xold = x; + self->yold = y; +} diff --git a/src/vectorGraphics/lineDraw.h b/src/vectorGraphics/lineDraw.h index 4af691e..1f96d50 100644 --- a/src/vectorGraphics/lineDraw.h +++ b/src/vectorGraphics/lineDraw.h @@ -31,8 +31,8 @@ typedef struct ld_handle { char *label; - int label_on_x, label_on_y; - list *xlabels, *x2labels, *ylabels, *y2labels; + int label_on_x, label_on_y, label_on_r; + list *xlabels, *x2labels, *ylabels, *y2labels, *rlabels; int penup, haddata; double xmin, xmax, ymin, ymax, wlin; chart_config *s; @@ -43,9 +43,12 @@ void truncate_at_axis(double *xout, double *yout, double x0, double y0, double x double ymin, double ymax, char *label, list *xlabels, list *x2labels, list *ylabels, list *y2labels); -void ld_init(line_drawer *self, chart_config *s, list *xlabels, list *x2labels, list *ylabels, list *y2labels); +void truncate_at_round_edge(double *xout, double *yout, double x0, double y0, double x1, double y1, + char *label, list *rlabels); -void ld_label(line_drawer *self, char *l, int label_on_x, int label_on_y); +void ld_init(line_drawer *self, chart_config *s, list *xlabels, list *x2labels, list *ylabels, list *y2labels, list *rlabels); + +void ld_label(line_drawer *self, char *l, int label_on_x, int label_on_y, int label_on_r); void ld_pen_up(line_drawer *self, double x, double y, const char *name, int new_line); @@ -55,5 +58,7 @@ void ld_point(line_drawer *self, double x, double y, const char *name); void ld_point_plot(line_drawer *self, double x, double y, const char *name); +void ld_point_plot_round(line_drawer *self, double x, double y, const char *name); + #endif