2013-09-01 20:30:51 +00:00
# include "swe-glib.h"
# include "gswe-types.h"
2013-09-01 11:52:18 +00:00
# include "gswe-moment.h"
2013-09-01 20:30:51 +00:00
# include "../../swe/src/swephexp.h"
2013-09-01 11:52:18 +00:00
# define GSWE_MOMENT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), GSWE_TYPE_MOMENT, GsweMomentPrivate))
2013-09-01 20:30:51 +00:00
/**
* 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
*/
2013-09-01 11:52:18 +00:00
struct _GsweMomentPrivate {
2013-09-01 12:31:23 +00:00
GsweTimestamp * timestamp ;
2013-09-01 11:52:18 +00:00
GsweCoordinates coordinates ;
2013-09-01 20:30:51 +00:00
GsweHouseSystem house_system ;
guint revision ;
GList * house_list ;
guint house_revision ;
2013-09-02 14:19:45 +00:00
GList * planet_list ;
2013-09-01 11:52:18 +00:00
} ;
enum {
2013-09-01 12:18:57 +00:00
SIGNAL_CHANGED ,
2013-09-01 11:52:18 +00:00
SIGNAL_LAST
} ;
enum {
PROP_0 ,
PROP_TIMESTAMP
} ;
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 ;
/**
2013-09-01 12:18:57 +00:00
* GsweMoment : : changed :
2013-09-01 11:52:18 +00:00
* @ moment : the GsweMoment object that received the signal
*
2013-09-01 12:18:57 +00:00
* The : : changed signal is emitted each time the time or coordinates are changed
2013-09-01 11:52:18 +00:00
*/
2013-09-01 12:18:57 +00:00
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 ) ;
2013-09-01 11:52:18 +00:00
/**
* GsweMoment : timestamp :
*
* The timestamp associated with this moment
*/
2013-09-01 12:31:23 +00:00
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 ) ) ;
2013-09-01 11:52:18 +00:00
}
static void
2013-09-01 12:18:57 +00:00
gswe_moment_emit_changed ( GsweMoment * moment )
2013-09-01 11:52:18 +00:00
{
2013-09-01 12:18:57 +00:00
g_signal_emit ( moment , gswe_moment_signals [ SIGNAL_CHANGED ] , 0 ) ;
2013-09-01 11:52:18 +00:00
}
void
2013-09-01 12:31:23 +00:00
gswe_moment_init ( GsweMoment * moment )
2013-09-01 11:52:18 +00:00
{
2013-09-01 12:31:23 +00:00
moment - > priv = GSWE_MOMENT_GET_PRIVATE ( moment ) ;
2013-09-01 11:52:18 +00:00
2013-09-01 12:31:23 +00:00
moment - > priv - > timestamp = NULL ;
2013-09-01 20:30:51 +00:00
moment - > priv - > house_list = NULL ;
moment - > priv - > planet_list = NULL ;
moment - > priv - > revision = 1 ;
2013-09-01 12:31:23 +00:00
//moment->priv->a_string = g_strdup("Maman");
}
static void
gswe_moment_timestamp_changed ( GsweMoment * moment , gpointer data )
{
2013-09-01 20:30:51 +00:00
moment - > priv - > revision + + ;
gswe_moment_emit_changed ( moment ) ;
2013-09-01 11:52:18 +00:00
}
static void
gswe_moment_dispose ( GObject * gobject )
{
2013-09-01 12:31:23 +00:00
GsweMoment * moment = GSWE_MOMENT ( gobject ) ;
g_signal_handlers_disconnect_by_func ( moment - > priv - > timestamp , gswe_moment_timestamp_changed , NULL ) ;
2013-09-01 11:52:18 +00:00
2013-09-01 12:31:23 +00:00
g_clear_object ( & moment - > priv - > timestamp ) ;
2013-09-01 11:52:18 +00:00
G_OBJECT_CLASS ( gswe_moment_parent_class ) - > dispose ( gobject ) ;
}
static void
gswe_moment_finalize ( GObject * gobject )
{
2013-09-01 20:30:51 +00:00
GsweMoment * moment = GSWE_MOMENT ( gobject ) ;
2013-09-01 11:52:18 +00:00
2013-09-01 20:30:51 +00:00
g_list_free_full ( moment - > priv - > house_list , g_free ) ;
2013-09-01 11:52:18 +00:00
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 ;
}
}
2013-09-02 14:17:23 +00:00
/**
* 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 .
*/
2013-09-01 11:52:18 +00:00
void
gswe_moment_set_timestamp ( GsweMoment * moment , GsweTimestamp * timestamp )
{
2013-09-01 12:31:23 +00:00
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 ) ;
2013-09-01 11:52:18 +00:00
2013-09-01 12:18:57 +00:00
/* Emit the changed signal to notify registrants of the change */
gswe_moment_emit_changed ( moment ) ;
2013-09-01 11:52:18 +00:00
}
2013-09-01 12:31:23 +00:00
/**
* gswe_moment_get_timestamp :
* @ moment : The GsweMoment object of which you requent its timestamp object
*
2013-09-02 14:17:23 +00:00
* 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 !
*
2013-09-01 12:31:23 +00:00
* Returns : a # GsweTimestamp object assigned to the given moment
*/
GsweTimestamp *
gswe_moment_get_timestamp ( GsweMoment * moment )
{
return moment - > priv - > timestamp ;
}
2013-09-01 11:52:18 +00:00
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 ) ;
}
2013-09-01 20:30:51 +00:00
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 ;
}
2013-09-02 14:19:45 +00:00
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 ;
}
2013-09-01 20:30:51 +00:00
static void
gswe_moment_calculate_house_positions ( GsweMoment * moment )
{
gdouble cusps [ 13 ] ,
ascmc [ 10 ] ;
gint i ;
GsweHouseSystemInfo * house_system_data ;
2013-09-02 14:19:45 +00:00
if ( moment - > priv - > house_revision = = moment - > priv - > revision ) {
return ;
}
2013-09-01 20:30:51 +00:00
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 - - ) {
gdouble * cusp = g_new0 ( gdouble , 1 ) ;
* cusp = cusps [ i ] ;
moment - > priv - > house_list = g_list_prepend ( moment - > priv - > house_list , cusp ) ;
}
moment - > priv - > house_revision = moment - > priv - > revision ;
2013-09-02 14:19:45 +00:00
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 ] ) ;
}
2013-09-01 20:30:51 +00:00
}
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 ;
}
2013-09-02 14:19:45 +00:00
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 ) ;
}
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 ;
}
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 ) ;
}
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 ;
}