| 182 | } |
| 183 | |
| 184 | double SrtmTile::GetBilinearHeight(ms::LatLon const & coord) const |
| 185 | { |
| 186 | if (!IsValid()) |
| 187 | return geometry::kInvalidAltitude; |
| 188 | |
| 189 | auto const ll = GetCoordInSeconds(coord); |
| 190 | |
| 191 | m2::Point<int> const p1(static_cast<int>(ll.m_lon), static_cast<int>(ll.m_lat)); |
| 192 | auto p2 = p1; |
| 193 | if (p2.x < kArcSecondsInDegree) |
| 194 | ++p2.x; |
| 195 | if (p2.y < kArcSecondsInDegree) |
| 196 | ++p2.y; |
| 197 | |
| 198 | // https://en.wikipedia.org/wiki/Bilinear_interpolation |
| 199 | double const denom = (p2.x - p1.x) * (p2.y - p1.y); |
| 200 | if (denom == 0) |
| 201 | return GetHeightRC(p1.y, p1.x); |
| 202 | |
| 203 | return (GetHeightRC(p1.y, p1.x) * (p2.x - ll.m_lon) * (p2.y - ll.m_lat) + |
| 204 | GetHeightRC(p1.y, p2.x) * (ll.m_lon - p1.x) * (p2.y - ll.m_lat) + |
| 205 | GetHeightRC(p2.y, p1.x) * (p2.x - ll.m_lon) * (ll.m_lat - p1.y) + |
| 206 | GetHeightRC(p2.y, p2.x) * (ll.m_lon - p1.x) * (ll.m_lat - p1.y)) / |
| 207 | denom; |
| 208 | } |
| 209 | |
| 210 | // static |
| 211 | std::string SrtmTile::GetPath(std::string const & dir, std::string const & base) |