public override Bitmap Fill(TileTreeNode n) { var stride = n.Stride; var demFirstY = n.Y * Height * n.Stride; var demFirstX = n.X * Width * n.Stride; Console.WriteLine($"PSRFiller X={n.X} Y={n.Y} Stride={n.Stride} demFirstY={demFirstY} demFirstX={demFirstX}"); var bitmap = n._bitmap ?? new Bitmap(Width, Height, PixelFormat.Format32bppArgb); var bitmapData = bitmap.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); unsafe { for (var iy = 0; iy < Height; iy++) { var rowptr = (byte *)(bitmapData.Scan0 + iy * bitmapData.Stride); for (var ix = 0; ix < Width; ix++) { var val = ImgFile.ReadByte(demFirstY + iy * stride, demFirstX + ix * stride); *(rowptr++) = val; // B *(rowptr++) = val; // G *(rowptr++) = val; // R *(rowptr++) = 255; // A } } } bitmap.UnlockBits(bitmapData); return(bitmap); }
public override Bitmap Fill(TileTreeNode n) { if (StabilityTileGenerator == null) { lock (StabilityTileGeneratorLock) { if (StabilityTileGenerator == null) { var generator = new IceStabilityTileGenerator(); generator.Load(); StabilityTileGenerator = generator; } } } var demFirstY = n.Y * Height * n.Stride; var demFirstX = n.X * Width * n.Stride; Console.WriteLine($"IceStabilityFiller X={n.X} Y={n.Y} Stride={n.Stride} demFirstY={demFirstY} demFirstX={demFirstX}"); lock (StabilityTileGeneratorLock) { var bitmap = new Bitmap(Width, Height, PixelFormat.Format32bppArgb); using (var g = Graphics.FromImage(bitmap)) { g.ScaleTransform(1f / n.Stride, 1f / n.Stride); g.TranslateTransform(-demFirstX, -demFirstY); StabilityTileGenerator.Draw(g, new Rectangle(demFirstX, demFirstY, Width * n.Stride, Height * n.Stride)); } return(bitmap); } }
/// <summary> /// Fetch a node. Create one if it's not already there. /// </summary> /// <param name="a">An address</param> /// <returns></returns> public TileTreeNode Fetch(int a) { if (_tileCache.TryGetValue(a, out TileTreeNode r)) { return(r); } r = new TileTreeNode(a, _CacheDirectory); _tileCache.Add(a, r); return(r); }
public override Bitmap Fill(TileTreeNode n) { var stride = n.Stride; var demFirstY = n.Y * Height * n.Stride; var demFirstX = n.X * Width * n.Stride; Console.WriteLine($"SlopeFiller isNorth={InMemoryTerrainManager.Singleton.IsNorth} X={n.X} Y={n.Y} Stride={n.Stride} demFirstY={demFirstY} demFirstX={demFirstX}"); var dem = new short[Height, Width]; var terrain = InMemoryTerrainManager.Singleton; for (var iy = 0; iy < Height; iy++) { for (var ix = 0; ix < TileTreeNode.Width; ix++) { dem[iy, ix] = terrain.Fetch(demFirstY + iy * stride, demFirstX + ix * stride); } } var bitmap = n._bitmap ?? new Bitmap(TileTreeNode.Width, TileTreeNode.Height, PixelFormat.Format32bppArgb); var green = Color.FromArgb(255, Color.PaleGreen).ToArgb(); var yellow = Color.FromArgb(255, Color.LightGoldenrodYellow).ToArgb(); var red = Color.FromArgb(255, Color.IndianRed).ToArgb(); var bitmapData = bitmap.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); unsafe { for (var y = 0; y < Height; y++) { var rowptr = (Int32 *)(bitmapData.Scan0 + y * bitmapData.Stride); for (var x = 0; x < Width; x++) { var slope = SlopesForHillshade(x, y, dem, Width, Height, 20f * stride); var angle_deg = Math.Atan(slope) * 180d / Math.PI; if (angle_deg <= 11d) // matches the round-down in the traverse planner. { *(rowptr++) = green; } else if (angle_deg <= 16d) { *(rowptr++) = yellow; } else { *(rowptr++) = red; } } } } bitmap.UnlockBits(bitmapData); return(bitmap); }
public void Draw(Graphics g, DisplayTransform t, ImageAttributes attributes = null) { var r = g.ClipBounds; //Console.WriteLine($"-- clipbounds={r}"); // Scale indicates the number of map pixels per screen pixel. // OffsetX and OffsetY indicate the offset of the window origin relative to the upper left // corner of the tile array at the current level. var level = (int)(Math.Log(t.Scale) / Log2); // Log2(Scale); level = Math.Min(TileTreeNode.TopLevel, Math.Max(0, level)); // Clip level var stride = TileTreeNode.PowersOf2[level]; var drawScale = t.Scale / stride; // range = [1,2) var cellSize = (int)(TileTreeNode.Width / drawScale); // range = (475, 950], width==height var cellMax = TileTreeNode.MapWidth / (TileTreeNode.Width * stride); var x1 = Math.Max(0, -t.OffsetX / cellSize - 1); var y1 = Math.Max(0, -t.OffsetY / cellSize - 1); var x2 = cellMax - 1; var y2 = cellMax - 1; for (var y = y1; y <= y2; y++) { var pixelY = t.OffsetY + y * cellSize; if (pixelY > r.Bottom) { //Console.WriteLine($" break pixelY {pixelY} > r.Bottom {r.Bottom}"); break; } for (var x = x1; x <= x2; x++) { var pixelX = t.OffsetX + x * cellSize; if (pixelX > r.Right) { //Console.WriteLine($" break pixelX {pixelX} > r.Right {r.Right}"); break; } //Console.WriteLine($" drawing x={pixelX} y={pixelY} x={x} y={y} width={r.Width} height={r.Height}"); var address = TileTreeNode.CalculateAddress(level, x, y); var cell = Fetch(address); var bitmap = Filler != null?cell.GenerateBitmap(Filler) : null; if (bitmap != null) { var r1 = new Rectangle(pixelX, pixelY, cellSize, cellSize); if (attributes == null) { g.DrawImage(bitmap, r1); } else { g.DrawImage(bitmap, r1, 0, 0, bitmap.Width, bitmap.Height, GraphicsUnit.Pixel, attributes); } } else { if (attributes == null) { g.FillRectangle(Brushes.DarkGray, pixelX, pixelY, cellSize, cellSize); } } } } }
public override Bitmap Fill(TileTreeNode n) { var stride = n.Stride; const double elevation = 30d * Math.PI / 180d; const double azimuth = -Math.PI / 2; var Zenith_rad = Math.PI / 2d - elevation; var Azimuth_rad = Math.PI - azimuth; // Convert from map azimuth to hillshade azimuth var demFirstY = n.Y * Height * n.Stride; var demFirstX = n.X * Width * n.Stride; Console.WriteLine($"HillshadeFiller isNorth={InMemoryTerrainManager.Singleton.IsNorth} X={n.X} Y={n.Y} Stride={n.Stride} demFirstY={demFirstY} demFirstX={demFirstX}"); var dem = new short[Height, Width]; var terrain = InMemoryTerrainManager.Singleton; for (var iy = 0; iy < Height; iy++) { for (var ix = 0; ix < TileTreeNode.Width; ix++) { dem[iy, ix] = terrain.Fetch(demFirstY + iy * stride, demFirstX + ix * stride); } } var bitmap = n._bitmap != null ? n._bitmap : new Bitmap(TileTreeNode.Width, TileTreeNode.Height, PixelFormat.Format8bppIndexed); var palette = bitmap.Palette; for (var i = 0; i < 256; i++) { palette.Entries[i] = Color.FromArgb(i, i, i); } bitmap.Palette = palette; var bitmapData = bitmap.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed); unsafe { for (var y = 0; y < Height; y++) { var rowptr = (byte *)(bitmapData.Scan0 + y * bitmapData.Stride); for (var x = 0; x < Width; x++) { SlopesForHillshade(x, y, dem, Width, Height, 20f * stride, out float dzdx, out float dzdy); double Aspect_rad; if (dzdx != 0f) { Aspect_rad = Math.Atan2(dzdy, -dzdx); if (Aspect_rad < 0f) { Aspect_rad = Math.PI * 2d + Aspect_rad; } } else { if (dzdy > 0f) { Aspect_rad = Math.PI / 2d; } else if (dzdy < 0) { Aspect_rad = 1.5d * Math.PI; } else { Aspect_rad = 0d; } } // Should be this. There's some inversion in the slopes (I think) //const double z_factor = 1d; //var Slope_rad = Math.Atan(z_factor * Math.Sqrt(dzdx * dzdx + dzdy * dzdy)); var Slope_rad = -Math.Atan(Math.Sqrt(dzdx * dzdx + dzdy * dzdy)); var Hillshade = (Math.Cos(Zenith_rad) * Math.Cos(Slope_rad)) + (Math.Sin(Zenith_rad) * Math.Sin(Slope_rad) * Math.Cos(Azimuth_rad - Aspect_rad)); Hillshade = Math.Max(0d, Hillshade); *(rowptr++) = (byte)(255 * Hillshade); } } } bitmap.UnlockBits(bitmapData); return(bitmap); }
abstract public Bitmap Fill(TileTreeNode n);