/********************************************************************** * * GEOS - Geometry Engine Open Source * http://geos.osgeo.org * * Copyright (C) 2020 Paul Ramsey * * This is free software; you can redistribute and/or modify it under * the terms of the GNU Lesser General Public Licence as published * by the Free Software Foundation. * See the COPYING file for more information. * **********************************************************************/ #pragma once #include #include #include // Forward declarations namespace geos { namespace geom { class Coordinate; } } namespace geos { namespace shape { // geos.shape namespace fractal { // geos.shape.fractal /** * Encodes points as the index along the planar Morton (Z-order) curve. * * The planar Morton (Z-order) curve is a continuous space-filling curve. * The Morton curve defines an ordering of the * points in the positive quadrant of the plane. * The index of a point along the Morton curve is called the Morton code. * * A sequence of subsets of the Morton curve can be defined by a level number. * Each level subset occupies a square range. * The curve at level n M(n) contains 2^(n + 1) points. * It fills the range square of side 2^level. * Curve points have ordinates in the range [0, 2^level - 1]. * The code for a given point is identical at all levels. * The level simply determines the number of points in the curve subset * and the size of the range square. * * This implementation represents codes using 32-bit integers. * This allows levels 0 to 16 to be handled. * The class supports encoding points * and decoding the point for a given code value. * * The Morton order has the property that it tends to preserve locality. * This means that codes which are near in value will have spatially proximate * points. The converse is not always true - the delta between * codes for nearby points is not always small. But the average delta * is small enough that the Morton order is an effective way of linearizing space * to support range queries. * * @author Martin Davis * * @see HilbertCode */ class GEOS_DLL MortonCode { public: /** * The maximum curve level that can be represented. */ static constexpr int MAX_LEVEL = 16; /** * Computes the index of the point (x,y) * in the Morton curve ordering. * * @param x the x ordinate of the point * @param y the y ordinate of the point * @return the index of the point along the Morton curve */ static uint32_t encode(int x, int y); /** * Computes the point on the Morton curve * for a given index. * * @param index the index of the point on the curve * @return the point on the curve */ static geom::Coordinate decode(uint32_t index); /** * The number of points in the curve for the given level. * The number of points is 22 * level. * * @param level the level of the curve * @return the number of points */ static uint32_t levelSize(uint32_t level); /** * The maximum ordinate value for points * in the curve for the given level. * The maximum ordinate is 2level - 1. * * @param level the level of the curve * @return the maximum ordinate value */ static uint32_t maxOrdinate(uint32_t level); /** * The level of the finite Morton curve which contains at least * the given number of points. * * @param numPoints the number of points required * @return the level of the curve */ static uint32_t level(uint32_t numPoints); private: static void checkLevel(uint32_t level) ; static uint32_t interleave(uint32_t x); static uint32_t deinterleave(uint32_t x); }; } // namespace geos.shape.fractal } // namespace geos.shape } // namespace geos