Skip to content

Commit

Permalink
Add rules to distance calculation
Browse files Browse the repository at this point in the history
No diagonal moves allowed.
Near-unit moves are OK.

refs #12, #13
  • Loading branch information
frostburn committed Mar 29, 2024
1 parent f7051aa commit 70028d6
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 4 deletions.
17 changes: 17 additions & 0 deletions src/__tests__/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,23 @@ describe('Kraig Grady lattice', () => {
{x1: 0, y1: 0, x2: 0, y2: -40, type: 'primary'},
]);
});

it('connects fractional monzos separated by a near-unit edge', () => {
const monzos = [
[0, -1 / 3],
[0, 0.66666666],
];
const options = kraigGrady9();
const {edges} = spanLattice(monzos, options);
expect(edges).toHaveLength(1);
});

it("doesn't connect fractional monzos separated by diagonal unit-edges", () => {
const monzos = [[], [0, 0.5, 0.5]];
const options = kraigGrady9();
const {edges} = spanLattice(monzos, options);
expect(edges).toHaveLength(0);
});
});

describe("Scott Dakota's PR24 lattice", () => {
Expand Down
30 changes: 26 additions & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import {LOG_PRIMES, dot, mmod, monzosEqual, sub} from 'xen-dev-utils';

// Small radius of tolerance to accept near unit distances between fractional coordinates as edges.
const EPSILON = 1e-6;

/**
* The type of an edge connecting two vertices or a gridline.
*
Expand Down Expand Up @@ -202,20 +205,39 @@ export function mergeEdges(edges: Edge[]) {
}

/**
* Calculate the taxicab norm / Manhattan distance between two vectors.
* Calculate the taxicab norm / Manhattan distance between two integral vectors.
* Restrict movement to whole steps for fractional vectors.
* Has a tolerance for small errors.
* @param a Prime exponents of a musical interval.
* @param b Prime exponents of a musical interval.
* @returns Integer representing the number of "moves" required to reach `b`from `a`. `NaN` if no legal moves exist.
*/
function taxicabDistance(a: number[], b: number[]): number {
function taxicabDistance(
a: number[],
b: number[],
tolerance = EPSILON
): number {
if (a.length > b.length) {
return taxicabDistance(b, a);
}
let result = 0;
for (let i = 0; i < a.length; ++i) {
result += Math.abs(a[i] - b[i]);
const distance = Math.abs(a[i] - b[i]);
const move = Math.round(distance);
if (Math.abs(distance - move) <= tolerance) {
result += move;
} else {
return NaN;
}
}
for (let i = a.length; i < b.length; ++i) {
result += Math.abs(b[i]);
const distance = Math.abs(b[i]);
const move = Math.round(distance);
if (Math.abs(distance - move) <= tolerance) {
result += move;
} else {
return NaN;
}
}
return result;
}
Expand Down

0 comments on commit 70028d6

Please sign in to comment.