[GIS] How to work with the STRtree Index when object in the index change it’s position

jts-topology-suitespatial-index

I'm work with the NTS(NetTopologySuite), I get large amounts of Point geometries, for fast querying the point object, I make the STRtree Index like this,


STRtree tree = new STRtree();
foreach (var p in allPoint)
{
tree.Insert(p.EnvelopeInternal, p);
}

While some point objects in the "allPoint" change it's position.
And I find I can't query the point which change position anymore..

How to work with it?

Thanks.

Best Answer

There are a couple of reasons why what you're trying to do here won't work.

  1. As dpp pointed out, you need to delete / reinsert changed coordinates on the index once something moves around. Otherwise, the index has no way of knowing that its cached metadata is dirty.
  2. Items cannot be inserted into an STRTree once it has been built, so it's not suitable for things that are constantly shifting around.

Quadtree is similar to STRTree and does support on-the-fly insert / remove operations. It's slower, but still OK in practice.

However, all that aside, is there some reason why you need the actual Point instead of just Coordinates? If Coordinate is OK or if you're fine with creating Point objects later on, then Dictionary<Coordinate, int> just seems like a much simpler solution than a spatial index.

Dictionary<Coordinate, int> coordinateMapping = new Dictionary<Coordinate, int>();

// to insert a new coordinate:
int n;
if (!coordinateMapping.TryGetValue(coordinateToInsert, out n))
{
    n = 0;
}
coordinateMapping[coordinateToInsert] = n + 1;
// now future queries will tell you how many of that coordinate are present.

// to determine how many of a given coordinate are present:
int n;
coordinateMapping.TryGetValue(coordinateToQuery, out n);
// check "n" for how many copies of that coordinate are present.

// to remove one of the coordinates from the index:
int n = coordinateMapping[coordinateToRemove];
// the above throws KeyNotFoundException if the coordinate was not present.
if (n == 1)
{
    coordinateMapping.Remove(coordinateToRemove);
}
else
{
    coordinateMapping[coordinateToRemove] = n - 1;
}