using EarthQuake.Core; using EarthQuake.Map.Tiles.Vector; using SkiaSharp; namespace EarthQuake.Map.Layers; /// /// マップタイルのうち、地表を描画するレイヤー /// /// public class VectorMapLandLayer(VectorMapLayer baseLayer) : VectorMapLayer(null, baseLayer.Land) { public override void Render(SKCanvas canvas, float scale, SKRect bounds) { if (Controller is null) return; var origin = GeomTransform.TranslateToNonTransform(bounds.Left, bounds.Top); VectorTilesController.GetXyzTile(origin, Math.Min(Header?.MaxZoom ?? 15, Math.Max(Header?.MinZoom ?? 5, (int)Math.Log2(scale) + 5)), out var point); VectorTilesController.GetXyzTileFromLatLon(Header?.MinLon ?? 0, Header?.MaxLat ?? 0, point.Z, out var leftTop); VectorTilesController.GetXyzTileFromLatLon(Header?.MaxLon ?? 0, Header?.MinLat ?? 0, point.Z, out var rightBottom); var zoom = (int)Math.Pow(2, point.Z); var h = (int)Math.Ceiling(bounds.Height / GeomTransform.Zoom / (GeomTransform.Height * 2f / zoom)); var w = (int)Math.Ceiling(bounds.Width / GeomTransform.Zoom / (360f / zoom)); h = Math.Min(h, zoom - point.Y); w = Math.Min(w, zoom - point.X); using var paint = new SKPaint(); paint.IsAntialias = true; paint.Typeface = Font; using var path = new SKPath(); var widthFactor = point.Z switch { < 8 => 1, < 10 => 2, < 12 => 8, _ => 14 }; // ズームするほど太くなっていっちゃうから調整 for (var j = 0; j <= h; j++) { for (var i = 0; i <= w; i++) { var currentPoint = point.Add(i, j); if (currentPoint.X < leftTop.X || currentPoint.Y < leftTop.Y || currentPoint.X > rightBottom.X || currentPoint.Y > rightBottom.Y) continue; if (!Controller.TryGetTile(currentPoint, out var tile) || tile?.Vertices is null) continue; foreach (var feature in tile.Vertices) { if (feature.Layer?.Id != Land) continue; // Land以外は別のクラスで描画する DrawLayer(canvas, scale, feature, paint, point, widthFactor, null!); } } } } private protected override void Initialize() { baseLayer.Update(); Controller = baseLayer.Controller; Header = baseLayer.Header; } }