Rose
MapProjection.h
1 
8 #pragma once
9 
10 #include <mutex>
11 #include <Button.h>
12 
13 #include "AntiAliasedDrawing.h"
14 #include "Cache.h"
15 #include "Math.h"
16 #include "Rose.h"
17 #include "Ephemeris.h"
19 #include "SettingsNames.h"
20 
21 namespace rose {
22 
23  static constexpr double GRAYLINE_COS = -0.208;
24  static constexpr double GRAYLINE_POW = 0.75;
25 
26  enum class EphemerisFile : size_t {
27  ClearSkyMoon,
28  ClearSkyAll,
29  CTAmateur,
30  CTCube,
31  CTVisual,
32  };
33 
34  enum class ProjectionType {
35  Mercator,
37  StationAzmuthal,
38  };
39 
44  enum class MapDataType : size_t {
45  TerrainDay = 0,
46  TerrainNight = 1,
47  CountriesDay = 0x2,
48  CountriesNight = 0x3,
49  MapCount,
50  };
51 
53  std::string name;
54  ImageId imageId;
55  bool passRiseOk{}, passSetOk{};
56  DateTime riseTime{};
57  DateTime setTime{};
58  double elevation{}, azimuth{}, range{}, rangeRate{};
59 
60  bool operator<(const SatelliteMetaData &other) const {
61  if (passRiseOk && other.passRiseOk)
62  return riseTime < other.riseTime;
63  else
64  return setTime < other.setTime;
65  }
66 
72  void setPassData(bool riseOk, bool setOk, DateTime rise, DateTime set) {
73  passRiseOk = riseOk;
74  passSetOk = setOk;
75  riseTime = rise;
76  setTime = set;
77  }
78 
83  [[nodiscard]] std::tuple<bool, bool, DateTime, DateTime> getPassData() const { return std::make_tuple(passRiseOk, passSetOk, riseTime, setTime); }
84 
96  [[nodiscard]] std::string passTimeString(time_t relative = 0) const;
97  };
98 
102 
103  void predict(DateTime dateTime) {
104  satellite.predict(dateTime);
105  }
106 
107  void updateMetaData(Observer observer) {
108  auto [elevation, azimuth, range, range_rate] = satellite.topo(observer);
109  metaData.elevation = elevation;
110  metaData.azimuth = azimuth;
111  metaData.range = range;
112  metaData.rangeRate = range_rate;
113  }
114  };
115 
120  class PartitionedLine : public std::vector<Position> {
121  protected:
123  using LineSegment = std::vector<Position>;
124 
126  using LineParts = std::vector<LineSegment>;
127 
129  LineParts mLineParts{};
130 
131  public:
132  PartitionedLine() : std::vector<Position>() {}
133 
134  ~PartitionedLine() = default;
135 
139  using Predicate = std::function<bool(Position &, Position &)>;
140 
141  void partition() {
142  LineSegment segment{};
143  std::copy(begin(), end(), std::back_inserter(segment));
144  mLineParts.emplace_back(segment);
145  clear();
146  }
147 
148  void partition(Predicate p) {
149  mLineParts.clear();
150  if (!empty()) {
151  auto first = begin();
152  auto last = end();
153  LineSegment work{};
154  work.emplace_back(*first);
155  ++first;
156  while (first != last) {
157  if (p(work.back(), *first)) {
158  work.emplace_back(*first);
159  } else {
160  if (work.size() > 1)
161  mLineParts.emplace_back(work);
162  work.clear();
163  work.emplace_back(*first);
164  }
165  ++first;
166  }
167  if (work.size() > 1)
168  mLineParts.emplace_back(work);
169  work.clear();
170  }
171  clear();
172  }
173 
174  bool draw(std::function<bool(const Position &, const Position &)> p) {
175  for (const auto &segment : mLineParts) {
176  Position p0 = segment.front();
177  std::for_each(segment.begin()+1, segment.end(), [&p,&p0](const Position &p1){
178  if (!p(p0,p1))
179  return false;
180  p0 = p1;
181  return true;
182  });
183  }
184  return true;
185  }
186  };
187 
192  class MapProjection : public Widget {
193  protected:
194  SignalSerialNumber mSignalSerialNumber{};
195  Rose::IconFileItem mMoonIconSpec{static_cast<ImageId>(set::AppImageId::Moon), Size{0, 0}, "full_moon.png"};
196 
198  static constexpr std::array<double, 3> GrayLineCos = {-0.105, -0.208,
199  -0.309};
200  static constexpr double GrayLinePow = .80;
201 
203  static constexpr std::array<set::AppImageId,5> mSatelliteIconArray{
204  set::AppImageId::DotPurple, set::AppImageId::DotYellow,
205  set::AppImageId::DotGreen, set::AppImageId::DotBlue, set::AppImageId::DotRed, };
206 
208  std::stack<set::AppImageId> mSatelliteIconStack{};
209 
210  bool mTerrestrialMode{};
211  bool mSatelliteMode{};
212  bool mCelestialMode{};
213  bool mAnnotationMode{};
214 
215  std::string mSatelliteFavorite{};
216 
217  std::future<bool> mFutureAziProj{};
218  std::future<bool> mFutureSun{};
219  std::atomic_bool mNewSurfaces{};
220  std::atomic_bool mAbortFuture{};
221 
222  ProjectionType mProjection{ProjectionType::Mercator};
223  std::shared_ptr<WebFileCache> mMapCache{};
224  ImageId mDayMapImage{};
225  ImageId mNightMapImage{};
226  GeoPosition mQth{};
227  GeoPosition mQthRad{};
228  GeoPosition mAntipode{};
229  Size mMapSize{};
230  int mSelectedSatellite{};
231 
232  std::array<sdl::Surface,static_cast<std::size_t>(MapDataType::MapCount)> mMapSurface{};
233  std::array<sdl::Surface,static_cast<std::size_t>(MapDataType::MapCount)> mAzSurface{};
234 
235  std::array<sdl::Surface,static_cast<std::size_t>(MapDataType::MapCount)/2> mMercatorTemp;
236  std::array<sdl::Surface,static_cast<std::size_t>(MapDataType::MapCount)/2> mAzimuthalTemp;
237 
238  std::atomic_bool mUpdateEphemeris{false};
239  std::array<std::filesystem::path, 5> mEphemerisFilePath{};
240  EphemerisFile mEphemerisFile{EphemerisFile::ClearSkyAll};
241  void updateEphemerisFile();
242  Observer mObserver{};
243 
244  std::vector<TrackedSatellite> mSatelliteList{};
245  std::mutex mSatListMutex{};
246  double mMinimumElevation{15.};
247 
249  static std::tuple<bool, bool, double, double, double, DateTime, DateTime>
250  findNextPass(const Satellite &satellite, const Observer &observer);
251 
252  std::array<sdl::Texture,2> mMercator{};
253  std::array<sdl::Texture,2> mAzimuthal{};
254 
255  sdl::Texture mNightAz{};
256  sdl::Texture mDayAz{};
257 
258  std::shared_ptr<Slot<std::string>> mSettingsUpdateRx{};
259 
264  void drawOrbitalPath(sdl::Renderer &renderer, TrackedSatellite &satellite, Position mapPos, int splitPixel);
265 
266  void drawFootprint(sdl::Renderer &renderer, TrackedSatellite &satellite, Position mapPos, int splitPixel);
267 
268  std::unique_ptr<AntiAliasedDrawing> mDrawingContext{};
269 
278  bool computeAzimuthalMaps();
279 
288  bool setForegroundBackground();
289 
294  struct MapIcon {
295  ImageId imageId{RoseImageInvalid};
296  GeoPosition geo{};
297  };
298 
299  std::array<MapIcon,2> mStationIcons{};
300  std::array<MapIcon,2> mCelestialIcons{};
301 
302  Satellite mMoon{};
303 
304  void setStationIcons(GeoPosition qth) {
305  mQth = qth;
306  mQthRad = GeoPosition{deg2rad(qth.lat()), deg2rad(qth.lon())};
307  mAntipode = antipode(mQthRad);
308  mStationIcons[0].geo = mQthRad;
309  mStationIcons[1].geo = mAntipode;
310  mStationIcons[0].imageId = static_cast<ImageId>(set::AppImageId::RingGreen);
311  mStationIcons[1].imageId = static_cast<ImageId>(set::AppImageId::RingRed);
312  }
313 
314  void setMoonPhase();
315  void setCelestialIcons();
316 
324  void drawMapItem(const MapIcon &mapItem, sdl::Renderer &renderer, Rectangle mapRectangle, ProjectionType projection,
325  int splitPixel);
326 
335  template<typename InputIterator>
336  void drawMapItems(InputIterator first, InputIterator last, sdl::Renderer &renderer, Rectangle mapRect,
337  ProjectionType projection, int splitPixel = 0) {
338  while (first != last) {
339  drawMapItem(*first, renderer, mapRect, projection, splitPixel);
340  ++first;
341  }
342  }
343 
344  public:
345  MapProjection() = delete;
346 
347  ~MapProjection() override = default;
348 
349  MapProjection(std::shared_ptr<WebFileCache> mapCache, Size mapSize);
350 
352  void initializeComposite() override;
353 
360  Rectangle widgetLayout(sdl::Renderer &renderer, Rectangle available, uint layoutStage) override;
361 
368  void draw(sdl::Renderer &renderer, Rectangle parentRect) override;
369 
370  std::shared_ptr<Slot<uint32_t>> mapFileRx{};
371  std::shared_ptr<Slot<int>> secondRx{};
372  std::shared_ptr<Slot<int>> minuteRx{};
373 
379  static GeoPosition antipode(const GeoPosition posRadians) {
380  return GeoPosition{-posRadians.lat(), (posRadians.lon() < 0. ? 1. : -1.) * (M_PI - abs(posRadians.lon()))};
381  }
382 
390  static GeoPosition geoPosition(int x, int y, Size mapSize) {
391  double lon = (2. * M_PI * (double)x / (double)mapSize.width()) - M_PI;
392  double lat = M_PI_2 - (double)y / (double)mapSize.height() * M_PI;
393  return GeoPosition{lat,lon};
394  }
395 
402  static Position mapPosition(GeoPosition map, Size mapSize) {
403  int x = util::roundToInt((map.lon() + M_PI) / (2. * M_PI) * (double)mapSize.width());
404  int y = util::roundToInt((M_PI_2 - map.lat()) / M_PI * (double)mapSize.height());
405  return Position{x, y};
406  }
407 
413  Position geoToMap(GeoPosition geo, ProjectionType projection, int splitPixel);
414 
419  void setMoonEphemerisFile(EphemerisFile item, const std::filesystem::path &filePath) {
420  mEphemerisFilePath[static_cast<std::size_t>(item)] = filePath;
421  if (item == EphemerisFile::ClearSkyMoon) {
422  // If the file is the Moon ephemeris set or update the Moon TLE.
423  Ephemeris ephemeris{filePath};
424  mMoon.setEphemeris(ephemeris["Moon"]);
425  setMoonPhase();
426  setCelestialIcons();
427  } else if (mEphemerisFile == item){
428  // If the ephemeris in use, update the the satellite ephemeris processor.
429  updateEphemerisFile();
430  }
431  }
432 
433  using SignalType = std::vector<TrackedSatellite>&;
434 
436  Signal<SignalType> trackedSatelliteTx{};
437 
439  std::shared_ptr<Slot<RadioBehavior::SignalType>> satelliteSelectRx{};
440  };
441 }
442 
Definition: MapProjection.h:318
Definition: MapProjection.h:294
Invalid image ID.
Definition: Constants.h:172
Encapsulate the day-in-space for orbital mechanics computations.
Definition: Plan13.h:141
std::tuple< double, double, double, double > topo(const Observer &obs)
Convert satellite co-ordinates to an observer frame.
Definition: Plan13.cpp:358
int roundToInt(T value, T multiplier=1.)
Round a floating point value to an integer.
Definition: Math.h:34
std::vector< Position > LineSegment
The type of a line segment.
Definition: MapProjection.h:123
Definition: MapProjection.h:52
Standard Mercator split a the International Date Line.
double lat
Latitude value.
Definition: MapProjection.h:166
static GeoPosition geoPosition(int x, int y, Size mapSize)
Convert a map coordinate (x,y) into a GeoPosition(lat,lon) in radians.
Definition: MapProjection.h:390
Definition: SatelliteModel.h:79
An encapsulation of the SDL_Texture structure.
Definition: Texture.h:40
static Position mapPosition(GeoPosition map, Size mapSize)
Convert a GeoPosition(lat,lon) in radians to a map Position(x,y) in pixels.
Definition: MapProjection.h:402
Definition: MapProjection.h:99
constexpr int & width()
Reference accessor for width.
Definition: ScreenMetrics.h:61
An abstraction of a geographic position.
Definition: MapProjection.h:165
A position in integer (x, y) co-ordinates.
Definition: Types.h:95
std::function< bool(Position &, Position &)> Predicate
A predicate which returns true if two Positions belong in the same partition.
Definition: MapProjection.h:139
Classes and functions for caching data fetched from the network.
void predict(const DateTime &dateTime)
Predict the satelite position at given DateTime.
Definition: Plan13.cpp:255
Data specifying an observer for computing relative visibility data.
Definition: Plan13.h:254
void setPassData(bool riseOk, bool setOk, DateTime rise, DateTime set)
Set the pass times for the Satellite.
Definition: MapProjection.h:72
void setMoonEphemerisFile(EphemerisFile item, const std::filesystem::path &filePath)
Set the Moon ephemeris.
Definition: MapProjection.h:419
A composite of a Position and a Size.
Definition: Types.h:307
void drawMapItems(InputIterator first, InputIterator last, sdl::Renderer &renderer, Rectangle mapRect, ProjectionType projection, int splitPixel=0)
Render a container of icons [first ...
Definition: MapProjection.h:336
double lon
Longitude value.
Definition: MapProjection.h:167
MapDataType
Map type ins order with the Night map after and one greater than the Day map.
Definition: MapProjection.h:44
An element of the application user interface.
Definition: Visual.h:451
SatelliteMetaData metaData
Minimal data for display of the satellite status.
Definition: MapProjection.h:100
Written as a workaround for an issue in the SDL2 Library.
Definition: Renderer.h:64
Partition lines across discontinuities introduced by the current map projection.
Definition: MapProjection.h:120
A size in integer dimensions.
Definition: Types.h:230
Satellite orbital mechanics.
Definition: Plan13.h:294
std::vector< LineSegment > LineParts
The type of a partitioned line.
Definition: MapProjection.h:126
static GeoPosition antipode(const GeoPosition posRadians)
Compute an antipode.
Definition: MapProjection.h:379
ToDo: There is an issue that the initial scroll interaction is lost if the click/press lands on a Wid...
Definition: CelestialOverlay.cpp:13
Mercator split so the Station location is centred.
std::tuple< bool, bool, DateTime, DateTime > getPassData() const
Get the data relative to.
Definition: MapProjection.h:83
constexpr int & height()
Reference accessor for height.
Definition: ScreenMetrics.h:67
Satellite satellite
The tracked Satellite.
Definition: MapProjection.h:101