[Kstars-devel] [kstars] kstars: Complete rewrite of satellites tracking system.

Jérome SONRIER jsid at emor3j.fr.eu.org
Thu Apr 14 02:28:43 CEST 2011


Git commit fdaf53a0029f884b771cf2ab9edc13e8ab399bc8 by Jérome SONRIER.
Committed on 05/04/2011 at 02:01.
Pushed by jsonrier into branch 'master'.

Complete rewrite of satellites tracking system.

CCMAIL: kstars-devel at kde.org

M  +7    -2    kstars/CMakeLists.txt     
M  +3    -1    kstars/colorscheme.cpp     
M  +3    -1    kstars/data/chart.colors     
M  +3    -1    kstars/data/classic.colors     
M  +3    -1    kstars/data/moonless-night.colors     
M  +3    -1    kstars/data/night.colors     
M  +53   -12   kstars/data/satellites.dat     
M  +17   -0    kstars/geolocation.cpp     
M  +5    -0    kstars/geolocation.h     
A  +-    --    kstars/icons/hi22-action-kstars_satellites.png         [License: Trivial file]
A  +-    --    kstars/icons/hi32-action-kstars_satellites.png         [License: Trivial file]
A  +-    --    kstars/icons/hi48-action-kstars_satellites.png         [License: Trivial file]
A  +-    --    kstars/icons/hi64-action-kstars_satellites.png         [License: Trivial file]
M  +39   -0    kstars/kspopupmenu.cpp     
M  +6    -0    kstars/kspopupmenu.h     
M  +2    -0    kstars/kstars.h     
M  +41   -5    kstars/kstars.kcfg     
M  +10   -2    kstars/kstarsactions.cpp     
M  +4    -0    kstars/kstarsinit.cpp     
M  +1    -0    kstars/kstarsui-win.rc     
M  +1    -0    kstars/kstarsui.rc     
A  +134  -0    kstars/options/opssatellites.cpp         [License: GPL (v2+)]
A  +64   -0    kstars/options/opssatellites.h         [License: GPL (v2+)]
A  +108  -0    kstars/options/opssatellites.ui         [License: UNKNOWN]  *
A  +87   -0    kstars/satellitegroup.cpp         [License: GPL (v2+)]
A  +79   -0    kstars/satellitegroup.h         [License: GPL (v2+)]
A  +185  -0    kstars/skycomponents/satellitescomponent.cpp         [License: GPL (v2+)]
A  +106  -0    kstars/skycomponents/satellitescomponent.h         [License: GPL (v2+)]
M  +2    -1    kstars/skycomponents/skylabeler.h     
M  +17   -0    kstars/skycomponents/skymapcomposite.cpp     
M  +3    -1    kstars/skycomponents/skymapcomposite.h     
M  +41   -0    kstars/skyglpainter.cpp     
M  +1    -0    kstars/skyglpainter.h     
A  +1263 -0    kstars/skyobjects/satellite.cpp         [License: GPL (v2+)]
A  +168  -0    kstars/skyobjects/satellite.h         [License: GPL (v2+)]
M  +2    -1    kstars/skyobjects/skyobject.h     
M  +5    -0    kstars/skypainter.h     
M  +31   -0    kstars/skyqpainter.cpp     
M  +1    -0    kstars/skyqpainter.h     

The files marked with a * at the end have a non valid license. Please read: http://techbase.kde.org/Policies/Licensing_Policy and use the headers which are listed at that page.


http://commits.kde.org/kstars/fdaf53a0029f884b771cf2ab9edc13e8ab399bc8

