Нужно ли точно определять numHorzDivisions

Benchmark created on


Setup

    const TILE_SIZE = 256;
    const RADIUS = 6378137; // экваториальный радиус
    const E = 0.0818191908426;
    const E2 = E * E;
    const f = 1 - Math.sqrt(1 - E2); // сжатие
    const POLAR_RADIUS = (1 - f) * RADIUS; // полярный радиус

    const EPS = 1e-1; // точность вычислений для формул Винсенти

    const C_PI180 = Math.PI / 180;
    const C_180PI = 180 / Math.PI;
    const EPSILON = 1e-10;

    const e2 = E * E;
    const e4 = e2 * e2;
    const e6 = e4 * e2;
    const e8 = e4 * e4;
    const subradius = 1 / RADIUS;
    const d2 = (e2 / 2) + (5 * e4 / 24) + (e6 / 12) + (13 * e8 / 360);
    const d4 = (7 * e4 / 48) + (29 * e6 / 240) + (811 * e8 / 11520);
    const d6 = (7 * e6 / 120) + (81 * e8 / 1120);
    const d8 = (4279 * e8 / 161280);
    const equator = 2 * Math.PI * RADIUS;
    const subequator = 1 / equator;
    const halfEquator = equator / 2;

    const TILE_POWER = Math.log2(TILE_SIZE);

    let currentZoom = 0;
    let pixelsPerMeter = TILE_SIZE * subequator;

    function cycleRestrict(value, min, max) {
        return value - (Math.floor((value - min) / (max - min)) * (max - min));
    }

    function geoToMercator(geo) {
        const latitude = Math.max(Math.min(geo[1], 90 - EPSILON), -90 + EPSILON) * C_PI180;
        const esinLat = E * Math.sin(latitude);

        return [
            RADIUS * cycleRestrict(geo[0] * C_PI180, -Math.PI, Math.PI),
            RADIUS * Math.log(
                Math.tan((Math.PI * 0.25) + (latitude * 0.5)) /
                Math.pow(Math.tan((Math.PI * 0.25) + (Math.asin(esinLat) * 0.5)), E)
            )
        ];
    }

    function yToLatitude(y) {
        const xphi = (Math.PI * 0.5) - (2 * Math.atan(1 / Math.exp(y * subradius)));
        const latitude = xphi +
            (d2 * Math.sin(2 * xphi)) +
            (d4 * Math.sin(4 * xphi)) +
            (d6 * Math.sin(6 * xphi)) +
            (d8 * Math.sin(8 * xphi));

        return latitude * C_180PI;
    }

    function toGlobalPixels(point, zoom) {
        if (zoom !== currentZoom) {
            pixelsPerMeter = Math.pow(2, zoom + TILE_POWER) * subequator;
            currentZoom = zoom;
        }

        const mercatorCoords = geoToMercator(point);
        return [
            (halfEquator + mercatorCoords[0]) * pixelsPerMeter,
            (halfEquator - mercatorCoords[1]) * pixelsPerMeter
        ];
    }

    function fromGlobalPixels(vector, zoom) {
        if (zoom !== currentZoom) {
            pixelsPerMeter = Math.pow(2, zoom + TILE_POWER) * subequator;
            currentZoom = zoom;
        }

        return [
            cycleRestrict(
                (Math.PI * vector[0] / Math.pow(2, zoom + TILE_POWER - 1)) - Math.PI, -Math.PI, Math.PI
            ) * C_180PI,
            yToLatitude(halfEquator - (vector[1] / pixelsPerMeter))
        ];
    }

Test runner

Ready to run.

Testing in
TestOps/sec
precise numHorzDivisions
var z = 7.2;
var p;
var numHorzDivisions = Math.pow(2, Math.floor((Math.pow(400 / 1600, 0.2) * 15 - z) / 2));

for(i = 0; i < numHorzDivisions; i++) {
	p = fromGlobalPixels([2345, 6789], z);
} 
ready
big numHorzDivisions
var z = 7.2;
var p;
const numHorzDivisions = Math.pow(2, Math.floor(15 - z) / 2);

for(i = 0; i < numHorzDivisions; i++) {
	p = fromGlobalPixels([2345, 6789], z);
}
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.