x5-geometry
Version:
Geometry and word processing utilities for XNet
110 lines (109 loc) • 5.69 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const geom_1 = require("../geom");
describe('Geometry Utilities', () => {
describe('haversine', () => {
it('should calculate distance between two points', () => {
// Test with known coordinates (San Francisco to Los Angeles)
const distance = (0, geom_1.haversine)(37.7749, -122.4194, 34.0522, -118.2437);
expect(distance).toBeGreaterThan(500000); // Should be roughly 550km
expect(distance).toBeLessThan(600000);
});
it('should handle same point', () => {
const distance = (0, geom_1.haversine)(0, 0, 0, 0);
expect(distance).toBe(0);
});
});
describe('travel', () => {
it('should calculate new position after travel', () => {
const start = [0, 0];
const result = (0, geom_1.travel)(start[0], start[1], 1000, 1000);
expect(result[0]).toBeGreaterThan(0);
expect(result[1]).toBeGreaterThan(0);
});
it('should travel short distances accurately', () => {
// San Francisco coordinates
const sf = [37.7749, -122.4194];
// Berkeley coordinates (about 25km away)
const berkeley = [37.8715, -122.2730];
// Calculate the distance between SF and Berkeley
const distance = (0, geom_1.haversine)(sf[0], sf[1], berkeley[0], berkeley[1]);
// Calculate the bearing angle (in radians)
const y = Math.sin((berkeley[1] - sf[1]) * Math.PI / 180) * Math.cos(berkeley[0] * Math.PI / 180);
const x = Math.cos(sf[0] * Math.PI / 180) * Math.sin(berkeley[0] * Math.PI / 180) -
Math.sin(sf[0] * Math.PI / 180) * Math.cos(berkeley[0] * Math.PI / 180) * Math.cos((berkeley[1] - sf[1]) * Math.PI / 180);
const bearing = Math.atan2(y, x);
// Calculate the x and y components of the travel vector
const Δx = distance * Math.sin(bearing);
const Δy = distance * Math.cos(bearing);
// Travel from SF to Berkeley
const result = (0, geom_1.travel)(sf[0], sf[1], Δx, Δy);
// The result should be close to Berkeley coordinates
expect(Math.abs(result[0] - berkeley[0])).toBeLessThan(0.01); // Within 0.01 degrees latitude
expect(Math.abs(result[1] - berkeley[1])).toBeLessThan(0.01); // Within 0.01 degrees longitude
});
});
describe('GPS Functions', () => {
it('should encode and decode GPS coordinates', () => {
const original = [37.7749, -122.4194]; // San Francisco
const encoded = (0, geom_1.encodeGPS)(original[0], original[1]);
const decoded = (0, geom_1.decodeGPS)(encoded);
// Allow for small floating point differences due to grid quantization
expect(Math.abs(decoded[0] - original[0])).toBeLessThan(0.1);
expect(Math.abs(decoded[1] - original[1])).toBeLessThan(0.1);
});
it('should handle coordinates within valid range', () => {
const testCases = [
[0, 0], // Origin
[37.7749, -122.4194], // San Francisco
[34.0522, -118.2437], // Los Angeles
[40.7128, -74.0060], // New York
[51.5074, -0.1278], // London
[35.6762, 139.6503], // Tokyo
];
for (const [lat, lon] of testCases) {
const encoded = (0, geom_1.encodeGPS)(lat, lon);
const decoded = (0, geom_1.decodeGPS)(encoded);
// Allow for grid quantization effects
expect(Math.abs(decoded[0] - lat)).toBeLessThan(0.1);
expect(Math.abs(decoded[1] - lon)).toBeLessThan(0.1);
}
});
it('should reject coordinates outside valid range', () => {
const invalidCases = [
[71, 0], // Latitude too high
[-71, 0], // Latitude too low
[0, 181], // Longitude too high
[0, -181], // Longitude too low
];
for (const [lat, lon] of invalidCases) {
expect(() => (0, geom_1.encodeGPS)(lat, lon)).toThrow();
}
});
it('should calculate GPS difference', () => {
const sf = (0, geom_1.encodeGPS)(37.7749, -122.4194); // San Francisco
const la = (0, geom_1.encodeGPS)(34.0522, -118.2437); // Los Angeles
const diff = (0, geom_1.gpsDiff)(sf, la);
expect(diff).toBeGreaterThan(500000); // Should be roughly 550km
expect(diff).toBeLessThan(600000);
});
it('should perform sigma test', () => {
const sf = (0, geom_1.encodeGPS)(37.7749, -122.4194); // San Francisco
const sf2 = (0, geom_1.encodeGPS)(37.7749, -122.4194); // Same coordinates
const result = (0, geom_1.sigmaTest)(sf, sf2);
expect(result).toBe(true);
});
it('should handle coordinate wrapping', () => {
// Test longitude wrapping
const p1 = (0, geom_1.encodeGPS)(0, 179);
const p2 = (0, geom_1.encodeGPS)(0, -179);
const diff = (0, geom_1.gpsDiff)(p1, p2);
expect(diff).toBeLessThan(300000); // Should be roughly 222km at equator
// Test latitude wrapping at maxLat
const p3 = (0, geom_1.encodeGPS)(69, 0);
const p4 = (0, geom_1.encodeGPS)(70, 0);
const latDiff = (0, geom_1.gpsDiff)(p3, p4);
expect(latDiff).toBeLessThan(200000); // Should be roughly 111km
});
});
});