mirror of https://github.com/CesiumGS/cesium.git
113 lines
2.4 KiB
JavaScript
113 lines
2.4 KiB
JavaScript
import Check from "./Check.js";
|
|
import DeveloperError from "./DeveloperError.js";
|
|
|
|
/**
|
|
* Hilbert Order helper functions.
|
|
*
|
|
* @namespace HilbertOrder
|
|
*/
|
|
const HilbertOrder = {};
|
|
|
|
/**
|
|
* Computes the Hilbert index at the given level from 2D coordinates.
|
|
*
|
|
* @param {number} level The level of the curve
|
|
* @param {number} x The X coordinate
|
|
* @param {number} y The Y coordinate
|
|
* @returns {number} The Hilbert index.
|
|
* @private
|
|
*/
|
|
HilbertOrder.encode2D = function (level, x, y) {
|
|
const n = Math.pow(2, level);
|
|
//>>includeStart('debug', pragmas.debug);
|
|
Check.typeOf.number("level", level);
|
|
Check.typeOf.number("x", x);
|
|
Check.typeOf.number("y", y);
|
|
if (level < 1) {
|
|
throw new DeveloperError("Hilbert level cannot be less than 1.");
|
|
}
|
|
if (x < 0 || x >= n || y < 0 || y >= n) {
|
|
throw new DeveloperError("Invalid coordinates for given level.");
|
|
}
|
|
//>>includeEnd('debug');
|
|
|
|
const p = {
|
|
x: x,
|
|
y: y,
|
|
};
|
|
let rx,
|
|
ry,
|
|
s,
|
|
index = BigInt(0);
|
|
|
|
for (s = n / 2; s > 0; s /= 2) {
|
|
rx = (p.x & s) > 0 ? 1 : 0;
|
|
ry = (p.y & s) > 0 ? 1 : 0;
|
|
index += BigInt(((3 * rx) ^ ry) * s * s);
|
|
rotate(n, p, rx, ry);
|
|
}
|
|
|
|
return index;
|
|
};
|
|
|
|
/**
|
|
* Computes the 2D coordinates from the Hilbert index at the given level.
|
|
*
|
|
* @param {number} level The level of the curve
|
|
* @param {bigint} index The Hilbert index
|
|
* @returns {number[]} An array containing the 2D coordinates ([x, y]) corresponding to the Morton index.
|
|
* @private
|
|
*/
|
|
HilbertOrder.decode2D = function (level, index) {
|
|
//>>includeStart('debug', pragmas.debug);
|
|
Check.typeOf.number("level", level);
|
|
Check.typeOf.bigint("index", index);
|
|
if (level < 1) {
|
|
throw new DeveloperError("Hilbert level cannot be less than 1.");
|
|
}
|
|
if (index < BigInt(0) || index >= BigInt(Math.pow(4, level))) {
|
|
throw new DeveloperError(
|
|
"Hilbert index exceeds valid maximum for given level.",
|
|
);
|
|
}
|
|
//>>includeEnd('debug');
|
|
|
|
const n = Math.pow(2, level);
|
|
const p = {
|
|
x: 0,
|
|
y: 0,
|
|
};
|
|
let rx, ry, s, t;
|
|
|
|
for (s = 1, t = index; s < n; s *= 2) {
|
|
rx = 1 & Number(t / BigInt(2));
|
|
ry = 1 & Number(t ^ BigInt(rx));
|
|
rotate(s, p, rx, ry);
|
|
p.x += s * rx;
|
|
p.y += s * ry;
|
|
t /= BigInt(4);
|
|
}
|
|
|
|
return [p.x, p.y];
|
|
};
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
function rotate(n, p, rx, ry) {
|
|
if (ry !== 0) {
|
|
return;
|
|
}
|
|
|
|
if (rx === 1) {
|
|
p.x = n - 1 - p.x;
|
|
p.y = n - 1 - p.y;
|
|
}
|
|
|
|
const t = p.x;
|
|
p.x = p.y;
|
|
p.y = t;
|
|
}
|
|
|
|
export default HilbertOrder;
|