Skip to content

Commit

Permalink
refactor: remove redundant lat lon to cell ids provider method
Browse files Browse the repository at this point in the history
  • Loading branch information
oscarlorentzon committed Mar 27, 2021
1 parent bc46f00 commit d318d4e
Show file tree
Hide file tree
Showing 8 changed files with 579 additions and 511 deletions.
276 changes: 84 additions & 192 deletions spec/api/GeohashGeometryProvider.spec.ts
Original file line number Diff line number Diff line change
@@ -1,39 +1,32 @@
import * as geohash from "latlon-geohash";
import { GeohashGeometryProvider } from "../../src/api/GeohashGeometryProvider";
import { LatLon } from "../../src/api/interfaces/LatLon";
import { MapillaryError } from "../../src/error/MapillaryError";
import * as GeoCoords from "../../src/geo/GeoCoords";

jest.mock("latlon-geohash");
const mockedGeohash = geohash as jest.Mocked<typeof geohash>;

describe("GeohashGeometryProvider.ctor", () => {
test("should be defined", () => {
const geometry = new GeohashGeometryProvider();

expect(geometry).toBeDefined();
});
});

describe("GeohashGeometryProvider.latLonToCellId", () => {
beforeEach(() => { mockedGeohash.encode.mockClear(); });

test("should call encoder correctly", () => {
const mockEncode = mockedGeohash.encode.mockReturnValueOnce("0/0");

const level = 7;
const geometry = new GeohashGeometryProvider();
const mockEncode = spyOn(geohash, "encode").and.returnValue("0/0");

const level = 22;
const geometry = new GeohashGeometryProvider(level);
const lat = -1;
const lon = 1;

geometry.latLonToCellId({ lat: -1, lon: 1 });
geometry.latLonToCellId({ lat, lon });

expect(mockEncode).toHaveBeenCalledTimes(1);
expect(mockEncode).toHaveBeenCalledWith(lat, lon, level);
});
});

