• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdeedu API Reference
  • KDE Home
  • Contact Us
 

kstars

  • sources
  • kde-4.12
  • kdeedu
  • kstars
  • kstars
  • tools
starhopper.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  starhopper.cpp - Star Hopping Guide for KStars
3  -------------------
4  begin : Mon 23rd Aug 2010
5  copyright : (C) 2010 Akarsh Simha
6  email : akarshsimha@gmail.com
7 ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "starhopper.h"
19 
20 #include "skyobjects/skyobject.h"
21 #include "skyobjects/starobject.h"
22 #include "starcomponent.h"
23 
24 #include "kstarsdata.h"
25 #include "ksutils.h"
26 
27 #include <QList>
28 
29 
30 QList<const StarObject *> StarHopper::computePath( const SkyPoint &src, const SkyPoint &dest, float fov_, float maglim_ ) {
31 
32  fov = fov_;
33  maglim = maglim_;
34  start = &src;
35  end = &dest;
36 
37  came_from.clear();
38  result_path.clear();
39 
40 
41  // Implements the A* search algorithm
42 
43  QList<SkyPoint const *> cSet;
44  QList<SkyPoint const *> oSet;
45  QHash<SkyPoint const *, double> g_score;
46  QHash<SkyPoint const *, double> f_score;
47  QHash<SkyPoint const *, double> h_score;
48 
49  kDebug() << "StarHopper is trying to compute a path from source: " << src.ra().toHMSString() << src.dec().toDMSString() << " to destination: " << dest.ra().toHMSString() << dest.dec().toDMSString() << "; a starhop of " << src.angularDistanceTo( &dest ).Degrees() << " degrees!";
50 
51  oSet.append( &src );
52  g_score[ &src ] = 0;
53  h_score[ &src ] = src.angularDistanceTo( &dest ).Degrees()/fov;
54  f_score[ &src ] = h_score[ &src ];
55 
56  while( !oSet.isEmpty() ) {
57  kDebug() << "Next step";
58  // Find the node with the lowest f_score value
59  SkyPoint const *curr_node = NULL;
60  double lowfscore = 1.0e8;
61  foreach( const SkyPoint *sp, oSet ) {
62  if( f_score[ sp ] < lowfscore ) {
63  lowfscore = f_score[ sp ];
64  curr_node = sp;
65  }
66  }
67  kDebug() << "Lowest fscore (vertex distance-plus-cost score) is " << lowfscore << " with coords: " << curr_node->ra().toHMSString() << curr_node->dec().toDMSString() << ". Considering this node now.";
68  if( curr_node == &dest || (curr_node != &src && h_score[ curr_node ] < 0.5) ) {
69  // We are at destination
70  reconstructPath( came_from[ curr_node ] );
71  kDebug() << "We've arrived at the destination! Yay! Result path count: " << result_path.count();
72 
73  // Just a test -- try to print out useful instructions to the debug console. Once we make star hopper unexperimental, we should move this to some sort of a display
74  kDebug() << "Star Hopping Directions: ";
75  const SkyPoint *prevHop = start;
76  foreach( const StarObject *hopStar, result_path ) {
77  QString direction;
78  double pa; // should be 0 to 2pi
79 
80  dms angDist = prevHop->angularDistanceTo( hopStar, &pa );
81 
82  dms dmsPA;
83  dmsPA.setRadians( pa );
84  direction = KSUtils::toDirectionString( dmsPA );
85 
86  kDebug() << " Slew " << angDist.Degrees() << " degrees " << direction << " to find a " << hopStar->spchar() << " star of mag " << hopStar->mag();
87  prevHop = hopStar;
88  }
89  kDebug() << " The destination is within a field-of-view";
90 
91  return result_path;
92  }
93 
94  oSet.removeOne( curr_node );
95  cSet.append( curr_node );
96 
97  // FIXME: Make sense. If current node ---> dest distance is
98  // larger than src --> dest distance by more than 20%, don't
99  // even bother considering it.
100 
101  if( h_score[ curr_node ] > h_score[ &src ] * 1.2 ) {
102  kDebug() << "Node under consideration has larger distance to destination (h-score) than start node! Ignoring it.";
103  continue;
104  }
105 
106  SkyPoint const *nhd_node;
107 
108  // Get the list of stars that are neighbours of this node
109  QList<StarObject *> neighbors;
110 
111  // FIXME: Actually, this should be done in
112  // HorizontalToEquatorial, but we do it here because SkyPoint
113  // needs a lot of fixing to handle unprecessed and precessed,
114  // equatorial and horizontal coordinates nicely
115  SkyPoint *CurrentNode = const_cast<SkyPoint *>(curr_node);
116  CurrentNode->deprecess( KStarsData::Instance()->updateNum() );
117  kDebug() << "Calling starsInAperture";
118  StarComponent::Instance()->starsInAperture( neighbors, *curr_node, fov, maglim );
119  kDebug() << "Choosing next node from a set of " << neighbors.count();
120  // Look for the potential next node
121  double curr_g_score = g_score[ curr_node ];
122  foreach( nhd_node, neighbors ) {
123  if( cSet.contains( nhd_node ) )
124  continue;
125 
126  // Compute the tentative g_score
127  double tentative_g_score = curr_g_score + cost( curr_node, nhd_node );
128  bool tentative_better;
129  if( !oSet.contains( nhd_node ) ) {
130  oSet.append( nhd_node );
131  tentative_better = true;
132  }
133  else if( tentative_g_score < g_score[ nhd_node ] )
134  tentative_better = true;
135  else
136  tentative_better = false;
137 
138  if( tentative_better ) {
139  came_from[ nhd_node ] = curr_node;
140  g_score[ nhd_node ] = tentative_g_score;
141  h_score[ nhd_node ] = nhd_node->angularDistanceTo( &dest ).Degrees() / fov;
142  f_score[ nhd_node ] = g_score[ nhd_node ] + h_score[ nhd_node ];
143  }
144  }
145  }
146  kDebug() << "REGRET! Returning empty list!";
147  return QList<StarObject const *>(); // Return an empty QList
148 }
149 
150 void StarHopper::reconstructPath( SkyPoint const *curr_node ) {
151  if( curr_node != start ) {
152  StarObject const *s = dynamic_cast<StarObject const *>(curr_node);
153  Q_ASSERT( s );
154  result_path.prepend( s );
155  reconstructPath( came_from[ s ] );
156  }
157 }
158 
159 float StarHopper::cost( const SkyPoint *curr, const SkyPoint *next ) {
160 
161  // This is a very heuristic method, that tries to produce a cost
162  // for each hop.
163 
164  float netcost = 0;
165 
166  // Convert 'next' into a StarObject
167  if( next == start ) {
168  // If the next hop is back to square one, junk it
169  return 1e8;
170  }
171  bool isThisTheEnd = (next == end);
172 
173  float magcost, speccost;
174  magcost = speccost = 0;
175 
176  if( !isThisTheEnd ) {
177  // We ought to be dealing with a star
178  StarObject const *nextstar = dynamic_cast<StarObject const *>(next);
179  Q_ASSERT( nextstar );
180 
181  // Test 1: How bright is the star?
182  magcost = nextstar->mag() - 7.0 + 5 * log10( fov ); // The brighter, the better. FIXME: 8.0 is now an arbitrary reference to the average faint star. Should actually depend on FOV, something like log( FOV ).
183 
184  // Test 2: Is the star strikingly red / yellow coloured?
185  QString SpType = nextstar->sptype();
186  char spclass = SpType.at( 0 ).toAscii();
187  speccost = ( spclass == 'G' || spclass == 'K' || spclass == 'M' ) ? -1 : 0;
188  /*
189  // Test 3: Is the star in the general direction of the object?
190  // We use the cosine rule to find the angle between the hop direction, and the direction to destination
191  // a = side joining curr to end
192  // b = side joining curr to next
193  // c = side joining next to end
194  // C = angle between curr-next and curr-end
195  double sina, sinb, cosa, cosb;
196  curr->angularDistanceTo(dest).SinCos( &sina, &cosa );
197  curr->angularDistanceTo(next).SinCos( &sinb, &cosb );
198  double cosc = cos(next->angularDistanceTo(end).radians());
199  double cosC = ( cosc - cosa * cosb ) / (sina * sinb);
200  float dircost;
201  if( cosC < 0 ) // Wrong direction!
202  dircost = 1e8; // Some humongous number;
203  else
204  dircost = sqrt( 1 - cosC * cosC ) / cosC; // tan( C )
205  */
206  }
207 
208  // Test 4: How far is the hop?
209  double distcost = (curr->angularDistanceTo( next ).Degrees() / fov); // 1 "magnitude" incremental cost for 1 FOV. Is this even required, or is it just equivalent to halving our distance unit? I think it is required since the hop is not necessarily in the direction of the object -- asimha
210 
211  // Test 5: How effective is the hop? [Might not be required with A*]
212  // double distredcost = -((src->angularDistanceTo( dest ).Degrees() - next->angularDistanceTo( dest ).Degrees()) * 60 / fov)*3; // 3 "magnitudes" for 1 FOV closer
213 
214  // Test 5: Is this an asterism, or are there bright stars clustered nearby?
215  QList<StarObject *> localNeighbors;
216  StarComponent::Instance()->starsInAperture( localNeighbors, *curr, fov/10, maglim + 1.0 );
217  double stardensitycost = 1 - localNeighbors.count(); // -1 "magnitude" for every neighbouring star
218 
219  netcost = magcost /*+ speccost*/ + distcost + stardensitycost;
220  if( netcost < 0 )
221  netcost = 0.1; // FIXME: Heuristics aren't supposed to be entirely random. This one is.
222  kDebug() << "Mag cost: " << magcost << "; Spec Cost: " << speccost << "; Dist Cost: " << distcost << "; Net cost: " << netcost;
223 
224  return netcost;
225 }
SkyPoint::deprecess
SkyPoint deprecess(const KSNumbers *num, long double epoch=J2000)
Obtain a Skypoint with RA0 and Dec0 set from the RA, Dec of this skypoint.
Definition: skypoint.cpp:190
SkyPoint::ra
const dms & ra() const
Definition: skypoint.h:171
StarObject::sptype
QString sptype(void) const
Returns entire spectral type string.
Definition: starobject.cpp:340
skyobject.h
KStarsData::Instance
static KStarsData * Instance()
Definition: kstarsdata.h:92
dms::Degrees
const double & Degrees() const
Definition: dms.h:98
starcomponent.h
StarHopper::computePath
QList< StarObject const * > computePath(const SkyPoint &src, const SkyPoint &dest, float fov_, float maglim_)
Definition: starhopper.cpp:30
starhopper.h
StarComponent::Instance
static StarComponent * Instance()
Definition: starcomponent.h:74
SkyPoint
The sky coordinates of a point in the sky.
Definition: skypoint.h:50
dms
An angle, stored as degrees, but expressible in many ways.
Definition: dms.h:42
SkyPoint::dec
const dms & dec() const
Definition: skypoint.h:174
StarObject::spchar
char spchar() const
Returns just the first character of the spectral type string.
Definition: starobject.cpp:344
SkyObject::mag
float mag(void) const
Definition: skyobject.h:182
StarComponent::starsInAperture
void starsInAperture(QList< StarObject * > &list, const SkyPoint &center, float radius, float maglim=-29)
Add to the given list, the stars from this component, that lie within the specified circular aperture...
Definition: starcomponent.cpp:611
starobject.h
KSUtils::toDirectionString
QString toDirectionString(dms angle)
Return a string corresponding to an angle specifying direction.
kstarsdata.h
ksutils.h
StarObject
This is a subclass of SkyObject.
Definition: starobject.h:41
SkyPoint::angularDistanceTo
dms angularDistanceTo(const SkyPoint *sp, double *const positionAngle=0) const
Computes the angular distance between two SkyObjects.
Definition: skypoint.cpp:608
QList
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:36:21 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

kstars

Skip menu "kstars"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdeedu API Reference

Skip menu "kdeedu API Reference"
  • Analitza
  •     lib
  • kalgebra
  • kalzium
  •   libscience
  • kanagram
  • kig
  •   lib
  • klettres
  • kstars
  • libkdeedu
  •   keduvocdocument
  • marble
  • parley
  • rocs
  •   App
  •   RocsCore
  •   VisualEditor
  •   stepcore

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal