Skip to content

Instantly share code, notes, and snippets.

@quommit
Last active November 8, 2022 10:51
Show Gist options
  • Save quommit/4596403 to your computer and use it in GitHub Desktop.
Save quommit/4596403 to your computer and use it in GitHub Desktop.
Sample C# code for indexing a series of polygon vertices using Z-order. In order to compile this code, download and reference NetTopologySuite, an open source spatial analysis library.
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using GeoAPI.Geometries;
using NetTopologySuite.Geometries;
using NetTopologySuite.IO;
using NetTopologySuite.Densify;
namespace MortonOrder
{
class MainClass
{
public struct IndexablePoint
{
public IGeometry Point;
public long ZValue;
public IndexablePoint (IGeometry point, long zvalue)
{
Point = point;
ZValue = zvalue;
}
}
public static void Main (string[] args)
{
IGeometryFactory gfactory = GeometryFactory.Fixed;
WKTReader greader = new WKTReader (gfactory);
//Polygon instance from WKT
IGeometry building = greader.Read ("POLYGON((0 0, 0 5, 10 5, 10 1, 2 1, 2 0, 0 0))");
//Densify polygon
IGeometry densification = Densifier.Densify (building, 1);
IndexablePoint[] points = new IndexablePoint[densification.NumPoints - 1];
//Calculate and store z-values using bit interleaving
for (int i = 0; i <= points.GetUpperBound (0); i++) {
IGeometry point = gfactory.CreatePoint (densification.Coordinates[i]);
uint x = (uint) point.Coordinate.X;
uint y = (uint) point.Coordinate.Y;
long zvalue = GetZValue (x, y);
points[i] = new IndexablePoint (point, zvalue);
}
}
//Generate a 64bit integer by bit interleaving a pair of 32bit unsigned integers
//representing a coordinate value. Resulting integer can be stored as a one-dimensional
//sortable key in an index which preserves spatial proximity.
static long GetZValue(uint x32, uint y32)
{
byte[] x32bytes = BitConverter.GetBytes(x32);
byte[] y32bytes = BitConverter.GetBytes(y32);
BitArray xba = new BitArray(x32bytes);
BitArray yba = new BitArray(y32bytes);
BitArray zba = new BitArray(64);
for (int i = 0; i < 32; i++) {
if (xba[i]) zba.Set(2 * i, true);
if (yba[i]) zba.Set((2 * i) + 1, true);
}
byte[] zbytes = new byte[8];
zba.CopyTo(zbytes, 0);
return BitConverter.ToInt64(zbytes, 0);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment