quadTree/earth/EarthQuadTreeStrategy.tstypescript
import * as mercator from "../../mercator";
import { Extent } from "../../Extent";
import { Node } from "../Node";
import { QuadTreeStrategy, QuadTreeStrategyParams } from "../QuadTreeStrategy";
import {
Segment,
TILEGROUP_NORTH,
TILEGROUP_SOUTH,
getTileGroupByLat,
getTileCellExtent,
getTileCellIndex
} from "../../segment/Segment";
import { SegmentLonLat } from "../../segment/SegmentLonLat";
import { LonLat } from "../../LonLat";
import { Vector } from "../../layer/Vector";
import { EarthEntityCollectionsTreeStrategy } from "./EarthEntityCollectionsTreeStrategy";
import { PlanetCamera } from "../../camera";
export class EarthQuadTreeStrategy extends QuadTreeStrategy {
/**
* Current visible north pole nodes tree nodes array.
* @public
* @type {Node}
*/
public _visibleNodesNorth: Record<number, Node>;
/**
* Current visible south pole nodes tree nodes array.
* @public
* @type {Node}
*/
public _visibleNodesSouth: Record<number, Node>;
constructor(params: QuadTreeStrategyParams) {
super({ name: "Earth", ...params });
this._visibleNodesNorth = {};
this._visibleNodesSouth = {};
}
public override collectVisibleNode(node: Node) {
let tg = node.segment._tileGroup;
if (tg === TILEGROUP_NORTH) {
this._visibleNodesNorth[node.nodeId] = node;
} else if (tg === TILEGROUP_SOUTH) {
this._visibleNodesSouth[node.nodeId] = node;
} else {
this._visibleNodes[node.nodeId] = node;
}
}
protected override _clearVisibleNodes() {
super._clearVisibleNodes();
this._visibleNodesNorth = {};
this._visibleNodesSouth = {};
}
public override createEntityCollectionsTreeStrategy(
layer: Vector,
nodeCapacity: number
): EarthEntityCollectionsTreeStrategy {
return new EarthEntityCollectionsTreeStrategy(this, layer, nodeCapacity);
}
public override init(camera: PlanetCamera) {
this._quadTreeList = [
new Node(
Segment,
this,
0,
null,
0,
Extent.createFromArray([-20037508.34, -20037508.34, 20037508.34, 20037508.34])
),
new Node(SegmentLonLat, this, 0, null, 0, Extent.createFromArray([-180, mercator.MAX_LAT, 180, 90])),
new Node(SegmentLonLat, this, 0, null, 0, Extent.createFromArray([-180, -90, 180, mercator.MIN_LAT]))
];
super.init(camera);
}
public override getTileXY(lonLat: LonLat, zoom: number): [number, number, number, number] {
let tileGroup = getTileGroupByLat(lonLat.lat, mercator.MAX_LAT),
z = zoom,
x: number,
y: number,
pz = 1 << z; /*Math.pow(2, z)*/
if (tileGroup === TILEGROUP_NORTH) {
x = getTileCellIndex(lonLat.lon, 360 / pz, -180);
y = getTileCellIndex(lonLat.lat, (90 - mercator.MAX_LAT) / pz, 90);
} else if (tileGroup === TILEGROUP_SOUTH) {
x = getTileCellIndex(lonLat.lon, 360 / pz, -180);
y = getTileCellIndex(lonLat.lat, (90 - mercator.MAX_LAT) / pz, mercator.MIN_LAT);
} else {
let merc = mercator.forward(lonLat);
x = getTileCellIndex(merc.lon, mercator.POLE2 / pz, -mercator.POLE);
y = getTileCellIndex(merc.lat, mercator.POLE2 / pz, mercator.POLE);
}
return [x, y, z, tileGroup];
}
public override getLonLatTileOffset(
lonLat: LonLat,
x: number,
y: number,
z: number,
gridSize: number
): [number, number] {
let coords = lonLat;
let extent: Extent;
if (lonLat.lat > mercator.MAX_LAT) {
let worldExtent = Extent.createFromArray([-180, mercator.MAX_LAT, 180, 90]);
extent = getTileCellExtent(x, y, z, worldExtent);
} else if (lonLat.lat < mercator.MIN_LAT) {
let worldExtent = Extent.createFromArray([-180, -90, 180, mercator.MIN_LAT]);
extent = getTileCellExtent(x, y, z, worldExtent);
} else {
coords = mercator.forward(lonLat);
extent = mercator.getTileExtent(x, y, z);
}
let sizeImgW = extent.getWidth() / (gridSize - 1),
sizeImgH = extent.getHeight() / (gridSize - 1);
let i = gridSize - Math.ceil((coords.lat - extent.southWest.lat) / sizeImgH) - 1,
j = Math.floor((coords.lon - extent.southWest.lon) / sizeImgW);
return [i, j];
}
}