CompareProjection::CompareProjection(const WindowProjection &projection) :corners(projection), latitude_cos(corners.top_left.latitude.fastcosine()), max_delta(SimpleSquareDistance(corners.top_left, corners.top_right, latitude_cos) / (projection.GetScreenWidth() * projection.GetScreenWidth())) { }
void RasterRenderer::ScanMap(const RasterMap &map, const WindowProjection &projection) { // Coordinates of the MapWindow center unsigned x = projection.GetScreenWidth() / 2; unsigned y = projection.GetScreenHeight() / 2; // GeoPoint corresponding to the MapWindow center GeoPoint center = projection.ScreenToGeo(x, y); // GeoPoint "next to" Gmid (depends on terrain resolution) GeoPoint neighbor = projection.ScreenToGeo(x + quantisation_pixels, y + quantisation_pixels); // Geographical edge length of pixel in the MapWindow center in meters pixel_size = M_SQRT1_2 * center.DistanceS(neighbor); // set resolution if (pixel_size < 3000) { // Data point size of the (terrain) map in meters multiplied by 256 auto map_pixel_size = map.PixelDistance(center, 1); // How many screen pixels does one data point stretch? auto q = map_pixel_size / pixel_size; /* round down to reduce slope shading artefacts (caused by RasterBuffer interpolation) */ quantisation_effective = std::max(1, (int)q); /* disable slope shading when zoomed in very near (not enough terrain resolution to make a useful slope calculation) */ if (quantisation_effective > 25) quantisation_effective = 0; } else /* disable slope shading when zoomed out very far (too tiny) */ quantisation_effective = 0; #ifdef ENABLE_OPENGL bounds = projection.GetScreenBounds().Scale(1.5); bounds.IntersectWith(map.GetBounds()); height_matrix.Fill(map, bounds, projection.GetScreenWidth() / quantisation_pixels, projection.GetScreenHeight() / quantisation_pixels, true); last_quantisation_pixels = quantisation_pixels; #else height_matrix.Fill(map, projection, quantisation_pixels, true); #endif }
void RasterRenderer::ScanMap(const RasterMap &map, const WindowProjection &projection) { // Coordinates of the MapWindow center unsigned x = projection.GetScreenWidth() / 2; unsigned y = projection.GetScreenHeight() / 2; // GeoPoint corresponding to the MapWindow center GeoPoint Gmid = projection.ScreenToGeo(x, y); // GeoPoint "next to" Gmid (depends on terrain resolution) GeoPoint Gneighbor = projection.ScreenToGeo(x + quantisation_pixels, y + quantisation_pixels); // Geographical edge length of pixel in the MapWindow center in meters pixel_size = fixed_sqrt_half * Gmid.Distance(Gneighbor); // set resolution fixed map_pixel_size = map.pixel_distance(Gmid, 1); fixed q = map_pixel_size / pixel_size; if (pixel_size < fixed(3000)) { /* round down to reduce slope shading artefacts (caused by RasterBuffer interpolation) */ quantisation_effective = std::max(1, (int)q); if (quantisation_effective > 25) /* disable slope shading when zoomed in very near (not enough terrain resolution to make a useful slope calculation) */ quantisation_effective = 0; } else /* disable slope shading when zoomed out very far (too tiny) */ quantisation_effective = 0; height_matrix.Fill(map, projection, quantisation_pixels, true); }
/** * Draws the terrain to the given canvas * @param canvas The drawing canvas * @param map_projection The Projection * @param sunazimuth Azimuth of the sun (for terrain shading) */ void TerrainRenderer::Draw(Canvas &canvas, const WindowProjection &map_projection, const Angle sunazimuth) { const bool do_water = true; const unsigned height_scale = 4; const int interp_levels = 2; const bool is_terrain = true; const bool do_shading = is_terrain && SlopeShading; const COLORRAMP *const color_ramp = &terrain_colors[TerrainRamp][0]; if (color_ramp != last_color_ramp) { raster_renderer.ColorTable(color_ramp, do_water, height_scale, interp_levels); last_color_ramp = color_ramp; } { RasterTerrain::Lease map(*terrain); raster_renderer.ScanMap(map, map_projection); } raster_renderer.GenerateImage(is_terrain, do_shading, height_scale, TerrainContrast, TerrainBrightness, sunazimuth); CopyTo(canvas, map_projection.GetScreenWidth(), map_projection.GetScreenHeight()); }
void TransparentRendererCache::AlphaBlendTo(Canvas &canvas, const WindowProjection &projection, uint8_t alpha) const { assert(canvas.IsDefined()); assert(buffer.IsDefined()); assert(projection.IsValid()); assert(compare_projection.IsDefined()); assert(Check(projection)); if (empty) return; const unsigned width = projection.GetScreenWidth(), height = projection.GetScreenHeight(); #ifdef USE_MEMORY_CANVAS canvas.AlphaBlendNotWhite(0, 0, width, height, buffer, 0, 0, width, height, alpha); #else canvas.AlphaBlend(0, 0, width, height, buffer, 0, 0, width, height, alpha); #endif }
bool TransparentRendererCache::Check(const WindowProjection &projection) const { assert(projection.IsValid()); return buffer.IsDefined() && buffer.GetWidth() == projection.GetScreenWidth() && buffer.GetHeight() == projection.GetScreenHeight() && compare_projection.Compare(projection); }
void TransparentRendererCache::CopyAndTo(Canvas &canvas, const WindowProjection &projection) const { if (empty) return; canvas.CopyAnd(0, 0, projection.GetScreenWidth(), projection.GetScreenHeight(), buffer, 0, 0); }
void HeightMatrix::Fill(const RasterMap &map, const WindowProjection &projection, unsigned quantisation_pixels, bool interpolate) { const unsigned screen_width = projection.GetScreenWidth(); const unsigned screen_height = projection.GetScreenHeight(); SetSize((screen_width + quantisation_pixels - 1) / quantisation_pixels, (screen_height + quantisation_pixels - 1) / quantisation_pixels); minimum = 0x7fff; maximum = 0; for (unsigned y = 0; y < screen_height; y += quantisation_pixels) { const FastRowRotation rotation = projection.GetScreenAngleRotation(y - projection.GetScreenOrigin().y); short *p = data.begin() + y * width / quantisation_pixels; for (unsigned x = 0; x < screen_width; x += quantisation_pixels) { #ifndef SLOW_TERRAIN_STUFF const FastRowRotation::Pair r = rotation.Rotate(x - projection.GetScreenOrigin().x); GeoPoint gp; gp.Latitude = projection.GetGeoLocation().Latitude - projection.PixelsToAngle(r.second); gp.Longitude = projection.GetGeoLocation().Longitude + projection.PixelsToAngle(r.first) * gp.Latitude.invfastcosine(); #else GeoPoint gp = projection.ScreenToGeo(x, y); #endif short h = interpolate ? map.GetFieldInterpolated(gp) : map.GetField(gp); if (!RasterBuffer::is_special(h)) { if (h < minimum) minimum = h; if (h > maximum) maximum = h; } *p++ = h; } assert(p <= data.end()); } }
/** * Draws the terrain to the given canvas * @param canvas The drawing canvas * @param map_projection The Projection * @param sunazimuth Azimuth of the sun (for terrain shading) */ void TerrainRenderer::Draw(Canvas &canvas, const WindowProjection &map_projection) const { #ifdef ENABLE_OPENGL const GeoBounds &bounds = raster_renderer.GetBounds(); assert(bounds.IsValid()); const RasterPoint vertices[] = { map_projection.GeoToScreen(bounds.GetNorthWest()), map_projection.GeoToScreen(bounds.GetNorthEast()), map_projection.GeoToScreen(bounds.GetSouthWest()), map_projection.GeoToScreen(bounds.GetSouthEast()), }; glVertexPointer(2, GL_VALUE, 0, vertices); const GLTexture &texture = raster_renderer.BindAndGetTexture(); const PixelSize allocated = texture.GetAllocatedSize(); const int src_x = 0, src_y = 0, src_width = raster_renderer.GetWidth(), src_height = raster_renderer.GetHeight(); GLfloat x0 = (GLfloat)src_x / allocated.cx; GLfloat y0 = (GLfloat)src_y / allocated.cy; GLfloat x1 = (GLfloat)(src_x + src_width) / allocated.cx; GLfloat y1 = (GLfloat)(src_y + src_height) / allocated.cy; const GLfloat coord[] = { x0, y0, x1, y0, x0, y1, x1, y1, }; OpenGL::glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); GLEnable scope(GL_TEXTURE_2D); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(2, GL_FLOAT, 0, coord); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glDisableClientState(GL_TEXTURE_COORD_ARRAY); #else CopyTo(canvas, map_projection.GetScreenWidth(), map_projection.GetScreenHeight()); #endif }
void RasterRenderer::ScanMap(const RasterMap &map, const WindowProjection &projection) { unsigned x = projection.GetScreenWidth() / 2; unsigned y = projection.GetScreenHeight() / 2; GeoPoint Gmid = projection.ScreenToGeo(x, y); pixel_size = fixed_sqrt_half * Distance(Gmid, projection.ScreenToGeo(x + quantisation_pixels, y + quantisation_pixels)); // set resolution fixed map_pixel_size = map.pixel_distance(Gmid, 1); quantisation_effective = (int)ceil(map_pixel_size / pixel_size); height_matrix.Fill(map, projection, quantisation_pixels, pixel_size * 3 < map_pixel_size * 2); }
CompareProjection::FourCorners::FourCorners(const WindowProjection &projection) :top_left(projection.ScreenToGeo(0, 0)), top_right(projection.ScreenToGeo(projection.GetScreenWidth(), 0)), bottom_left(projection.ScreenToGeo(0, projection.GetScreenHeight())), bottom_right(projection.ScreenToGeo(projection.GetScreenWidth(), projection.GetScreenHeight())) {}
CompareProjection::FourCorners::FourCorners(const WindowProjection &projection) :GeoQuadrilateral{projection.ScreenToGeo(0, 0), projection.ScreenToGeo(projection.GetScreenWidth(), 0), projection.ScreenToGeo(0, projection.GetScreenHeight()), projection.ScreenToGeo(projection.GetScreenWidth(), projection.GetScreenHeight())} {}
void WeatherTerrainRenderer::Draw(Canvas &canvas, const WindowProjection &projection, const Angle sunazimuth) { bool do_water = false; unsigned height_scale; const int interp_levels = 5; const bool is_terrain = false; const bool do_shading = is_terrain; const COLORRAMP *color_ramp; switch (weather->GetParameter()) { case 1: // wstar height_scale = 2; // max range 256*(2**2) = 1024 cm/s = 10 m/s color_ramp = &weather_colors[0][0]; break; case 2: // bl wind spd height_scale = 3; color_ramp = &weather_colors[1][0]; break; case 3: // hbl height_scale = 4; color_ramp = &weather_colors[2][0]; break; case 4: // dwcrit height_scale = 4; color_ramp = &weather_colors[2][0]; break; case 5: // blcloudpct do_water = true; height_scale = 0; color_ramp = &weather_colors[3][0]; break; case 6: // sfctemp height_scale = 0; color_ramp = &weather_colors[4][0]; break; case 7: // hwcrit height_scale = 4; color_ramp = &weather_colors[2][0]; break; case 8: // wblmaxmin height_scale = 1; // max range 256*(1**2) = 512 cm/s = 5.0 m/s color_ramp = &weather_colors[5][0]; break; case 9: // blcwbase height_scale = 4; color_ramp = &weather_colors[2][0]; break; default: TerrainRenderer::Draw(canvas, projection, sunazimuth); return; } const RasterMap *map = weather->GetMap(); if (map == NULL) { TerrainRenderer::Draw(canvas, projection, sunazimuth); return; } if (color_ramp != last_color_ramp) { raster_renderer.ColorTable(color_ramp, do_water, height_scale, interp_levels); last_color_ramp = color_ramp; } raster_renderer.ScanMap(*map, projection); raster_renderer.GenerateImage(is_terrain, do_shading, height_scale, TerrainContrast, TerrainBrightness, sunazimuth); CopyTo(canvas, projection.GetScreenWidth(), projection.GetScreenHeight()); ScanSpotHeights(); }