| 135 | } |
| 136 | |
| 137 | double SrtmTile::GetTriangleHeight(ms::LatLon const & coord) const |
| 138 | { |
| 139 | if (!IsValid()) |
| 140 | return geometry::kInvalidAltitude; |
| 141 | |
| 142 | auto const ll = GetCoordInSeconds(coord); |
| 143 | |
| 144 | m2::Point<int> const p1(std::lround(ll.m_lon), std::lround(ll.m_lat)); |
| 145 | |
| 146 | auto p2 = p1; |
| 147 | if (p2.x > ll.m_lon) |
| 148 | { |
| 149 | if (p2.x > 0) |
| 150 | --p2.x; |
| 151 | } |
| 152 | else if (p2.x < ll.m_lon) |
| 153 | { |
| 154 | if (p2.x < kArcSecondsInDegree) |
| 155 | ++p2.x; |
| 156 | } |
| 157 | |
| 158 | auto p3 = p1; |
| 159 | if (p3.y > ll.m_lat) |
| 160 | { |
| 161 | if (p3.y > 0) |
| 162 | --p3.y; |
| 163 | } |
| 164 | else if (p3.y < ll.m_lat) |
| 165 | { |
| 166 | if (p3.y < kArcSecondsInDegree) |
| 167 | ++p3.y; |
| 168 | } |
| 169 | |
| 170 | // Approximate height from triangle p1, p2, p3. |
| 171 | // p1.y == p2.y; p1.x == p3.x |
| 172 | // https://stackoverflow.com/questions/36090269/finding-height-of-point-on-height-map-triangles |
| 173 | int const det = (p2.y - p3.y) * (p1.x - p3.x) + (p3.x - p2.x) * (p1.y - p3.y); |
| 174 | if (det == 0) |
| 175 | return GetHeightRC(p1.y, p1.x); |
| 176 | |
| 177 | double const a1 = ((p2.y - p3.y) * (ll.m_lon - p3.x) + (p3.x - p2.x) * (ll.m_lat - p3.y)) / det; |
| 178 | double const a2 = ((p3.y - p1.y) * (ll.m_lon - p3.x) + (p1.x - p3.x) * (ll.m_lat - p3.y)) / det; |
| 179 | double const a3 = 1 - a1 - a2; |
| 180 | |
| 181 | return a1 * GetHeightRC(p1.y, p1.x) + a2 * GetHeightRC(p2.y, p2.x) + a3 * GetHeightRC(p3.y, p3.x); |
| 182 | } |
| 183 | |
| 184 | double SrtmTile::GetBilinearHeight(ms::LatLon const & coord) const |
| 185 | { |