Cogs.Core
RasterLevel.cpp
1#include "RasterLevel.h"
2
3#include <algorithm>
4
5#include "RasterSource.h"
6
7Cogs::RasterLevel::RasterLevel(RasterSource * source,
8 int level,
9 GeodeticExtent extent,
10 float noData,
11 int longitudePosts,
12 int latitudePosts,
13 int longitudePostsPerTile,
14 int latitudePostsPerTile,
15 double postDeltaLongitude,
16 double postDeltaLatitude) :
17 source(source),
18 level(level),
19 extent(extent),
20 noData(noData),
21 longitudePosts(longitudePosts),
22 latitudePosts(latitudePosts),
23 longitudePostsPerTile(longitudePostsPerTile),
24 latitudePostsPerTile(latitudePostsPerTile),
25 postDeltaLongitude(postDeltaLongitude),
26 postDeltaLatitude(postDeltaLatitude)
27{
28 indexExtent = Extent{ 0, 0, longitudePosts - 1, latitudePosts - 1 };
29}
30
31double Cogs::RasterLevel::longitudeToIndex(double longitude) const
32{
33 return (longitude - extent.getWest()) / postDeltaLongitude;
34}
35
36double Cogs::RasterLevel::latitudeToIndex(double latitude) const
37{
38 return (latitude - extent.getSouth()) / postDeltaLatitude;
39}
40
41double Cogs::RasterLevel::indexToLongitude(int longitudeIndex) const
42{
43 return extent.getWest() + longitudeIndex * postDeltaLongitude;
44}
45
46double Cogs::RasterLevel::indexToLatitude(int latitudeIndex) const
47{
48 return extent.getSouth() + latitudeIndex * postDeltaLatitude;
49}
50
51void Cogs::RasterLevel::getTilesInExtent(const Extent & extent, std::vector<RasterTileRegion> & results) const
52{
53 static std::vector<Extent> extents;
54 static std::vector<RasterTileIdentifier> ids;
55
56 extents.clear();
57 ids.clear();
58
59 getTilesInExtent(extent, ids, extents);
60
61 ReadLock lock(*source);
62
63 for (size_t i = 0; i < ids.size(); ++i) {
64 auto tile = source->getTile(ids[i]);
65
66 if (tile) {
67 results.emplace_back(RasterTileRegion{ tile, extents[i] });
68 }
69 }
70}
71
72void Cogs::RasterLevel::getTilesInExtent(const Extent & extent, std::vector<RasterTileIdentifier> & ids, std::vector<Extent> & extents) const
73{
74 int tileXStart = extent.west / longitudePostsPerTile;
75 int tileXStop = extent.east / longitudePostsPerTile;
76
77 if (extent.west < 0) {
78 --tileXStart;
79 }
80
81 if (extent.east < 0) {
82 --tileXStop;
83 }
84
85 int tileYStart = extent.south / latitudePostsPerTile;
86 int tileYStop = extent.north / latitudePostsPerTile;
87
88 if (extent.south < 0) {
89 --tileYStart;
90 }
91
92 if (extent.north < 0) {
93 --tileYStop;
94 }
95
96 // Calculate the max X and Y tile index.
97 const int maxTileX = longitudePosts / longitudePostsPerTile + ((longitudePosts % longitudePostsPerTile) ? 1 : 0) - 1;
98 const int maxTileY = latitudePosts / latitudePostsPerTile + ((latitudePosts % latitudePostsPerTile) ? 1 : 0) - 1;
99
100 for (int tileY = tileYStart; tileY <= tileYStop; ++tileY) {
101 const int tileYOrigin = tileY * latitudePostsPerTile;
102
103 const int currentTileSouth = std::max(extent.south - tileYOrigin, 0);
104 const int currentTileNorth = std::min(extent.north - tileYOrigin, latitudePostsPerTile - 1);
105
106 for (int tileX = tileXStart; tileX <= tileXStop; ++tileX) {
107 const int tileXOrigin = tileX * longitudePostsPerTile;
108
109 const int currentTileWest = std::max(extent.west - tileXOrigin, 0);
110 const int currentTileEast = std::min(extent.east - tileXOrigin, longitudePostsPerTile - 1);
111
112 // Only return tile regions for tiles that have indexes inside the level.
113 if (tileX >= 0 && tileX <= maxTileX && tileY >= 0 && tileY <= maxTileY) {
114 ids.emplace_back(RasterTileIdentifier { level, tileX, tileY });
115
116 extents.emplace_back(Extent{ currentTileWest, currentTileSouth, currentTileEast, currentTileNorth });
117 }
118 }
119 }
120}