Skip to content

Instantly share code, notes, and snippets.

@maurolepore
Last active January 26, 2018 12:06
Show Gist options
  • Save maurolepore/bcafbf378e10aae2dd597508ffd1d1d6 to your computer and use it in GitHub Desktop.
Save maurolepore/bcafbf378e10aae2dd597508ffd1d1d6 to your computer and use it in GitHub Desktop.

https://github.com/forestgeo/ttt/issues/33 Author: Gabriel Arellano gabriel.arellano.torres@gmail.com

# A general function to calculate distances in a n-dimensional toroid:
dist_in_torus <- function(x, lower = rep(-Inf, ncol(x)), upper = rep(Inf, ncol(x)))
{
	# x: the matrix with the coordinates of the points
	# lower and upper: the minimum and maximum possible values of the coordinates along each dimension
	
	# By default, this function returns the distance in the Euclidean space
	# by assuming borders infinitely apart (i.e. points in a small portion
	# of an infinitely large toroid).
	
	# The shortest distance in the toroid is the hypotenuse
	# of the smallest hyper-triangle. The 'internal' distance
	# is the typical distance based on the coordinates, as
	# in the Euclidean space. The 'external' distance is
	# crossing borders, going around. There are only
	# two ways of measuring distance along each dimension.
	
	n = ncol(x) # number of dimensions
	ranges <- upper - lower # size of the n-dimensional space considered
	
	# Internal and external cathetuses along each dimension:
	internal.cats <- sapply(1:n, function(i) abs(outer(x[,i], x[,i], '-')), simplify = "array")
	external.cats <- sapply(1:n, function(i) ranges[i] - internal.cats[,,i])
	
	# The shortest cathetuses along each dimension
	# define the smallest hyper-triangle:
	shortest.cats <- pmin(internal.cats, external.cats)
	
	# Application of the Pythagorean theorem across layers:
	hypo <- sqrt(rowSums(shortest.cats^2, dims = 2))
	return(hypo)
}

# Example
x <- data.frame(runif(10, min = 3, max = 5),  runif(10, min = 13, max = 15))

d0 <- dist(x) # Euclidean distances
d1 <- dist_in_torus(x) # default behaviour
d2 <- dist_in_torus(x, lower = c(3, 13), upper = c(5, 15)) # distances in the toroid

par(mfrow = c(1, 3))
plot(x, xlim = c(3, 5), ylim = c(13, 15), xlab = "x", ylab = "y")
plot(c(d0), c(as.dist(d1)),  main = "default = Euclidean = infinite toroid"); abline(0, 1)
plot(c(d0), c(as.dist(d2)), main = "finite toroid"); abline(0, 1)

@maurolepore
Copy link
Author

maurolepore commented Jan 26, 2018

.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment