#include "swe-glib.h" #include "gswe-types.h" #include "gswe-moment.h" #include "swe-glib-private.h" #include "../swe/src/swephexp.h" #define SYNODIC 29.53058867 #define GSWE_MOMENT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), GSWE_TYPE_MOMENT, GsweMomentPrivate)) /** * GsweMomentPrivate: * @timestamp: a #GsweTimestmp object representing the current local time at * the given position specified by @coordinates. Be warned though, * that the time zone is NOT checked against the coordinates! * @coordinates: the coordinates of the observers position * @revision: an internal counter which is incremented whenever the timestamp * or the coordinates change. Planetary positions are recalculated * if this number changes */ struct _GsweMomentPrivate { GsweTimestamp *timestamp; GsweCoordinates coordinates; GsweHouseSystem house_system; guint revision; GList *house_list; guint house_revision; GList *planet_list; guint points_revision; GHashTable *element_points; GHashTable *quality_points; guint moon_phase_revision; GsweMoonPhaseData moon_phase; GList *aspect_list; guint aspect_revision; GList *mirrorpoint_list; guint mirrorpoint_revision; }; enum { SIGNAL_CHANGED, SIGNAL_LAST }; enum { PROP_0, PROP_TIMESTAMP }; struct GsweAspectFinder { GswePlanet planet1; GswePlanet planet2; }; static guint gswe_moment_signals[SIGNAL_LAST] = {0}; static void gswe_moment_dispose(GObject *gobject); static void gswe_moment_finalize(GObject *gobject); static void gswe_moment_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); static void gswe_moment_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); G_DEFINE_TYPE(GsweMoment, gswe_moment, G_TYPE_OBJECT); static void gswe_moment_class_init(GsweMomentClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); g_type_class_add_private(klass, sizeof(GsweMomentPrivate)); gobject_class->dispose = gswe_moment_dispose; gobject_class->finalize = gswe_moment_finalize; gobject_class->set_property = gswe_moment_set_property; gobject_class->get_property = gswe_moment_get_property; /** * GsweMoment::changed: * @moment: the GsweMoment object that received the signal * * The ::changed signal is emitted each time the time or coordinates are changed */ gswe_moment_signals[SIGNAL_CHANGED] = g_signal_new("changed", G_OBJECT_CLASS_TYPE(gobject_class), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET(GsweMomentClass, changed), NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 0); /** * GsweMoment:timestamp: * * The timestamp associated with this moment */ g_object_class_install_property(gobject_class, PROP_TIMESTAMP, g_param_spec_object("timestamp", "Timestamp", "Timestamp of this moment", GSWE_TYPE_TIMESTAMP, G_PARAM_READWRITE)); } static void gswe_moment_emit_changed(GsweMoment *moment) { g_signal_emit(moment, gswe_moment_signals[SIGNAL_CHANGED], 0); } void gswe_moment_init(GsweMoment *moment) { moment->priv = GSWE_MOMENT_GET_PRIVATE(moment); moment->priv->timestamp = NULL; moment->priv->house_list = NULL; moment->priv->planet_list = NULL; moment->priv->aspect_list = NULL; moment->priv->mirrorpoint_list = NULL; moment->priv->element_points = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, NULL); moment->priv->quality_points = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, NULL); moment->priv->house_revision = 0; moment->priv->points_revision = 0; moment->priv->moon_phase_revision = 0; moment->priv->aspect_revision = 0; moment->priv->mirrorpoint_revision = 0; moment->priv->revision = 1; } static void gswe_moment_timestamp_changed(GsweMoment *moment, gpointer data) { moment->priv->revision++; gswe_moment_emit_changed(moment); } static void gswe_moment_dispose(GObject *gobject) { GsweMoment *moment = GSWE_MOMENT(gobject); g_signal_handlers_disconnect_by_func(moment->priv->timestamp, gswe_moment_timestamp_changed, NULL); g_clear_object(&moment->priv->timestamp); G_OBJECT_CLASS(gswe_moment_parent_class)->dispose(gobject); } static void gswe_moment_finalize(GObject *gobject) { GsweMoment *moment = GSWE_MOMENT(gobject); g_list_free_full(moment->priv->house_list, g_free); g_list_free_full(moment->priv->planet_list, g_free); G_OBJECT_CLASS(gswe_moment_parent_class)->finalize(gobject); } static void gswe_moment_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { GsweMoment *moment = GSWE_MOMENT(object); switch (prop_id) { case PROP_TIMESTAMP: gswe_moment_set_timestamp(moment, (g_value_get_object(value))); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void gswe_moment_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { GsweMoment *moment = GSWE_MOMENT(object); GsweMomentPrivate *priv = moment->priv; switch (prop_id) { case PROP_TIMESTAMP: g_value_set_object(value, priv->timestamp); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } /** * gswe_moment_set_timestamp: * @moment: A GsweMoment object * @timestamp: A GsweTimestamp object. The moment object holds a reference on * timestamp, which is cleared when a new timestamp is set, or the * moment object is disposed. * * Sets a new timestamp for this planetary moment. Also emits the ::changed * signal to notify owner of this change. This helps redrawing screen data * according to the new time value. */ void gswe_moment_set_timestamp(GsweMoment *moment, GsweTimestamp *timestamp) { if (moment->priv->timestamp != NULL) { g_signal_handlers_disconnect_by_func(moment->priv->timestamp, gswe_moment_timestamp_changed, NULL); g_clear_object(&moment->priv->timestamp); } moment->priv->timestamp = timestamp; g_object_ref(timestamp); g_signal_connect(G_OBJECT(timestamp), "changed", G_CALLBACK(gswe_moment_timestamp_changed), NULL); /* Emit the changed signal to notify registrants of the change */ gswe_moment_emit_changed(moment); } /** * gswe_moment_get_timestamp: * @moment: The GsweMoment object of which you requent its timestamp object * * Get the timestamp object of the given GsweMoment. The moment object holds a * reference to this object, so if you need the timestamp object after moment * is disposed, call g_object_ref() on it! * * Returns: a #GsweTimestamp object assigned to the given moment */ GsweTimestamp * gswe_moment_get_timestamp(GsweMoment *moment) { return moment->priv->timestamp; } GQuark gswe_moment_error_quark(void) { return g_quark_from_static_string("swe-glib-gswe-moment-error"); } GsweMoment * gswe_moment_new(void) { return (GsweMoment *)g_object_new(GSWE_TYPE_MOMENT, NULL); } GsweMoment * gswe_moment_new_full(GsweTimestamp *timestamp, gdouble longitude, gdouble latitude, gdouble altitude, GsweHouseSystem house_system) { GsweMoment *moment = gswe_moment_new(); moment->priv->timestamp = timestamp; g_object_ref(timestamp); g_signal_connect(G_OBJECT(timestamp), "changed", G_CALLBACK(gswe_moment_timestamp_changed), NULL); moment->priv->coordinates.longitude = longitude; moment->priv->coordinates.latitude = latitude; moment->priv->coordinates.altitude = altitude; moment->priv->house_system = house_system; return moment; } static gint find_by_planet_id(gconstpointer a, gconstpointer b) { const GswePlanetData *planet_data = a; const GswePlanet *planet = b; if (planet_data->planet_id == *planet) { return 0; } return 1; } static void gswe_calculate_data_by_position(GsweMoment *moment, GswePlanet planet, gdouble position) { GswePlanetData *planet_data = (GswePlanetData *)(g_list_find_custom(moment->priv->planet_list, &planet, find_by_planet_id)->data); GsweZodiac sign; GsweSignInfo *sign_info; if (planet_data == NULL) { return; } if (planet_data->revision == moment->priv->revision) { return; } sign = (GsweZodiac)ceil(position / 30.0); if ((sign_info = g_hash_table_lookup(gswe_sign_info_table, GINT_TO_POINTER(sign))) == NULL) { g_error("Calculations brought an unknown sign!"); } planet_data->position = position; planet_data->retrograde = FALSE; planet_data->house = gswe_moment_get_house(moment, position); planet_data->sign = sign_info; planet_data->revision = moment->priv->revision; } static void gswe_moment_calculate_house_positions(GsweMoment *moment) { gdouble cusps[13], ascmc[10]; gint i; GsweHouseSystemInfo *house_system_data; if (moment->priv->house_revision == moment->priv->revision) { return; } if ((house_system_data = g_hash_table_lookup(gswe_house_system_info_table, GINT_TO_POINTER(moment->priv->house_system))) == NULL) { g_error("Unknown house system!"); } swe_houses(gswe_timestamp_get_julian_day(moment->priv->timestamp), moment->priv->coordinates.latitude, moment->priv->coordinates.longitude, house_system_data->sweph_id, cusps, ascmc); g_list_free_full(moment->priv->house_list, g_free); moment->priv->house_list = NULL; for (i = 12; i >= 1; i--) { GsweHouseData *house_data = g_new0(GsweHouseData, 1); house_data->house = i; house_data->cusp_position = cusps[i]; if ((house_data->sign = g_hash_table_lookup(gswe_sign_info_table, GINT_TO_POINTER((gint)ceilf(cusps[i] / 30.0)))) == NULL) { g_error("Calculations brought an unknown sign!"); } moment->priv->house_list = g_list_prepend(moment->priv->house_list, house_data); } moment->priv->house_revision = moment->priv->revision; if (gswe_moment_has_planet(moment, GSWE_PLANET_ASCENDENT)) { gswe_calculate_data_by_position(moment, GSWE_PLANET_ASCENDENT, ascmc[0]); } if (gswe_moment_has_planet(moment, GSWE_PLANET_MC)) { gswe_calculate_data_by_position(moment, GSWE_PLANET_MC, ascmc[1]); } if (gswe_moment_has_planet(moment, GSWE_PLANET_VERTEX)) { gswe_calculate_data_by_position(moment, GSWE_PLANET_VERTEX, ascmc[3]); } } GList * gswe_moment_get_house_cusps(GsweMoment *moment) { if (moment->priv->house_revision != moment->priv->revision) { gswe_moment_calculate_house_positions(moment); } return moment->priv->house_list; } gboolean gswe_moment_has_planet(GsweMoment *moment, GswePlanet planet) { return (g_list_find_custom(moment->priv->planet_list, &planet, find_by_planet_id) != NULL); } void gswe_moment_add_planet(GsweMoment *moment, GswePlanet planet) { GswePlanetData *planet_data = g_new0(GswePlanetData, 1); GswePlanetInfo *planet_info; if (gswe_moment_has_planet(moment, planet)) { return; } if ((planet_info = g_hash_table_lookup(gswe_planet_info_table, GINT_TO_POINTER(planet))) == NULL) { g_warning("Unknown planet ID: %d", planet); return; } planet_data->planet_id = planet; planet_data->planet_info = planet_info; planet_data->position = 0.0; planet_data->house = 1; planet_data->sign = NULL; planet_data->revision = 0; moment->priv->planet_list = g_list_append(moment->priv->planet_list, planet_data); } static void planet_add(gpointer key, gpointer value, gpointer user_data) { GswePlanet planet = (GswePlanet)GPOINTER_TO_INT(key); GsweMoment *moment = GSWE_MOMENT(user_data); gswe_moment_add_planet(moment, planet); } void gswe_moment_add_all_planets(GsweMoment *moment) { g_hash_table_foreach(gswe_planet_info_table, planet_add, moment); } static void gswe_moment_calculate_planet(GsweMoment *moment, GswePlanet planet) { GswePlanetData *planet_data = (GswePlanetData *)(g_list_find_custom(moment->priv->planet_list, &planet, find_by_planet_id)->data); gchar serr[AS_MAXCH]; gint ret; gdouble x2[6]; if (planet_data == NULL) { return; } if (planet_data->revision == moment->priv->revision) { return; } if (planet_data->planet_info->real_body == FALSE) { g_warning("The position data of planet %d can not be calculated by this function", planet); return; } swe_set_topo(moment->priv->coordinates.longitude, moment->priv->coordinates.latitude, moment->priv->coordinates.altitude); if ((ret = swe_calc(gswe_timestamp_get_julian_day(moment->priv->timestamp), planet_data->planet_info->sweph_id, SEFLG_SPEED | SEFLG_TOPOCTR, x2, serr)) < 0) { g_warning("Swiss Ephemeris error: %s", serr); return; } else if (ret != (SEFLG_SPEED | SEFLG_TOPOCTR)) { g_warning("Swiss Ephemeris error: %s", serr); } gswe_calculate_data_by_position(moment, planet, x2[0]); planet_data->retrograde = (x2[3] < 0); } void calculate_planet(gpointer data, gpointer user_data) { GswePlanetData *planet_data = data; GsweMoment *moment = user_data; gswe_moment_calculate_planet(moment, planet_data->planet_id); } void gswe_moment_calculate_all_planets(GsweMoment *moment) { g_list_foreach(moment->priv->planet_list, calculate_planet, moment); } GList * gswe_moment_get_planets(GsweMoment *moment) { return moment->priv->planet_list; } gint gswe_moment_get_house(GsweMoment *moment, gdouble position) { gint i; gswe_moment_calculate_house_positions(moment); for (i = 1; i <= 12; i++) { gint j = (i < 12) ? i + 1 : 1; gdouble cusp_i = *(gdouble *)g_list_nth_data(moment->priv->house_list, i - 1), cusp_j = *(gdouble *)g_list_nth_data(moment->priv->house_list, j - 1); if (cusp_j < cusp_i) { if ((position >= cusp_i) || (position < cusp_j)) { return i; } } else { if ((position >= cusp_i) && (position < cusp_j)) { return i; } } } return 0; } GswePlanetData * gswe_moment_get_planet(GsweMoment *moment, GswePlanet planet) { GswePlanetData *planet_data = (GswePlanetData *)(g_list_find_custom(moment->priv->planet_list, &planet, find_by_planet_id)->data); if (planet_data == NULL) { return NULL; } gswe_moment_calculate_planet(moment, planet); return planet_data; } static void add_points(GswePlanetData *planet_data, GsweMoment *moment) { guint point; gswe_moment_calculate_planet(moment, planet_data->planet_id); point = GPOINTER_TO_INT(g_hash_table_lookup(moment->priv->element_points, GINT_TO_POINTER(planet_data->sign->element))) + planet_data->planet_info->points; g_hash_table_replace(moment->priv->element_points, GINT_TO_POINTER(planet_data->sign->element), GINT_TO_POINTER(point)); point = GPOINTER_TO_INT(g_hash_table_lookup(moment->priv->quality_points, GINT_TO_POINTER(planet_data->sign->quality))); point += planet_data->planet_info->points; g_hash_table_replace(moment->priv->quality_points, GINT_TO_POINTER(planet_data->sign->quality), GINT_TO_POINTER(point)); } static void gswe_moment_calculate_points(GsweMoment *moment) { if (moment->priv->points_revision == moment->priv->revision) { return; } g_hash_table_remove_all(moment->priv->element_points); g_hash_table_remove_all(moment->priv->quality_points); g_list_foreach(moment->priv->planet_list, (GFunc)add_points, moment); moment->priv->points_revision = moment->priv->revision; } guint gswe_moment_get_element_points(GsweMoment *moment, GsweElement element) { guint point; gswe_moment_calculate_points(moment); point = GPOINTER_TO_INT(g_hash_table_lookup(moment->priv->element_points, GINT_TO_POINTER(element))); return point; } guint gswe_moment_get_quality_points(GsweMoment *moment, GsweQuality quality) { guint point; gswe_moment_calculate_points(moment); point = GPOINTER_TO_INT(g_hash_table_lookup(moment->priv->quality_points, GINT_TO_POINTER(quality))); return point; } GsweMoonPhaseData * gswe_moment_get_moon_phase(GsweMoment *moment) { gdouble difference, phase_percent; if (moment->priv->moon_phase_revision == moment->priv->revision) { return &(moment->priv->moon_phase); } difference = (gswe_timestamp_get_julian_day(moment->priv->timestamp) - gswe_timestamp_get_julian_day(gswe_full_moon_base_date)); phase_percent = fmod((difference * 100) / SYNODIC, 100); if (phase_percent < 0) { phase_percent += 100.0; } if ((phase_percent < 0) || (phase_percent > 100)) { g_error("Error during Moon phase calculation!"); } moment->priv->moon_phase.illumination = (50.0 - fabs(phase_percent - 50.0)) * 2; if (phase_percent == 0) { moment->priv->moon_phase.phase = GSWE_MOON_PHASE_NEW; } else if (phase_percent < 25) { moment->priv->moon_phase.phase = GSWE_MOON_PHASE_WAXING_CRESCENT; } else if (phase_percent == 25) { moment->priv->moon_phase.phase = GSWE_MOON_PHASE_WAXING_HALF; } else if (phase_percent < 50) { moment->priv->moon_phase.phase = GSWE_MOON_PHASE_WAXING_GIBBOUS; } else if (phase_percent == 50) { moment->priv->moon_phase.phase = GSWE_MOON_PHASE_FULL; } else if (phase_percent < 75) { moment->priv->moon_phase.phase = GSWE_MOON_PHASE_WANING_GIBBOUS; } else if (phase_percent == 75) { moment->priv->moon_phase.phase = GSWE_MOON_PHASE_WANING_HALF; } else if (phase_percent < 100) { moment->priv->moon_phase.phase = GSWE_MOON_PHASE_WANING_CRESCENT; } else { moment->priv->moon_phase.phase = GSWE_MOON_PHASE_DARK; } moment->priv->moon_phase_revision = moment->priv->revision; return &(moment->priv->moon_phase); } static gint find_aspect_by_both_planets(GsweAspectData *aspect, struct GsweAspectFinder *aspect_finder) { if (((aspect->planet1->planet_id == aspect_finder->planet1) && (aspect->planet2->planet_id == aspect_finder->planet2)) || ((aspect->planet1->planet_id == aspect_finder->planet2) && (aspect->planet2->planet_id == aspect_finder->planet1))) { return 0; } return 1; } static gboolean find_aspect(gpointer aspect_p, GsweAspectInfo *aspect_info, GsweAspectData *aspect_data) { GsweAspect aspect = GPOINTER_TO_INT(aspect_p); gdouble diff, planet_orb, aspect_orb; aspect_data->distance = fabs(aspect_data->planet1->position - aspect_data->planet2->position); if (aspect_data->distance > 180.0) { aspect_data->distance = 360.0 - aspect_data->distance; } diff = fabs(aspect_info->size - aspect_data->distance); planet_orb = fmin(aspect_data->planet1->planet_info->orb, aspect_data->planet2->planet_info->orb); aspect_orb = fmax(1.0, planet_orb - aspect_info->orb_modifier); if (diff < aspect_orb) { aspect_data->aspect = aspect; aspect_data->aspect_info = aspect_info; if (aspect_info->size == 0) { aspect_data->difference = (1 - ((360.0 - diff) / 360.0)) * 100.0; } else { aspect_data->difference = (1 - ((aspect_info->size - diff) / aspect_info->size)) * 100.0; } return TRUE; } return FALSE; } static void gswe_moment_calculate_aspects(GsweMoment *moment) { GList *oplanet, *iplanet; if (moment->priv->aspect_revision == moment->priv->revision) { return; } gswe_moment_calculate_all_planets(moment); g_list_free_full(moment->priv->aspect_list, g_free); for (oplanet = moment->priv->planet_list; oplanet; oplanet = oplanet->next) { for (iplanet = moment->priv->planet_list; iplanet; iplanet = iplanet->next) { GswePlanetData *outer_planet = oplanet->data, *inner_planet = iplanet->data; struct GsweAspectFinder aspect_finder; GsweAspectData *aspect_data; if (outer_planet->planet_id == inner_planet->planet_id) { continue; } aspect_finder.planet1 = outer_planet->planet_id; aspect_finder.planet2 = inner_planet->planet_id; if (g_list_find_custom(moment->priv->aspect_list, &aspect_finder, (GCompareFunc)find_aspect_by_both_planets) != NULL) { continue; } aspect_data = g_new0(GsweAspectData, 1); aspect_data->planet1 = outer_planet; aspect_data->planet2 = inner_planet; aspect_data->aspect = GSWE_ASPECT_NONE; (void)g_hash_table_find(gswe_aspect_info_table, (GHRFunc)find_aspect, aspect_data); if (aspect_data->aspect == GSWE_ASPECT_NONE) { aspect_data->aspect_info = g_hash_table_lookup(gswe_aspect_info_table, GINT_TO_POINTER(GSWE_ASPECT_NONE)); } moment->priv->aspect_list = g_list_prepend(moment->priv->aspect_list, aspect_data); } } moment->priv->aspect_revision = moment->priv->revision; } /** * gswe_moment_get_aspects: * @moment: the GsweMoment to operate on * * Gets all planetary aspects between the planets added by * gswe_moment_add_planet() or gswe_moment_add_all_planets(). * * Returns: a GList of #GsweAspectData. Both the GList and GsweAspectData * objects belong to @moment, and should not be freed or modified. */ GList * gswe_moment_get_aspects(GsweMoment *moment) { gswe_moment_calculate_aspects(moment); return moment->priv->aspect_list; } /** * gswe_moment_get_planet_aspects: * @moment: the GsweMoment to operate on * @planet: the planet whose aspects you want to get * * Get all the aspects between @planet and all the other planets added with * gswe_moment_add_planet() or gswe_moment_add_all_planets(). * * Returns: a GList of #GsweAspectData. The GsweAspectData structures belong to * @moment, but the GList should be freed using g_list_free(). If the * planet has no aspects, or the planet has not been added to @moment, * returns NULL. */ GList * gswe_moment_get_planet_aspects(GsweMoment *moment, GswePlanet planet) { GList *ret = NULL, *aspect; gswe_moment_calculate_aspects(moment); for (aspect = moment->priv->aspect_list; aspect; aspect = aspect->next) { GsweAspectData *aspect_data = aspect->data; if ((aspect_data->planet1->planet_id == planet) || (aspect_data->planet2->planet_id == planet)) { ret = g_list_prepend(ret, aspect_data); } } return ret; } static gboolean find_mirror(gpointer mirror_p, GsweMirrorInfo *mirror_info, GsweMirrorData *mirror_data) { GsweMirror mirror = GPOINTER_TO_INT(mirror_p); gdouble start_point, mirror_position, planet_orb; if (mirror == GSWE_MIRROR_NONE) { return FALSE; } planet_orb = fmin(mirror_data->planet1->planet_info->orb, mirror_data->planet2->planet_info->orb); start_point = (mirror_info->start_sign->sign_id - 1) * 30.0; if (mirror_info->middle_axis == TRUE) { start_point += 15.0; } mirror_position = 2 * start_point - mirror_data->planet1->position; if (mirror_position < 0) { mirror_position += 360.0; } if ((mirror_data->difference = fabs(mirror_data->planet2->position - mirror_position)) <= planet_orb) { mirror_data->mirror_info = mirror_info; mirror_data->mirror = mirror; return TRUE; } else { mirror_data->difference = 0.0; } return FALSE; } static gint find_mirror_by_both_planets(GsweMirrorData *mirror, struct GsweAspectFinder *mirror_finder) { if (((mirror->planet1->planet_id == mirror_finder->planet1) && (mirror->planet2->planet_id == mirror_finder->planet2)) || ((mirror->planet1->planet_id == mirror_finder->planet2) && (mirror->planet2->planet_id == mirror_finder->planet1))) { return 0; } return 1; } static void gswe_moment_calculate_mirrorpoints(GsweMoment *moment) { GList *oplanet, *iplanet; if (moment->priv->mirrorpoint_revision == moment->priv->revision) { return; } gswe_moment_calculate_all_planets(moment); g_list_free_full(moment->priv->mirrorpoint_list, g_free); for (oplanet = moment->priv->planet_list; oplanet; oplanet = oplanet->next) { for (iplanet = moment->priv->planet_list; iplanet; iplanet = iplanet->next) { GswePlanetData *outer_planet = oplanet->data, *inner_planet = iplanet->data; GsweMirrorData *mirror_data; struct GsweAspectFinder mirror_finder; if (outer_planet->planet_id == inner_planet->planet_id) { continue; } mirror_finder.planet1 = outer_planet->planet_id; mirror_finder.planet2 = inner_planet->planet_id; if (g_list_find_custom(moment->priv->mirrorpoint_list, &mirror_finder, (GCompareFunc)find_mirror_by_both_planets) != NULL) { continue; } mirror_data = g_new0(GsweMirrorData, 1); mirror_data->planet1 = outer_planet; mirror_data->planet2 = inner_planet; mirror_data->mirror = GSWE_MIRROR_NONE; (void)g_hash_table_find(gswe_mirror_info_table, (GHRFunc)find_mirror, mirror_data); if (mirror_data->mirror == GSWE_MIRROR_NONE) { mirror_data->mirror_info = g_hash_table_lookup(gswe_mirror_info_table, GINT_TO_POINTER(GSWE_MIRROR_NONE)); } moment->priv->mirrorpoint_list = g_list_prepend(moment->priv->mirrorpoint_list, mirror_data); } } moment->priv->mirrorpoint_revision = moment->priv->revision; } GList * gswe_moment_get_all_mirrorpoints(GsweMoment *moment) { gswe_moment_calculate_mirrorpoints(moment); return moment->priv->mirrorpoint_list; } GList * gswe_moment_get_all_planet_mirrorpoints(GsweMoment *moment, GswePlanet planet) { GList *ret = NULL, *mirror; gswe_moment_calculate_mirrorpoints(moment); for (mirror = moment->priv->mirrorpoint_list; mirror; mirror = mirror->next) { GsweMirrorData *mirror_data = mirror->data; if ((mirror_data->planet1->planet_id == planet) || (mirror_data->planet2->planet_id == planet)) { ret = g_list_prepend(ret, mirror_data); } } return ret; } GList * gswe_moment_get_mirror_mirrorpoints(GsweMoment *moment, GsweMirror mirror) { GList *ret = NULL, *mirror_l; gswe_moment_calculate_mirrorpoints(moment); for (mirror_l = moment->priv->mirrorpoint_list; mirror_l; mirror_l = mirror_l->next) { GsweMirrorData *mirror_data = mirror_l->data; if (mirror_data->mirror == mirror) { ret = g_list_prepend(ret, mirror_data); } } return ret; } GList * gswe_moment_get_mirror_planet_mirrorpoints(GsweMoment *moment, GsweMirror mirror, GswePlanet planet) { GList *ret = NULL, *mirror_l; gswe_moment_calculate_mirrorpoints(moment); for (mirror_l = moment->priv->mirrorpoint_list; mirror_l; mirror_l = mirror_l->next) { GsweMirrorData *mirror_data = mirror_l->data; if (((mirror_data->planet1->planet_id == planet) || (mirror_data->planet2->planet_id == planet)) && (mirror_data->mirror == mirror)) { ret = g_list_prepend(ret, mirror_data); } } return ret; }