"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
 * @module Tiles
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.QuadId = void 0;
const core_bentley_1 = require("@itwin/core-bentley");
const core_geometry_1 = require("@itwin/core-geometry");
const core_common_1 = require("@itwin/core-common");
const scratchCartographic1 = core_common_1.Cartographic.createZero();
const scratchCartographic2 = core_common_1.Cartographic.createZero();
/** Identifies a node within a [quad tree](https://en.wikipedia.org/wiki/Quadtree), such as a [[MapTile]] within a [[MapTileTree]].
 * A quad tree recursively sub-divides a two-dimensional space along the X and Y axes such that each node on level L has four child nodes on
 * level L+1.
 * @public
 */
class QuadId {
    /** The level of the node within the tree, increasing with each subdivision, as a non-negative integer. */
    level;
    /** The node's position along the X axis as a non-negative integer. */
    column;
    /** The node's position along the Y axis as a non-negative integer. */
    row;
    /** @alpha */
    get isValid() {
        return this.level >= 0;
    }
    /** @alpha */
    static createFromContentId(stringId) {
        const idParts = stringId.split("_");
        (0, core_bentley_1.assert)(idParts.length === 3);
        if (3 !== idParts.length)
            return new QuadId(-1, -1, -1);
        return new QuadId(parseInt(idParts[0], 10), parseInt(idParts[1], 10), parseInt(idParts[2], 10));
    }
    /** @alpha */
    get contentId() {
        return QuadId.getTileContentId(this.level, this.column, this.row);
    }
    /** @alpha */
    static getTileContentId(level, column, row) {
        return `${level}_${column}_${row}`;
    }
    /** @alpha */
    get debugString() {
        return `Level: ${this.level} Column: ${this.column} Row: ${this.row}`;
    }
    /** Construct a new QuadId. The inputs are expected to be non-negative integers. */
    constructor(level, column, row) {
        this.level = level;
        this.column = column;
        this.row = row;
    }
    /** Compute the QuadIds corresponding to this node's four child nodes. */
    getChildIds(columnCount = 2, rowCount = 2) {
        const childIds = [];
        const level = this.level + 1;
        const column = this.column * 2;
        const row = this.row * 2;
        for (let j = 0; j < rowCount; j++)
            for (let i = 0; i < columnCount; i++)
                childIds.push(new QuadId(level, column + i, row + j));
        return childIds;
    }
    /** Compute the region of the surface of the Earth represented by this node according to the specified tiling scheme. */
    getLatLongRangeDegrees(mapTilingScheme) {
        return this._getLatLongRange(mapTilingScheme, "degrees");
    }
    /** Compute the region of the surface of the Earth represented by this node according to the specified tiling scheme. */
    getLatLongRangeRadians(mapTilingScheme) {
        return this._getLatLongRange(mapTilingScheme, "radians");
    }
    _getLatLongRange(mapTilingScheme, units) {
        const range = core_geometry_1.Range2d.createNull();
        const factor = "degrees" === units ? core_geometry_1.Angle.degreesPerRadian : 1;
        mapTilingScheme.tileXYToCartographic(this.column, this.row, this.level, scratchCartographic1);
        range.extendXY(scratchCartographic1.longitude * factor, scratchCartographic1.latitude * factor);
        mapTilingScheme.tileXYToCartographic(this.column + 1, this.row + 1, this.level, scratchCartographic2);
        range.extendXY(scratchCartographic2.longitude * factor, scratchCartographic2.latitude * factor);
        return range;
    }
    /** @alpha */
    getAngleSweep(mapTilingScheme) {
        mapTilingScheme.tileXYToCartographic(this.column, this.row, this.level, scratchCartographic1);
        mapTilingScheme.tileXYToCartographic(this.column + 1, this.row + 1, this.level, scratchCartographic2);
        return {
            longitude: core_geometry_1.AngleSweep.createStartEndRadians(scratchCartographic1.longitude, scratchCartographic2.longitude),
            latitude: core_geometry_1.AngleSweep.createStartEndRadians(core_common_1.Cartographic.parametricLatitudeFromGeodeticLatitude(scratchCartographic1.latitude), core_common_1.Cartographic.parametricLatitudeFromGeodeticLatitude(scratchCartographic2.latitude)),
        };
    }
    /** Returns true if this node is adjacent to the south pole according to the specified tiling scheme. */
    bordersSouthPole(mapTilingScheme) {
        return mapTilingScheme.tileBordersSouthPole(this.row, this.level);
    }
    /** Returns true if this node is adjacent to the north pole according to the specified tiling scheme. */
    bordersNorthPole(mapTilingScheme) {
        return mapTilingScheme.tileBordersNorthPole(this.row, this.level);
    }
    /** Compares this Id to another according to the conventions of an [OrderedComparator]($bentley). */
    compare(other) {
        return (0, core_bentley_1.compareNumbers)(this.level, other.level) ||
            (0, core_bentley_1.compareNumbers)(this.row, other.row) ||
            (0, core_bentley_1.compareNumbers)(this.column, other.column);
    }
    /** Creates a QuadId from a JSON representation */
    static fromJSON(props) {
        return new QuadId(props.level, props.column, props.row);
    }
    /** Convert this QuadId to a JSON representation */
    static toJSON(props) {
        return {
            level: props.level,
            column: props.column,
            row: props.row,
        };
    }
}
exports.QuadId = QuadId;
//# sourceMappingURL=QuadId.js.map