ThinkGeo.com    |     Documentation    |     Premium Support

SqliteFeatureLayer and InMemoryFeatureLayer display problem

Hi,

I have a simple test where I add a set of points to sqlite database and then add it to Map View.

I then run a query on this layer and add that data to the map as an InMemory layer.

For simplicity I color the sql layer green and the in memory layer in larger red diamonds.

Here are a set of images that show the problem. Basically, at different zoom levels some of the green are missing and at others some of the red are missing even though the database and in memory layer have exactly 2500 points in them.

The issue appears a bit random to me. There are also display issues where the point sizes appear to change and even some aliasing.

I am using v14 libs.

Hi Damian,

I’ve never seen this issue before. Can you upload this demo project to us?

Thanks,
Ben

Sure. Here it is.

You can also test the value style issue.

Regards,
Damian

WeirdDisplayIssue.zip (1.8 MB)

Hi Damin,

Thanks for the demo, here is the best solution for your case:

  1. Change the LayerOverlay to SingleTile
    CultureOverlay.TileType = TileType.SingleTile;
  2. 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

My index feature.id was off by 1. I fixed that now.

SingleTile fixes the problem, but I think this is going to cause some performance issue as I add images and WMTS to CultureOverlay in my main project.

Regards,
Damian

You can put the sqlite layer to its own overlay, so don’t need to mess up with other overlays. And yep, we are going to fix it for multi tile.