mirror of
https://github.com/mapillary/mapillary-js.git
synced 2026-01-25 14:07:28 +00:00
904 lines
32 KiB
TypeScript
904 lines
32 KiB
TypeScript
import { Image } from "../../../src/graph/Image";
|
|
import { EdgeCalculator } from "../../../src/graph/edge/EdgeCalculator";
|
|
import { EdgeCalculatorDirections } from "../../../src/graph/edge/EdgeCalculatorDirections";
|
|
import { EdgeCalculatorSettings } from "../../../src/graph/edge/EdgeCalculatorSettings";
|
|
import { PotentialEdge } from "../../../src/graph/edge/interfaces/PotentialEdge";
|
|
import { EdgeCalculatorHelper } from "../../helper/EdgeCalculatorHelper";
|
|
import { NavigationDirection } from "../../../src/graph/edge/NavigationDirection";
|
|
|
|
describe("EdgeCalculator.computeSphericalEdges", () => {
|
|
let edgeCalculator: EdgeCalculator;
|
|
let settings: EdgeCalculatorSettings;
|
|
let directions: EdgeCalculatorDirections;
|
|
|
|
let helper: EdgeCalculatorHelper;
|
|
|
|
let image: Image;
|
|
let potentialEdge1: PotentialEdge;
|
|
|
|
beforeEach(() => {
|
|
settings = new EdgeCalculatorSettings();
|
|
settings.sphericalMinDistance = 0.1;
|
|
settings.sphericalMaxDistance = 20;
|
|
settings.sphericalPreferredDistance = 5;
|
|
settings.sphericalMaxItems = 4;
|
|
});
|
|
|
|
beforeEach(() => {
|
|
directions = new EdgeCalculatorDirections();
|
|
edgeCalculator = new EdgeCalculator(settings, directions);
|
|
|
|
helper = new EdgeCalculatorHelper();
|
|
});
|
|
|
|
beforeEach(() => {
|
|
image = helper.createDefaultImage(true);
|
|
|
|
potentialEdge1 = helper.createPotentialEdge("pkey1");
|
|
potentialEdge1.distance = settings.sphericalMaxDistance / 2;
|
|
potentialEdge1.spherical = true;
|
|
});
|
|
|
|
it("should throw when image is not full", () => {
|
|
image = helper.createCoreImage("", { alt: 0, lat: 0, lng: 0 }, "");
|
|
|
|
expect(() => { edgeCalculator.computeSphericalEdges(image, []); }).toThrowError(Error);
|
|
});
|
|
|
|
it("should have a spherical edge", () => {
|
|
let sphericalEdges = edgeCalculator.computeSphericalEdges(image, [potentialEdge1]);
|
|
|
|
expect(sphericalEdges.length).toBe(1);
|
|
|
|
let sphericalEdge = sphericalEdges[0];
|
|
|
|
expect(sphericalEdge.target).toBe(potentialEdge1.id);
|
|
expect(sphericalEdge.data.direction).toBe(NavigationDirection.Spherical);
|
|
});
|
|
|
|
it("should have a spherical edge irrespective of rotation", () => {
|
|
potentialEdge1.directionChange = Math.PI;
|
|
|
|
let sphericalEdges = edgeCalculator.computeSphericalEdges(image, [potentialEdge1]);
|
|
|
|
expect(sphericalEdges.length).toBe(1);
|
|
|
|
let sphericalEdge = sphericalEdges[0];
|
|
|
|
expect(sphericalEdge.target).toBe(potentialEdge1.id);
|
|
expect(sphericalEdge.data.direction).toBe(NavigationDirection.Spherical);
|
|
});
|
|
|
|
it("should not have a spherical edge with to long distance", () => {
|
|
potentialEdge1.distance = settings.sphericalMaxDistance + 1;
|
|
|
|
let sphericalEdges = edgeCalculator.computeSphericalEdges(image, [potentialEdge1]);
|
|
|
|
expect(sphericalEdges.length).toBe(0);
|
|
});
|
|
|
|
it("should not have a spherical edge with to short distance", () => {
|
|
potentialEdge1.distance = settings.sphericalMinDistance / 2;
|
|
|
|
let sphericalEdges = edgeCalculator.computeSphericalEdges(image, [potentialEdge1]);
|
|
|
|
expect(sphericalEdges.length).toBe(0);
|
|
});
|
|
|
|
it("should not have a spherical edge for non spherical", () => {
|
|
potentialEdge1.spherical = false;
|
|
|
|
let sphericalEdges = edgeCalculator.computeSphericalEdges(image, [potentialEdge1]);
|
|
|
|
for (let sphericalEdge of sphericalEdges) {
|
|
expect(sphericalEdge.data.direction === NavigationDirection.Spherical).toBe(false);
|
|
}
|
|
});
|
|
|
|
it("should not have a spherical edge when image is not spherical", () => {
|
|
image = helper.createDefaultImage(false);
|
|
|
|
let sphericalEdges = edgeCalculator.computeSphericalEdges(image, [potentialEdge1]);
|
|
|
|
expect(sphericalEdges.length).toBe(0);
|
|
});
|
|
});
|
|
|
|
describe("EdgeCalculator.computeSphericalEdges", () => {
|
|
let edgeCalculator: EdgeCalculator;
|
|
let settings: EdgeCalculatorSettings;
|
|
let directions: EdgeCalculatorDirections;
|
|
|
|
let helper: EdgeCalculatorHelper;
|
|
|
|
let image: Image;
|
|
let potentialEdge1: PotentialEdge;
|
|
let potentialEdge2: PotentialEdge;
|
|
|
|
beforeEach(() => {
|
|
settings = new EdgeCalculatorSettings();
|
|
settings.sphericalMinDistance = 0.1;
|
|
settings.sphericalMaxDistance = 20;
|
|
settings.sphericalPreferredDistance = 5;
|
|
settings.sphericalMaxItems = 4;
|
|
});
|
|
|
|
beforeEach(() => {
|
|
directions = new EdgeCalculatorDirections();
|
|
edgeCalculator = new EdgeCalculator(settings, directions);
|
|
|
|
helper = new EdgeCalculatorHelper();
|
|
});
|
|
|
|
beforeEach(() => {
|
|
image = helper.createDefaultImage(true);
|
|
|
|
potentialEdge1 = helper.createPotentialEdge("pkey1");
|
|
potentialEdge1.distance = settings.sphericalPreferredDistance;
|
|
potentialEdge1.spherical = true;
|
|
|
|
potentialEdge2 = helper.createPotentialEdge("pkey2");
|
|
potentialEdge2.distance = settings.sphericalPreferredDistance;
|
|
potentialEdge2.spherical = true;
|
|
});
|
|
|
|
it("should have a spherical edge closest to preferred distance", () => {
|
|
potentialEdge1.distance = settings.sphericalPreferredDistance + 1;
|
|
potentialEdge2.distance = settings.sphericalPreferredDistance;
|
|
|
|
let sphericalEdges = edgeCalculator.computeSphericalEdges(image, [potentialEdge1, potentialEdge2]);
|
|
|
|
expect(sphericalEdges.length).toBe(1);
|
|
|
|
let sphericalEdge = sphericalEdges[0];
|
|
|
|
expect(sphericalEdge.target).toBe(potentialEdge2.id);
|
|
expect(sphericalEdge.data.direction).toBe(NavigationDirection.Spherical);
|
|
});
|
|
|
|
it("should have a spherical edge closest to preferred distance", () => {
|
|
potentialEdge1.distance = settings.sphericalPreferredDistance - 1;
|
|
potentialEdge2.distance = settings.sphericalPreferredDistance;
|
|
|
|
let sphericalEdges = edgeCalculator.computeSphericalEdges(image, [potentialEdge1, potentialEdge2]);
|
|
|
|
expect(sphericalEdges.length).toBe(1);
|
|
|
|
let sphericalEdge = sphericalEdges[0];
|
|
|
|
expect(sphericalEdge.target).toBe(potentialEdge2.id);
|
|
expect(sphericalEdge.data.direction).toBe(NavigationDirection.Spherical);
|
|
});
|
|
|
|
it("should have a spherical edge with same sequence", () => {
|
|
potentialEdge1.sameSequence = false;
|
|
potentialEdge2.sameSequence = true;
|
|
|
|
let sphericalEdges = edgeCalculator.computeSphericalEdges(image, [potentialEdge1, potentialEdge2]);
|
|
|
|
expect(sphericalEdges.length).toBe(1);
|
|
|
|
let sphericalEdge = sphericalEdges[0];
|
|
|
|
expect(sphericalEdge.target).toBe(potentialEdge2.id);
|
|
expect(sphericalEdge.data.direction).toBe(NavigationDirection.Spherical);
|
|
});
|
|
|
|
it("should have a spherical edge with same sequence", () => {
|
|
potentialEdge1.sameMergeCC = false;
|
|
potentialEdge2.sameMergeCC = true;
|
|
|
|
let sphericalEdges = edgeCalculator.computeSphericalEdges(image, [potentialEdge1, potentialEdge2]);
|
|
|
|
expect(sphericalEdges.length).toBe(1);
|
|
|
|
let sphericalEdge = sphericalEdges[0];
|
|
|
|
expect(sphericalEdge.target).toBe(potentialEdge2.id);
|
|
expect(sphericalEdge.data.direction).toBe(NavigationDirection.Spherical);
|
|
});
|
|
|
|
it("should have a spherical edge with smallest motion change", () => {
|
|
potentialEdge1.motionChange = 0.2;
|
|
potentialEdge2.motionChange = 0.1;
|
|
|
|
let sphericalEdges = edgeCalculator.computeSphericalEdges(image, [potentialEdge1, potentialEdge2]);
|
|
|
|
expect(sphericalEdges.length).toBe(1);
|
|
|
|
let sphericalEdge = sphericalEdges[0];
|
|
|
|
expect(sphericalEdge.target).toBe(potentialEdge2.id);
|
|
expect(sphericalEdge.data.direction).toBe(NavigationDirection.Spherical);
|
|
});
|
|
});
|
|
|
|
describe("EdgeCalculator.computeSphericalEdges", () => {
|
|
let edgeCalculator: EdgeCalculator;
|
|
let settings: EdgeCalculatorSettings;
|
|
let directions: EdgeCalculatorDirections;
|
|
|
|
let helper: EdgeCalculatorHelper;
|
|
|
|
let image: Image;
|
|
|
|
let potentialEdge1: PotentialEdge;
|
|
let potentialEdge2: PotentialEdge;
|
|
let potentialEdge3: PotentialEdge;
|
|
let potentialEdge4: PotentialEdge;
|
|
|
|
beforeEach(() => {
|
|
settings = new EdgeCalculatorSettings();
|
|
settings.sphericalMinDistance = 0.1;
|
|
settings.sphericalMaxDistance = 20;
|
|
settings.sphericalPreferredDistance = 5;
|
|
settings.sphericalMaxItems = 4;
|
|
});
|
|
|
|
beforeEach(() => {
|
|
directions = new EdgeCalculatorDirections();
|
|
edgeCalculator = new EdgeCalculator(settings, directions);
|
|
|
|
helper = new EdgeCalculatorHelper();
|
|
});
|
|
|
|
beforeEach(() => {
|
|
image = helper.createDefaultImage(true);
|
|
|
|
potentialEdge1 = helper.createPotentialEdge("pkey1");
|
|
potentialEdge1.distance = settings.sphericalMaxDistance / 2;
|
|
potentialEdge1.spherical = true;
|
|
|
|
potentialEdge2 = helper.createPotentialEdge("pkey2");
|
|
potentialEdge2.distance = settings.sphericalMaxDistance / 2;
|
|
potentialEdge2.spherical = true;
|
|
|
|
potentialEdge3 = helper.createPotentialEdge("pkey3");
|
|
potentialEdge3.distance = settings.sphericalMaxDistance / 2;
|
|
potentialEdge3.spherical = true;
|
|
|
|
potentialEdge4 = helper.createPotentialEdge("pkey4");
|
|
potentialEdge4.distance = settings.sphericalMaxDistance / 2;
|
|
potentialEdge4.spherical = true;
|
|
});
|
|
|
|
it("should have only have one spherical edge based on motion change", () => {
|
|
potentialEdge1.motionChange = Math.PI / 4;
|
|
potentialEdge2.motionChange = -Math.PI / 4;
|
|
potentialEdge3.motionChange = Math.PI / 8;
|
|
potentialEdge4.motionChange = 0;
|
|
|
|
let sphericalEdges = edgeCalculator.computeSphericalEdges(
|
|
image,
|
|
[potentialEdge1, potentialEdge2, potentialEdge3, potentialEdge4]);
|
|
|
|
expect(sphericalEdges.length).toBe(1);
|
|
|
|
let sphericalEdge = sphericalEdges[0];
|
|
|
|
expect(sphericalEdge.target).toBe(potentialEdge4.id);
|
|
expect(sphericalEdge.data.direction).toBe(NavigationDirection.Spherical);
|
|
});
|
|
|
|
it("should have a spherical edge in four directions", () => {
|
|
potentialEdge1.motionChange = 0;
|
|
potentialEdge2.motionChange = Math.PI / 2;
|
|
potentialEdge3.motionChange = Math.PI;
|
|
potentialEdge4.motionChange = -Math.PI / 2;
|
|
|
|
let sphericalEdges = edgeCalculator.computeSphericalEdges(
|
|
image,
|
|
[potentialEdge1, potentialEdge2, potentialEdge3, potentialEdge4]);
|
|
|
|
expect(sphericalEdges.length).toBe(4);
|
|
|
|
let keys: string[] = [
|
|
potentialEdge1.id,
|
|
potentialEdge2.id,
|
|
potentialEdge3.id,
|
|
potentialEdge4.id,
|
|
];
|
|
|
|
for (let key of keys) {
|
|
let edge = null;
|
|
for (let sphericalEdge of sphericalEdges) {
|
|
if (sphericalEdge.target === key) {
|
|
edge = sphericalEdge;
|
|
}
|
|
}
|
|
|
|
expect(edge.data.direction).toBe(NavigationDirection.Spherical);
|
|
}
|
|
});
|
|
|
|
it("should not have multiple spherical edges in same slice", () => {
|
|
potentialEdge1.motionChange = 0;
|
|
potentialEdge2.motionChange = Math.PI / 36;
|
|
potentialEdge3.motionChange = Math.PI;
|
|
potentialEdge4.motionChange = -35 * Math.PI / 36;
|
|
|
|
let sphericalEdges = edgeCalculator.computeSphericalEdges(
|
|
image,
|
|
[potentialEdge1, potentialEdge2, potentialEdge3, potentialEdge4]);
|
|
|
|
expect(sphericalEdges.length).toBe(2);
|
|
|
|
let keys: string[] = [
|
|
potentialEdge1.id,
|
|
potentialEdge3.id,
|
|
];
|
|
|
|
for (let key of keys) {
|
|
let edge = null;
|
|
for (let sphericalEdge of sphericalEdges) {
|
|
if (sphericalEdge.target === key) {
|
|
edge = sphericalEdge;
|
|
}
|
|
}
|
|
|
|
expect(edge.data.direction).toBe(NavigationDirection.Spherical);
|
|
}
|
|
});
|
|
|
|
it("should not have spherical edges too close to each other on different slices", () => {
|
|
potentialEdge1.motionChange = Math.PI / 6;
|
|
potentialEdge2.motionChange = 2 * Math.PI / 6;
|
|
|
|
let sphericalEdges = edgeCalculator.computeSphericalEdges(
|
|
image,
|
|
[potentialEdge1, potentialEdge2]);
|
|
|
|
expect(sphericalEdges.length).toBe(1);
|
|
|
|
let sphericalEdge = sphericalEdges[0];
|
|
|
|
expect(sphericalEdge.target).toBe(potentialEdge1.id);
|
|
expect(sphericalEdge.data.direction).toBe(NavigationDirection.Spherical);
|
|
});
|
|
});
|
|
|
|
describe("EdgeCalculator.computeSphericalEdges", () => {
|
|
let edgeCalculator: EdgeCalculator;
|
|
let settings: EdgeCalculatorSettings;
|
|
let directions: EdgeCalculatorDirections;
|
|
|
|
let helper: EdgeCalculatorHelper;
|
|
|
|
let image: Image;
|
|
let potentialEdge1: PotentialEdge;
|
|
|
|
beforeEach(() => {
|
|
settings = new EdgeCalculatorSettings();
|
|
settings.sphericalMinDistance = 0.1;
|
|
settings.sphericalMaxDistance = 20;
|
|
settings.sphericalPreferredDistance = 5;
|
|
settings.sphericalMaxItems = 4;
|
|
settings.sphericalMaxStepTurnChange = Math.PI / 8;
|
|
});
|
|
|
|
beforeEach(() => {
|
|
directions = new EdgeCalculatorDirections();
|
|
|
|
edgeCalculator = new EdgeCalculator(settings, directions);
|
|
|
|
helper = new EdgeCalculatorHelper();
|
|
});
|
|
|
|
beforeEach(() => {
|
|
image = helper.createDefaultImage(true);
|
|
|
|
potentialEdge1 = helper.createPotentialEdge("pkey1");
|
|
potentialEdge1.distance = settings.sphericalPreferredDistance;
|
|
potentialEdge1.spherical = false;
|
|
});
|
|
|
|
it("should have a step forward edge", () => {
|
|
potentialEdge1.motionChange = 0;
|
|
potentialEdge1.directionChange = 0;
|
|
|
|
let sphericalEdges = edgeCalculator.computeSphericalEdges(image, [potentialEdge1]);
|
|
|
|
expect(sphericalEdges.length).toBe(1);
|
|
|
|
let sphericalEdge = sphericalEdges[0];
|
|
|
|
expect(sphericalEdge.target).toBe(potentialEdge1.id);
|
|
expect(sphericalEdge.data.direction).toBe(NavigationDirection.StepForward);
|
|
});
|
|
|
|
it("should have a step left edge", () => {
|
|
potentialEdge1.motionChange = Math.PI / 2;
|
|
potentialEdge1.directionChange = 0;
|
|
|
|
let sphericalEdges = edgeCalculator.computeSphericalEdges(image, [potentialEdge1]);
|
|
|
|
expect(sphericalEdges.length).toBe(1);
|
|
|
|
let sphericalEdge = sphericalEdges[0];
|
|
|
|
expect(sphericalEdge.target).toBe(potentialEdge1.id);
|
|
expect(sphericalEdge.data.direction).toBe(NavigationDirection.StepLeft);
|
|
});
|
|
|
|
it("should have a step left edge for direction change", () => {
|
|
potentialEdge1.motionChange = 0;
|
|
potentialEdge1.directionChange = -Math.PI / 2;
|
|
|
|
let sphericalEdges = edgeCalculator.computeSphericalEdges(image, [potentialEdge1]);
|
|
|
|
expect(sphericalEdges.length).toBe(1);
|
|
|
|
let sphericalEdge = sphericalEdges[0];
|
|
|
|
expect(sphericalEdge.target).toBe(potentialEdge1.id);
|
|
expect(sphericalEdge.data.direction).toBe(NavigationDirection.StepLeft);
|
|
});
|
|
|
|
it("should have a step right edge", () => {
|
|
potentialEdge1.motionChange = -Math.PI / 2;
|
|
potentialEdge1.directionChange = 0;
|
|
|
|
let sphericalEdges = edgeCalculator.computeSphericalEdges(image, [potentialEdge1]);
|
|
|
|
expect(sphericalEdges.length).toBe(1);
|
|
|
|
let sphericalEdge = sphericalEdges[0];
|
|
|
|
expect(sphericalEdge.target).toBe(potentialEdge1.id);
|
|
expect(sphericalEdge.data.direction).toBe(NavigationDirection.StepRight);
|
|
});
|
|
|
|
it("should have a step right edge for direction change", () => {
|
|
potentialEdge1.motionChange = 0;
|
|
potentialEdge1.directionChange = Math.PI / 2;
|
|
|
|
let sphericalEdges = edgeCalculator.computeSphericalEdges(image, [potentialEdge1]);
|
|
|
|
expect(sphericalEdges.length).toBe(1);
|
|
|
|
let sphericalEdge = sphericalEdges[0];
|
|
|
|
expect(sphericalEdge.target).toBe(potentialEdge1.id);
|
|
expect(sphericalEdge.data.direction).toBe(NavigationDirection.StepRight);
|
|
});
|
|
|
|
it("should have a step backward edge", () => {
|
|
potentialEdge1.motionChange = Math.PI;
|
|
potentialEdge1.directionChange = 0;
|
|
|
|
let sphericalEdges = edgeCalculator.computeSphericalEdges(image, [potentialEdge1]);
|
|
|
|
expect(sphericalEdges.length).toBe(1);
|
|
|
|
let sphericalEdge = sphericalEdges[0];
|
|
|
|
expect(sphericalEdge.target).toBe(potentialEdge1.id);
|
|
expect(sphericalEdge.data.direction).toBe(NavigationDirection.StepBackward);
|
|
});
|
|
|
|
it("should have a step backward edge for direction change", () => {
|
|
potentialEdge1.motionChange = 0;
|
|
potentialEdge1.directionChange = Math.PI;
|
|
|
|
let sphericalEdges = edgeCalculator.computeSphericalEdges(image, [potentialEdge1]);
|
|
|
|
expect(sphericalEdges.length).toBe(1);
|
|
|
|
let sphericalEdge = sphericalEdges[0];
|
|
|
|
expect(sphericalEdge.target).toBe(potentialEdge1.id);
|
|
expect(sphericalEdge.data.direction).toBe(NavigationDirection.StepBackward);
|
|
});
|
|
|
|
it("should have a step forward edge in opposite motion direction", () => {
|
|
potentialEdge1.motionChange = Math.PI;
|
|
potentialEdge1.directionChange = Math.PI;
|
|
|
|
let sphericalEdges = edgeCalculator.computeSphericalEdges(image, [potentialEdge1]);
|
|
|
|
expect(sphericalEdges.length).toBe(1);
|
|
|
|
let sphericalEdge = sphericalEdges[0];
|
|
|
|
expect(sphericalEdge.target).toBe(potentialEdge1.id);
|
|
expect(sphericalEdge.data.direction).toBe(NavigationDirection.StepForward);
|
|
});
|
|
|
|
it("should have a step forward edge in perpendicular motion direction", () => {
|
|
potentialEdge1.motionChange = Math.PI / 2;
|
|
potentialEdge1.directionChange = Math.PI / 2;
|
|
|
|
let sphericalEdges = edgeCalculator.computeSphericalEdges(image, [potentialEdge1]);
|
|
|
|
expect(sphericalEdges.length).toBe(1);
|
|
|
|
let sphericalEdge = sphericalEdges[0];
|
|
|
|
expect(sphericalEdge.target).toBe(potentialEdge1.id);
|
|
expect(sphericalEdge.data.direction).toBe(NavigationDirection.StepForward);
|
|
});
|
|
|
|
it("should have a step forward edge in perpendicular motion direction", () => {
|
|
potentialEdge1.motionChange = -Math.PI / 2;
|
|
potentialEdge1.directionChange = -Math.PI / 2;
|
|
|
|
let sphericalEdges = edgeCalculator.computeSphericalEdges(image, [potentialEdge1]);
|
|
|
|
expect(sphericalEdges.length).toBe(1);
|
|
|
|
let sphericalEdge = sphericalEdges[0];
|
|
|
|
expect(sphericalEdge.target).toBe(potentialEdge1.id);
|
|
expect(sphericalEdge.data.direction).toBe(NavigationDirection.StepForward);
|
|
});
|
|
|
|
it("should not have a step forward edge when turn is to large", () => {
|
|
potentialEdge1.motionChange = 0;
|
|
potentialEdge1.directionChange = settings.sphericalMaxStepTurnChange + Math.PI / 18;
|
|
|
|
let sphericalEdges = edgeCalculator.computeSphericalEdges(image, [potentialEdge1]);
|
|
|
|
expect(sphericalEdges.length).toBe(0);
|
|
});
|
|
|
|
it("should not have a step forward edge when turn is to large", () => {
|
|
potentialEdge1.motionChange = 0;
|
|
potentialEdge1.directionChange = -settings.sphericalMaxStepTurnChange - Math.PI / 18;
|
|
|
|
let sphericalEdges = edgeCalculator.computeSphericalEdges(image, [potentialEdge1]);
|
|
|
|
expect(sphericalEdges.length).toBe(0);
|
|
});
|
|
|
|
it("should not have a step left edge when turn is to large", () => {
|
|
potentialEdge1.motionChange = 0;
|
|
potentialEdge1.directionChange = Math.PI / 2 + settings.sphericalMaxStepTurnChange + Math.PI / 18;
|
|
|
|
let sphericalEdges = edgeCalculator.computeSphericalEdges(image, [potentialEdge1]);
|
|
|
|
expect(sphericalEdges.length).toBe(0);
|
|
});
|
|
|
|
it("should not have a step left edge when turn is to large", () => {
|
|
potentialEdge1.motionChange = 0;
|
|
potentialEdge1.directionChange = Math.PI / 2 - settings.sphericalMaxStepTurnChange - Math.PI / 18;
|
|
|
|
let sphericalEdges = edgeCalculator.computeSphericalEdges(image, [potentialEdge1]);
|
|
|
|
expect(sphericalEdges.length).toBe(0);
|
|
});
|
|
});
|
|
|
|
describe("EdgeCalculator.computeSphericalEdges", () => {
|
|
let edgeCalculator: EdgeCalculator;
|
|
let settings: EdgeCalculatorSettings;
|
|
let directions: EdgeCalculatorDirections;
|
|
|
|
let helper: EdgeCalculatorHelper;
|
|
|
|
let image: Image;
|
|
let potentialEdge1: PotentialEdge;
|
|
let potentialEdge2: PotentialEdge;
|
|
|
|
beforeEach(() => {
|
|
settings = new EdgeCalculatorSettings();
|
|
settings.sphericalMinDistance = 0.1;
|
|
settings.sphericalMaxDistance = 20;
|
|
settings.sphericalPreferredDistance = 5;
|
|
settings.sphericalMaxItems = 4;
|
|
settings.sphericalMaxStepTurnChange = Math.PI / 8;
|
|
});
|
|
|
|
beforeEach(() => {
|
|
directions = new EdgeCalculatorDirections();
|
|
|
|
edgeCalculator = new EdgeCalculator(settings, directions);
|
|
|
|
helper = new EdgeCalculatorHelper();
|
|
});
|
|
|
|
beforeEach(() => {
|
|
image = helper.createDefaultImage(true);
|
|
|
|
potentialEdge1 = helper.createPotentialEdge("pkey1");
|
|
potentialEdge1.distance = settings.sphericalPreferredDistance;
|
|
potentialEdge1.spherical = false;
|
|
|
|
potentialEdge2 = helper.createPotentialEdge("pkey2");
|
|
potentialEdge2.distance = settings.sphericalPreferredDistance;
|
|
potentialEdge2.spherical = false;
|
|
});
|
|
|
|
it("should prefer a step forward edge with preferred distance", () => {
|
|
potentialEdge1.distance = settings.sphericalPreferredDistance + 1;
|
|
potentialEdge2.distance = settings.sphericalPreferredDistance;
|
|
|
|
let sphericalEdges = edgeCalculator.computeSphericalEdges(image, [potentialEdge1, potentialEdge2]);
|
|
|
|
expect(sphericalEdges.length).toBe(1);
|
|
|
|
let sphericalEdge = sphericalEdges[0];
|
|
|
|
expect(sphericalEdge.target).toBe(potentialEdge2.id);
|
|
expect(sphericalEdge.data.direction).toBe(NavigationDirection.StepForward);
|
|
});
|
|
|
|
it("should prefer a step forward edge with preferred distance", () => {
|
|
potentialEdge1.distance = settings.sphericalPreferredDistance - 1;
|
|
potentialEdge2.distance = settings.sphericalPreferredDistance;
|
|
|
|
let sphericalEdges = edgeCalculator.computeSphericalEdges(image, [potentialEdge1, potentialEdge2]);
|
|
|
|
expect(sphericalEdges.length).toBe(1);
|
|
|
|
let sphericalEdge = sphericalEdges[0];
|
|
|
|
expect(sphericalEdge.target).toBe(potentialEdge2.id);
|
|
expect(sphericalEdge.data.direction).toBe(NavigationDirection.StepForward);
|
|
});
|
|
|
|
it("should prefer a step forward edge with smaller motion change", () => {
|
|
potentialEdge1.motionChange = Math.PI / 18;
|
|
potentialEdge2.motionChange = Math.PI / 36;
|
|
|
|
let sphericalEdges = edgeCalculator.computeSphericalEdges(image, [potentialEdge1, potentialEdge2]);
|
|
|
|
expect(sphericalEdges.length).toBe(1);
|
|
|
|
let sphericalEdge = sphericalEdges[0];
|
|
|
|
expect(sphericalEdge.target).toBe(potentialEdge2.id);
|
|
expect(sphericalEdge.data.direction).toBe(NavigationDirection.StepForward);
|
|
});
|
|
|
|
it("should prefer a step forward edge with smaller motion change", () => {
|
|
potentialEdge1.motionChange = -Math.PI / 18;
|
|
potentialEdge2.motionChange = -Math.PI / 36;
|
|
|
|
let sphericalEdges = edgeCalculator.computeSphericalEdges(image, [potentialEdge1, potentialEdge2]);
|
|
|
|
expect(sphericalEdges.length).toBe(1);
|
|
|
|
let sphericalEdge = sphericalEdges[0];
|
|
|
|
expect(sphericalEdge.target).toBe(potentialEdge2.id);
|
|
expect(sphericalEdge.data.direction).toBe(NavigationDirection.StepForward);
|
|
});
|
|
|
|
it("should prefer a step forward edge with same merge connected component", () => {
|
|
potentialEdge1.sameMergeCC = false;
|
|
potentialEdge2.sameMergeCC = true;
|
|
|
|
let sphericalEdges = edgeCalculator.computeSphericalEdges(image, [potentialEdge1, potentialEdge2]);
|
|
|
|
expect(sphericalEdges.length).toBe(1);
|
|
|
|
let sphericalEdge = sphericalEdges[0];
|
|
|
|
expect(sphericalEdge.target).toBe(potentialEdge2.id);
|
|
expect(sphericalEdge.data.direction).toBe(NavigationDirection.StepForward);
|
|
});
|
|
});
|
|
|
|
describe("EdgeCalculator.computeSphericalEdges", () => {
|
|
let edgeCalculator: EdgeCalculator;
|
|
let settings: EdgeCalculatorSettings;
|
|
let directions: EdgeCalculatorDirections;
|
|
|
|
let helper: EdgeCalculatorHelper;
|
|
|
|
let image: Image;
|
|
|
|
let potentialEdge1: PotentialEdge;
|
|
let potentialEdge2: PotentialEdge;
|
|
let potentialEdge3: PotentialEdge;
|
|
let potentialEdge4: PotentialEdge;
|
|
|
|
beforeEach(() => {
|
|
settings = new EdgeCalculatorSettings();
|
|
settings.sphericalMinDistance = 0.1;
|
|
settings.sphericalMaxDistance = 20;
|
|
settings.sphericalPreferredDistance = 5;
|
|
settings.sphericalMaxItems = 4;
|
|
});
|
|
|
|
beforeEach(() => {
|
|
directions = new EdgeCalculatorDirections();
|
|
edgeCalculator = new EdgeCalculator(settings, directions);
|
|
|
|
helper = new EdgeCalculatorHelper();
|
|
});
|
|
|
|
beforeEach(() => {
|
|
image = helper.createDefaultImage(true);
|
|
|
|
potentialEdge1 = helper.createPotentialEdge("pkey1");
|
|
potentialEdge1.distance = settings.sphericalMaxDistance / 2;
|
|
potentialEdge1.spherical = false;
|
|
|
|
potentialEdge2 = helper.createPotentialEdge("pkey2");
|
|
potentialEdge2.distance = settings.sphericalMaxDistance / 2;
|
|
potentialEdge2.spherical = false;
|
|
|
|
potentialEdge3 = helper.createPotentialEdge("pkey3");
|
|
potentialEdge3.distance = settings.sphericalMaxDistance / 2;
|
|
potentialEdge3.spherical = false;
|
|
|
|
potentialEdge4 = helper.createPotentialEdge("pkey4");
|
|
potentialEdge4.distance = settings.sphericalMaxDistance / 2;
|
|
potentialEdge4.spherical = false;
|
|
});
|
|
|
|
it("should have a forward, left, backward and right spherical edge at the same motion", () => {
|
|
potentialEdge1.directionChange = 0;
|
|
potentialEdge2.directionChange = -Math.PI / 2;
|
|
potentialEdge3.directionChange = Math.PI;
|
|
potentialEdge4.directionChange = Math.PI / 2;
|
|
|
|
let sphericalEdges = edgeCalculator.computeSphericalEdges(
|
|
image,
|
|
[potentialEdge1, potentialEdge2, potentialEdge3, potentialEdge4]);
|
|
|
|
expect(sphericalEdges.length).toBe(4);
|
|
|
|
for (let sphericalEdge of sphericalEdges) {
|
|
if (sphericalEdge.target === potentialEdge1.id) {
|
|
expect(sphericalEdge.data.direction).toBe(NavigationDirection.StepForward);
|
|
} else if (sphericalEdge.target === potentialEdge2.id) {
|
|
expect(sphericalEdge.data.direction).toBe(NavigationDirection.StepLeft);
|
|
} else if (sphericalEdge.target === potentialEdge3.id) {
|
|
expect(sphericalEdge.data.direction).toBe(NavigationDirection.StepBackward);
|
|
} else if (sphericalEdge.target === potentialEdge4.id) {
|
|
expect(sphericalEdge.data.direction).toBe(NavigationDirection.StepRight);
|
|
}
|
|
}
|
|
});
|
|
|
|
it("should not have any step edges in the spherical edge direction", () => {
|
|
potentialEdge1.spherical = true;
|
|
|
|
potentialEdge2.directionChange = 0;
|
|
potentialEdge3.directionChange = Math.PI / 2;
|
|
potentialEdge4.directionChange = Math.PI;
|
|
|
|
let sphericalEdges = edgeCalculator.computeSphericalEdges(
|
|
image,
|
|
[potentialEdge1, potentialEdge2, potentialEdge3, potentialEdge4]);
|
|
|
|
expect(sphericalEdges.length).toBe(1);
|
|
|
|
let sphericalEdge = sphericalEdges[0];
|
|
|
|
expect(sphericalEdge.target).toBe(potentialEdge1.id);
|
|
expect(sphericalEdge.data.direction).toBe(NavigationDirection.Spherical);
|
|
});
|
|
|
|
it("should not have a step left or right edge based on step forward edges", () => {
|
|
potentialEdge1.directionChange = 0;
|
|
potentialEdge1.motionChange = Math.PI / 18;
|
|
|
|
potentialEdge2.directionChange = Math.PI / 4;
|
|
potentialEdge2.motionChange = Math.PI / 4 + Math.PI / 36;
|
|
|
|
potentialEdge3.directionChange = 3 * Math.PI / 4;
|
|
potentialEdge3.motionChange = Math.PI / 4 + Math.PI / 36;
|
|
|
|
let sphericalEdges = edgeCalculator.computeSphericalEdges(
|
|
image,
|
|
[potentialEdge1, potentialEdge2, potentialEdge3]);
|
|
|
|
expect(sphericalEdges.length).toBe(1);
|
|
|
|
let sphericalEdge = sphericalEdges[0];
|
|
|
|
expect(sphericalEdge.target).toBe(potentialEdge1.id);
|
|
expect(sphericalEdge.data.direction).toBe(NavigationDirection.StepForward);
|
|
});
|
|
});
|
|
|
|
describe("EdgeCalculator.computePerspectiveToSphericalEdges", () => {
|
|
let calculator: EdgeCalculator;
|
|
let settings: EdgeCalculatorSettings;
|
|
let directions: EdgeCalculatorDirections;
|
|
|
|
let helper: EdgeCalculatorHelper;
|
|
|
|
let image: Image;
|
|
let potentialEdge1: PotentialEdge;
|
|
let potentialEdge2: PotentialEdge;
|
|
|
|
beforeEach(() => {
|
|
settings = new EdgeCalculatorSettings();
|
|
settings.sphericalMinDistance = 0.1;
|
|
settings.sphericalMaxDistance = 20;
|
|
settings.sphericalPreferredDistance = 5;
|
|
settings.sphericalMaxItems = 4;
|
|
});
|
|
|
|
beforeEach(() => {
|
|
directions = new EdgeCalculatorDirections();
|
|
calculator = new EdgeCalculator(settings, directions);
|
|
|
|
helper = new EdgeCalculatorHelper();
|
|
});
|
|
|
|
beforeEach(() => {
|
|
image = helper.createDefaultImage();
|
|
|
|
potentialEdge1 = helper.createPotentialEdge("pkey1");
|
|
potentialEdge1.distance = settings.sphericalMaxDistance / 2;
|
|
potentialEdge1.spherical = true;
|
|
|
|
potentialEdge2 = helper.createPotentialEdge("pkey2");
|
|
potentialEdge2.distance = settings.sphericalMaxDistance / 2;
|
|
potentialEdge2.spherical = true;
|
|
});
|
|
|
|
it("should return a spherical edge", () => {
|
|
let sphericalEdges = calculator.computePerspectiveToSphericalEdges(image, [potentialEdge1]);
|
|
|
|
expect(sphericalEdges.length).toBe(1);
|
|
|
|
let sphericalEdge = sphericalEdges[0];
|
|
|
|
expect(sphericalEdge.target).toBe(potentialEdge1.id);
|
|
expect(sphericalEdge.data.direction).toBe(NavigationDirection.Spherical);
|
|
});
|
|
|
|
it("should not return a spherical edge when image is spherical", () => {
|
|
image = helper.createDefaultImage(true);
|
|
|
|
let sphericalEdges = calculator.computePerspectiveToSphericalEdges(image, [potentialEdge1]);
|
|
|
|
expect(sphericalEdges.length).toBe(0);
|
|
});
|
|
|
|
it("should return only one spherical edge", () => {
|
|
let sphericalEdges = calculator.computePerspectiveToSphericalEdges(image, [potentialEdge1, potentialEdge2]);
|
|
|
|
expect(sphericalEdges.length).toBe(1);
|
|
});
|
|
|
|
it("should return the spherical edge closest to preferred distance", () => {
|
|
potentialEdge1.distance = settings.sphericalPreferredDistance - 1;
|
|
potentialEdge2.distance = settings.sphericalPreferredDistance;
|
|
|
|
let sphericalEdges = calculator.computePerspectiveToSphericalEdges(image, [potentialEdge1, potentialEdge2]);
|
|
|
|
expect(sphericalEdges.length).toBe(1);
|
|
|
|
let sphericalEdge = sphericalEdges[0];
|
|
|
|
expect(sphericalEdge.target).toBe(potentialEdge2.id);
|
|
expect(sphericalEdge.data.direction).toBe(NavigationDirection.Spherical);
|
|
});
|
|
|
|
it("should return the spherical edge preferring forward motion", () => {
|
|
potentialEdge1.motionChange = -Math.PI / 9;
|
|
potentialEdge2.motionChange = Math.PI / 18;
|
|
|
|
let sphericalEdges = calculator.computePerspectiveToSphericalEdges(image, [potentialEdge1, potentialEdge2]);
|
|
|
|
expect(sphericalEdges.length).toBe(1);
|
|
|
|
let sphericalEdge = sphericalEdges[0];
|
|
|
|
expect(sphericalEdge.target).toBe(potentialEdge2.id);
|
|
expect(sphericalEdge.data.direction).toBe(NavigationDirection.Spherical);
|
|
});
|
|
|
|
it("should return the spherical edge preferring same connected component", () => {
|
|
potentialEdge1.sameMergeCC = false;
|
|
potentialEdge2.sameMergeCC = true;
|
|
|
|
let sphericalEdges = calculator.computePerspectiveToSphericalEdges(image, [potentialEdge1, potentialEdge2]);
|
|
|
|
expect(sphericalEdges.length).toBe(1);
|
|
|
|
let sphericalEdge = sphericalEdges[0];
|
|
|
|
expect(sphericalEdge.target).toBe(potentialEdge2.id);
|
|
expect(sphericalEdge.data.direction).toBe(NavigationDirection.Spherical);
|
|
});
|
|
});
|