Distance

Benchmark created on


Setup

function getRandomArbitrary(min, max) {
  return Math.random() * (max - min) + min;
}

function get_x(e)
{
	if("real_x" in e) return e.real_x;
	return e.x;
}

function get_y(e)
{
	if("real_y" in e) return e.real_y;
	return e.y;
}

function get_width(e) // visual width
{
	if(e.proxy_character) return e.awidth;
	if("awidth" in e) return e.awidth;
	return (e.width||0)/(e.mscale||1);
}

function get_height(e) // visual height
{
	if(e.proxy_character) return e.aheight;
	if("aheight" in e) return e.aheight;
	return (e.height||0)/(e.mscale||1);
}

function distance(_a, _b) {
	// https://discord.com/channels/238332476743745536/1025784763958693958
	if (!_a || !_b) return 99999999;
	if ("in" in _a && "in" in _b && _a.in != _b.in) return 99999999;
	if ("map" in _a && "map" in _b && _a.map != _b.map) return 99999999;

	const a_x = get_x(_a)
	const a_y = get_y(_a)
	const b_x = get_x(_b)
	const b_y = get_y(_b)
  
	const a_w2 = get_width(_a) / 2
	const a_h = get_height(_a)
	const b_w2 = get_width(_b) / 2
	const b_h = get_height(_b)

	// Check if they're just 2 points
	if(a_w2 == 0 && a_h == 0 && b_w2 == 0 && b_h == 0) return Math.hypot(a_x - b_x, a_y - b_y)

	// Check overlap
	if ((a_x - a_w2) <= (b_x + b_w2)
		&& (a_x + a_w2) >= (b_x - b_w2)
		&& (a_y) >= (b_y - b_h) 
		&& (a_y - a_h) <= (b_y) ) return 0

	// TODO: If one is just a single point, we're computing 8 needless calculations.
	// Compare the 4 corners to each other
	let min = 99999999
	for(const a_c of [{ x: a_x + a_w2, y: a_y - a_h},
					  { x: a_x + a_w2, y: a_y},
					  { x: a_x - a_w2, y: a_y - a_h},
					  { x: a_x - a_w2, y: a_y}]) {
	  for(const b_c of [{ x: b_x + b_w2, y: b_y - b_h},
						{ x: b_x + b_w2, y: b_y},
						{ x: b_x - b_w2, y: b_y - b_h},
						{ x: b_x - b_w2, y: b_y}]) {
		const d = Math.hypot(a_c.x - b_c.x, a_c.y - b_c.y)
		if(d < min) min = d
	  }
	}
	return min
}

function newDistance(a, b) {
	// https://discord.com/channels/238332476743745536/1025784763958693958
	if (!a || !b) return 99999999;
	if ("in" in a && "in" in b && a.in != b.in) return 99999999;
	if ("map" in a && "map" in b && a.map != b.map) return 99999999;

	const a_x = get_x(a);
	const a_y = get_y(a);
	const b_x = get_x(b);
	const b_y = get_y(b);

	const aHalfWidth = get_width(a) / 2;
	const aHeight = get_height(a);
	const bHalfWidth = get_width(b) / 2;
	const bHeight = get_height(b);

	// Compute bounds of each rectangle
	const aLeft = a_x - aHalfWidth;
	const aRight = a_x + aHalfWidth;
	const aTop = a_y - aHeight;
	const aBottom = a_y;

	const bLeft = b_x - bHalfWidth;
	const bRight = b_x + bHalfWidth;
	const bTop = b_y - bHeight;
	const bBottom = b_y;

	const dx = Math.max(bLeft - aRight, aLeft - bRight, 0);
	const dy = Math.max(bTop - aBottom, aTop - bBottom, 0);

	return Math.hypot(dx, dy);
}

const randomA = { x: getRandomArbitrary(-1000, 1000), y: getRandomArbitrary(-1000, 1000), width: Math.max(0, getRandomArbitrary(-100, 100)), height: Math.max(0, getRandomArbitrary(0, 100)) }
const randomB = { x: getRandomArbitrary(-1000, 1000), y: getRandomArbitrary(-1000, 1000), width: Math.max(0, getRandomArbitrary(-100, 100)), height: Math.max(0, getRandomArbitrary(0, 100)) }

Test runner

Ready to run.

Testing in
TestOps/sec
Old Distance
for(let i = 0; i < 1000; i++) {
	distance(randomA, randomB)
}
ready
New Distance
for(let i = 0; i < 1000; i++) {
	newDistance(randomA, randomB)
}
ready
Same or less than the original
for(let i = 0; i < 100; i++) {
	const randomA = { x: getRandomArbitrary(-1000, 1000), y: getRandomArbitrary(-1000, 1000), width: Math.max(0, getRandomArbitrary(-100, 100)), height: Math.max(0, getRandomArbitrary(0, 100)) }
	const randomB = { x: getRandomArbitrary(-1000, 1000), y: getRandomArbitrary(-1000, 1000), width: Math.max(0, getRandomArbitrary(-100, 100)), height: Math.max(0, getRandomArbitrary(-100, 100)) }
	const origResult = distance(randomA, randomB);
	const newResult = newDistance(randomA, randomB);
	const difference = Math.abs(newResult - origResult)
	if(newResult > origResult) {console.error(randomA); console.error(randomB); console.error(origResult, newResult, difference); throw new Error('Increase in distance detected') }
}
ready

Revisions

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