quadTree/cube/CubeQuadTreeStrategy.tstypescript
import { Extent } from "../../Extent";
import { LonLat } from "../../LonLat";
import { PlanetCamera } from "../../camera";
import { CUBE_FACE_LINKS, CUBE_NODE_ID_OFFSET, cube, cubeEquiangular } from "../../proj/cube";
import type { CubeProj } from "../../proj/cube";
import { SegmentCube } from "../../segment/SegmentCube";
import type { Vector } from "../../layer/Vector";
import { CubeEntityCollectionsTreeStrategy } from "./CubeEntityCollectionsTreeStrategy";
import { Node } from "../Node";
import { E, N, S, W } from "../quadTree";
import { QuadTreeStrategy } from "../QuadTreeStrategy";
import type { QuadTreeStrategyParams } from "../QuadTreeStrategy";
/**
* Quad trees on the six faces of a cube inflated to the ellipsoid: the tiles are close to squares all over the
* planet and there are no poles in the tree.
* @class
* @extends {QuadTreeStrategy}
*/
export class CubeQuadTreeStrategy extends QuadTreeStrategy {
constructor(params: QuadTreeStrategyParams) {
super({ name: "cube", proj: cube, ...params });
this.rootTileWidth = 90;
}
public override init(camera: PlanetCamera) {
const roots = CUBE_FACE_LINKS.map((_, face) => {
const root = new Node(SegmentCube, this, 0, null, 0, Extent.createFromArray([face, 0, face + 1, 1]));
root.nodeId = CUBE_NODE_ID_OFFSET + face;
return root;
});
roots.forEach((root, face) => {
const l = CUBE_FACE_LINKS[face];
root.rootNeighbors = [roots[l[N][0]], roots[l[E][0]], roots[l[S][0]], roots[l[W][0]]];
});
this._quadTreeList = roots;
super.init(camera);
}
public override createEntityCollectionsTreeStrategy(
layer: Vector,
nodeCapacity: number
): CubeEntityCollectionsTreeStrategy {
return new CubeEntityCollectionsTreeStrategy(this, layer, nodeCapacity);
}
public override getTileXY(lonLat: LonLat, zoom: number): [number, number, number, number] {
const p = (this.projection as CubeProj).fromLonLat(lonLat),
face = Math.floor(p.lon),
pz = 1 << zoom;
return [Math.floor((p.lon - face) * pz), Math.min(Math.floor((1.0 - p.lat) * pz), pz - 1), zoom, face];
}
public override getLonLatTileOffset(
lonLat: LonLat,
x: number,
y: number,
z: number,
gridSize: number
): [number, number] {
const p = (this.projection as CubeProj).fromLonLat(lonLat),
face = Math.floor(p.lon),
pz = 1 << z,
cells = gridSize - 1;
return [Math.floor(((1.0 - p.lat) * pz - y) * cells), Math.floor(((p.lon - face) * pz - x) * cells)];
}
}
/**
* The cube with tiles of about the same size all over the planet: equal steps on a face are equal angles.
* @class
* @extends {CubeQuadTreeStrategy}
*/
export class EquiangularCubeQuadTreeStrategy extends CubeQuadTreeStrategy {
constructor(params: QuadTreeStrategyParams) {
super({ name: "cubeEquiangular", proj: cubeEquiangular, ...params });
}
}