Last active
November 8, 2022 10:51
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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