Hi Damin,
Thanks for the demo, here is the best solution for your case:
- Change the LayerOverlay to SingleTile
CultureOverlay.TileType = TileType.SingleTile;
- The rtree index in your demo sqlite (System1.Sqlite) is not right, you can rebuild the index like following:
using System;
using System.Data;
using System.Collections.ObjectModel;
using Microsoft.Data.Sqlite;
using ThinkGeo.Core;
public class SpatialIndexHelper
{
private readonly string _connectionString;
public SpatialIndexHelper(string dbPath)
{
_connectionString = $"Data Source={dbPath}";
}
public void RebuildRTreeIndex(string tableName, string geometryColumn, string idColumn)
{
using (var conn = new SqliteConnection(_connectionString))
{
conn.Open();
// 1. Drop old index tables
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = $@"
DROP TABLE IF EXISTS idx_{tableName}_geometry;
DROP TABLE IF EXISTS idx_{tableName}_geometry_node;
DROP TABLE IF EXISTS idx_{tableName}_geometry_parent;
DROP TABLE IF EXISTS idx_{tableName}_geometry_rowid;";
cmd.ExecuteNonQuery();
}
// 2. Create a new RTree index table
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = $@"
CREATE VIRTUAL TABLE idx_{tableName}_geometry
USING rtree(id, minx, maxx, miny, maxy);";
cmd.ExecuteNonQuery();
}
// 3. Read all features and calculate bounding boxes
var layer = new SqliteFeatureLayer(_connectionString, tableName, idColumn, geometryColumn);
layer.Open();
var features = layer.QueryTools.GetAllFeatures(ReturningColumnsType.AllColumns);
foreach (var feature in features)
{
var bbox = feature.GetBoundingBox();
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = $@"
INSERT OR REPLACE INTO idx_{tableName}_geometry
(id, minx, maxx, miny, maxy)
VALUES (@id, @minx, @maxx, @miny, @maxy);";
cmd.Parameters.AddWithValue("@id", feature.Id);
cmd.Parameters.AddWithValue("@minx", bbox.LowerLeftPoint.X);
cmd.Parameters.AddWithValue("@maxx", bbox.UpperRightPoint.X);
cmd.Parameters.AddWithValue("@miny", bbox.LowerLeftPoint.Y);
cmd.Parameters.AddWithValue("@maxy", bbox.UpperRightPoint.Y);
cmd.ExecuteNonQuery();
}
}
layer.Close();
}
Console.WriteLine("RTree index has been rebuilt successfully ✅");
}
}
var helper = new SpatialIndexHelper(@"D:\test\System1.Sqlite");
helper.RebuildRTreeIndex("Shots", "geometry", "Id");
The issue still occurs when switching back to MultiTile, and the root cause is a multi-threading problem during label rendering. (Drawing a Glyph
for PointSymbolType.Diamond
triggers the issue, while PointSymbolType.Circle
works fine since it’s rendered as simple circles under the hood.) We’ll continue investigating this, but in your case, I’d recommend using SingleTile anyway.
Thanks,
Ben