public void TestCustemProjection() { var services = new ServiceCollection(); services.AddSingleton <ILoggerFactory>(new LoggerFactory().AddConsole(LogLevel.Trace)); services.AddNodeServices((o) => { o.ProjectPath = PlatformServices.Default.Application.ApplicationBasePath + "/../../.."; }); var serviceProvider = services.BuildServiceProvider(); var node = serviceProvider.GetService <INodeServices>(); var p1 = new[] { 12.62929948218958, 55.661805096493985 }; var proj4Str = $"+proj=tmerc +lat_0={p1[1]} +lon_0={p1[0]} +x_0=0 +y_0=0 +towgs84=0,0,0,0,0,0,0 +units=m +vunits=m +no_defs"; var extent = new[] { -20000.0, -20000, 20000, 20000 }; var tileConverter = new VectorTileConverter(new VectorTileConverterOptions { CoordinateTransform = async(p) => { var local = await node.InvokeAsync <double[]>("./proj4", "EPSG:4326", proj4Str, p); return(new double[] { (local[0] - extent[0]) / (extent[2] - extent[0]), -(local[1] - extent[3]) / (extent[3] - extent[1]), 0 }); } }); var p2 = tileConverter.ProjectPoint(p1); Assert.AreEqual(0.5, p2[0], 10e-6, $"X {nameof(TestCustemProjection)} expected to be 0.5"); Assert.AreEqual(0.5, p2[1], 10e-6, $"Y {nameof(TestCustemProjection)} expected to be 0.5"); { var bottomLeft = tileConverter.ProjectPoint(node.InvokeAsync <double[]>("./proj4", proj4Str, "EPSG:4326", new[] { extent[0], extent[1] }).GetAwaiter().GetResult()); Assert.AreEqual(0, bottomLeft[0], 10e-6, $"X {nameof(TestCustemProjection)} {nameof(bottomLeft)} expected to be 0"); Assert.AreEqual(1, bottomLeft[1], 10e-6, $"Y {nameof(TestCustemProjection)} {nameof(bottomLeft)} expected to be 1"); } { var topLeft = tileConverter.ProjectPoint(node.InvokeAsync <double[]>("./proj4", proj4Str, "EPSG:4326", new[] { extent[0], extent[3] }).GetAwaiter().GetResult()); Assert.AreEqual(0, topLeft[0], 10e-6, $"X {nameof(TestCustemProjection)} {nameof(topLeft)} expected to be 0"); Assert.AreEqual(0, topLeft[1], 10e-6, $"Y {nameof(TestCustemProjection)} {nameof(topLeft)} expected to be 0"); } { var topRight = tileConverter.ProjectPoint(node.InvokeAsync <double[]>("./proj4", proj4Str, "EPSG:4326", new[] { extent[2], extent[3] }).GetAwaiter().GetResult()); Assert.AreEqual(1, topRight[0], 10e-6, $"X {nameof(TestCustemProjection)} {nameof(topRight)} expected to be 1"); Assert.AreEqual(0, topRight[1], 10e-6, $"Y {nameof(TestCustemProjection)} {nameof(topRight)} expected to be 0"); } { var bottomRight = tileConverter.ProjectPoint(node.InvokeAsync <double[]>("./proj4", proj4Str, "EPSG:4326", new[] { extent[2], extent[1] }).GetAwaiter().GetResult()); Assert.AreEqual(1, bottomRight[0], 10e-6, $"X {nameof(TestCustemProjection)} {nameof(bottomRight)} expected to be 1"); Assert.AreEqual(1, bottomRight[1], 10e-6, $"Y {nameof(TestCustemProjection)} {nameof(bottomRight)} expected to be 1"); } }
public GeoJsonVectorTiles(ILoggerFactory loggerFactory, T options = null, VectorTileConverter converter = null, VectorTileWrapper wrapper = null, VectorTileClipper clipper = null, VectorTileTransformer transformer = null) { Logger = loggerFactory.CreateLogger <GeoJsonVectorTiles <T> >(); Converter = converter ?? new VectorTileConverter(); Clipper = clipper ?? new VectorTileClipper(); Wrapper = wrapper ?? new VectorTileWrapper(Clipper); Options = options ?? new T(); Transformer = transformer ?? new VectorTileTransformer(); Tiles = Options.Tiles ?? new DefaultTileStore(); }
public void TestBottomRightLatLng() { var tileConverter = new VectorTileConverter(); var p1 = new[] { 180.0, -90.0 }; var p2 = tileConverter.ProjectPoint(p1); Assert.AreEqual(1, p2[0], $"Longtitude {nameof(TestBottomRightLatLng)} Test expected to be 1"); Assert.AreEqual(1, p2[1], $"Latitude {nameof(TestBottomRightLatLng)} expected to be 1"); }
public void TestTopLeftLatLng() { var tileConverter = new VectorTileConverter(); var p1 = new[] { -180.0, 90.0 }; var p2 = tileConverter.ProjectPoint(p1); Assert.AreEqual(0, p2[0], $"Longtitude {nameof(TestTopLeftLatLng)} Test expected to be 0"); Assert.AreEqual(0, p2[1], $"Latitude {nameof(TestTopLeftLatLng)} expected to be 0"); }
private static async Task RunAsync(string[] args, CancellationToken cannelcationtoken) { var services = new ServiceCollection(); services.AddSingleton <ILoggerFactory>(new LoggerFactory().AddConsole(LogLevel.Trace)); services.AddTransient <GeoJsonVectorTiles <GeoJsonVectorTilesOptions> >(); services.AddNodeServices((o) => { o.ProjectPath = Directory.GetCurrentDirectory(); // PlatformServices.Default.Application.ApplicationBasePath + "/../../.."; }); var serviceProvider = services.BuildServiceProvider(); var node = serviceProvider.GetService <INodeServices>(); var logger = serviceProvider.GetService <ILoggerFactory>().CreateLogger <Program>(); var proj4Str = args[Array.IndexOf(args, "--proj") + 1]; var extent = args.Skip(Array.IndexOf(args, "--extent") + 1).Take(4).Select(double.Parse).ToArray(); var maxZoom = 0; var max = (extent[2] - extent[0]) / 4096.0; while (max > 0.01) { max /= 2; maxZoom++; } maxZoom = 22; var tileConverter = new VectorTileConverter(new VectorTileConverterOptions { CoordinateTransform = async(p) => { var local = await node.InvokeAsync <double[]>("./proj4", "EPSG:4326", proj4Str, p); return(new double[] { (local[0] - extent[0]) / (extent[2] - extent[0]), -(local[1] - extent[3]) / (extent[3] - extent[1]), 0 }); } }); services.AddSingleton(new GeoJsonVectorTilesOptions() { MaxZoom = maxZoom }); services.AddSingleton(tileConverter); serviceProvider = services.BuildServiceProvider(); var points = File.ReadAllText(args[0]); var featureCollection = JsonConvert.DeserializeObject <GeoJsonObject>(points, new GeoJsonObjectConverter()) as GeoJsonFeatureCollection; var processor = serviceProvider.GetRequiredService <GeoJsonVectorTiles <GeoJsonVectorTilesOptions> >(); processor.ProcessData(featureCollection); var q = new Queue <VectorTileCoord>(); q.Enqueue(new VectorTileCoord(0, 0, 0)); while (q.Any()) { var tileCoord = q.Dequeue(); var tile = processor.GetTile(tileCoord.Z, tileCoord.X, tileCoord.Y); if (tile != null && tileCoord.Z < maxZoom && tile.Features.Count > 10) { logger.LogInformation("[{tileZ},{tileX},{tileY}] : Finding clusters for {featureCount}", tileCoord.Z, tileCoord.X, tileCoord.Y, tile.Features.Count); List <ClusterId> centers = GetCenters(tile); logger.LogInformation("[{tileZ},{tileX},{tileY}] : {clusterCount}|{singlePointCount} clusters found for {featureCount} features", tileCoord.Z, tileCoord.X, tileCoord.Y, centers.Count, centers.Count(c => c.Features.Count == 1), tile.Features.Count); if (centers.Any() && centers.Count < tile.Features.Count) { foreach (var child in tileCoord.GetChildCoordinate()) { q.Enqueue(child); } } tile.Features = new List <VectorTileFeature>(); foreach (var center in centers) { if (center.Features.Count == 1) { tile.Features.AddRange(center.Features); } else { tile.Features.Add(new VectorTileFeature { Type = 1, Geometry = new VectorTileGeometry() { new[] { Math.Round(center.Features.Average(f => f.GetPoints().First()[0])), Math.Round(center.Features.Average(f => f.GetPoints().First()[1])) } }, Tags = new Dictionary <string, object> { { "clusterId", Guid.NewGuid().ToString() }, { "count", center.Features.Count } } }); } } } // tile = tile ?? new VectorTile { X = tileCoord.X, Y = tileCoord.Y, Z2 = 1 << tileCoord.Z, Features = new List<VectorTileFeature>(), Transformed = true }; if (tile != null) { logger.LogInformation("[{tileZ},{tileX},{tileY}] : Writing tile with {featureCount}", tileCoord.Z, tileCoord.X, tileCoord.Y, tile.Features.Count); var file = $"{args[1]}/{tileCoord.Z}/{tileCoord.X}/{tileCoord.Y}.vector.pbf"; Directory.CreateDirectory(Path.GetDirectoryName(file)); var stream = await node.InvokeAsync <NodeBuffer>("./topbf", new VectorTile { Features = tile.Features, X = tile.X, Y = tile.Y, Z2 = tile.Z2, Transformed = tile.Transformed }, file); // File.WriteAllBytes(file+".pbf", stream.Data); // return; } } }
static async Task Main(string[] args) { var host = new WebHostBuilder() .UseKestrel() .ConfigureServices((ctx, appservices) => { appservices.AddMvc(); }) .Configure(app => { app.UseDeveloperExceptionPage(); //app.UseDirectoryBrowser(new DirectoryBrowserOptions //{ // FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "tmp")), //}); app.UseStaticFiles(new StaticFileOptions { FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "tmp")), ServeUnknownFileTypes = true, ContentTypeProvider = new FileExtensionContentTypeProvider(new Dictionary <string, string> { { ".vector.pdf", "vectorfile" } }) }); app.UseMvc(); }) .Build(); await host.RunAsync(); var services = new ServiceCollection(); services.AddSingleton(new LoggerFactory().AddConsole(LogLevel.Trace)); services.AddTransient <GeoJsonVectorTiles <GeoJsonVectorTilesOptions> >(); services.AddNodeServices((o) => { o.ProjectPath = Directory.GetCurrentDirectory(); // PlatformServices.Default.Application.ApplicationBasePath + "/../../.."; }); var maxZoom = 6; var serviceProvider = services.BuildServiceProvider(); var node = serviceProvider.GetService <INodeServices>(); var logger = serviceProvider.GetService <ILoggerFactory>().CreateLogger <Program>(); var tileConverter = new VectorTileConverter(); services.AddSingleton(new GeoJsonVectorTilesOptions() { MaxZoom = maxZoom, Buffer = 256 }); services.AddSingleton(tileConverter); serviceProvider = services.BuildServiceProvider(); var points = File.ReadAllText(args[0]); var featureCollection = JsonConvert.DeserializeObject <GeoJsonObject>(points, new GeoJsonObjectConverter()) as GeoJsonFeatureCollection; // featureCollection.Features = featureCollection.Features.Where(f => f.Geometry is Polygon).ToArray(); foreach (var feature in featureCollection.Features) { feature.Properties = new Dictionary <string, object> { { "tileId", Regex.Replace(feature.Properties["_font_COLOR_000000_TILE_ID_font"] as string, "<[^>]+>", string.Empty) } }; } // var pointsList = new PointsList(); // var features = featureCollection.Features.Where(f => f.Geometry is Point).ToArray(); // for (uint i = 0; i < features.Length; i++) // { // pointsList.AddPoint(i, (features[i].Geometry as Point).Coordinates); // } // double maxRadius = 0.1; // int minPoints = features.Length / 25; // var optics = new OPTICS(maxRadius, minPoints, pointsList); // optics.BuildReachability(); // var reachablity = optics.ReachabilityPoints().GroupBy(k => k.Reachability); //var featuresList = new List<GeoJsonFeature>(); // foreach (var item in reachablity) // { // Console.WriteLine($"{item.Key}: {item.Count()} - {string.Join(",", item.Select(k => k.PointId))}"); // var hull = t.ComputeConvexHull(item.Select(k => features[k.PointId]).Select(k => (k.Geometry as Point).Coordinates)); // featuresList.Add(new GeoJsonFeature // { // //Type = 3, // Geometry = new Polygon { Coordinates = new double[][][] { hull.ToArray() } }, // Properties = new Dictionary<string, object> // { // { "tileId", Math.Round( item.Key,2)}, // {"count", item.Count() } // } // }); // // Console.WriteLine(item.PointId + ";" + item.Reachability); // } // featureCollection.Features = featuresList.ToArray(); //var clusters = featureCollection.Features.Where(f => f.Geometry is Polygon).GroupBy(f => (f.Properties["tileId"] as string).Substring(0, 3)); //var fl = new List<GeoJsonFeature>(); //foreach (var cluster in clusters) //{ // var b = cluster.SelectMany(c => (c.Geometry as Polygon).Coordinates[0]); // var meanX = b.Select(b1 => b1[0]).Average(); // var meanY = b.Select(b1 => b1[1]).Average(); // fl.Add(new GeoJsonFeature { // Geometry = new Point { Coordinates= new double[] { meanX,meanY} } , // Properties = new Dictionary<string, object> { { "tileId", cluster.Key },{ "label",true } } } ); //} // featureCollection.Features = featureCollection.Features.Concat(fl).ToArray(); var processor = serviceProvider.GetRequiredService <GeoJsonVectorTiles <GeoJsonVectorTilesOptions> >(); processor.ProcessData(featureCollection); var q = new Queue <VectorTileCoord>(); q.Enqueue(new VectorTileCoord(0, 0, 0)); while (q.Any()) { var tileCoord = q.Dequeue(); var tile = processor.GetTile(tileCoord.Z, tileCoord.X, tileCoord.Y); if (tile != null) { if (tileCoord.Z < maxZoom) { if (tile.Features.Count > 0) { foreach (var child in tileCoord.GetChildCoordinate()) { q.Enqueue(child); } } } if (tile.Features.Count > 25) { } // var groups = tile.Features.Where(f=>f.Type == 3).GroupBy(f => (f.Tags["tileId"] as string).Substring(0, 3)); //if (tile.NumPoints > 512) //{ // tile.Features = tile.Features.Where(f => f.Type == 1 && f.Tags.ContainsKey("label")).ToList(); // foreach (var group in groups) // { // var hull = t.ComputeConvexHull(group.SelectMany(k => k.GetRings().SelectMany(m => m))); // tile.Features.Add(new VectorTileFeature // { // Type = 3, // Geometry = new[] { new VectorTileGeometry(hull) }, // Tags = new Dictionary<string, object> // { // { "tileId", group.Key}, // {"count", group.Count() } // } // }); // } //} logger.LogInformation("[{tileZ},{tileX},{tileY}] : Writing tile with {featureCount}", tileCoord.Z, tileCoord.X, tileCoord.Y, tile.Features.Count); var file = $"{args[1]}/{tileCoord.Z}/{tileCoord.X}/{tileCoord.Y}.vector.pbf"; Directory.CreateDirectory(Path.GetDirectoryName(file)); var stream = await node.InvokeAsync <NodeBuffer>("./topbf", new VectorTile { Features = tile.Features, X = tile.X, Y = tile.Y, Z2 = tile.Z2, Transformed = tile.Transformed }, file); // File.WriteAllBytes(file+".pbf", stream.Data); // return; } } }