Skip to content

add enable_zoom_feature option #222

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,8 @@ If --username and/or --dbname are not specified the current username is used as

--skip_create_tiles (Default: false) Skip creating tiles (Cesium)

--enable_zoom_features (Default: false) Creates extra tiles on lower zoom levels containing larger features (Cesium)

--zoom (Default: 15) Zoom level (Mapbox)

--help Display this help screen.
Expand Down
4 changes: 2 additions & 2 deletions src/b3dm.tileset/CesiumTiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
namespace B3dm.Tileset;
public static class CesiumTiler
{
public static void CreateImplicitTileset(Version version, bool createGltf, string outputDirectory, double[] translation, double geometricError, double[] rootBoundingVolumeRegion, string subtreesDirectory, List<Tile> tiles, string tilesetVersion="")
public static void CreateImplicitTileset(Version version, bool createGltf, string outputDirectory, double[] translation, double geometricError, double[] rootBoundingVolumeRegion, string subtreesDirectory, List<Tile> tiles, string tilesetVersion="", string refinement="")
{
if (!Directory.Exists(subtreesDirectory)) {
Directory.CreateDirectory(subtreesDirectory);
Expand All @@ -28,7 +28,7 @@ public static void CreateImplicitTileset(Version version, bool createGltf, strin
var availableLevels = tiles.Max(t => t.Z) + 1;
Console.WriteLine("Available Levels: " + availableLevels);
Console.WriteLine("Subtree Levels: " + subtreeLevels);
var tilesetjson = TreeSerializer.ToImplicitTileset(translation, rootBoundingVolumeRegion, geometricError, availableLevels, subtreeLevels, version, createGltf, tilesetVersion);
var tilesetjson = TreeSerializer.ToImplicitTileset(translation, rootBoundingVolumeRegion, geometricError, availableLevels, subtreeLevels, version, createGltf, tilesetVersion, refinement);
var file = $"{outputDirectory}{Path.AltDirectorySeparatorChar}tileset.json";
var json = JsonConvert.SerializeObject(tilesetjson, Formatting.Indented, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore });
Console.WriteLine("SubdivisionScheme: QUADTREE");
Expand Down
4 changes: 2 additions & 2 deletions src/b3dm.tileset/GeometryRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,15 @@ public static double[] GetGeometriesBoundingBox(NpgsqlConnection conn, string ge
return result;
}

public static List<GeometryRecord> GetGeometrySubset(NpgsqlConnection conn, string geometry_table, string geometry_column, double[] bbox, int source_epsg, int target_srs, string shaderColumn = "", string attributesColumns = "", string query = "", string radiusColumn = "")
public static List<GeometryRecord> GetGeometrySubset(NpgsqlConnection conn, string geometry_table, string geometry_column, double[] bbox, int source_epsg, int target_srs, string shaderColumn = "", string attributesColumns = "", string query = "", string radiusColumn = "", string sqlPostFix = "")
{
var sqlselect = GetSqlSelect(geometry_column, shaderColumn, attributesColumns, radiusColumn, target_srs);
var sqlFrom = "FROM " + geometry_table;

var b = GetTileBoundingBox(bbox);

var sqlWhere = GetWhere(geometry_column, source_epsg, b.xmin, b.ymin, b.xmax, b.ymax, query);
var sql = sqlselect + sqlFrom + sqlWhere;
var sql = sqlselect + sqlFrom + sqlWhere + sqlPostFix ;

var geometries = GetGeometries(conn, shaderColumn, attributesColumns, sql, radiusColumn);
return geometries;
Expand Down
18 changes: 6 additions & 12 deletions src/b3dm.tileset/QuadtreeTiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public class QuadtreeTiler
private readonly string table;
private readonly NpgsqlConnection conn;
private readonly int source_epsg;
private readonly int target_srs;
private readonly string geometryColumn;
private readonly int maxFeaturesPerTile;
private readonly string query;
Expand All @@ -29,11 +30,12 @@ public class QuadtreeTiler
private readonly bool skipCreateTiles;
private readonly string radiusColumn;

public QuadtreeTiler(NpgsqlConnection conn, string table, int source_epsg, string geometryColumn, int maxFeaturesPerTile, string query, double[] translation, string colorColumn, string attributesColumn, string lodColumn, string outputFolder, List<int> lods, string copyright = "", bool skipCreateTiles = false, string radiusColumn = "")
public QuadtreeTiler(NpgsqlConnection conn, string table, int source_epsg, int target_srs, string geometryColumn, int maxFeaturesPerTile, string query, double[] translation, string colorColumn, string attributesColumn, string lodColumn, string outputFolder, List<int> lods, string copyright = "", bool skipCreateTiles = false, string radiusColumn = "")
{
this.table = table;
this.conn = conn;
this.source_epsg = source_epsg;
this.target_srs = target_srs;
this.geometryColumn = geometryColumn;
this.maxFeaturesPerTile = maxFeaturesPerTile;
this.query = query;
Expand Down Expand Up @@ -89,19 +91,10 @@ public List<Tile> GenerateTiles(BoundingBox bbox, Tile tile, List<Tile> tiles, i
}
}
else {

var file = $"{tile.Z}_{tile.X}_{tile.Y}";
if (lodColumn != String.Empty) {
file += $"_{lod}";
}

var ext = createGltf ? ".glb" : ".b3dm";
file += ext;
var file = TileName.GetFileName(tile, createGltf, lodColumn, lod);
Console.Write($"\rCreating tile: {file} ");
tile.ContentUri = file;

int target_srs = 4978;

byte[] bytes = null;

var geometries = GeometryRepository.GetGeometrySubset(conn, table, geometryColumn, tile.BoundingBox, source_epsg, target_srs, colorColumn, attributesColumn, where, radiusColumn);
Expand All @@ -125,7 +118,8 @@ public List<Tile> GenerateTiles(BoundingBox bbox, Tile tile, List<Tile> tiles, i
t2.BoundingBox = tile.BoundingBox;
var lodNextTiles = GenerateTiles(bbox, t2, new List<Tile>(), nextLod, addOutlines, defaultColor, defaultMetallicRoughness, doubleSided, defaultAlphaMode, createGltf);
tile.Children = lodNextTiles;
};
}
;
}

// next code is used to fix geometries that have centroid in the tile, but some parts outside...
Expand Down
21 changes: 21 additions & 0 deletions src/b3dm.tileset/TileName.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System;
using subtree;

namespace B3dm.Tileset
{
public static class TileName
{
public static string GetFileName(Tile tile, bool createGltf, string lodColumn1 = "", int? lod = null)
{
var file = $"{tile.Z}_{tile.X}_{tile.Y}";
if (lodColumn1 != String.Empty) {
file += $"_{lod}";
}

var ext = createGltf ? ".glb" : ".b3dm";
file += ext;
return file;
}

}
}
5 changes: 2 additions & 3 deletions src/b3dm.tileset/TreeSerializer.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using B3dm.Tileset.Extensions;
using subtree;
using Wkx;
Expand All @@ -10,7 +9,7 @@ namespace B3dm.Tileset;

public static class TreeSerializer
{
public static TileSet ToImplicitTileset(double[] transform, double[] box, double maxGeometricError, int availableLevels, int subtreeLevels, Version version = null, bool createGltf = false, string tilesetVersion = "")
public static TileSet ToImplicitTileset(double[] transform, double[] box, double maxGeometricError, int availableLevels, int subtreeLevels, Version version = null, bool createGltf = false, string tilesetVersion = "", string refine = "")
{
var ext = createGltf ? ".glb" : ".b3dm";
var geometricError = maxGeometricError;
Expand All @@ -19,7 +18,7 @@ public static TileSet ToImplicitTileset(double[] transform, double[] box, double
0.0,1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
transform[0], transform[1], transform[2], 1.0};
var root = GetRoot(geometricError, t, box);
var root = GetRoot(geometricError, t, box,refine);
var content = new Content() { uri = "content/{level}_{x}_{y}" + ext };
root.content = content;
var subtrees = new Subtrees() { uri = "subtrees/{level}_{x}_{y}.subtree" };
Expand Down
6 changes: 3 additions & 3 deletions src/pg2b3dm.database.tests/UnitTest1.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public void ImplicitTilingTest()
var center_wgs84 = bbox_wgs84.bbox.GetCenter();
var translation = SpatialConverter.GeodeticToEcef((double)center_wgs84.X!, (double)center_wgs84.Y!, 0);
var trans = new double[] { translation.X, translation.Y, translation.Z };
var implicitTiler = new QuadtreeTiler(conn, "delaware_buildings", 4326, "geom_triangle", 50, string.Empty,
var implicitTiler = new QuadtreeTiler(conn, "delaware_buildings", 4326, 4978, "geom_triangle", 50, string.Empty,
trans,
"shaders",
string.Empty,
Expand Down Expand Up @@ -93,7 +93,7 @@ public void LodTest()
var translation = SpatialConverter.GeodeticToEcef((double)center_wgs84.X!, (double)center_wgs84.Y!, 0);
var trans = new double[] { translation.X, translation.Y, translation.Z };

var implicitTiler = new QuadtreeTiler(conn, "delaware_buildings_lod", 4326, "geom_triangle", 10, string.Empty,
var implicitTiler = new QuadtreeTiler(conn, "delaware_buildings_lod", 4326, 4978, "geom_triangle", 10, string.Empty,
trans,
"shaders",
string.Empty,
Expand All @@ -119,7 +119,7 @@ public void GeometryTest()
var center_wgs84 = bbox_wgs84.bbox.GetCenter();
var translation = SpatialConverter.GeodeticToEcef((double)center_wgs84.X!, (double)center_wgs84.Y!, 0);
var trans = new double[] { translation.X, translation.Y, translation.Z };
var implicitTiler = new QuadtreeTiler(conn, "geom_test", 4326, "geom3d", 50, string.Empty,
var implicitTiler = new QuadtreeTiler(conn, "geom_test", 4326, 4978, "geom3d", 50, string.Empty,
trans,
string.Empty,
string.Empty,
Expand Down
3 changes: 2 additions & 1 deletion src/pg2b3dm/Options.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ public class Options
[Option("skip_create_tiles", Required = false, Default = false, HelpText = "Skip creating tiles, only create tileset.json files (Cesium)", SetName = "Cesium")]
public bool SkipCreateTiles { get; set; }


[Option("enable_zoom_features", Required = false, Default = false, HelpText = "Creates extra tiles on lower zoom levels containing larger features", SetName = "Cesium")]
public bool EnableZoomFeatures{ get; set; }
// mapbox specific options
[Option("zoom", Required = false, Default = 15, HelpText = "Zoom level (Mapbox)", SetName = "Mapbox")]
public int Zoom { get; set; }
Expand Down
31 changes: 29 additions & 2 deletions src/pg2b3dm/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ static void Main(string[] args)
Console.WriteLine($"Doublesided: {doubleSided}");
Console.WriteLine($"Default AlphaMode: {defaultAlphaMode}");
Console.WriteLine($"Create glTF tiles: {createGltf}");
Console.WriteLine($"Enable zoom features: {o.EnableZoomFeatures}");

var att = !string.IsNullOrEmpty(o.AttributeColumns) ? o.AttributeColumns : "-";
Console.WriteLine($"Attribute columns: {att}");
Expand Down Expand Up @@ -175,16 +176,42 @@ static void Main(string[] args)
Console.WriteLine($"Maximum features per tile: " + o.MaxFeaturesPerTile);

var tile = new Tile(0, 0, 0);
var target_srs = 4978;
tile.BoundingBox = bbox.ToArray();
Console.WriteLine($"Start generating tiles...");
var quadtreeTiler = new QuadtreeTiler(conn, table, source_epsg, geometryColumn, o.MaxFeaturesPerTile, query, translation, o.ShadersColumn, o.AttributeColumns, lodcolumn, contentDirectory, lods, o.Copyright, skipCreateTiles, o.RadiusColumn);
var quadtreeTiler = new QuadtreeTiler(conn, table, source_epsg, target_srs, geometryColumn, o.MaxFeaturesPerTile, query, translation, o.ShadersColumn, o.AttributeColumns, lodcolumn, contentDirectory, lods, o.Copyright, skipCreateTiles, o.RadiusColumn);
var tiles = quadtreeTiler.GenerateTiles(bbox, tile, new List<Tile>(), lodcolumn != string.Empty ? lods.First() : 0, addOutlines, defaultColor, defaultMetallicRoughness, doubleSided, defaultAlphaMode, createGltf);
Console.WriteLine();
Console.WriteLine("Tiles created: " + tiles.Count(tile => tile.Available));


if (o.EnableZoomFeatures) {
var level_min = tiles.Where(tiles => tiles.Available).Min(t => t.Z);
var level_max = tiles.Where(tiles => tiles.Available).Max(t => t.Z);

var extraTiles = new List<Tile>();
foreach (var t in tiles) {
if (!t.Available && t.Z >= level_min && t.Z < level_max) {
var fileName = TileName.GetFileName(t, createGltf);
Console.Write($"\rCreating extra tile: {fileName}");
var postfixSql = $" ORDER BY ST_Area({geometryColumn}) DESC LIMIT {o.MaxFeaturesPerTile}";
var geometries = GeometryRepository.GetGeometrySubset(conn, table, geometryColumn, tile.BoundingBox, source_epsg, target_srs, o.ShadersColumn, o.AttributeColumns, where, o.RadiusColumn, postfixSql);
var bytes = TileWriter.ToTile(geometries, translation, copyright: copyright, addOutlines: addOutlines, defaultColor: defaultColor, defaultMetallicRoughness: defaultMetallicRoughness, doubleSided: doubleSided, defaultAlphaMode: defaultAlphaMode, createGltf: createGltf);
File.WriteAllBytes($"{contentDirectory}{Path.AltDirectorySeparatorChar}{fileName}", bytes);
t.Available = true;
extraTiles.Add(t);
}
}
Console.WriteLine();
Console.WriteLine("Extra tiles created: " + extraTiles.Count);

tiles.AddRange(extraTiles);
}


if (tiles.Count(tile => tile.Available) > 0) {
if (useImplicitTiling) {
CesiumTiler.CreateImplicitTileset(version, createGltf, outputDirectory, translation, o.GeometricError, rootBoundingVolumeRegion, subtreesDirectory, tiles, tilesetVersion);
CesiumTiler.CreateImplicitTileset(version, createGltf, outputDirectory, translation, o.GeometricError, rootBoundingVolumeRegion, subtreesDirectory, tiles, tilesetVersion, refinement);
}
else {
CesiumTiler.CreateExplicitTilesetsJson(version, outputDirectory, translation, o.GeometricError, o.GeometricErrorFactor, refinement, use10, rootBoundingVolumeRegion, tile, tiles, tilesetVersion);
Expand Down