diff --git a/kstars/CMakeLists.txt b/kstars/CMakeLists.txt
index a6b1e2a..03b7545 100644
--- a/kstars/CMakeLists.txt
+++ b/kstars/CMakeLists.txt
@@ -196,6 +196,7 @@ set(libkstarscomponents_SRCS
    skycomponents/solarsystemcomposite.cpp 
    #skycomponents/satellitecomposite.cpp
    #skycomponents/satellitecomponent.cpp
+   skycomponents/satellitescomponent.cpp
    skycomponents/starcomponent.cpp 
    skycomponents/deepstarcomponent.cpp
    skycomponents/deepskycomponent.cpp 
@@ -246,7 +247,8 @@ set(kstars_options_SRCS
   options/opscatalog.cpp
   options/opscolors.cpp
   options/opsguides.cpp
-  options/opssolarsystem.cpp 
+  options/opssolarsystem.cpp
+  options/opssatellites.cpp
 )
 
 set(kstars_optionsui_SRCS
@@ -254,7 +256,8 @@ set(kstars_optionsui_SRCS
   options/opscatalog.ui
   options/opscolors.ui
   options/opsguides.ui
-  options/opssolarsystem.ui 
+  options/opssolarsystem.ui
+  options/opssatellites.ui
 )
 
 set(kstars_skyobjects_SRCS
@@ -273,6 +276,7 @@ set(kstars_skyobjects_SRCS
   skyobjects/skypoint.cpp
   skyobjects/starobject.cpp
   skyobjects/trailobject.cpp
+  skyobjects/satellite.cpp
 )
 
 set(kstars_dialogs_SRCS
@@ -326,6 +330,7 @@ set(kstars_extra_SRCS
 	texture.cpp texturemanager.cpp
 	timezonerule.cpp 
 	thumbnailpicker.cpp thumbnaileditor.cpp binfilehelper.cpp
+	satellitegroup.cpp
 )
 
 set(oal_SRCS
diff --git a/kstars/colorscheme.cpp b/kstars/colorscheme.cpp
index c23b826..9d669a1 100644
--- a/kstars/colorscheme.cpp
+++ b/kstars/colorscheme.cpp
@@ -73,7 +73,9 @@ ColorScheme::ColorScheme() : FileName() {
     appendItem("AngularRuler",     i18n("Angular Distance Ruler"), "#445566");
     appendItem("ObsListColor",     i18n("Observing List Label"),   "#FF0000");
     appendItem("StarHopRouteColor", i18n("Star-Hop Route"),        "#00FFFF");
-    appendItem("SatColor",         i18n("Satellite Track"),        "#007777");
+    appendItem("VisibleSatColor",  i18n("Visible Satellites"),     "#00FF00");
+    appendItem("SatColor",         i18n("Satellites"),             "#FF0000");
+    appendItem("SatLabelColor",    i18n("Satellites Labels"),      "#640000");
 
     //Load colors from config object
     loadFromConfig();
diff --git a/kstars/data/chart.colors b/kstars/data/chart.colors
index 352a00e..5515c1b 100644
--- a/kstars/data/chart.colors
+++ b/kstars/data/chart.colors
@@ -25,4 +25,6 @@
 #BB9900 :PlanetTrailColor
 #000000 :AngularRuler
 #990000 :ObsListColor
-#007777 :SatColor
+#00FF00 :VisibleSatColor
+#FF0000 :SatColor
+#640000 :SatLabelColor
diff --git a/kstars/data/classic.colors b/kstars/data/classic.colors
index 5991bb6..31e6706 100644
--- a/kstars/data/classic.colors
+++ b/kstars/data/classic.colors
@@ -25,4 +25,6 @@
 #996633 :PlanetTrailColor
 #FFFFFF :AngularRuler
 #FFFF00 :ObsListColor
-#00AAAA :SatColor
+#00FF00 :VisibleSatColor
+#FF0000 :SatColor
+#640000 :SatLabelColor
diff --git a/kstars/data/moonless-night.colors b/kstars/data/moonless-night.colors
index 18bee4d..c1d3b06 100644
--- a/kstars/data/moonless-night.colors
+++ b/kstars/data/moonless-night.colors
@@ -25,4 +25,6 @@
 #993311 :PlanetTrailColor
 #445566 :AngularRuler
 #FF0000 :ObsListColor
-#007777 :SatColor
+#00FF00 :VisibleSatColor
+#FF0000 :SatColor
+#640000 :SatLabelColor
diff --git a/kstars/data/night.colors b/kstars/data/night.colors
index 64e0358..a31f69e 100644
--- a/kstars/data/night.colors
+++ b/kstars/data/night.colors
@@ -25,4 +25,6 @@
 #992200 :PlanetTrailColor
 #770000 :AngularRuler
 #FFAA00 :ObsListColor
-#994400 :SatColor
+#00FF00 :VisibleSatColor
+#FF0000 :SatColor
+#640000 :SatLabelColor
diff --git a/kstars/data/satellites.dat b/kstars/data/satellites.dat
index ae4597d..835b6f0 100644
--- a/kstars/data/satellites.dat
+++ b/kstars/data/satellites.dat
@@ -1,12 +1,53 @@
-HUBBLE
-1 20580U 90037B   07094.96316038  .00000553  00000-0  30218-4 0 08530
-2 20580 028.4680 307.6048 0003464 040.6680 319.4168 15.00217914728957
-UARS
-1 21701U 91063B   07094.91359636  .00009071  00000-0  15177-3 0 00567
-2 21701 056.9736 271.7556 0098591 053.3697 307.6374 15.47444966854408
-ISS
-1 25544U 98067A   07096.05241544  .00018679  00000-0  10406-3 0  9688
-2 25544 051.6324 116.6836 0015959 034.7733 325.4839 15.78512434479385
-ENVISAT
-1 27386U 02009A   07118.76468073  .00000023  00000-0  24704-4 0  6392
-2 27386 098.5492 186.3684 0001106 104.6779 255.4513 14.32247138269785
+# Edit this file to add satellites
+# Each line is a group of satellite
+#
+# Format :
+# Groupe Name;local_filename;url
+# * Groupe Name : This is the name of the group witch will be use in kstars
+# * local_filename : This is the name of the file used to store TLE data
+# * url : The url where the TLE data file can be retrive (you can leave this field blank, in this case, kstars will not update the file)
+#
+
+Last Launches;new.tle;http://celestrak.com/NORAD/elements/tle-new.txt
+International Space Station;iss.tle;http://celestrak.com/NORAD/elements/stations.txt
+Brightest;visual.tle;http://celestrak.com/NORAD/elements/visual.txt
+#FENGYUN 1C Debris;fengyun-1c-debris.tle;http://celestrak.com/NORAD/elements/1999-025.txt
+#IRIDIUM 33 Debris;iridium-33-debris.tle;http://celestrak.com/NORAD/elements/iridium-33-debris.txt
+#COSMOS 2251 Debris;cosmos-2251-debris.tle;http://celestrak.com/NORAD/elements/cosmos-2251-debris.txt
+Weather;weather.tle;http://celestrak.com/NORAD/elements/weather.txt
+NOAA;noaa.tle;http://celestrak.com/NORAD/elements/noaa.txt
+GOES;goes.tle;http://celestrak.com/NORAD/elements/goes.txt
+Earth Resources;resource.tle;http://celestrak.com/NORAD/elements/resource.txt
+Search & Rescue (SARSAT);sarsat.tle;http://celestrak.com/NORAD/elements/sarsat.txt
+Disaster Monitoring;dmc.tle;http://celestrak.com/NORAD/elements/dmc.txt
+Tracking and Data Relay Satellite System (TDRSS);tdrss.tle;http://celestrak.com/NORAD/elements/tdrss.txt
+Geostationary;geo.tle;http://celestrak.com/NORAD/elements/geo.txt
+Intelsat;intelsat.tle;http://celestrak.com/NORAD/elements/intelsat.txt
+Gorizont;gorizont.tle;http://celestrak.com/NORAD/elements/gorizont.txt
+Raduga;raduga.tle;http://celestrak.com/NORAD/elements/raduga.txt
+Molniya;molniya.tle;http://celestrak.com/NORAD/elements/molniya.txt
+Iridium;iridium.tle;http://celestrak.com/NORAD/elements/iridium.txt
+Orbcomm;orbcomm.tle;http://celestrak.com/NORAD/elements/orbcomm.txt
+Globalstar;globalstar.tle;http://celestrak.com/NORAD/elements/globalstar.txt
+Amateur Radio;amateur.tle;http://celestrak.com/NORAD/elements/amateur.txt
+Experimental;x-comm.tle;http://celestrak.com/NORAD/elements/x-comm.txt
+Other;other-comm.tle;http://celestrak.com/NORAD/elements/other-comm.txt
+GPS Operational;gps-ops.tle;http://celestrak.com/NORAD/elements/gps-ops.txt
+Glonass Operational;glo-ops.tle;http://celestrak.com/NORAD/elements/glo-ops.txt
+Galileo;galileo.tle;http://celestrak.com/NORAD/elements/galileo.txt
+Satellite-Based Augmentation System (WAAS/EGNOS/MSAS);sbas.tle;http://celestrak.com/NORAD/elements/sbas.txt
+Navy Navigation Satellite System (NNSS);nnss.tle;http://celestrak.com/NORAD/elements/nnss.txt
+Russian LEO Navigation;musson.tle;http://celestrak.com/NORAD/elements/musson.txt
+Space & Earth Science;science.tle;http://celestrak.com/NORAD/elements/science.txt
+Geodetic;geodetic.tle;http://celestrak.com/NORAD/elements/geodetic.txt
+Engineering;engineering.tle;http://celestrak.com/NORAD/elements/engineering.txt
+Education;education.tle;http://celestrak.com/NORAD/elements/education.txt
+Miscellaneous Military;military.tle;http://celestrak.com/NORAD/elements/military.txt
+Radar Calibration;radar.tle;http://celestrak.com/NORAD/elements/radar.txt
+CubeSats;cubesats.tle;http://celestrak.com/NORAD/elements/cubesat.txt
+Other Miscellaneous;other.tle;http://celestrak.com/NORAD/elements/other.txt
+Supplemental GPS;gps.tle;http://celestrak.com/NORAD/elements/supplemental/gps.txt
+Supplemental GLONASS;glonass.tle;http://celestrak.com/NORAD/elements/supplemental/glonass.txt
+Supplemental METEOSAT;meteosat.tle;http://celestrak.com/NORAD/elements/supplemental/meteosat.txt
+Supplemental INTELSAT;intelsat.tle;http://celestrak.com/NORAD/elements/supplemental/intelsat.txt
+Supplemental ORBCOMM;orbcomm.tle;http://celestrak.com/NORAD/elements/supplemental/orbcomm.txt
diff --git a/kstars/geolocation.cpp b/kstars/geolocation.cpp
index 552e20a..fb0947a 100644
--- a/kstars/geolocation.cpp
+++ b/kstars/geolocation.cpp
@@ -153,3 +153,20 @@ void GeoLocation::TopocentricVelocity(double vtopo[], dms gst) {
     vtopo[1] = d0 * Wearth * ce /1000.;
     vtopo[2] = 0.;
 }
+
+double GeoLocation::LMST( double jd )
+{
+    int divresult;
+    double ut, tu, gmst, theta;
+
+    ut = ( jd + 0.5 ) - floor( jd + 0.5 );
+    jd -= ut;
+    tu = ( jd - 2451545. ) / 36525.;
+    
+    gmst = 24110.54841 + tu * ( 8640184.812866 + tu * ( 0.093104 - tu * 6.2e-6 ) );
+    divresult = (int)( ( gmst + 8.6400e4 * 1.00273790934 * ut ) / 8.6400e4 );
+    gmst = ( gmst + 8.6400e4 * 1.00273790934 * ut ) - (double)divresult * 8.6400e4;
+    theta = 2. * dms::PI * gmst / (24. * 60. * 60.);
+    divresult = (int)( ( theta + Longitude.radians() ) / ( 2. * dms::PI ) );
+    return( ( theta + Longitude.radians() ) - (double)divresult * 2. * dms::PI );
+}
diff --git a/kstars/geolocation.h b/kstars/geolocation.h
index 0da111f..e45d96a 100644
--- a/kstars/geolocation.h
+++ b/kstars/geolocation.h
@@ -245,6 +245,11 @@ public:
      */
     void TopocentricVelocity(double vtopo[], dms gt);
 
+    /**@Return Local Mean Sidereal Time.
+     * @param jd Julian date
+     */
+    double LMST( double jd );
+
 private:
     dms Longitude, Latitude;
     QString Name, Province, Country;
diff --git a/kstars/icons/hi22-action-kstars_satellites.png b/kstars/icons/hi22-action-kstars_satellites.png
new file mode 100644
index 0000000..4642c37
Binary files /dev/null and b/kstars/icons/hi22-action-kstars_satellites.png differ
diff --git a/kstars/icons/hi32-action-kstars_satellites.png b/kstars/icons/hi32-action-kstars_satellites.png
new file mode 100644
index 0000000..e14c73d
Binary files /dev/null and b/kstars/icons/hi32-action-kstars_satellites.png differ
diff --git a/kstars/icons/hi48-action-kstars_satellites.png b/kstars/icons/hi48-action-kstars_satellites.png
new file mode 100644
index 0000000..3926f1e
Binary files /dev/null and b/kstars/icons/hi48-action-kstars_satellites.png differ
diff --git a/kstars/icons/hi64-action-kstars_satellites.png b/kstars/icons/hi64-action-kstars_satellites.png
new file mode 100644
index 0000000..9881d0a
Binary files /dev/null and b/kstars/icons/hi64-action-kstars_satellites.png differ
diff --git a/kstars/kspopupmenu.cpp b/kstars/kspopupmenu.cpp
index a1c4ce0..f04d822 100644
--- a/kstars/kspopupmenu.cpp
+++ b/kstars/kspopupmenu.cpp
@@ -27,6 +27,7 @@
 #include "skyobjects/trailobject.h"
 #include "skyobjects/deepskyobject.h"
 #include "skyobjects/ksmoon.h"
+#include "skyobjects/satellite.h"
 #include "skycomponents/skymapcomposite.h"
 #include "skymap.h"
 
@@ -158,6 +159,44 @@ void KSPopupMenu::createMoonMenu( KSMoon *moon ) {
     addLinksToMenu( moon, false ); //don't offer DSS images for planets
 }
 
+void KSPopupMenu::createSatelliteMenu( Satellite *satellite ) {
+    KStars* ks = KStars::Instance();
+    QString velocity, altitude, range;
+    velocity.setNum( satellite->velocity() );
+    altitude.setNum( satellite->altitude() );
+    range.setNum( satellite->range() );
+
+    clear();
+    
+    addFancyLabel( satellite->name() );
+    addFancyLabel( satellite->id() );
+    addFancyLabel( i18n( "satellite" ) );
+    addFancyLabel( KStarsData::Instance()->skyComposite()->getConstellationBoundary()->constellationName( satellite ) );
+
+    addSeparator();
+
+    addFancyLabel( i18n( "Velocity : %1 km/s", velocity ), -2 );
+    addFancyLabel( i18n( "Altitude : %1 km", altitude ), -2 );
+    addFancyLabel( i18n( "Range : %1 km", range ), -2 );
+
+    addSeparator();
+
+    //Insert item for centering on object
+    addAction( i18n( "Center && Track" ), ks->map(), SLOT( slotCenter() ) );
+    //Insert item for measuring distances
+    //FIXME: add key shortcut to menu items properly!
+    addAction( i18n( "Angular Distance To...            [" ), ks->map(),
+               SLOT(slotBeginAngularDistance()) );
+    addAction( i18n( "Starhop from here to...            " ), ks->map(),
+               SLOT(slotBeginStarHop()) );
+
+    //Insert "Add/Remove Label" item
+    if ( ks->map()->isObjectLabeled( satellite ) )
+        addAction( i18n( "Remove Label" ), ks->map(), SLOT( slotRemoveObjectLabel() ) );
+    else
+        addAction( i18n( "Attach Label" ), ks->map(), SLOT( slotAddObjectLabel() ) );
+}
+
 void KSPopupMenu::initPopupMenu( SkyObject *obj, QString name, QString type, QString info,
                                  bool showDetails, bool showObsList )
 {
diff --git a/kstars/kspopupmenu.h b/kstars/kspopupmenu.h
index 06c8929..ba9c3ab 100644
--- a/kstars/kspopupmenu.h
+++ b/kstars/kspopupmenu.h
@@ -27,6 +27,7 @@ class SkyPoint;
 class SkyObject;
 class DeepSkyObject;
 class KSMoon;
+class Satellite;
 
 /**@class KSPopupMenu
 	*The KStars Popup Menu.  The menu is sensitive to the 
@@ -96,6 +97,11 @@ public:
 
     void createMoonMenu( KSMoon *moon );
 
+    /**@short Create a popup menu for a satellite.
+     * @param satellite the satellite which the menu describes.
+     */
+    void createSatelliteMenu( Satellite *satellite );
+
     /**@short Create a popup menu for empty sky.
      *
      * The popup menu when right-clicking on nothing is still useful.
diff --git a/kstars/kstars.h b/kstars/kstars.h
index a08f477..099f0c3 100644
--- a/kstars/kstars.h
+++ b/kstars/kstars.h
@@ -57,6 +57,7 @@ class Execute;
 class OpsCatalog;
 class OpsGuides;
 class OpsSolarSystem;
+class OpsSatellites;
 class OpsColors;
 class OpsAdvanced;
 class OpsINDI;
@@ -633,6 +634,7 @@ private:
     OpsCatalog *opcatalog;
     OpsGuides *opguides;
     OpsSolarSystem *opsolsys;
+    OpsSatellites *opssatellites;
     OpsColors *opcolors;
     OpsAdvanced *opadvanced;
     OpsINDI *opsindi;
diff --git a/kstars/kstars.kcfg b/kstars/kstars.kcfg
index 0cf47d9..6d088d7 100644
--- a/kstars/kstars.kcfg
+++ b/kstars/kstars.kcfg
@@ -508,11 +508,6 @@
 			<whatsthis>Toggle whether Pluto is drawn in the sky map.</whatsthis>
 			<default>true</default>
 		</entry>
-		<entry name="ShowSatellites" type="Bool">
-			<label>Draw satellite tracks in the sky map?</label>
-			<whatsthis>Toggle whether satellite tracks are drawn in the sky map.</whatsthis>
-			<default>false</default>
-		</entry>
 		<entry name="ShowStars" type="Bool">
 			<label>Draw stars in the sky map?</label>
 			<whatsthis>Toggle whether stars are drawn in the sky map.</whatsthis>
@@ -839,6 +834,21 @@
 			<whatsthis>The color for telescope target symbols.</whatsthis>
 			<default>#8B8</default>
 		</entry>
+        <entry name="VisibleSatColor" type="String">
+            <label>Color of visible satellites</label>
+            <whatsthis>Color of visible satellites.</whatsthis>
+            <default>#00FF00</default>
+        </entry>
+        <entry name="SatColor" type="String">
+            <label>Color of invisible satellites</label>
+            <whatsthis>Color of invisible satellites.</whatsthis>
+            <default>#FF0000</default>
+        </entry>
+        <entry name="SatLabelColor" type="String">
+            <label>Color of satellites labels</label>
+            <whatsthis>Color of satellites labels.</whatsthis>
+            <default>#640000</default>
+        </entry>
 		<entry name="UserLabelColor" type="String">
 			<label>Color of user-added labels</label>
 			<whatsthis>The color for user-added object labels.</whatsthis>
@@ -1048,4 +1058,30 @@
 			<default>80</default>
 		</entry>
 	</group>
+	<group name="Satellites">
+        <entry name="ShowSatellites" type="Bool">
+            <label>Draw satellites in the sky map?</label>
+            <whatsthis>Toggle whether satellite tracks are drawn in the sky map.</whatsthis>
+            <default>false</default>
+        </entry>
+        <entry name="ShowVisibleSatellites" type="Bool">
+            <label>Draw only visible satellites in the sky map</label>
+            <whatsthis>Toggle whether satellite tracks are drawn in the sky map.</whatsthis>
+            <default>false</default>
+        </entry>
+        <entry name="DrawSatellitesLikeStars" type="Bool">
+            <label>If selected, satellites will be draw like stars, otherwise, draw satellites as small colored square.</label>
+            <whatsthis>If selected, satellites will be draw like stars, otherwise, draw satellites as small colored square.</whatsthis>
+            <default>false</default>
+        </entry>
+        <entry name="ShowSatellitesLabels" type="Bool">
+            <label>Draw satellite labels?</label>
+            <whatsthis>Toggle whether satellite labels are drawn in the sky map.</whatsthis>
+            <default>false</default>
+        </entry>
+        <entry name="SelectedSatellites" type="StringList">
+            <label>Selected satellites.</label>
+            <whatsthis>List of selected satellites.</whatsthis>
+        </entry>
+    </group>
 </kcfg>
diff --git a/kstars/kstarsactions.cpp b/kstars/kstarsactions.cpp
index de4930f..ae42857 100644
--- a/kstars/kstarsactions.cpp
+++ b/kstars/kstarsactions.cpp
@@ -46,6 +46,7 @@
 #include "options/opscatalog.h"
 #include "options/opsguides.h"
 #include "options/opssolarsystem.h"
+#include "options/opssatellites.h"
 #include "options/opscolors.h"
 #include "options/opsadvanced.h"
 
@@ -165,6 +166,11 @@ void KStars::slotViewToolBar() {
         if ( kcd ) {
             opguides->kcfg_ShowFlags->setChecked( a->isChecked() );
         }
+    } else if ( a == actionCollection()->action( "show_satellites" ) ) {
+        Options::setShowSatellites( a->isChecked() );
+        if ( kcd ) {
+            opssatellites->kcfg_ShowSatellites->setChecked( a->isChecked() );
+        }
     }
 
     // update time for all objects because they might be not initialized
@@ -381,12 +387,14 @@ void KStars::slotViewOps() {
 
     opcatalog    = new OpsCatalog( this );
     opguides     = new OpsGuides( this );
-    opsolsys = new OpsSolarSystem( this );
+    opsolsys     = new OpsSolarSystem( this );
+    opssatellites= new OpsSatellites( this );
     opcolors     = new OpsColors( this );
-    opadvanced  = new OpsAdvanced( this );
+    opadvanced   = new OpsAdvanced( this );
 
     dialog->addPage(opcatalog, i18n("Catalogs"), "kstars_catalog");
     dialog->addPage(opsolsys, i18n("Solar System"), "kstars_solarsystem");
+    dialog->addPage(opssatellites, i18n("Satellites"), "kstars_satellites");
     dialog->addPage(opguides, i18n("Guides"), "kstars_guides");
     dialog->addPage(opcolors, i18n("Colors"), "kstars_colors");
 
diff --git a/kstars/kstarsinit.cpp b/kstars/kstarsinit.cpp
index 280ff55..f2b1b1a 100644
--- a/kstars/kstarsinit.cpp
+++ b/kstars/kstarsinit.cpp
@@ -467,6 +467,10 @@ void KStars::initActions() {
         << i18nc("Toggle flags in the display", "Flags" )
         << KIcon("kstars_flag" )
         << ToolTip( i18n("Toggle flags") );
+    actionCollection()->add<KToggleAction>("show_satellites", this, SLOT( slotViewToolBar() ) )
+        << i18nc("Toggle satellites in the display", "Satellites" )
+        << KIcon("kstars_satellites" )
+        << ToolTip( i18n("Toggle satellites") );
 
     setXMLFile("kstarsui.rc" );
 
diff --git a/kstars/kstarsui-win.rc b/kstars/kstarsui-win.rc
index 707f486..b1c387e 100644
--- a/kstars/kstarsui-win.rc
+++ b/kstars/kstarsui-win.rc
@@ -135,6 +135,7 @@
 	<Action name="show_stars" />
 	<Action name="show_deepsky" />
 	<Action name="show_planets" />
+	<Action name="show_satellites" />
 	<Action name="show_clines" />
 	<Action name="show_cnames" />
 	<Action name="show_cbounds" />
diff --git a/kstars/kstarsui.rc b/kstars/kstarsui.rc
index ee77923..dd583e0 100644
--- a/kstars/kstarsui.rc
+++ b/kstars/kstarsui.rc
@@ -135,6 +135,7 @@
 	<Action name="show_stars" />
 	<Action name="show_deepsky" />
 	<Action name="show_planets" />
+	<Action name="show_satellites" />
 	<Action name="show_clines" />
 	<Action name="show_cnames" />
 	<Action name="show_cbounds" />
diff --git a/kstars/options/opssatellites.cpp b/kstars/options/opssatellites.cpp
new file mode 100644
index 0000000..d4dc715
--- /dev/null
+++ b/kstars/options/opssatellites.cpp
@@ -0,0 +1,134 @@
+/***************************************************************************
+                          opssatellites.cpp  -  K Desktop Planetarium
+                             -------------------
+    begin                : Mon 21 Mar 2011
+    copyright            : (C) 2011 by Jérôme SONRIER
+    email                : jsid at emor3j.fr.eu.org
+ ***************************************************************************/
+/***************************************************************************
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+#include "opssatellites.h"
+
+#include <qcheckbox.h>
+#include <QTreeWidgetItem>
+
+
+
+#include "Options.h"
+#include "kstars.h"
+#include "kstarsdata.h"
+#include "skymapcomposite.h"
+#include "skycomponents/satellitescomponent.h"
+#include "satellitegroup.h"
+
+OpsSatellites::OpsSatellites( KStars *_ks )
+        : QFrame( _ks ), ksw(_ks)
+{
+    setupUi( this );
+
+    m_ConfigDialog = KConfigDialog::exists( "settings" );
+
+    // Ppulate satellites list
+    updateListView();
+    
+    // Signals and slots connections
+    connect( UpdateTLEButton, SIGNAL( clicked() ), this, SLOT( slotUpdateTLEs() ) );
+    connect( kcfg_ShowSatellites, SIGNAL( toggled( bool ) ), SLOT( slotShowSatellites( bool ) ) );
+    connect( m_ConfigDialog, SIGNAL( applyClicked() ), SLOT( slotApply() ) );
+    connect( m_ConfigDialog, SIGNAL( okClicked() ), SLOT( slotApply() ) );
+    connect( m_ConfigDialog, SIGNAL( cancelClicked() ), SLOT( slotCancel() ) );
+}
+
+OpsSatellites::~OpsSatellites() {
+
+}
+
+void OpsSatellites::slotUpdateTLEs()
+{
+    // Get new data files
+    KStarsData::Instance()->skyComposite()->satellites()->updateTLEs();
+
+    // Refresh satellites list
+    updateListView();
+}
+
+void OpsSatellites::updateListView()
+{
+    KStarsData* data = KStarsData::Instance();
+
+    // Clear satellites list
+    SatListTreeView->clear();
+
+    // Add each groups and satellites in the list
+    foreach ( SatelliteGroup* sat_group, data->skyComposite()->satellites()->groups() ) {
+        // Add the group
+        QTreeWidgetItem *group_item = new QTreeWidgetItem( SatListTreeView, QStringList() << sat_group->name() );
+        SatListTreeView->insertTopLevelItem( SatListTreeView->topLevelItemCount(), group_item );
+
+        // Add all satellites of the group
+        for ( int i=0; i<sat_group->count(); ++i ) {
+            // Create a checkbox to (un)select satellite
+            QCheckBox *sat_cb = new QCheckBox( SatListTreeView );
+            sat_cb->setText( sat_group->at(i)->name() );
+            if ( Options::selectedSatellites().contains( sat_group->at(i)->name() ) )
+                sat_cb->setCheckState( Qt::Checked );
+
+            // Create our item
+            QTreeWidgetItem *sat_item = new QTreeWidgetItem( group_item );
+            // Add checkbox to our item
+            SatListTreeView->setItemWidget( sat_item, 0, sat_cb );
+            // Add item to satellites list
+            group_item->addChild( sat_item );
+        }
+    }
+}
+
+void OpsSatellites::slotApply()
+{
+    KStarsData* data = KStarsData::Instance();
+    QString sat_name;
+    QStringList selected_satellites;
+
+    // Retrive each satellite in the list and select it if checkbox is checked
+    for ( int i=0; i<SatListTreeView->topLevelItemCount(); ++i ) {
+        QTreeWidgetItem *top_level_item = SatListTreeView->topLevelItem( i );
+        for ( int j=0; j<top_level_item->childCount(); ++j ) {
+            QTreeWidgetItem *item = top_level_item->child( j );
+            QCheckBox *check_box = qobject_cast<QCheckBox*>( SatListTreeView->itemWidget( item, 0 ) );
+            sat_name = check_box->text().replace("&", "");
+            Satellite *sat = data->skyComposite()->satellites()->findSatellite( sat_name );
+            if ( sat ) {
+                if ( check_box->checkState() == Qt::Checked ) {
+                    data->skyComposite()->satellites()->findSatellite( sat_name )->setSelected( true );
+                    selected_satellites.append( sat_name );
+                } else {
+                    data->skyComposite()->satellites()->findSatellite( sat_name )->setSelected( false );
+                }
+            }
+        }
+    }
+
+    Options::setSelectedSatellites( selected_satellites );
+}
+
+void OpsSatellites::slotCancel()
+{
+    // Update satellites list
+    updateListView();
+}
+
+void OpsSatellites::slotShowSatellites( bool on )
+{
+    kcfg_ShowVisibleSatellites->setEnabled( on );
+    kcfg_ShowSatellitesLabels->setEnabled( on );
+    kcfg_DrawSatellitesLikeStars->setEnabled( on );
+}
+
+#include "opssatellites.moc"
diff --git a/kstars/options/opssatellites.h b/kstars/options/opssatellites.h
new file mode 100644
index 0000000..3cb55d8
--- /dev/null
+++ b/kstars/options/opssatellites.h
@@ -0,0 +1,64 @@
+/***************************************************************************
+                          opssatellites.h  -  K Desktop Planetarium
+                             -------------------
+    begin                : Mon 21 Mar 2011
+    copyright            : (C) 2011 by Jérôme SONRIER
+    email                : jsid at emor3j.fr.eu.org
+ ***************************************************************************/
+/***************************************************************************
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+#ifndef OPSSATELLITES_H_
+#define OPSSATELLITES_H_
+
+#include "ui_opssatellites.h"
+
+#include <kconfigdialog.h>
+
+
+class KStars;
+
+/**@class OpsSatellites
+ *The Satellites Tab of the Options window.  In this Tab the user can configure
+ *satellites options and select satellites that should be draw 
+ *@author Jérôme SONRIER
+ *@version 1.0
+ */
+class OpsSatellites : public QFrame, public Ui::OpsSatellites
+{
+    Q_OBJECT
+
+public:
+    /**
+     * Constructor
+     */
+    OpsSatellites( KStars *_ks );
+
+    /**
+     * Destructor
+     */
+    ~OpsSatellites();
+    
+private:
+    /**
+     * Refresh satellites list
+     */
+    void updateListView();
+    
+    KStars *ksw;
+    KConfigDialog *m_ConfigDialog;
+
+private slots:
+    void slotUpdateTLEs();
+    void slotShowSatellites( bool on );
+    void slotApply();
+    void slotCancel();
+};
+
+#endif  //OPSSATELLITES_H_
diff --git a/kstars/options/opssatellites.ui b/kstars/options/opssatellites.ui
new file mode 100644
index 0000000..21853df
--- /dev/null
+++ b/kstars/options/opssatellites.ui
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>OpsSatellites</class>
+ <widget class="QWidget" name="OpsSatellites">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>468</width>
+    <height>504</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QGridLayout" name="gridLayout">
+   <item row="1" column="0">
+    <layout class="QVBoxLayout" name="verticalLayout">
+     <item>
+      <layout class="QHBoxLayout" name="horizontalLayout">
+       <item>
+        <widget class="QCheckBox" name="kcfg_ShowSatellites">
+         <property name="text">
+          <string>Show satellites</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QCheckBox" name="kcfg_ShowVisibleSatellites">
+         <property name="text">
+          <string>Show only visible satellites</string>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </item>
+     <item>
+      <layout class="QHBoxLayout" name="horizontalLayout_2">
+       <item>
+        <widget class="QCheckBox" name="kcfg_ShowSatellitesLabels">
+         <property name="text">
+          <string>Show labels</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QCheckBox" name="kcfg_DrawSatellitesLikeStars">
+         <property name="text">
+          <string>Draw satellites like stars</string>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </item>
+     <item>
+      <widget class="KPushButton" name="UpdateTLEButton">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="text">
+        <string>Update TLEs</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QTreeWidget" name="SatListTreeView">
+       <property name="rootIsDecorated">
+        <bool>true</bool>
+       </property>
+       <property name="headerHidden">
+        <bool>true</bool>
+       </property>
+       <property name="columnCount">
+        <number>1</number>
+       </property>
+       <attribute name="headerVisible">
+        <bool>false</bool>
+       </attribute>
+       <attribute name="headerCascadingSectionResizes">
+        <bool>false</bool>
+       </attribute>
+       <attribute name="headerDefaultSectionSize">
+        <number>60</number>
+       </attribute>
+       <column>
+        <property name="text">
+         <string notr="true">1</string>
+        </property>
+       </column>
+      </widget>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>KPushButton</class>
+   <extends>QPushButton</extends>
+   <header>kpushbutton.h</header>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/kstars/satellitegroup.cpp b/kstars/satellitegroup.cpp
new file mode 100644
index 0000000..23915aa
--- /dev/null
+++ b/kstars/satellitegroup.cpp
@@ -0,0 +1,87 @@
+/***************************************************************************
+                          satellitegroup.cpp  -  K Desktop Planetarium
+                             -------------------
+    begin                : Tue 22 Mar 2011
+    copyright            : (C) 2011 by Jerome SONRIER
+    email                : jsid at emor3j.fr.eu.org
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+#include <QFile>
+
+#include <kstandarddirs.h>
+
+#include "satellitegroup.h"
+#include "ksutils.h"
+
+
+SatelliteGroup::SatelliteGroup( QString name, QString tle_filename, KUrl update_url )
+{
+    m_name = name;
+    m_tle_file = tle_filename;
+    m_tle_url = update_url;
+
+    // Read TLE file and create satellites
+    readTLE();
+}
+
+SatelliteGroup::~SatelliteGroup()
+{
+}
+
+void SatelliteGroup::readTLE()
+{
+    QFile file;
+    QString line1, line2;
+
+    // Delete all satellites
+    empty();
+    
+    // Read TLE file
+    if ( KSUtils::openDataFile( file, m_tle_file ) ) {
+        QTextStream stream( &file );
+        while ( !stream.atEnd() ) {
+            // Read satellite name
+            QString sat_name = stream.readLine().trimmed();
+            line1 = stream.readLine();
+            line2 = stream.readLine();
+
+            // Create a new satellite and add it to the list of satellites
+            append( new Satellite( sat_name, line1, line2 ) );
+        }
+        file.close();
+    }
+}
+
+void SatelliteGroup::updateSatellitesPos()
+{
+    for ( int i=0; i<size(); i++ ) {
+        Satellite *sat = at( i );
+        if ( sat->selected() )
+            sat->updatePos();
+    }
+}
+
+KUrl SatelliteGroup::tleFilename()
+{
+    // Return absolute path with "file:" before the path
+    return KUrl( "file:" + KStandardDirs::locateLocal("appdata", "") + m_tle_file );
+}
+
+KUrl SatelliteGroup::tleUrl()
+{
+    return m_tle_url;
+}
+
+QString SatelliteGroup::name()
+{
+    return m_name;
+}
diff --git a/kstars/satellitegroup.h b/kstars/satellitegroup.h
new file mode 100644
index 0000000..ad9d2c4
--- /dev/null
+++ b/kstars/satellitegroup.h
@@ -0,0 +1,79 @@
+/***************************************************************************
+                          satellitegroup.h  -  K Desktop Planetarium
+                             -------------------
+    begin                : Tue 22 Mar 2011
+    copyright            : (C) 2011 by Jerome SONRIER
+    email                : jsid at emor3j.fr.eu.org
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+#ifndef SATELLITEGROUP_H
+#define SATELLITEGROUP_H
+
+
+#include <QString>
+
+#include <KUrl>
+#include "skyobjects/satellite.h"
+#include "skypainter.h"
+
+
+/**
+    *@class SatelliteGroup
+    *Represents a group of artificial satellites.
+    *@author Jérôme SONRIER
+    *@version 1.0
+    */
+class SatelliteGroup : public QList<Satellite*>
+{
+public:
+    /**
+     *@short Constructor
+     */
+    SatelliteGroup( QString name, QString tle_filename, KUrl update_url );
+
+    /**
+     *@short Destructor
+     */
+    ~SatelliteGroup();
+
+    /**
+     *Read TLE file of the group and create all satellites found in the file.
+     */
+    void readTLE();
+
+    /**
+     *Compute current position of the each satellites in the group.
+     */
+    void updateSatellitesPos();
+
+    /**
+     *@return TLE filename
+     */
+    KUrl tleFilename();
+
+    /**
+     *@return URL from which new TLE file must be download
+     */
+    KUrl tleUrl();
+
+    /**
+     *@return Name of the group
+     */
+    QString name();
+
+private:
+    QString m_name;             // Group name
+    QString m_tle_file;         // TLE filename
+    KUrl    m_tle_url;          // URL used to update TLE file
+};
+
+#endif
diff --git a/kstars/skycomponents/satellitescomponent.cpp b/kstars/skycomponents/satellitescomponent.cpp
new file mode 100644
index 0000000..f0d650d
--- /dev/null
+++ b/kstars/skycomponents/satellitescomponent.cpp
@@ -0,0 +1,185 @@
+/***************************************************************************
+                          satellitescomponent.cpp  -  K Desktop Planetarium
+                             -------------------
+    begin                : Tue 02 Mar 2011
+    copyright            : (C) 2009 by Jerome SONRIER
+    email                : jsid at emor3j.fr.eu.org
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+#include "satellitescomponent.h"
+
+#include <QStringList>
+#include <QObject>
+#include <QProgressDialog>
+
+#include <kjob.h>
+#include <kio/job.h>
+#include <kio/copyjob.h>
+#include <kio/netaccess.h>
+#include <kio/jobuidelegate.h>
+
+#include "klocale.h"
+
+#include "satellitegroup.h"
+#include "Options.h"
+#include "ksfilereader.h"
+#include "skylabeler.h"
+#include "kstarsdata.h"
+
+SatellitesComponent::SatellitesComponent( SkyComposite *parent ) :
+    SkyComponent( parent )
+{
+    KSFileReader fileReader;
+    QString line;
+    QStringList group_infos;
+    
+    if ( ! fileReader.open( "satellites.dat" ) ) return;
+
+    emitProgressText( i18n("Loading satellites" ) );
+    
+
+    while ( fileReader.hasMoreLines() ) {
+        line = fileReader.readLine();
+        if ( line.trimmed().isEmpty() || line.at( 0 ) == '#' )
+            continue;
+        group_infos = line.split( ";" );
+        m_groups.append( new SatelliteGroup( group_infos.at( 0 ), group_infos.at( 1 ), KUrl( group_infos.at( 2 ) ) ) );
+    }
+}
+
+SatellitesComponent::~SatellitesComponent()
+{
+
+}
+
+bool SatellitesComponent::selected() {
+    return Options::showSatellites();
+}
+
+void SatellitesComponent::update( KSNumbers * )
+{
+    // Return if satellites must not be draw
+    if( ! selected() )
+        return;
+    
+    foreach( SatelliteGroup *group, m_groups ) {
+        group->updateSatellitesPos();
+    }
+}
+
+void SatellitesComponent::draw( SkyPainter *skyp )
+{
+    // Return if satellites must not be draw
+    if( ! selected() )
+        return;
+
+    foreach( SatelliteGroup *group, m_groups ) {
+        for ( int i=0; i<group->size(); i++ ) {
+            Satellite *sat = group->at( i );
+            if ( sat->selected() ) {
+                if ( Options::showVisibleSatellites() ) {
+                    if ( sat->isVisible() )
+                        skyp->drawSatellite( sat );
+                } else {
+                    skyp->drawSatellite( sat );
+                }
+            }
+        }
+    }
+}
+
+void SatellitesComponent::drawLabel( Satellite *sat, QPointF pos )
+{
+    SkyLabeler *labeler = SkyLabeler::Instance();
+    labeler->setPen( KStarsData::Instance()->colorScheme()->colorNamed( "SatLabelColor" ) );
+    labeler->drawNameLabel( sat, pos );
+}
+
+void SatellitesComponent::drawTrails( SkyPainter *skyp ) {
+
+}
+
+void SatellitesComponent::updateTLEs()
+{
+    int i = 0;
+    
+    QProgressDialog progressDlg( i18n( "Update TLEs..." ), i18n( "Abort" ), 0, m_groups.count() );
+    progressDlg.setWindowModality( Qt::WindowModal );
+    progressDlg.setValue( 0 );
+        
+    foreach ( SatelliteGroup *group, m_groups ) {
+        if ( progressDlg.wasCanceled() )
+            return;
+
+        if( group->tleUrl().isEmpty() )
+            continue;
+        
+        progressDlg.setLabelText( i18n( "Update %1 satellites", group->name() ) );
+        KIO::Job* getJob = KIO::file_copy( group->tleUrl(), group->tleFilename(), -1, KIO::Overwrite | KIO::HideProgressInfo );
+        if( KIO::NetAccess::synchronousRun( getJob, 0 ) ) {
+            group->readTLE();
+            group->updateSatellitesPos();
+            progressDlg.setValue( ++i );
+        } else {
+            getJob->ui()->showErrorMessage();
+        }   
+    }
+}
+
+QList<SatelliteGroup*> SatellitesComponent::groups()
+{
+    return m_groups;
+}
+
+Satellite* SatellitesComponent::findSatellite( QString name )
+{
+    foreach ( SatelliteGroup *group, m_groups ) {
+        for ( int i=0; i<group->size(); i++ ) {
+            Satellite *sat = group->at( i );
+            if ( sat->name() == name )
+                return sat;
+        }
+    }
+
+    return 0;
+}
+
+SkyObject* SatellitesComponent::objectNearest( SkyPoint* p, double& maxrad ) {
+    if ( ! selected() )
+        return 0;
+
+    //KStarsData* data = KStarsData::Instance();
+
+    SkyObject *oBest = 0;
+    double rBest = maxrad;
+    double r;
+
+    foreach ( SatelliteGroup *group, m_groups ) {
+        for ( int i=0; i<group->size(); i++ ) {
+            Satellite *sat = group->at( i );
+            if ( ! sat->selected() )
+                continue;
+
+            r = sat->angularDistanceTo( p ).Degrees();
+            //kDebug() << sat->name();
+            //kDebug() << "r = " << r << " - max = " << rBest;
+            //kDebug() << "ra2=" << sat->ra().Degrees() << " - dec2=" << sat->dec().Degrees();
+            if ( r < rBest ) {
+                rBest = r;
+                oBest = sat;
+            }
+        }
+    }
+
+    maxrad = rBest;
+    return oBest;
+}
diff --git a/kstars/skycomponents/satellitescomponent.h b/kstars/skycomponents/satellitescomponent.h
new file mode 100644
index 0000000..74218ed
--- /dev/null
+++ b/kstars/skycomponents/satellitescomponent.h
@@ -0,0 +1,106 @@
+/***************************************************************************
+                          satellitescomponent.h  -  K Desktop Planetarium
+                             -------------------
+    begin                : Tue 02 Mar 2011
+    copyright            : (C) 2009 by Jerome SONRIER
+    email                : jsid at emor3j.fr.eu.org
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+#ifndef SATELLITESCOMPONENT_H
+#define SATELLITESCOMPONENT_H
+
+#include <QList>
+
+#include <kio/job.h>
+
+#include "skycomponent.h"
+#include "satellitegroup.h"
+
+class Satellite;
+
+/**
+	*@class SatellitesComponent
+	*Represents artificial satellites on the sky map.
+	*@author Jérôme SONRIER
+	*@version 1.0
+	*/
+class SatellitesComponent : public SkyComponent
+{
+public:
+    /**
+     *@short Constructor
+     *@param parent pointer to the parent SkyComposite
+     */
+    SatellitesComponent( SkyComposite *parent );
+
+    /**
+     *@short Destructor
+     */
+    ~SatellitesComponent();
+
+    /**
+     *@return true if satellites must be draw.
+     */
+    virtual bool selected();
+
+    /**
+     *Draw all satellites.
+     *@param skyp SkyPainter to use
+     */
+    virtual void draw( SkyPainter *skyp );
+
+    /**
+     *Update satellites position.
+     *@param num
+     */
+    virtual void update( KSNumbers *num );
+
+    /**
+     *Download new TLE files
+     */
+    void updateTLEs();
+
+    /**
+     *@return The list of all groups
+     */
+    QList<SatelliteGroup*> groups();
+
+    /**
+     *Search a satellite by name.
+     *@param name The name of the satellite
+     *@return Satellite that was find or 0
+     */
+    Satellite* findSatellite( QString name );
+
+    /**
+     *Draw label of a satellite.
+     *@param sat The satellite
+     *@param pos The position of the satellite
+     */
+    void drawLabel( Satellite *sat, QPointF pos );
+
+    /**
+     *Search the nearest satellite from point p
+     *@param p
+     *@param maxrad
+     */
+    SkyObject* objectNearest( SkyPoint* p, double& maxrad );
+
+protected:
+    virtual void drawTrails( SkyPainter* skyp );
+
+private:
+    QList<SatelliteGroup*> m_groups;    // List of all groups
+    KIO::Job *m_downloadJob;
+};
+
+#endif
diff --git a/kstars/skycomponents/skylabeler.h b/kstars/skycomponents/skylabeler.h
index b7b168e..a7c2874 100644
--- a/kstars/skycomponents/skylabeler.h
+++ b/kstars/skycomponents/skylabeler.h
@@ -122,9 +122,10 @@ public:
         COMET_LABEL,
         PLANET_LABEL,
         JUPITER_MOON_LABEL,
-	SATURN_MOON_LABEL,
+        SATURN_MOON_LABEL,
         DEEP_SKY_LABEL,
         CONSTEL_NAME_LABEL,
+        SATELLITE_LABEL,
         RUDE_LABEL, ///Rude labels block other labels FIXME: find a better solution
         NUM_LABEL_TYPES
     } ;
diff --git a/kstars/skycomponents/skymapcomposite.cpp b/kstars/skycomponents/skymapcomposite.cpp
index ef0d2ad..b0c108e 100644
--- a/kstars/skycomponents/skymapcomposite.cpp
+++ b/kstars/skycomponents/skymapcomposite.cpp
@@ -44,6 +44,7 @@
 #include "deepstarcomponent.h"
 //#include "satellitecomposite.h"
 #include "flagcomponent.h"
+#include "satellitescomponent.h"
 
 
 #include "skymesh.h"
@@ -97,6 +98,7 @@ SkyMapComposite::SkyMapComposite(SkyComposite *parent ) :
     addComponent( m_ObservingList = new TargetListComponent( this , 0, QPen(),
                                                              &Options::obsListSymbol, &Options::obsListText ) );
     addComponent( m_StarHopRouteList = new TargetListComponent( this , 0, QPen() ) );
+    addComponent( m_Satellites       = new SatellitesComponent( this ) );
 
     connect( this, SIGNAL( progressText( const QString & ) ),
              KStarsData::Instance(), SIGNAL( progressText( const QString & ) ) );
@@ -138,6 +140,7 @@ void SkyMapComposite::update(KSNumbers *num )
     //12. Solar system
     m_SolarSystem->update( num );
     //13. Satellites
+    m_Satellites->update( num );
     //m_Satellites->update( data, num );
     //14. Horizon
     m_Horizon->update( num );
@@ -237,6 +240,8 @@ void SkyMapComposite::draw( SkyPainter *skyp )
 
     m_SolarSystem->drawTrails( skyp );
     m_SolarSystem->draw( skyp );
+    
+    m_Satellites->draw( skyp );
 
     // TODO: Fix satellites sometime
     //    m_Satellites->draw( psky );
@@ -333,6 +338,14 @@ SkyObject* SkyMapComposite::objectNearest( SkyPoint *p, double &maxrad ) {
         oBest = oTry;
     }
 
+    rTry = maxrad;
+    oTry = m_Satellites->objectNearest( p, rTry );
+    if ( rTry < rBest ) {
+        rBest = rTry;
+        oBest = oTry;
+    }
+    if ( oBest )
+        kDebug() << "OBEST=" << oBest->name() << " - " << oBest->name2();
     maxrad = rBest;
     return oBest; //will be 0 if no object nearer than maxrad was found
 
@@ -518,4 +531,8 @@ FlagComponent* SkyMapComposite::flags() {
     return m_Flags;
 }
 
+SatellitesComponent* SkyMapComposite::satellites() {
+    return m_Satellites;
+}
+
 #include "skymapcomposite.moc"
diff --git a/kstars/skycomponents/skymapcomposite.h b/kstars/skycomponents/skymapcomposite.h
index 45cc5bb..51734bf 100644
--- a/kstars/skycomponents/skymapcomposite.h
+++ b/kstars/skycomponents/skymapcomposite.h
@@ -43,9 +43,9 @@ class MilkyWay;
 class SolarSystemComposite;
 class StarComponent;
 class DeepStarComponent;
-//class SatelliteComposite;
 class TargetListComponent;
 class TargetListComponent;
+class SatellitesComponent;
 
 class DeepSkyObject;
 class KSPlanetBase;
@@ -164,6 +164,7 @@ public:
     void reloadCNames();
 
     FlagComponent* flags();
+    SatellitesComponent* satellites();
 
     //Accessors for StarComponent
     SkyObject* findStarByGenetiveName( const QString name );
@@ -212,6 +213,7 @@ private:
     FlagComponent               *m_Flags;
     TargetListComponent         *m_ObservingList;
     TargetListComponent         *m_StarHopRouteList;
+    SatellitesComponent         *m_Satellites;
 
     SkyMesh*                m_skyMesh;
     SkyLabeler*             m_skyLabeler;
diff --git a/kstars/skyglpainter.cpp b/kstars/skyglpainter.cpp
index 576f329..eee233b 100644
--- a/kstars/skyglpainter.cpp
+++ b/kstars/skyglpainter.cpp
@@ -39,11 +39,13 @@ using Eigen::Rotation2Df;
 #include "skycomponents/linelistlabel.h"
 #include "skycomponents/skymapcomposite.h"
 #include "skycomponents/flagcomponent.h"
+#include "skycomponents/satellitescomponent.h"
 
 #include "skyobjects/deepskyobject.h"
 #include "skyobjects/kscomet.h"
 #include "skyobjects/ksasteroid.h"
 #include "skyobjects/trailobject.h"
+#include "skyobjects/satellite.h"
 
 Vector2f SkyGLPainter::m_vertex[NUMTYPES][6*BUFSIZE];
 Vector2f SkyGLPainter::m_texcoord[NUMTYPES][6*BUFSIZE];
@@ -720,3 +722,42 @@ void SkyGLPainter::setPen(const QPen& pen)
 
 }
 
+void SkyGLPainter::drawSatellite( Satellite* sat ) {
+    KStarsData *data = KStarsData::Instance();
+    bool visible = false;
+    Vector2f pos, vertex;
+
+    sat->HorizontalToEquatorial( data->lst(), data->geo()->lat() );
+
+    pos = m_proj->toScreenVec( sat, true, &visible );
+
+    if( !visible || !m_proj->onScreen( pos ) )
+        return;
+
+    if ( Options::drawSatellitesLikeStars() ) {
+        drawPointSource(sat, 3.5, 'B');
+    } else {
+        if ( sat->isVisible() )
+            setPen( data->colorScheme()->colorNamed( "VisibleSatColor" ) );
+        else
+            setPen( data->colorScheme()->colorNamed( "SatColor" ) );
+
+        glDisable( GL_TEXTURE_2D );
+        glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
+        glBegin( GL_QUADS );
+
+        vertex = pos + Vector2f( -1.0, -1.0 );
+        glVertex2fv(vertex.data());
+        vertex = pos + Vector2f(  1.0, -1.0 );
+        glVertex2fv(vertex.data());
+        vertex = pos + Vector2f(  1.0,  1.0 );
+        glVertex2fv(vertex.data());
+        vertex = pos + Vector2f( -1.0,  1.0 );
+        glVertex2fv(vertex.data());
+
+        glEnd();
+    }
+
+    if ( Options::showSatellitesLabels() )
+        data->skyComposite()->satellites()->drawLabel( sat, QPointF( pos.x(), pos.y() ) );
+}
diff --git a/kstars/skyglpainter.h b/kstars/skyglpainter.h
index 84d677f..78a0785 100644
--- a/kstars/skyglpainter.h
+++ b/kstars/skyglpainter.h
@@ -47,6 +47,7 @@ public:
     virtual void setBrush(const QBrush& brush);
     virtual void setPen(const QPen& pen);
     virtual void drawHorizon( bool filled, SkyPoint *labelPoint = 0, bool *drawLabel = 0);
+    virtual void drawSatellite( Satellite* sat );
     void drawText( int x, int y, const QString text, QFont font, QColor color );
 private:
     bool addItem(SkyPoint* p, int type, float width, char sp = 'a');
diff --git a/kstars/skyobjects/satellite.cpp b/kstars/skyobjects/satellite.cpp
new file mode 100644
index 0000000..de99c7b
--- /dev/null
+++ b/kstars/skyobjects/satellite.cpp
@@ -0,0 +1,1263 @@
+/***************************************************************************
+                          satellite.cpp  -  K Desktop Planetarium
+                             -------------------
+    begin                : Tue 02 Mar 2011
+    copyright            : (C) 2009 by Jerome SONRIER
+    email                : jsid at emor3j.fr.eu.org
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+
+#include "satellite.h"
+
+#include "math.h"
+#include <kdebug.h>
+
+#include "kstarsdata.h"
+#include "ksplanetbase.h"
+#include "skymapcomposite.h"
+#include "kssun.h"
+#include "Options.h"
+#include "kspopupmenu.h"
+
+// Define some constants
+//  WGS-72 constants
+#define MU              398600.8            // Earth gravitational constant (km3/s2)
+#define RADIUSEARTHKM   6378.135            // Earth radius (km)
+#define XKE             0.07436691613317    // 60.0 / sqrt(RADIUSEARTHKM^3/MU)
+#define TUMIN           13.44683969695931   // sqrt(RADIUSEARTHKM^3/MU) / 60.0
+#define J2              0.001082616         // The second gravitational zonal harmonic of the Earth
+#define J3              -0.00000253881      // The third gravitational zonal harmonic of the Earth
+#define J4              -0.00000165597      // The fourth gravitational zonal harmonic of the Earth
+#define J3OJ2           -2.34506972e-3      // J3 / J2
+
+// Mathematical constants
+#define PI      3.14159265358979323846
+#define TWOPI   6.2831853071795864769       // 2*PI
+#define PIO2    1.5707963267948966192       // PI/2
+#define X3PIO2  4.7123889803846898577       // 3*PI/2
+#define X2O3    .66666666666666666667       // 2/3
+#define DEG2RAD 1.745329251994330e-2        // Deg -> Rad
+
+// Other constants
+#define MINPD   1440                        // Minutes per day
+#define MEANALT 0.84                        // Mean altitude (km)
+#define SR      6.96000e5                   // Solar radius - km (IAU 76)
+#define AU      1.49597870691e8             // Astronomical unit - km (IAU 76)
+#define XPDOTP  229.1831180523293           // 1440.0 / (2.0 * pi)
+#define SS      1.0122292801892716288       // Parameter for the SGP4 density function
+#define QZMS2T  1.8802791590152706439e-9    // (( 120.0 - 78.0) / RADIUSEARTHKM )^4
+#define F       3.35281066474748e-3         // Flattening factor
+#define MFACTOR 7.292115e-5
+
+
+Satellite::Satellite( const QString name, const QString line1, const QString line2 )
+{
+    //m_name          = name;
+    m_number        = line1.mid( 2, 5 ).toInt();
+    m_class         = line1.at( 7 );
+    m_id            = line1.mid( 9, 8 );
+    m_epoch         = line1.mid( 18, 14 ).toDouble();
+    m_first_deriv   = line1.mid( 33, 10 ).toDouble() / ( XPDOTP * MINPD );
+    m_second_deriv  = line1.mid( 44, 6 ).toDouble() * ( 1.0e-5 / pow( 10.0, line1.mid( 51, 1 ).toDouble() ) )  / ( XPDOTP * MINPD*MINPD );
+    m_bstar         = line1.mid( 53, 6 ).toDouble() * 1.0e-5 / pow( 10.0, line1.mid( 60, 1 ).toDouble() );
+    m_ephem_type    = line1.mid( 62, 1 ).toInt();
+    m_elem_number   = line1.mid( 64, 4 ).toInt();
+    m_inclination   = line2.mid( 8, 8 ).toDouble() * DEG2RAD;
+    m_ra            = line2.mid( 17, 8 ).toDouble() * DEG2RAD;
+    m_eccentricity  = line2.mid( 26, 7 ).toDouble() * 1.0e-7;
+    m_arg_perigee   = line2.mid( 34, 8 ).toDouble() * DEG2RAD;
+    m_mean_anomaly  = line2.mid( 43, 8 ).toDouble() * DEG2RAD;
+    m_mean_motion   = line2.mid( 52, 11 ).toDouble() * TWOPI / MINPD;
+    m_nb_revolution = line2.mid( 63, 5 ).toInt();
+
+    setName( name );
+    setName2( name );
+    setLongName( name + " (" + m_id + ")");
+    setType( SkyObject::SATELLITE );
+    setMag( 0.0 );
+
+    if ( Options::selectedSatellites().contains( name ) )
+        m_is_selected = true;
+    else
+        m_is_selected = false;
+
+    // Convert TLE epoch to Julian date
+    double day = modf( m_epoch * 1.e-3, &m_epoch_year) * 1.e3;
+    if ( m_epoch_year < 57. )
+        m_epoch_year += 2000.;
+    else
+        m_epoch_year += 1900.;
+    double year= m_epoch_year - 1.;
+    long i = year / 100;
+    long A = i;
+    i = A / 4;
+    long B = 2 - A + i;
+    i = 365.25 * year;
+    i += 30.6001 * 14;
+    m_tle_jd = i + 1720994.5 + B + day;
+
+    init();
+}
+
+Satellite::~Satellite()
+{
+
+}
+
+void Satellite::init()
+{
+    double  ao    , cosio , sinio , cosio2,
+            omeosq, posq  ,   rp  , rteosq, eccsq , con42 , ainv  ,
+            cnodm , snodm , cosim , sinim , cosomm, sinomm, cc1sq ,
+            cc2   , cc3   , coef  , coef1 , cosio4, day   , dndt  ,
+            em    , emsq  , eeta  , etasq , gam   , argpm , nodem ,
+            inclm , mm    , nm    , perige, pinvsq, psisq , qzms24,
+            rtemsq, s1    , s2    , s3    , s4    , s5    , s6    ,
+            s7    , sfour , ss1   , ss2   , ss3   , ss4   , ss5   ,
+            ss6   , ss7   , sz1   , sz2   , sz3   , sz11  , sz12  ,
+            sz13  , sz21  , sz22  , sz23  , sz31  , sz32  , sz33  ,
+            tc    , temp  , temp1 , temp2 , temp3 , tsi   , xpidot,
+            xhdot1, z1    , z2    , z3    , z11   , z12   , z13   ,
+            z21   , z22   , z23   , z31   , z32   , z33   , ak    ,
+            d1    , del   , adel  , po    , ds70  , ts70  , tfrac ,
+            c1    , thgr70, fk5r  , c1p2p;
+ 
+    // Init near earth variables
+    isimp=false;
+    aycof =0. ; con41 =0. ; cc1     =0. ; cc4    =0. ; cc5    =0. ; d2      =0. ; d3    =0. ; d4    =0. ;
+    delmo =0. ; eta   =0. ; argpdot =0. ; omgcof =0. ; sinmao =0. ; t       =0. ; t2cof =0. ; t3cof =0. ;
+    t4cof =0. ; t5cof =0. ; x1mth2  =0. ; x7thm1 =0. ; mdot   =0. ; nodedot =0. ; xlcof =0. ; xmcof =0. ;
+    nodecf= 0.;
+
+    // Init deep space variables
+    irez=0;
+    d2201 =0. ; d2211 =0. ; d3210 =0.  ; d3222 =0. ; d4410 =0. ; d4422 =0. ; d5220 =0. ; d5232 =0. ;
+    d5421 =0. ; d5433 =0. ; dedt  =0.  ; del1  =0. ; del2  =0. ; del3  =0. ; didt  =0. ; dmdt  =0. ;
+    dnodt =0. ; domdt =0. ; e3    =0.  ; ee2   =0. ; peo   =0. ; pgho  =0. ; pho   =0. ; pinco =0. ;
+    plo   =0. ; se2   =0. ; se3   =0.  ; sgh2  =0. ; sgh3  =0. ; sgh4  =0. ; sh2   =0. ; sh3   =0. ;
+    si2   =0. ; si3   =0. ; sl2   =0.  ; sl3   =0. ; sl4   =0. ; gsto  =0. ; xfact =0. ; xgh2  =0. ;
+    xgh3  =0. ; xgh4  =0. ; xh2   =0.  ; xh3   =0. ; xi2   =0. ; xi3   =0. ; xl2   =0. ; xl3   =0. ;
+    xl4   =0. ; xlamo =0. ; zmol  =0.  ; zmos  =0. ; atime =0. ; xli   =0. ; xni =0.;
+
+    method = 'n';
+
+    m_is_visible = false;
+
+    // Divisor for divide by zero check on inclination
+    const double temp4 =  1.5e-12;
+
+    /*----- Initializes variables for sgp4 -----*/
+    // Calculate auxillary epoch quantities
+    eccsq  = m_eccentricity * m_eccentricity;
+    omeosq = 1.0 - eccsq;
+    rteosq = sqrt( omeosq );
+    cosio  = cos( m_inclination );
+    cosio2 = cosio * cosio;
+
+    // Un-kozai the mean motion
+    ak    = pow( XKE / m_mean_motion, X2O3 );
+    d1    = 0.75 * J2 * ( 3.0 * cosio2 - 1.0 ) / ( rteosq * omeosq );
+    del   = d1 / ( ak * ak );
+    adel  = ak * ( 1.0 - del*del - del * ( 1.0 / 3.0 + 134.0 * del*del / 81.0 ) );
+    del   = d1 / ( adel * adel );
+    m_mean_motion = m_mean_motion / (1.0 + del);
+    
+    ao    = pow( XKE / m_mean_motion, X2O3 );
+    sinio = sin( m_inclination );
+    po    = ao * omeosq;
+    con42 = 1.0 - 5.0 * cosio2;
+    con41 = -con42 - ( 2.0 * cosio2 );
+    ainv  = 1.0 / ao;
+    posq  = po * po;
+    rp    = ao * ( 1.0 - m_eccentricity );
+    method = 'n';
+
+    // Find sidereal time
+    ts70  = m_tle_jd - 2433281.5 - 7305.0;
+    ds70  = floor( ts70 + 1.0e-8 );
+    tfrac = ts70 - ds70;
+    // find greenwich location at epoch
+    c1    = 1.72027916940703639e-2;
+    thgr70= 1.7321343856509374;
+    fk5r  = 5.07551419432269442e-15;
+    c1p2p = c1 + TWOPI;
+    gsto  = fmod( thgr70 + c1*ds70 + c1p2p*tfrac + ts70*ts70*fk5r, TWOPI );
+    if ( gsto < 0.0 )
+        gsto = gsto + TWOPI;
+
+    if ( ( omeosq >= 0.0 ) || ( m_mean_motion >= 0.0 ) ) {
+        if ( rp < ( 220.0 / RADIUSEARTHKM + 1.0 ) )
+            isimp = true;
+        sfour  = SS;
+        qzms24 = QZMS2T;
+        perige = ( rp - 1.0 ) * RADIUSEARTHKM;
+
+        // For perigees below 156 km, s and qoms2t are altered
+        if ( perige < 156.0 ) {
+            sfour  = perige - 78.0;
+            if ( perige < 98.0 )
+                sfour = 20.0;
+            qzms24 = pow( ( ( 120.0 - sfour ) / RADIUSEARTHKM ), 4.0);
+            sfour  = sfour / RADIUSEARTHKM + 1.0;
+        }
+        pinvsq = 1.0 / posq;
+
+        tsi   = 1.0 / ( ao - sfour );
+        eta   = ao * m_eccentricity * tsi;
+        etasq = eta * eta;
+        eeta  = m_eccentricity * eta;
+        psisq = fabs( 1.0 - etasq );
+        coef  = qzms24 * pow( tsi, 4.0 );
+        coef1 = coef / pow( psisq, 3.5 );
+        cc2   = coef1 * m_mean_motion * ( ao * ( 1.0 + 1.5 * etasq + eeta *
+                ( 4.0 + etasq ) ) + 0.375 * J2 * tsi / psisq * con41 *
+                ( 8.0 + 3.0 * etasq * ( 8.0 + etasq ) ) );
+        cc1   = m_bstar * cc2;
+        cc3   = 0.0;
+        if ( m_eccentricity > 1.0e-4 )
+            cc3 = -2.0 * coef * tsi * J3OJ2 * m_mean_motion * sinio / m_eccentricity;
+        x1mth2 = 1.0 - cosio2;
+        cc4    = 2.0 * m_mean_motion * coef1 * ao * omeosq *
+                 ( eta * ( 2.0 + 0.5 * etasq ) + m_eccentricity *
+                 ( 0.5 + 2.0 * etasq ) - J2 * tsi / ( ao * psisq ) *
+                 ( -3.0 * con41 * ( 1.0 - 2.0 * eeta + etasq *
+                 ( 1.5 - 0.5 * eeta ) ) + 0.75 * x1mth2 *
+                 ( 2.0 * etasq - eeta * ( 1.0 + etasq ) ) * cos( 2.0 * m_arg_perigee ) ) );
+        cc5 = 2.0 * coef1 * ao * omeosq * ( 1.0 + 2.75 * ( etasq + eeta ) + eeta * etasq );
+
+        cosio4 = cosio2 * cosio2;
+        temp1  = 1.5 * J2 * pinvsq * m_mean_motion;
+        temp2  = 0.5 * temp1 * J2 * pinvsq;
+        temp3  = -0.46875 * J4 * pinvsq * pinvsq * m_mean_motion;
+        mdot   = m_mean_motion + 0.5 * temp1 * rteosq * con41 + 0.0625 *
+                 temp2 * rteosq * ( 13.0 - 78.0 * cosio2 + 137.0 * cosio4 );
+        argpdot= -0.5 * temp1 * con42 + 0.0625 * temp2 *
+                 ( 7.0 - 114.0 * cosio2 + 395.0 * cosio4 ) +
+                 temp3 * ( 3.0 - 36.0 * cosio2 + 49.0 * cosio4 );
+        xhdot1 = -temp1 * cosio;
+        nodedot= xhdot1 + ( 0.5 * temp2 * ( 4.0 - 19.0 * cosio2 ) +
+                  2.0 * temp3 * ( 3.0 - 7.0 * cosio2 ) ) * cosio;
+        xpidot = argpdot + nodedot;
+        omgcof = m_bstar * cc3 * cos( m_arg_perigee );
+        xmcof  = 0.0;
+        if ( m_eccentricity > 1.0e-4)
+            xmcof = -X2O3 * coef * m_bstar / eeta;
+        nodecf = 3.5 * omeosq * xhdot1 * cc1;
+        t2cof  = 1.5 * cc1;
+        // Do not divide by zero
+        if ( fabs( 1.0 + cosio ) > 1.5e-12 )
+            xlcof = -0.25 * J3OJ2 * sinio * ( 3.0 + 5.0 * cosio ) / ( 1.0 + cosio );
+        else
+            xlcof = -0.25 * J3OJ2 * sinio * ( 3.0 + 5.0 * cosio ) / temp4;
+        aycof  = -0.5 * J3OJ2 * sinio;
+        delmo  = pow( ( 1.0 + eta * cos( m_mean_anomaly ) ), 3 );
+        sinmao = sin( m_mean_anomaly );
+        x7thm1 = 7.0 * cosio2 - 1.0;
+        
+        // Deep space initialization
+        if ( ( TWOPI / m_mean_motion ) >= 225.0 ) {
+            method = 'd';
+            isimp = true;
+            tc    =  0.0;
+            inclm = m_inclination;
+
+            // Init deep space common variables
+            // Define some constants
+            const double zes     =  0.01675;
+            const double zel     =  0.05490;
+            const double c1ss    =  2.9864797e-6;
+            const double c1l     =  4.7968065e-7;
+            const double zsinis  =  0.39785416;
+            const double zcosis  =  0.91744867;
+            const double zcosgs  =  0.1945905;
+            const double zsings  = -0.98088458;
+
+            int lsflg;
+            double a1    , a2    , a3    , a4    , a5    , a6    , a7    ,
+                   a8    , a9    , a10   , betasq, cc    , ctem  , stem  ,
+                   x1    , x2    , x3    , x4    , x5    , x6    , x7    ,
+                   x8    , xnodce, xnoi  , zcosg , zcosgl, zcosh , zcoshl,
+                   zcosi , zcosil, zsing , zsingl, zsinh , zsinhl, zsini ,
+                   zsinil, zx    , zy;
+
+            nm     = m_mean_motion;
+            em     = m_eccentricity;
+            snodm  = sin( m_ra );
+            cnodm  = cos( m_ra );
+            sinomm = sin( m_arg_perigee );
+            cosomm = cos( m_arg_perigee );
+            sinim  = sin( m_inclination );
+            cosim  = cos( m_inclination );
+            emsq   = em * em;
+            betasq = 1.0 - emsq;
+            rtemsq = sqrt( betasq );
+
+            // Initialize lunar solar terms
+            peo    = 0.0;
+            pinco  = 0.0;
+            plo    = 0.0;
+            pgho   = 0.0;
+            pho    = 0.0;
+            day    = m_tle_jd - 2433281.5 + 18261.5 + tc / 1440.0;
+            xnodce = fmod( 4.5236020 - 9.2422029e-4 * day, TWOPI );
+            stem   = sin( xnodce );
+            ctem   = cos( xnodce );
+            zcosil = 0.91375164 - 0.03568096 * ctem;
+            zsinil = sqrt( 1.0 - zcosil * zcosil );
+            zsinhl = 0.089683511 * stem / zsinil;
+            zcoshl = sqrt( 1.0 - zsinhl * zsinhl );
+            gam    = 5.8351514 + 0.0019443680 * day;
+            zx     = 0.39785416 * stem / zsinil;
+            zy     = zcoshl * ctem + 0.91744867 * zsinhl * stem;
+            zx     = atan2( zx, zy );
+            zx     = gam + zx - xnodce;
+            zcosgl = cos( zx );
+            zsingl = sin( zx );
+
+            // Solar terms
+            zcosg = zcosgs;
+            zsing = zsings;
+            zcosi = zcosis;
+            zsini = zsinis;
+            zcosh = cnodm;
+            zsinh = snodm;
+            cc    = c1ss;
+            xnoi  = 1.0 / nm;
+
+            for ( lsflg = 1; lsflg <= 2; lsflg++ ) {
+                a1  =   zcosg * zcosh + zsing * zcosi * zsinh;
+                a3  =  -zsing * zcosh + zcosg * zcosi * zsinh;
+                a7  =  -zcosg * zsinh + zsing * zcosi * zcosh;
+                a8  =   zsing * zsini;
+                a9  =   zsing * zsinh + zcosg * zcosi * zcosh;
+                a10 =   zcosg * zsini;
+                a2  =   cosim * a7 + sinim * a8;
+                a4  =   cosim * a9 + sinim * a10;
+                a5  =  -sinim * a7 + cosim * a8;
+                a6  =  -sinim * a9 + cosim * a10;
+
+                x1  =  a1 * cosomm + a2 * sinomm;
+                x2  =  a3 * cosomm + a4 * sinomm;
+                x3  = -a1 * sinomm + a2 * cosomm;
+                x4  = -a3 * sinomm + a4 * cosomm;
+                x5  =  a5 * sinomm;
+                x6  =  a6 * sinomm;
+                x7  =  a5 * cosomm;
+                x8  =  a6 * cosomm;
+
+                z31 = 12.0 * x1 * x1 - 3.0 * x3 * x3;
+                z32 = 24.0 * x1 * x2 - 6.0 * x3 * x4;
+                z33 = 12.0 * x2 * x2 - 3.0 * x4 * x4;
+                z1  = 3.0 *  ( a1 * a1 + a2 * a2 ) + z31 * emsq;
+                z2  = 6.0 *  ( a1 * a3 + a2 * a4 ) + z32 * emsq;
+                z3  = 3.0 *  ( a3 * a3 + a4 * a4 ) + z33 * emsq;
+                z11 = -6.0 * a1 * a5 + emsq *  ( -24.0 * x1 * x7-6.0 * x3 * x5 );
+                z12 = -6.0 * ( a1 * a6 + a3 * a5 ) + emsq *
+                      ( -24.0 * ( x2 * x7 + x1 * x8 ) - 6.0 * ( x3 * x6 + x4 * x5 ) );
+                z13 = -6.0 * a3 * a6 + emsq * ( -24.0 * x2 * x8 - 6.0 * x4 * x6 );
+                z21 = 6.0 * a2 * a5 + emsq * ( 24.0 * x1 * x5 - 6.0 * x3 * x7 );
+                z22 = 6.0 * ( a4 * a5 + a2 * a6 ) + emsq *
+                      ( 24.0 * ( x2 * x5 + x1 * x6 ) - 6.0 * ( x4 * x7 + x3 * x8 ) );
+                z23 = 6.0 * a4 * a6 + emsq * ( 24.0 * x2 * x6 - 6.0 * x4 * x8 );
+                z1  = z1 + z1 + betasq * z31;
+                z2  = z2 + z2 + betasq * z32;
+                z3  = z3 + z3 + betasq * z33;
+                s3  = cc * xnoi;
+                s2  = -0.5 * s3 / rtemsq;
+                s4  = s3 * rtemsq;
+                s1  = -15.0 * em * s4;
+                s5  = x1 * x3 + x2 * x4;
+                s6  = x2 * x3 + x1 * x4;
+                s7  = x2 * x4 - x1 * x3;
+
+                // Lunar terms
+                if ( lsflg == 1 ) {
+                    ss1   = s1;
+                    ss2   = s2;
+                    ss3   = s3;
+                    ss4   = s4;
+                    ss5   = s5;
+                    ss6   = s6;
+                    ss7   = s7;
+                    sz1   = z1;
+                    sz2   = z2;
+                    sz3   = z3;
+                    sz11  = z11;
+                    sz12  = z12;
+                    sz13  = z13;
+                    sz21  = z21;
+                    sz22  = z22;
+                    sz23  = z23;
+                    sz31  = z31;
+                    sz32  = z32;
+                    sz33  = z33;
+                    zcosg = zcosgl;
+                    zsing = zsingl;
+                    zcosi = zcosil;
+                    zsini = zsinil;
+                    zcosh = zcoshl * cnodm + zsinhl * snodm;
+                    zsinh = snodm * zcoshl - cnodm * zsinhl;
+                    cc    = c1l;
+                }
+            }
+
+            zmol = fmod( 4.7199672 + 0.22997150  * day - gam, TWOPI );
+            zmos = fmod( 6.2565837 + 0.017201977 * day, TWOPI );
+
+            //  Solar terms
+            se2  =   2.0 * ss1 * ss6;
+            se3  =   2.0 * ss1 * ss7;
+            si2  =   2.0 * ss2 * sz12;
+            si3  =   2.0 * ss2 * ( sz13 - sz11 );
+            sl2  =  -2.0 * ss3 * sz2;
+            sl3  =  -2.0 * ss3 * ( sz3 - sz1 );
+            sl4  =  -2.0 * ss3 * ( -21.0 - 9.0 * emsq ) * zes;
+            sgh2 =   2.0 * ss4 * sz32;
+            sgh3 =   2.0 * ss4 * ( sz33 - sz31 );
+            sgh4 = -18.0 * ss4 * zes;
+            sh2  =  -2.0 * ss2 * sz22;
+            sh3  =  -2.0 * ss2 * ( sz23 - sz21 );
+
+            // Lunar terms
+            ee2  =   2.0 * s1 * s6;
+            e3   =   2.0 * s1 * s7;
+            xi2  =   2.0 * s2 * z12;
+            xi3  =   2.0 * s2 * ( z13 - z11 );
+            xl2  =  -2.0 * s3 * z2;
+            xl3  =  -2.0 * s3 * ( z3 - z1 );
+            xl4  =  -2.0 * s3 * ( -21.0 - 9.0 * emsq ) * zel;
+            xgh2 =   2.0 * s4 * z32;
+            xgh3 =   2.0 * s4 * ( z33 - z31 );
+            xgh4 = -18.0 * s4 * zel;
+            xh2  =  -2.0 * s2 * z22;
+            xh3  =  -2.0 * s2 * ( z23 - z21 );
+            
+            // Apply deep space long period periodic contributions to the mean elements
+            double f2   , f3   , pe   , pgh  , ph  , pinc, pl ,
+                   sel  , ses  , sghl , sghs , shll, shs,  sil,
+                   sinzf, sis  , sll  , sls  , zf  , zm;
+
+            // Define some constants
+            const double zns = 1.19459e-5;
+            const double znl = 1.5835218e-4;
+
+            // Calculate time varying periodics
+            zm    = zmos;
+            zf    = zm + 2.0 * zes * sin( zm );
+            sinzf = sin( zf );
+            f2    =  0.5 * sinzf * sinzf - 0.25;
+            f3    = -0.5 * sinzf * cos( zf );
+            ses   = se2* f2 + se3 * f3;
+            sis   = si2 * f2 + si3 * f3;
+            sls   = sl2 * f2 + sl3 * f3 + sl4 * sinzf;
+            sghs  = sgh2 * f2 + sgh3 * f3 + sgh4 * sinzf;
+            shs   = sh2 * f2 + sh3 * f3;
+            zm    = zmol;
+            
+            zf    = zm + 2.0 * zel * sin( zm );
+            sinzf = sin( zf );
+            f2    =  0.5 * sinzf * sinzf - 0.25;
+            f3    = -0.5 * sinzf * cos( zf );
+            sel   = ee2 * f2 + e3 * f3;
+            sil   = xi2 * f2 + xi3 * f3;
+            sll   = xl2 * f2 + xl3 * f3 + xl4 * sinzf;
+            sghl  = xgh2 * f2 + xgh3 * f3 + xgh4 * sinzf;
+            shll  = xh2 * f2 + xh3 * f3;
+            pe    = ses + sel;
+            pinc  = sis + sil;
+            pl    = sls + sll;
+            pgh   = sghs + sghl;
+            ph    = shs + shll;
+
+            argpm  = 0.0;
+            nodem  = 0.0;
+            mm     = 0.0;
+
+            // Deep space contributions to mean motion dot due to geopotential resonance with half day and one day orbits
+            double ainv2 , aonv=0.0, cosisq, eoc , f220  , f221  , f311  ,
+                   f321  , f322  , f330  , f441  , f442  , f522  , f523  ,
+                   f542  , f543  , g200  , g201  , g211  , g300  , g310  ,
+                   g322  , g410  , g422  , g520  , g521  , g532  , g533  ,
+                   sgs   , sini2 , temp  , temp1 , theta , xno2  , emo   ,
+                   emsqo;
+
+            // Define some constant
+            const double q22    = 1.7891679e-6;
+            const double q31    = 2.1460748e-6;
+            const double q33    = 2.2123015e-7;
+            const double root22 = 1.7891679e-6;
+            const double root44 = 7.3636953e-9;
+            const double root54 = 2.1765803e-9;
+            const double rptim  = 4.37526908801129966e-3; // this equates to 7.29211514668855e-5 rad/sec
+            const double root32 = 3.7393792e-7;
+            const double root52 = 1.1428639e-7;
+
+            // Deep space initialization
+            irez = 0;
+            if ( ( nm < 0.0052359877 ) && ( nm > 0.0034906585 ) )
+                irez = 1;
+            if ( ( nm >= 8.26e-3 ) && ( nm <= 9.24e-3 ) && ( em >= 0.5 ) )
+                irez = 2;
+
+            // Solar terms
+            ses  =  ss1 * zns * ss5;
+            sis  =  ss2 * zns * ( sz11 + sz13 );
+            sls  = -zns * ss3 * ( sz1 + sz3 - 14.0 - 6.0 * emsq );
+            sghs =  ss4 * zns * ( sz31 + sz33 - 6.0 );
+            shs  = -zns * ss2 * ( sz21 + sz23 );
+            if ( ( inclm < 5.2359877e-2 ) || ( inclm > PI - 5.2359877e-2 ) )
+                shs = 0.0;
+            if ( sinim != 0.0 )
+                shs = shs / sinim;
+            sgs  = sghs - cosim * shs;
+
+            // Lunar terms
+            dedt = ses + s1 * znl * s5;
+            didt = sis + s2 * znl * ( z11 + z13 );
+            dmdt = sls - znl * s3 * ( z1 + z3 - 14.0 - 6.0 * emsq );
+            sghl = s4 * znl * ( z31 + z33 - 6.0 );
+            shll = -znl * s2 * ( z21 + z23 );
+            if ( ( inclm < 5.2359877e-2 ) || ( inclm > PI - 5.2359877e-2 ) )
+                shll = 0.0;
+            domdt = sgs + sghl;
+            dnodt = shs;
+            if ( sinim != 0.0 ) {
+                domdt = domdt - cosim / sinim * shll;
+                dnodt = dnodt + shll / sinim;
+            }
+
+            // Calculate deep space resonance effects
+            dndt   = 0.0;
+            theta  = fmod( gsto + tc * rptim, TWOPI );
+
+            // Initialize the resonance terms
+            if ( irez != 0 ) {
+                aonv = pow( nm / XKE, X2O3 );
+
+                // Geopotential resonance for 12 hour orbits
+                if ( irez == 2 ) {
+                    cosisq = cosim * cosim;
+                    emo    = em;
+                    em     = m_eccentricity;
+                    emsqo  = emsq;
+                    emsq   = eccsq;
+                    eoc    = em * emsq;
+                    g201   = -0.306 - ( em - 0.64 ) * 0.440;
+
+                    if ( em <= 0.65 ) {
+                        g211 =    3.616  -  13.2470 * em +  16.2900 * emsq;
+                        g310 =  -19.302  + 117.3900 * em - 228.4190 * emsq +  156.5910 * eoc;
+                        g322 =  -18.9068 + 109.7927 * em - 214.6334 * emsq +  146.5816 * eoc;
+                        g410 =  -41.122  + 242.6940 * em - 471.0940 * emsq +  313.9530 * eoc;
+                        g422 = -146.407  + 841.8800 * em - 1629.014 * emsq + 1083.4350 * eoc;
+                        g520 = -532.114  + 3017.977 * em - 5740.032 * emsq + 3708.2760 * eoc;
+                    } else {
+                        g211 =   -72.099 +   331.819 * em -   508.738 * emsq +   266.724 * eoc;
+                        g310 =  -346.844 +  1582.851 * em -  2415.925 * emsq +  1246.113 * eoc;
+                        g322 =  -342.585 +  1554.908 * em -  2366.899 * emsq +  1215.972 * eoc;
+                        g410 = -1052.797 +  4758.686 * em -  7193.992 * emsq +  3651.957 * eoc;
+                        g422 = -3581.690 + 16178.110 * em - 24462.770 * emsq + 12422.520 * eoc;
+                        if ( em > 0.715 )
+                            g520 =-5149.66 + 29936.92 * em - 54087.36 * emsq + 31324.56 * eoc;
+                        else
+                            g520 = 1464.74 -  4664.75 * em +  3763.64 * emsq;
+                    }
+                    if ( em < 0.7 ) {
+                        g533 = -919.22770 + 4988.6100 * em - 9064.7700 * emsq + 5542.21  * eoc;
+                        g521 = -822.71072 + 4568.6173 * em - 8491.4146 * emsq + 5337.524 * eoc;
+                        g532 = -853.66600 + 4690.2500 * em - 8624.7700 * emsq + 5341.4  * eoc;
+                    } else {
+                        g533 =-37995.780 + 161616.52 * em - 229838.20 * emsq + 109377.94 * eoc;
+                        g521 =-51752.104 + 218913.95 * em - 309468.16 * emsq + 146349.42 * eoc;
+                        g532 =-40023.880 + 170470.89 * em - 242699.48 * emsq + 115605.82 * eoc;
+                    }
+
+                    sini2=  sinim * sinim;
+                    f220 =  0.75 * ( 1.0 + 2.0 * cosim + cosisq );
+                    f221 =  1.5 * sini2;
+                    f321 =  1.875 * sinim  *  ( 1.0 - 2.0 * cosim - 3.0 * cosisq );
+                    f322 = -1.875 * sinim  *  ( 1.0 + 2.0 * cosim - 3.0 * cosisq );
+                    f441 = 35.0 * sini2 * f220;
+                    f442 = 39.3750 * sini2 * sini2;
+                    f522 =  9.84375 * sinim * (sini2 * ( 1.0 - 2.0 * cosim- 5.0 * cosisq ) +
+                            0.33333333 * ( -2.0 + 4.0 * cosim + 6.0 * cosisq ) );
+                    f523 = sinim * ( 4.92187512 * sini2 * ( -2.0 - 4.0 * cosim +
+                           10.0 * cosisq ) + 6.56250012 * ( 1.0+2.0 * cosim - 3.0 * cosisq ) );
+                    f542 = 29.53125 * sinim * ( 2.0 - 8.0 * cosim + cosisq *
+                           ( -12.0 + 8.0 * cosim + 10.0 * cosisq ) );
+                    f543 = 29.53125 * sinim * ( -2.0 - 8.0 * cosim + cosisq *
+                           ( 12.0 + 8.0 * cosim - 10.0 * cosisq ) );
+                    xno2  =  nm * nm;
+                    ainv2 =  aonv * aonv;
+                    temp1 =  3.0 * xno2 * ainv2;
+                    temp  =  temp1 * root22;
+                    d2201 =  temp * f220 * g201;
+                    d2211 =  temp * f221 * g211;
+                    temp1 =  temp1 * aonv;
+                    temp  =  temp1 * root32;
+                    d3210 =  temp * f321 * g310;
+                    d3222 =  temp * f322 * g322;
+                    temp1 =  temp1 * aonv;
+                    temp  =  2.0 * temp1 * root44;
+                    d4410 =  temp * f441 * g410;
+                    d4422 =  temp * f442 * g422;
+                    temp1 =  temp1 * aonv;
+                    temp  =  temp1 * root52;
+                    d5220 =  temp * f522 * g520;
+                    d5232 =  temp * f523 * g532;
+                    temp  =  2.0 * temp1 * root54;
+                    d5421 =  temp * f542 * g521;
+                    d5433 =  temp * f543 * g533;
+                    xlamo =  fmod( m_mean_anomaly + m_ra + m_ra - theta - theta, TWOPI );
+                    xfact =  mdot + dmdt + 2.0 * ( nodedot + dnodt - rptim ) - m_mean_motion;
+                    em    = emo;
+                    emsq  = emsqo;
+                }
+
+                if ( irez == 1 ) {
+                    g200  = 1.0 + emsq * ( -2.5 + 0.8125 * emsq );
+                    g310  = 1.0 + 2.0 * emsq;
+                    g300  = 1.0 + emsq * ( -6.0 + 6.60937 * emsq );
+                    f220  = 0.75 * ( 1.0 + cosim ) * ( 1.0 + cosim );
+                    f311  = 0.9375 * sinim * sinim * ( 1.0 + 3.0 * cosim ) - 0.75 * ( 1.0 + cosim );
+                    f330  = 1.0 + cosim;
+                    f330  = 1.875 * f330 * f330 * f330;
+                    del1  = 3.0 * nm * nm * aonv * aonv;
+                    del2  = 2.0 * del1 * f220 * g200 * q22;
+                    del3  = 3.0 * del1 * f330 * g300 * q33 * aonv;
+                    del1  = del1 * f311 * g310 * q31 * aonv;
+                    xlamo = fmod( m_mean_anomaly + m_ra + m_arg_perigee - theta, TWOPI );
+                    xfact = mdot + xpidot - rptim + dmdt + domdt + dnodt - m_mean_motion;
+                }
+
+                xli   = xlamo;
+                xni   = m_mean_motion;
+                atime = 0.0;
+                nm    = m_mean_motion + dndt;
+            }
+        }
+
+        // Set variables if not deep space
+        if ( ! isimp ) {
+            cc1sq = cc1 * cc1;
+            d2    = 4.0 * ao * tsi * cc1sq;
+            temp  = d2 * tsi * cc1 / 3.0;
+            d3    = ( 17.0 * ao + sfour ) * temp;
+            d4    = 0.5 * temp * ao * tsi * ( 221.0 * ao + 31.0 * sfour ) * cc1;
+            t3cof = d2 + 2.0 * cc1sq;
+            t4cof = 0.25 * ( 3.0 * d3 + cc1 * ( 12.0 * d2 + 10.0 * cc1sq ) );
+            t5cof = 0.2 * ( 3.0 * d4 + 12.0 * cc1 * d3 + 6.0 * d2 * d2 + 15.0 * cc1sq * ( 2.0 * d2 + cc1sq ) );
+        }
+    }
+}
+
+void Satellite::updatePos()
+{
+    KStarsData *data = KStarsData::Instance();
+    sgp4( ( data->clock()->utc().djd() - m_tle_jd ) * MINPD );
+}
+
+int Satellite::sgp4( double tsince )
+{
+    KStarsData *data = KStarsData::Instance();
+    
+    int ktr;
+    double am   , axnl  , aynl , betal ,  cosim , cnod  ,
+           cos2u, coseo1, cosi , cosip ,  cosisq, cossu , cosu,
+           delm , delomg, em   , emsq  ,  ecose , el2   , eo1 ,
+           ep   , esine , argpm, argpp ,  argpdf, pl    , mrt = 0.0,
+           mvt  , rdotl , rl   , rvdot ,  rvdotl, sinim , dndt,
+           sin2u, sineo1, sini , sinip ,  sinsu , sinu  ,
+           snod , su    , t2   , t3    ,  t4    , tem5  , temp,
+           temp1, temp2 , tempa, tempe ,  templ , u     , ux  ,
+           uy   , uz    , vx   , vy    ,  vz    , inclm , mm  ,
+           nm   , nodem , xinc , xincp ,  xl    , xlm   , mp  ,
+           xmdf , xmx   , xmy  , nodedf, xnode  , nodep , tc  ,
+           sat_posx, sat_posy , sat_posz, sat_posw, sat_velx ,
+           sat_vely  , sat_velz , sinlat, obs_posx, obs_posy,
+           obs_posz, obs_posw, obs_velx, obs_vely, obs_velz,
+           coslat, thetageo, sintheta, costheta, c, sq, achcp,
+           vkmpersec;
+
+    const double temp4 =   1.5e-12;
+
+    double jul_utc = data->clock()->utc().djd();
+
+    vkmpersec = RADIUSEARTHKM * XKE / 60.0;
+
+    // Update for secular gravity and atmospheric drag
+    xmdf    = m_mean_anomaly + mdot * tsince;
+    argpdf  = m_arg_perigee + argpdot * tsince;
+    nodedf  = m_ra + nodedot * tsince;
+    argpm   = argpdf;
+    mm      = xmdf;
+    t2      = tsince * tsince;
+    nodem   = nodedf + nodecf * t2;
+    tempa   = 1.0 - cc1 * tsince;
+    tempe   = m_bstar * cc4 * tsince;
+    templ   = t2cof * t2;
+
+    if ( ! isimp ) {
+        delomg = omgcof * tsince;
+        delm   = xmcof * ( pow( ( 1.0 + eta * cos( xmdf ) ), 3 ) - delmo);
+        temp   = delomg + delm;
+        mm     = xmdf + temp;
+        argpm  = argpdf - temp;
+        t3     = t2 * tsince;
+        t4     = t3 * tsince;
+        tempa  = tempa - d2 * t2 - d3 * t3 - d4 * t4;
+        tempe  = tempe + m_bstar * cc5 * ( sin( mm ) - sinmao );
+        templ  = templ + t3cof * t3 + t4 * ( t4cof + tsince * t5cof );
+    }
+
+    nm    = m_mean_motion;
+    em    = m_eccentricity;
+    inclm = m_inclination;
+
+    if ( method == 'd' ) {
+        tc = tsince;
+        // Deep space contributions to mean elements for perturbing third body
+        int iretn , iret;
+        double delt, ft, theta, x2li, x2omi, xl, xldot, xnddt, xndt, xomi;
+
+        // Define some constants
+        const double fasx2 = 0.13130908;
+        const double fasx4 = 2.8843198;
+        const double fasx6 = 0.37448087;
+        const double g22   = 5.7686396;
+        const double g32   = 0.95240898;
+        const double g44   = 1.8014998;
+        const double g52   = 1.0508330;
+        const double g54   = 4.4108898;
+        const double rptim = 4.37526908801129966e-3; // this equates to 7.29211514668855e-5 rad/sec
+        const double stepp =    720.0;
+        const double stepn =   -720.0;
+        const double step2 = 259200.0;
+
+        // Calculate deep space resonance effects
+        dndt   = 0.0;
+        theta  = fmod( gsto + tc * rptim, TWOPI );
+        em     = em + dedt * tsince;
+
+        inclm  = inclm + didt * tsince;
+        argpm  = argpm + domdt * tsince;
+        nodem  = nodem + dnodt * tsince;
+        mm     = mm + dmdt * tsince;
+
+        // Update resonances : numerical (euler-maclaurin) integration
+        ft = 0.0;
+        if ( irez != 0 ) {
+            if ( ( atime == 0.0 ) || ( tsince * atime <= 0.0 ) || ( fabs( tsince ) < fabs( atime ) ) ) {
+                atime  = 0.0;
+                xni    = m_mean_motion;
+                xli    = xlamo;
+            }
+            
+            if ( tsince > 0.0 )
+                delt = stepp;
+            else
+                delt = stepn;
+
+            iretn = 381; // added for do loop
+            iret  =   0; // added for loop
+
+            while ( iretn == 381 ) {
+                // Near - synchronous resonance terms
+                if ( irez != 2 ) {
+                    xndt  = del1 * sin( xli - fasx2 ) + del2 * sin( 2.0 * ( xli - fasx4 ) ) +
+                            del3 * sin( 3.0 * ( xli - fasx6 ) );
+                    xldot = xni + xfact;
+                    xnddt = del1 * cos( xli - fasx2 ) +
+                            2.0 * del2 * cos( 2.0 * ( xli - fasx4 ) ) +
+                            3.0 * del3 * cos( 3.0 * ( xli - fasx6 ) );
+                    xnddt = xnddt * xldot;
+                } else {
+                    // Near - half-day resonance terms
+                    xomi  = m_arg_perigee + argpdot * atime;
+                    x2omi = xomi + xomi;
+                    x2li  = xli + xli;
+                    xndt  = d2201 * sin( x2omi + xli - g22 ) + d2211 * sin( xli - g22 ) +
+                            d3210 * sin( xomi + xli - g32 )  + d3222 * sin( -xomi + xli - g32 )+
+                            d4410 * sin( x2omi + x2li - g44 )+ d4422 * sin( x2li - g44 ) +
+                            d5220 * sin( xomi + xli - g52 )  + d5232 * sin( -xomi + xli - g52 )+
+                            d5421 * sin( xomi + x2li - g54 ) + d5433 * sin( -xomi + x2li - g54 );
+                    xldot = xni + xfact;
+                    xnddt = d2201 * cos( x2omi + xli - g22 ) + d2211 * cos( xli - g22 ) +
+                            d3210 * cos( xomi + xli - g32 ) + d3222 * cos( -xomi + xli - g32 ) +
+                            d5220 * cos( xomi + xli - g52 ) + d5232 * cos( -xomi + xli - g52 ) +
+                            2.0 * ( d4410 * cos( x2omi + x2li - g44 ) +
+                            d4422 * cos( x2li - g44 ) + d5421 * cos( xomi + x2li - g54 ) +
+                            d5433 * cos( -xomi + x2li - g54 ) );
+                    xnddt = xnddt * xldot;
+                }
+
+                if ( fabs( tsince - atime ) >= stepp ) {
+                    iret  = 0;
+                    iretn = 381;
+                } else {
+                    ft    = tsince - atime;
+                    iretn = 0;
+                }
+
+                if ( iretn == 381 ) {
+                    xli   = xli + xldot * delt + xndt * step2;
+                    xni   = xni + xndt * delt + xnddt * step2;
+                    atime = atime + delt;
+                }
+            }
+
+            nm = xni + xndt * ft + xnddt * ft * ft * 0.5;
+            xl = xli + xldot * ft + xndt * ft * ft * 0.5;
+
+            if (irez != 1) {
+                mm   = xl - 2.0 * nodem + 2.0 * theta;
+                dndt = nm - m_mean_motion;
+            } else {
+                mm   = xl - nodem - argpm + theta;
+                dndt = nm - m_mean_motion;
+            }
+
+            nm = m_mean_motion + dndt;
+        }
+    }
+
+    if ( nm <= 0.0 ) {
+        kDebug() << "Mean motion less than 0.0";
+        return(2);
+    }
+
+    am = pow( ( XKE / nm ), X2O3 ) * tempa * tempa;
+    nm = XKE / pow( am, 1.5 );
+    em = em - tempe;
+
+    if ( ( em >= 1.0 ) || ( em < -0.001 ) ) {
+        kDebug() << "Eccentricity >= 1.0 or < -0.001";
+        return(1);
+    }
+
+    if ( em < 1.0e-6 )
+        em  = 1.0e-6;
+
+    mm     = mm + m_mean_motion * templ;
+    xlm    = mm + argpm + nodem;
+    emsq   = em * em;
+    temp   = 1.0 - emsq;
+
+    nodem  = fmod( nodem, TWOPI );
+    argpm  = fmod( argpm, TWOPI );
+    xlm    = fmod( xlm, TWOPI );
+    mm     = fmod( xlm - argpm - nodem, TWOPI );
+
+    // Compute extra mean quantities
+    sinim = sin( inclm );
+    cosim = cos( inclm );
+
+    // Add lunar-solar periodics
+    ep     = em;
+    xincp  = inclm;
+    argpp  = argpm;
+    nodep  = nodem;
+    mp     = mm;
+    sinip  = sinim;
+    cosip  = cosim;
+    if ( method == 'd' ) {
+        double alfdp, betdp, cosip, cosop, dalf, dbet, dls,
+               f2   , f3   , pe   , pgh  , ph  , pinc, pl ,
+               sel  , ses  , sghl , sghs , shll, shs , sil,
+               sinip, sinop, sinzf, sis  , sll , sls , xls,
+               xnoh , zf   , zm;
+
+        // Define some constants
+        const double zns   = 1.19459e-5;
+        const double zes   = 0.01675;
+        const double znl   = 1.5835218e-4;
+        const double zel   = 0.05490;
+
+        // Calculate time varying periodics
+        zm    = zmos + zns * tsince;
+        zf    = zm + 2.0 * zes * sin( zm );
+        sinzf = sin( zf );
+        f2    =  0.5 * sinzf * sinzf - 0.25;
+        f3    = -0.5 * sinzf * cos( zf );
+        ses   = se2* f2 + se3 * f3;
+        sis   = si2 * f2 + si3 * f3;
+        sls   = sl2 * f2 + sl3 * f3 + sl4 * sinzf;
+        sghs  = sgh2 * f2 + sgh3 * f3 + sgh4 * sinzf;
+        shs   = sh2 * f2 + sh3 * f3;
+        zm    = zmol + znl * tsince;
+
+        zf    = zm + 2.0 * zel * sin( zm );
+        sinzf = sin( zf );
+        f2    =  0.5 * sinzf * sinzf - 0.25;
+        f3    = -0.5 * sinzf * cos( zf );
+        sel   = ee2 * f2 + e3 * f3;
+        sil   = xi2 * f2 + xi3 * f3;
+        sll   = xl2 * f2 + xl3 * f3 + xl4 * sinzf;
+        sghl  = xgh2 * f2 + xgh3 * f3 + xgh4 * sinzf;
+        shll  = xh2 * f2 + xh3 * f3;
+        pe    = ses + sel;
+        pinc  = sis + sil;
+        pl    = sls + sll;
+        pgh   = sghs + sghl;
+        ph    = shs + shll;
+
+        pe    = pe - peo;
+        pinc  = pinc - pinco;
+        pl    = pl - plo;
+        pgh   = pgh - pgho;
+        ph    = ph - pho;
+        xincp = xincp + pinc;
+        ep    = ep + pe;
+        sinip = sin( xincp );
+        cosip = cos( xincp );
+
+        // Apply periodics directly
+        if ( xincp >= 0.2 ) {
+            ph     = ph / sinip;
+            pgh    = pgh - cosip * ph;
+            argpp  = argpp + pgh;
+            nodep  = nodep + ph;
+            mp     = mp + pl;
+        } else {
+            // Apply periodics with lyddane modification
+            sinop  = sin( nodep );
+            cosop  = cos( nodep );
+            alfdp  = sinip * sinop;
+            betdp  = sinip * cosop;
+            dalf   =  ph * cosop + pinc * cosip * sinop;
+            dbet   = -ph * sinop + pinc * cosip * cosop;
+            alfdp  = alfdp + dalf;
+            betdp  = betdp + dbet;
+            nodep  = fmod( nodep, TWOPI );
+            if ( nodep < 0.0 )
+                nodep += TWOPI;
+            xls    = mp + argpp + cosip * nodep;
+            dls    = pl + pgh - pinc * nodep * sinip;
+            xls    = xls + dls;
+            xnoh   = nodep;
+            nodep  = atan2( alfdp, betdp );
+            if ( ( nodep < 0.0) )
+                nodep += TWOPI;
+            if ( fabs( xnoh - nodep ) > PI ) {
+                if ( nodep < xnoh )
+                    nodep += TWOPI;
+                else
+                    nodep -= TWOPI;
+            }
+            mp    = mp + pl;
+            argpp = xls - mp - cosip * nodep;
+        }
+
+        if ( xincp < 0.0 ) {
+            xincp = -xincp;
+            nodep = nodep + PI;
+            argpp = argpp - PI;
+        }
+
+        if ( ( ep < 0.0 ) || ( ep > 1.0 ) ) {
+            kDebug() << "Eccentricity < 0.0  or > 1.0";
+            return( 3 );
+        }
+    }
+
+    // Long period periodics
+    if ( method == 'd' ) {
+        sinip =  sin( xincp );
+        cosip =  cos( xincp );
+        aycof = -0.5 * J3OJ2 * sinip;
+        if ( fabs( cosip + 1.0 ) > 1.5e-12 )
+            xlcof = -0.25 * J3OJ2 * sinip * ( 3.0 + 5.0 * cosip ) / ( 1.0 + cosip );
+        else
+            xlcof = -0.25 * J3OJ2 * sinip * ( 3.0 + 5.0 * cosip ) / temp4;
+    }
+    axnl = ep * cos( argpp );
+    temp = 1.0 / ( am * ( 1.0 - ep * ep ) );
+    aynl = ep* sin( argpp ) + temp * aycof;
+    xl   = mp + argpp + nodep + temp * xlcof * axnl;
+
+    // Solve kepler's equation
+    u    = fmod( xl - nodep, TWOPI );
+    eo1  = u;
+    tem5 = 9999.9;
+    ktr = 1;
+    while ( ( fabs( tem5 ) >= 1.0e-12 ) && ( ktr <= 10 ) ) {
+        sineo1 = sin( eo1 );
+        coseo1 = cos( eo1 );
+        tem5   = 1.0 - coseo1 * axnl - sineo1 * aynl;
+        tem5   = ( u - aynl * coseo1 + axnl * sineo1 - eo1 ) / tem5;
+        if ( fabs( tem5 ) >= 0.95 )
+            tem5 = tem5 > 0.0 ? 0.95 : -0.95;
+        eo1    = eo1 + tem5;
+        ktr = ktr + 1;
+    }
+
+    // Short period preliminary quantities
+    ecose = axnl * coseo1 + aynl * sineo1;
+    esine = axnl * sineo1 - aynl * coseo1;
+    el2   = axnl * axnl + aynl * aynl;
+    pl    = am * ( 1.0 - el2 );
+
+    if ( pl < 0.0 ) {
+        kDebug() << "Semi-latus rectum < 0.0";
+        return( 4 );
+    }
+
+    rl     = am * ( 1.0 - ecose );
+    rdotl  = sqrt( am ) * esine / rl;
+    rvdotl = sqrt( pl ) / rl;
+    betal  = sqrt( 1.0 - el2 );
+    temp   = esine / ( 1.0 + betal );
+    sinu   = am / rl * ( sineo1 - aynl - axnl * temp );
+    cosu   = am / rl * ( coseo1 - axnl + aynl * temp );
+    su     = atan2( sinu, cosu );
+    sin2u  = ( cosu + cosu ) * sinu;
+    cos2u  = 1.0 - 2.0 * sinu * sinu;
+    temp   = 1.0 / pl;
+    temp1  = 0.5 * J2 * temp;
+    temp2  = temp1 * temp;
+
+    // Update for short period periodics
+    if ( method == 'd' ) {
+        cosisq = cosip * cosip;
+        con41  = 3.0 * cosisq - 1.0;
+        x1mth2 = 1.0 - cosisq;
+        x7thm1 = 7.0 * cosisq - 1.0;
+    }
+    mrt   = rl * ( 1.0 - 1.5 * temp2 * betal * con41 ) +
+            0.5 * temp1 * x1mth2 * cos2u;
+    su    = su - 0.25 * temp2 * x7thm1 * sin2u;
+    xnode = nodep + 1.5 * temp2 * cosip * sin2u;
+    xinc  = xincp + 1.5 * temp2 * cosip * sinip * cos2u;
+    mvt   = rdotl - nm * temp1 * x1mth2 * sin2u / XKE;
+    rvdot = rvdotl + nm * temp1 * ( x1mth2 * cos2u +
+            1.5 * con41 ) / XKE;
+
+    // Orientation vectors
+    sinsu =  sin( su );
+    cossu =  cos( su );
+    snod  =  sin( xnode );
+    cnod  =  cos( xnode );
+    sini  =  sin( xinc );
+    cosi  =  cos( xinc );
+    xmx   = -snod * cosi;
+    xmy   =  cnod * cosi;
+    ux    =  xmx * sinsu + cnod * cossu;
+    uy    =  xmy * sinsu + snod * cossu;
+    uz    =  sini * sinsu;
+    vx    =  xmx * cossu - cnod * sinsu;
+    vy    =  xmy * cossu - snod * sinsu;
+    vz    =  sini * cossu;
+
+    // Position and velocity (in km and km/sec)
+    sat_posx = ( mrt * ux )* RADIUSEARTHKM;
+    sat_posy = ( mrt * uy )* RADIUSEARTHKM;
+    sat_posz = ( mrt * uz )* RADIUSEARTHKM;
+    sat_posw = sqrt( sat_posx*sat_posx + sat_posy*sat_posy + sat_posz*sat_posz );
+    sat_velx = ( mvt * ux + rvdot * vx ) * vkmpersec;
+    sat_vely = ( mvt * uy + rvdot * vy ) * vkmpersec;
+    sat_velz = ( mvt * uz + rvdot * vz ) * vkmpersec;
+    m_velocity =  sqrt( sat_velx*sat_velx + sat_vely*sat_vely + sat_velz*sat_velz );
+
+//     printf("tsince=%.15f\n", tsince);
+//     printf("sat_posx=%.15f\n", sat_posx);
+//     printf("sat_posy=%.15f\n", sat_posy);
+//     printf("sat_posz=%.15f\n", sat_posz);
+//     printf("sat_velx=%.15f\n", sat_velx);
+//     printf("sat_vely=%.15f\n", sat_vely);
+//     printf("sat_velz=%.15f\n", sat_velz);
+
+    if ( mrt < 1.0 ) {
+        kDebug() << "Satellite has decayed";
+        return( 6 );
+    }
+
+    // Observer ECI position and velocity
+    sinlat = sin( data->geo()->lat()->radians() );
+    coslat = cos( data->geo()->lat()->radians() );
+    thetageo = data->geo()->LMST( jul_utc );
+    sintheta = sin( thetageo );
+    costheta = cos( thetageo );
+    c = 1.0 / sqrt( 1.0 + F * ( F - 2.0 ) * sinlat * sinlat );
+    sq = ( 1.0 - F ) * ( 1.0 - F ) * c;
+    achcp = ( RADIUSEARTHKM * c + MEANALT) * coslat;
+    obs_posx = achcp * costheta;
+    obs_posy = achcp * sintheta;
+    obs_posz = ( RADIUSEARTHKM * sq + MEANALT ) * sinlat;
+    obs_posw = sqrt( obs_posx*obs_posx + obs_posy*sat_posy + obs_posz*obs_posz );
+    obs_velx = -MFACTOR * obs_posy;
+    obs_vely = MFACTOR * obs_posx;
+    obs_velz = 0.;
+
+    m_altitude = sat_posw - obs_posw + MEANALT;
+
+    // Az and Dec
+    double range_posx = sat_posx - obs_posx;
+    double range_posy = sat_posy - obs_posy;
+    double range_posz = sat_posz - obs_posz;
+    m_range = sqrt( range_posx*range_posx + range_posy*range_posy + range_posz*range_posz );
+//     double range_velx = sat_velx - obs_velx;
+//     double range_vely = sat_velx - obs_vely;
+//     double range_velz = sat_velx - obs_velz;
+
+    double top_s = sinlat*costheta*range_posx + sinlat*sintheta*range_posy - coslat*range_posz;
+    double top_e = -sintheta*range_posx + costheta*range_posy;
+    double top_z = coslat*costheta*range_posx + coslat*sintheta*range_posy + sinlat*range_posz;
+
+    double azimut = atan( -top_e / top_s );
+    if ( top_s > 0. )
+        azimut += PI;
+    if ( azimut < 0. )
+        azimut += TWOPI;
+    double elevation = arcSin( top_z / m_range );
+
+//     printf("azimut=%.15f\n\r", azimut / DEG2RAD);
+//     printf("elevation=%.15f\n\r", elevation / DEG2RAD);
+
+    setAz( azimut / DEG2RAD );
+    setAlt( elevation / DEG2RAD );
+    HorizontalToEquatorial( data->lst(), data->geo()->lat() );
+
+    // is the satellite visible ?
+    // Find ECI coordinates of the sun
+    double mjd, year, T, M, L, e, C, O, Lsa, nu, R, eps;
+
+    mjd  = jul_utc - 2415020.0;
+    year = 1900.0 + mjd / 365.25;
+    T    = ( mjd + deltaET( year ) / ( MINPD * 60.0 ) ) / 36525.0;
+    M    = DEG2RAD * ( Modulus( 358.47583 + Modulus( 35999.04975 * T, 360.0 ) - ( 0.000150 + 0.0000033 * T ) * T*T, 360.0 ) );
+    L    = DEG2RAD * ( Modulus( 279.69668 + Modulus( 36000.76892 * T, 360.0 ) + 0.0003025 * T*T, 360.0 ) );
+    e    = 0.01675104 - ( 0.0000418 + 0.000000126 * T ) * T;
+    C    = DEG2RAD * ( ( 1.919460 - ( 0.004789 + 0.000014 * T ) * T ) *
+           sin( M ) + ( 0.020094 - 0.000100 *  T) *
+           sin( 2 * M ) + 0.000293 * sin( 3 * M ) );
+    O    = DEG2RAD * ( Modulus( 259.18 - 1934.142 * T, 360.0 ) );
+    Lsa  = Modulus( L + C - DEG2RAD * ( 0.00569  -0.00479 * sin( O ) ), TWOPI );
+    nu   = Modulus( M + C, TWOPI);
+    R    = 1.0000002 * ( 1.0 - e*e ) / ( 1.0 + e * cos( nu ) );
+    eps  = DEG2RAD * ( 23.452294 - ( 0.0130125 + ( 0.00000164 - 0.000000503 * T ) * T ) * T + 0.00256 * cos( O ) );
+    R    = AU * R;
+
+    double sun_posx = R * cos( Lsa );
+    double sun_posy = R * sin( Lsa ) * cos( eps );
+    double sun_posz = R * sin( Lsa ) * sin( eps );
+    double sun_posw = R;
+
+    // Calculates satellite's eclipse status and depth
+    double sd_sun, sd_earth, delta, depth;
+
+    // Determine partial eclipse
+    sd_earth = arcSin( RADIUSEARTHKM / sat_posw );
+    double rho_x = sun_posx - sat_posx;
+    double rho_y = sun_posy - sat_posy;
+    double rho_z = sun_posz - sat_posz;
+    double rho_w = sqrt( rho_x*rho_x + rho_y*rho_y + rho_z*rho_z );
+    sd_sun = arcSin( SR / rho_w );
+    double earth_x = -1.0 * sat_posx;
+    double earth_y = -1.0 * sat_posy;
+    double earth_z = -1.0 * sat_posz;
+    double earth_w = sat_posw;
+    delta = PIO2 - arcSin( ( sun_posx*earth_x + sun_posy*earth_y + sun_posz*earth_z )  / ( sun_posw*earth_w ) );
+    depth = sd_earth - sd_sun - delta;
+    KSSun *sun = (KSSun*)data->skyComposite()->findByName( "Sun" );
+
+    if( sd_earth < sd_sun )
+        m_is_eclipsed = false;
+    else {
+        if ( depth >= 0 )
+            m_is_eclipsed = true;
+        else
+            m_is_eclipsed = false;
+    }
+
+    if ( !m_is_eclipsed && sun->alt().Degrees() <= -12.0 && elevation >= 0.0 )
+        m_is_visible = true;
+    else
+        m_is_visible = false;
+
+    return( 0 );
+}
+
+double Satellite::arcSin( double arg )
+{
+    if ( fabs( arg ) >= 1. )
+        if ( arg > 0. )
+            return PIO2;
+        else if ( arg < 0. )
+            return -PIO2;
+        else
+            return 0.;
+    else
+        return( atan( arg / sqrt( 1. - arg*arg ) ) );
+}
+
+double Satellite::deltaET( double year )
+{
+    double delta_et;
+
+    delta_et=26.465+0.747622*(year-1950)+1.886913*sin(TWOPI*(year-1975)/33);
+
+    return delta_et;
+}
+
+double Satellite::Modulus(double arg1, double arg2)
+{
+    int i;
+    double ret_val;
+
+    ret_val=arg1;
+    i=ret_val/arg2;
+    ret_val-=i*arg2;
+
+    if (ret_val<0.0)
+        ret_val+=arg2;
+
+    return ret_val;
+}
+
+bool Satellite::isVisible()
+{
+    return m_is_visible;
+}
+
+bool Satellite::selected()
+{
+    return m_is_selected;
+}
+
+void Satellite::setSelected( bool selected )
+{
+    m_is_selected = selected;
+}
+
+void Satellite::initPopupMenu( KSPopupMenu *pmenu ) {
+    pmenu->createSatelliteMenu( this );
+}
+
+double Satellite::velocity()
+{
+    return m_velocity;
+}
+
+double Satellite::altitude()
+{
+    return m_altitude;
+}
+
+double Satellite::range()
+{
+    return m_range;
+}
+
+QString Satellite::id()
+{
+    return m_id;
+}
diff --git a/kstars/skyobjects/satellite.h b/kstars/skyobjects/satellite.h
new file mode 100644
index 0000000..c6eb63d
--- /dev/null
+++ b/kstars/skyobjects/satellite.h
@@ -0,0 +1,168 @@
+/***************************************************************************
+                          satellite.h  -  K Desktop Planetarium
+                             -------------------
+    begin                : Tue 02 Mar 2011
+    copyright            : (C) 2009 by Jerome SONRIER
+    email                : jsid at emor3j.fr.eu.org
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+#ifndef SATELLITE_H
+#define SATELLITE_H
+
+
+#include <QString>
+
+#include "skyobject.h"
+#include "skypoint.h"
+
+class KSPopupMenu;
+
+/**
+    *@class Satellite
+    *Represents an artificial satellites.
+    *@author Jérôme SONRIER
+    *@version 0.1
+    */
+class Satellite : public SkyObject
+{
+public:
+    /**
+     *@short Constructor
+     */
+    Satellite( QString name, QString line1, QString line2 );
+
+    /**
+     *@short Destructor
+     */
+    ~Satellite();
+
+    /**
+     *@short Update satellite position
+     */
+    void updatePos();
+
+    /**
+     *@return True if the satellite is visible (above horizon, in the sunlight and sun at least 12° under horizon)
+     */
+    bool isVisible();
+
+    /**
+     *@return True if the satellite is selected
+     */
+    bool selected();
+
+    /**
+     *@short Select or not the satellite
+     */
+    void setSelected( bool selected );
+
+    /**
+     *@return Satellite velocity in km/s
+     */
+    double velocity();
+
+    /**
+     *@return Satellite altitude in km
+     */
+    double altitude();
+
+    /**
+     *@return Satellite range from observer in km
+     */
+    double range();
+
+    /**
+     *@return Satellite international designator
+     */
+    QString id();
+
+private:
+    /**
+     *@short Compute non time dependant parameters
+     */
+    void init();
+
+    /**
+     *@short Compute satellite position
+     */
+    int sgp4( double tsince );
+
+    /**
+     *@return Arcsine of the argument
+     */
+    double arcSin( double arg );
+
+    /**
+     *Provides the difference between UT (approximately the same as UTC)
+     *and ET (now referred to as TDT).
+     *This function is based on a least squares fit of data from 1950
+     *to 1991 and will need to be updated periodically.
+     */
+    double deltaET( double year );
+
+    /**
+     *@return arg1 mod arg2
+     */
+    double Modulus(double arg1, double arg2);
+
+    
+    virtual void initPopupMenu( KSPopupMenu *pmenu );
+    
+    // TLE
+    int     m_number;           // Satellite Number
+    QChar   m_class;            // Security Classification
+    QString m_id;               // International Designator
+    double  m_epoch_year;       // Epoch Year
+    double  m_epoch;            // Epoch (Day of the year and fractional portion of the day)
+    double  m_first_deriv;      // First Time Derivative of the Mean Motion
+    double  m_second_deriv;     // Second Time Derivative of Mean Motion
+    double  m_bstar;            // BSTAR drag term (decimal point assumed)
+    int     m_ephem_type;       // Ephemeris type
+    int     m_elem_number;      // Element number
+    double  m_inclination;      // Inclination [Radians]
+    double  m_ra;               // Right Ascension of the Ascending Node [Radians]
+    double  m_eccentricity;     // Eccentricity
+    double  m_arg_perigee;      // Argument of Perigee [Radians]
+    double  m_mean_anomaly;     // Mean Anomaly [Radians]
+    double  m_mean_motion;      // Mean Motion [Radians per minutes]
+    int     m_nb_revolution;    // Revolution number at epoch [Revs]
+    double  m_tle_jd;           // TLE epoch converted to julian date
+
+    // Satellite
+    bool m_is_visible;          // True if the satellite is visible
+    bool m_is_eclipsed;         // True if the satellite is in the shadow of the earth
+    bool m_is_selected;         // True if the satellite is selected
+    double m_velocity;          // Satellite velocity in km/s
+    double m_altitude;          // Satellite altitude in km
+    double m_range;             // Satellite range from observer in km
+
+    // Near Earth
+    bool isimp;
+    double aycof  , con41  , cc1    , cc4      , cc5    , d2      , d3   , d4    ,
+           delmo  , eta    , argpdot, omgcof   , sinmao , t       , t2cof, t3cof ,
+           t4cof  , t5cof  , x1mth2 , x7thm1   , mdot   , nodedot , xlcof, xmcof ,
+           nodecf;
+
+    // Deep Space
+    int irez;
+    double d2201  , d2211  , d3210  , d3222    , d4410  , d4422   , d5220 , d5232 ,
+           d5421  , d5433  , dedt   , del1     , del2   , del3    , didt  , dmdt  ,
+           dnodt  , domdt  , e3     , ee2      , peo    , pgho    , pho   , pinco ,
+           plo    , se2    , se3    , sgh2     , sgh3   , sgh4    , sh2   , sh3   ,
+           si2    , si3    , sl2    , sl3      , sl4    , gsto    , xfact , xgh2  ,
+           xgh3   , xgh4   , xh2    , xh3      , xi2    , xi3     , xl2   , xl3   ,
+           xl4    , xlamo  , zmol   , zmos     , atime  , xli     , xni;
+
+    char method;
+};
+
+#endif
diff --git a/kstars/skyobjects/skyobject.h b/kstars/skyobjects/skyobject.h
index 7348b8c..6f6a061 100644
--- a/kstars/skyobjects/skyobject.h
+++ b/kstars/skyobjects/skyobject.h
@@ -107,7 +107,8 @@ public:
     enum TYPE { STAR=0, CATALOG_STAR=1, PLANET=2, OPEN_CLUSTER=3, GLOBULAR_CLUSTER=4,
                 GASEOUS_NEBULA=5, PLANETARY_NEBULA=6, SUPERNOVA_REMNANT=7, GALAXY=8,
                 COMET=9, ASTEROID=10, CONSTELLATION=11, MOON=12, ASTERISM=13, 
-                GALAXY_CLUSTER=14, DARK_NEBULA=15, QUASAR=16, MULT_STAR=17, RADIO_SOURCE=18, TYPE_UNKNOWN };
+                GALAXY_CLUSTER=14, DARK_NEBULA=15, QUASAR=16, MULT_STAR=17, RADIO_SOURCE=18,
+                SATELLITE=19, TYPE_UNKNOWN };
 
     /**
      *@return object's primary name.
diff --git a/kstars/skypainter.h b/kstars/skypainter.h
index f081043..1340568 100644
--- a/kstars/skypainter.h
+++ b/kstars/skypainter.h
@@ -36,6 +36,7 @@ class SkyMap;
 class SkipList;
 class LineList;
 class LineListLabel;
+class Satellite;
 
 
 /** @short Draws things on the sky, without regard to backend.
@@ -141,6 +142,10 @@ public:
         */
     virtual void drawFlags() = 0;
 
+    /** @short Draw a satellite
+        */
+    virtual void drawSatellite( Satellite* sat ) = 0;
+
     virtual void drawHorizon( bool filled, SkyPoint *labelPoint = 0, bool *drawLabel = 0) = 0;
 
 protected:
diff --git a/kstars/skyqpainter.cpp b/kstars/skyqpainter.cpp
index 9f967e2..91257fc 100644
--- a/kstars/skyqpainter.cpp
+++ b/kstars/skyqpainter.cpp
@@ -31,11 +31,13 @@
 #include "skycomponents/linelistlabel.h"
 #include "skycomponents/skymapcomposite.h"
 #include "skycomponents/flagcomponent.h"
+#include "skycomponents/satellitescomponent.h"
 
 #include "skyobjects/deepskyobject.h"
 #include "skyobjects/kscomet.h"
 #include "skyobjects/ksasteroid.h"
 #include "skyobjects/trailobject.h"
+#include "skyobjects/satellite.h"
 
 #include "projections/projector.h"
 #include "ksutils.h"
@@ -705,3 +707,32 @@ void SkyQPainter::drawHorizon(bool filled, SkyPoint* labelPoint, bool* drawLabel
     }
 }
 
+void SkyQPainter::drawSatellite( Satellite* sat ) {
+    KStarsData *data = KStarsData::Instance();
+    QPointF pos;
+    bool visible = false;
+    
+    sat->HorizontalToEquatorial( data->lst(), data->geo()->lat() );
+
+    pos = m_proj->toScreen( sat, true, &visible );
+
+    if( !visible || !m_proj->onScreen( pos ) )
+        return;
+
+    if ( Options::drawSatellitesLikeStars() ) {
+        drawPointSource(pos, 3.5, 'B');
+    } else {
+        if ( sat->isVisible() )
+            setPen( data->colorScheme()->colorNamed( "VisibleSatColor" ) );
+        else
+            setPen( data->colorScheme()->colorNamed( "SatColor" ) );
+
+        drawLine( QPoint( pos.x() - 0.5, pos.y() - 0.5 ), QPoint( pos.x() + 0.5, pos.y() - 0.5 ) );
+        drawLine( QPoint( pos.x() + 0.5, pos.y() - 0.5 ), QPoint( pos.x() + 0.5, pos.y() + 0.5 ) );
+        drawLine( QPoint( pos.x() + 0.5, pos.y() + 0.5 ), QPoint( pos.x() - 0.5, pos.y() + 0.5 ) );
+        drawLine( QPoint( pos.x() - 0.5, pos.y() + 0.5 ), QPoint( pos.x() - 0.5, pos.y() - 0.5 ) );
+    }
+
+    if ( Options::showSatellitesLabels() )
+        data->skyComposite()->satellites()->drawLabel( sat, pos );
+}
diff --git a/kstars/skyqpainter.h b/kstars/skyqpainter.h
index da907d0..df7cc9b 100644
--- a/kstars/skyqpainter.h
+++ b/kstars/skyqpainter.h
@@ -58,6 +58,7 @@ public:
     virtual void drawObservingList(const QList<SkyObject*>& obs);
     virtual void drawFlags();
     virtual void drawHorizon( bool filled, SkyPoint *labelPoint = 0, bool *drawLabel = 0);
+    virtual void drawSatellite( Satellite* sat );
 private:
     ///This function exists so that we can draw other objects (e.g., planets) as point sources.
     virtual void drawPointSource(const QPointF& pos, float size, char sp = 'A');



More information about the Kstars-devel mailing list