describe("GeohashGeometryProvider.latLonToCellIds", () => {
describe("GeohashGeometryProvider.bboxToCellIds", () => {
const setupSpies: (tileSize: number) => void =
(tileSize: number): void => {
spyOn(geohash, "encode").and.callFake(
Expand Down Expand Up @@ -75,6 +68,20 @@ describe("GeohashGeometryProvider.latLonToCellIds", () => {
};
});

spyOn(GeoCoords, "geodeticToEnu").and.callFake(
(
lat: number,
lon: number,
_: number,
refLat: number,
refLon: number)
: number[] => {
return [
tileSize * (lat - refLat),
tileSize * (lon - refLon),
0];
});

spyOn(GeoCoords, "enuToGeodetic").and.callFake(
(x: number, y: number, _: number, refLat: number, refLon: number): number[] => {
return [
Expand All @@ -84,168 +91,38 @@ describe("GeohashGeometryProvider.latLonToCellIds", () => {
});
};

test("should return h of position only", () => {
test("should return cell", () => {
const geometry = new GeohashGeometryProvider();

const threshold = 20;
const tileSize = 2 * (threshold + 1);

const tileSize = 1;
setupSpies(tileSize);

const hs = geometry.latLonToCellIds({ lat: 0, lon: 0 }, threshold);
const sw: LatLon = { lat: -0.1, lon: -0.1 };
const ne: LatLon = { lat: 0.1, lon: 0.1 };
const cellIds = geometry.bboxToCellIds(sw, ne);

expect(hs.length).toBe(1);
expect(hs[0]).toBe("0/0");
expect(cellIds.length).toBe(1);
expect(cellIds[0]).toBe("0/0");
});

test("should return h of position and north neighbour", () => {
test("should return cell and adjacent", () => {
const geometry = new GeohashGeometryProvider();

const threshold = 20;
const tileSize = 2 * (threshold + 1);

const tileSize = 1;
setupSpies(tileSize);

const hs = geometry
.latLonToCellIds(
{ lat: 0, lon: 0.4 },
threshold);

expect(hs.length).toBe(9);
expect(hs.indexOf("0/0")).not.toBe(-1);
expect(hs.indexOf("0/1")).not.toBe(-1);
expect(hs.indexOf("0/-1")).not.toBe(-1);
expect(hs.indexOf("1/0")).not.toBe(-1);
expect(hs.indexOf("1/-1")).not.toBe(-1);
expect(hs.indexOf("1/1")).not.toBe(-1);
expect(hs.indexOf("-1/0")).not.toBe(-1);
expect(hs.indexOf("-1/-1")).not.toBe(-1);
expect(hs.indexOf("-1/1")).not.toBe(-1);
});

test("should return neighbors", () => {
const geometry = new GeohashGeometryProvider();

const threshold = 20;
const tileSize = 2 * (threshold + 1);

setupSpies(tileSize);

const hs = geometry
.latLonToCellIds(
{ lat: 0.4, lon: 0 },
threshold);

expect(hs.length).toBe(9);
expect(hs.indexOf("0/0")).not.toBe(-1);
expect(hs.indexOf("0/1")).not.toBe(-1);
expect(hs.indexOf("0/-1")).not.toBe(-1);
expect(hs.indexOf("1/0")).not.toBe(-1);
expect(hs.indexOf("1/-1")).not.toBe(-1);
expect(hs.indexOf("1/1")).not.toBe(-1);
expect(hs.indexOf("-1/0")).not.toBe(-1);
expect(hs.indexOf("-1/-1")).not.toBe(-1);
expect(hs.indexOf("-1/1")).not.toBe(-1);
});

test("should return neighbors", () => {
const geometry = new GeohashGeometryProvider();

const threshold = 20;
const tileSize = 2 * (threshold + 1);

setupSpies(tileSize);

const hs = geometry
.latLonToCellIds(
{ lat: 0, lon: -0.4 },
threshold);

expect(hs.length).toBe(9);
expect(hs.indexOf("0/0")).not.toBe(-1);
expect(hs.indexOf("0/1")).not.toBe(-1);
expect(hs.indexOf("0/-1")).not.toBe(-1);
expect(hs.indexOf("1/0")).not.toBe(-1);
expect(hs.indexOf("1/-1")).not.toBe(-1);
expect(hs.indexOf("1/1")).not.toBe(-1);
expect(hs.indexOf("-1/0")).not.toBe(-1);
expect(hs.indexOf("-1/-1")).not.toBe(-1);
expect(hs.indexOf("-1/1")).not.toBe(-1);
});

test("should return neighbours", () => {
const geometry = new GeohashGeometryProvider();

const threshold = 20;
const tileSize = 2 * (threshold + 1);

setupSpies(tileSize);

const hs = geometry
.latLonToCellIds(
{ lat: -0.4, lon: 0 },
threshold);

expect(hs.length).toBe(9);
expect(hs.indexOf("0/0")).not.toBe(-1);
expect(hs.indexOf("0/1")).not.toBe(-1);
expect(hs.indexOf("0/-1")).not.toBe(-1);
expect(hs.indexOf("1/0")).not.toBe(-1);
expect(hs.indexOf("1/-1")).not.toBe(-1);
expect(hs.indexOf("1/1")).not.toBe(-1);
expect(hs.indexOf("-1/0")).not.toBe(-1);
expect(hs.indexOf("-1/-1")).not.toBe(-1);
expect(hs.indexOf("-1/1")).not.toBe(-1);
});

test("should return h of position and north east neighbours", () => {
const geometry = new GeohashGeometryProvider();

const threshold = 20;
const tileSize = 2 * (threshold + 1);

setupSpies(tileSize);

const hs = geometry
.latLonToCellIds(
{ lat: 0.4, lon: 0.4 },
threshold);

expect(hs.length).toBe(9);
expect(hs.indexOf("0/0")).not.toBe(-1);
expect(hs.indexOf("0/1")).not.toBe(-1);
expect(hs.indexOf("0/-1")).not.toBe(-1);
expect(hs.indexOf("1/0")).not.toBe(-1);
expect(hs.indexOf("1/-1")).not.toBe(-1);
expect(hs.indexOf("1/1")).not.toBe(-1);
expect(hs.indexOf("-1/0")).not.toBe(-1);
expect(hs.indexOf("-1/-1")).not.toBe(-1);
expect(hs.indexOf("-1/1")).not.toBe(-1);
});

test("should return h of position and all neighbours", () => {
const geometry = new GeohashGeometryProvider();

const threshold = 20;
const tileSize = 2 * (threshold - 1);

setupSpies(tileSize);

const hs = geometry
.latLonToCellIds(
{ lat: 0, lon: 0 },
threshold);

expect(hs.length).toBe(9);
expect(hs.indexOf("0/0")).not.toBe(-1);
expect(hs.indexOf("0/1")).not.toBe(-1);
expect(hs.indexOf("-1/1")).not.toBe(-1);
expect(hs.indexOf("-1/0")).not.toBe(-1);
expect(hs.indexOf("-1/-1")).not.toBe(-1);
expect(hs.indexOf("0/-1")).not.toBe(-1);
expect(hs.indexOf("1/-1")).not.toBe(-1);
expect(hs.indexOf("1/0")).not.toBe(-1);
expect(hs.indexOf("1/1")).not.toBe(-1);
const sw: LatLon = { lat: -0.6, lon: -0.6 };
const ne: LatLon = { lat: 0.6, lon: 0.6 };
const cellIds = geometry.bboxToCellIds(sw, ne);

expect(cellIds.length).toBe(9);
expect(cellIds.indexOf("0/0")).not.toBe(-1);
expect(cellIds.indexOf("0/1")).not.toBe(-1);
expect(cellIds.indexOf("0/-1")).not.toBe(-1);
expect(cellIds.indexOf("1/0")).not.toBe(-1);
expect(cellIds.indexOf("1/-1")).not.toBe(-1);
expect(cellIds.indexOf("1/1")).not.toBe(-1);
expect(cellIds.indexOf("-1/0")).not.toBe(-1);
expect(cellIds.indexOf("-1/-1")).not.toBe(-1);
expect(cellIds.indexOf("-1/1")).not.toBe(-1);
});
});

Expand All @@ -254,37 +131,52 @@ describe("GeohashGeometryProvider.bboxToCellIds", () => {
const geometry = new GeohashGeometryProvider();

expect(() => {
geometry.bboxToCellIds(
{ lat: 0, lon: 0 },
{ lat: -1, lon: 1 });
})
.toThrowError(MapillaryError);
geometry
.bboxToCellIds(
{ lat: 0, lon: 0 },
{ lat: -1, lon: 1 });
}).toThrowError(MapillaryError);

expect(() => {
geometry.bboxToCellIds(
{ lat: 0, lon: 0 },
{ lat: 1, lon: -1 });
})
.toThrowError(MapillaryError);
geometry
.bboxToCellIds(
{ lat: 0, lon: 0 },
{ lat: 1, lon: -1 });
}).toThrowError(MapillaryError);

expect(() => {
geometry.bboxToCellIds(
{ lat: 0, lon: 0 },
{ lat: -1, lon: -1 });
})
.toThrowError(MapillaryError);
geometry
.bboxToCellIds(
{ lat: 0, lon: 0 },
{ lat: -1, lon: -1 });
}).toThrowError(MapillaryError);
});

test(
"should call latLonToCellIds with center and correct threshold",
() => {
describe("GeohashGeometryProvider.getAdjacent", () => {
it("should always be 8", () => {
const geometry = new GeohashGeometryProvider();

spyOn(GeoCoords, "geodeticToEnu").and.returnValue([10, 20, 0]);
const encodeHsSpy = spyOn(geometry, "latLonToCellIds").and.stub();

geometry.bboxToCellIds({ lat: 0, lon: 0 }, { lat: 1, lon: 3 });

expect(encodeHsSpy.calls.count()).toBe(1);
expect(encodeHsSpy.calls.argsFor(0)[0].lat).toBe(0.5);
expect(encodeHsSpy.calls.argsFor(0)[0].lon).toBe(1.5);
const latLons: LatLon[] = [
{ lat: 45, lon: 0 },
{ lat: 0, lon: 45 },
{ lat: -45, lon: 0 },
{ lat: 0, lon: -45 },
{ lat: 45, lon: 45 },
{ lat: -45, lon: -45 },
{ lat: 45, lon: -45 },
{ lat: -45, lon: 45 },
{ lat: -45, lon: 135 },
{ lat: -45, lon: 180 },
{ lat: 0, lon: 180 },
{ lat: 45, lon: 180 },
];

for (let latLon of latLons) {
console.log(latLon)
const cellId = geometry.latLonToCellId(latLon);
const adjacent = geometry.getAdjacent(cellId);
expect(adjacent.length).toBe(8);
}
});
});
});

0 comments on commit d318d4e

Please sign in to comment.