##The following program computes the Euclidean distance between two points point1 and point2.
 
distonplane <- function(point1,point2)
{
diff <- point1 - point2
distance <- sqrt(sum(diff^2))
distance
}


#The following program computes the distance on the surface of the earth between two points point1 and point2. Both the points are of the form (Longitude, Latitude)
  
geodetic.distance <- function(point1, point2)
{
R <- 6371
p1rad <- point1 * pi/180
p2rad <- point2 * pi/180
d <- sin(p1rad[2])*sin(p2rad[2])+cos(p1rad[2])*cos(p2rad[2])*cos(abs(p1rad[1]-p2rad[1]))	
d <- acos(d)
R*d
}

#The following function computes the distance on the surface of the earth between two points point1 and point2, by measuring the length of the chord between the two points. This approximation is better than the no.curvature.distance.stretch - both the points are of the form (Longitude, Latitude)

distance.chord <- function(point1,point2)
{
R <- 6371

p1rad <- point1 * pi/180
p2rad <- point2 * pi/180

lat <- p1rad[2]
lon <- p1rad[1]

u1 <- c(cos(lat)*cos(lon), cos(lat)*sin(lon), sin(lat))

lat <- p2rad[2]
lon <- p2rad[1]

u2 <- c(cos(lat)*cos(lon),cos(lat)*sin(lon),sin(lat))

R*sqrt(sum((u1-u2)^2))

}

#Inter-site chordal distance matrix
distance.chord.matrix <- function(long, lat) {

NSITES <- length(long)
latitude <- lat	
longitude <- long	
loc <- cbind(longitude, latitude)	

d <- matrix(nrow=NSITES, ncol=NSITES)	

for(i in 1:(NSITES-1)) {	
d[i,i] <- 0.0		
	for (j in (i+1):NSITES) {					
	d[i,j] <- distance.chord(loc[i,],loc[j,])
	d[j,i] <- d[i,j]
	}	
}
d[NSITES, NSITES] <- 0.0
d
}

#The following program computes the distance on the surface of the earth between two points point1 and point2, ignoring the curvarture, and straightening the arc of latitude and longitude. So it uses Euclidean distance to approximate the geodetic distance, making necessary scale adjustments, but often leads to gross over-estimation, as we move towards the poles. Both the points are of the form (Longitude, Latitude)

distance.stretch <- function(point1,point2)
{
R <- 6371
p1rad <- point1 * pi/180
p2rad <- point2 * pi/180
distance <- R*distonplane(p1rad, p2rad)
distance
}


#Inter-site stretched distance matrix
distance.stretch.matrix <- function(long, lat) {

NSITES <- length(long)
latitude <- lat	
longitude <- long	
loc <- cbind(longitude, latitude)	

d <- matrix(nrow=NSITES, ncol=NSITES)	

for(i in 1:(NSITES-1)) {	
d[i,i] <- 0.0		
	for (j in (i+1):NSITES) {					
	d[i,j] <- distance.stretch(loc[i,],loc[j,])
	d[j,i] <- d[i,j]
	}	
}
d[NSITES, NSITES] <- 0.0
d
}

#The following function transforms spherical coordinates to Euclidean coordinates. Input a Nx2 matrix with each row = (Longitude,Latitude) for N sites.

spherical.to.cartesian <- function(point)
{
R <- 6371

prad <- point * pi / 180

lat <- prad[,2]
lon <- prad[,1]

u <- c(R*cos(lat)*cos(lon), R*cos(lat)*sin(lon), R*sin(lat))

u 
}


#Here is my program to compute geodetic inter-site distance matrix. Input requires *vectors* in degrees. 

geodetic.distance.matrix <- function (long,lat) {		

NSITES <- length(lat)
R <- 6371

latitude <- lat	
longitude <- long	
latlong <- cbind(latitude, longitude)*pi/180	

d <- matrix(nrow=NSITES, ncol=NSITES)	

for(i in 1:(NSITES-1)) {	
d[i,i] <- 1.0		
	for (j in (i+1):NSITES) {					
	d[i,j] <- sin(latlong[i,1]) * sin(latlong[j,1]) + 			cos(latlong[i,1]) * cos(latlong[j,1])	*				cos(abs(latlong[i,2] - latlong[j,2]))
	d[j,i] <- d[i,j]
	}	
}
d[NSITES, NSITES] <- 1.0
d <- R*acos(d)
d

}

#Here is another version of the above program - with a dataframe as input, having lat and long as components.
geodetic.distance.dataframe <- function(dataframe, lat, long) {	
	NSITES <- nrow(dataframe)
		
	latitude <- dataframe$lat	
	longitude <- dataframe$long	

	latlong <- cbind(latitude, longitude)*pi/180	

	d <- matrix(nrow=NSITES, ncol=NSITES)

	for(i in 1:(NSITES-1)) {		
	d[i,i] <- 1.0
		for (j in (i+1):NSITES) {			
			d[i,j] <- sin(latlong[i,1])*sin(latlong[j,1]) + cos(latlong[i,1]) * cos(latlong[j,1])*cos(abs(latlong[i,2] - latlong[j,2]))			
			d[j,i] <- d[i,j]		
		}	
	}

d[NSITES, NSITES] <- 1.0
d <- acos(d)

for (i in 1: NSITES) { 	
	for (j in i:NSITES) { 		
		if (d[i,j] < 0.00000000001) {d[i,j] <- 0}
			d[j,i] <- d[i,j]	 	
		}
	}
d <- ifelse (d < 0.000000000001, 0.0, d)
R <- 6371
d <- R*d
d

}


#Montse Fuentes' program to compute geodetic distance: equivalent to geodetic.distance

rdistearth<-
function(loc1, loc2)
{
        if(missing(loc2))
                loc2 <- loc1
        R <- 6371
        lat <- loc1[, 2]
        lon <- loc1[, 1]
        coslat1 <- cos((lat * pi)/180)
        sinlat1 <- sin((lat * pi)/180)
        coslon1 <- cos((lon * pi)/180)
        sinlon1 <- sin((lon * pi)/180)
        lat <- loc2[, 2]
        lon <- loc2[, 1]
        coslat2 <- cos((lat * pi)/180)
        sinlat2 <- sin((lat * pi)/180)
        coslon2 <- cos((lon * pi)/180)
        sinlon2 <- sin((lon * pi)/180)
        PP1 <- cbind(coslat1 * coslon1, coslat1 * sinlon1, sinlat1)
        PP2 <- cbind(coslat2 * coslon2, coslat2 * sinlon2, sinlat2)
        pp <- (PP1 %*% t(PP2))
        R * acos(ifelse(pp > 1, 1, pp))
}

#Fuentes' style program to compute chordal distance
library(fields)
rdistchord <-
function(loc1, loc2)
{
        if(missing(loc2))
                loc2 <- loc1
        R <- 6371
        lat <- loc1[, 2]
        lon <- loc1[, 1]
        coslat1 <- cos((lat * pi)/180)
        sinlat1 <- sin((lat * pi)/180)
        coslon1 <- cos((lon * pi)/180)
        sinlon1 <- sin((lon * pi)/180)
        lat <- loc2[, 2]
        lon <- loc2[, 1]
        coslat2 <- cos((lat * pi)/180)
        sinlat2 <- sin((lat * pi)/180)
        coslon2 <- cos((lon * pi)/180)
        sinlon2 <- sin((lon * pi)/180)
        PP1 <- cbind(coslat1 * coslon1, coslat1 * sinlon1, sinlat1)
        PP2 <- cbind(coslat2 * coslon2, coslat2 * sinlon2, sinlat2)
        pp <- rdist(PP1,PP2)
        R * pp
}

#Fuentes' style program to compute euclid distance

rdisteuclid <-
function(loc1, loc2)
{
        if(missing(loc2))
                loc2 <- loc1
        R <- 6371
        lat <- loc1[, 2]
        lon <- loc1[, 1]
        x1 <- lat * (pi/180)
        y1 <- lon * (pi/180)
        lat <- loc2[, 2]
        lon <- loc2[, 1]
        x2 <- lat * (pi/180)
        y2 <- lon * (pi/180)
        PP1 <- cbind(x1, y1)
        PP2 <- cbind(x2, y2)
        pp <- rdist(PP1,PP2)
        R * pp
}

#Montse Fuentes' projection on the plane Centered around the center of gravity

lonlat.to.miles<-
function(lon.lat)
{
        x <- lon.lat[, 1]
        y <- lon.lat[, 2]
        mx <- mean(x)
        my <- mean(y)
        temp <- cbind(rep(mx, 2), range(y))
        sy <- rdistearth(temp)[2, 1]
        temp <- cbind(range(x), rep(my, 2))
        sx <- rdistearth(temp)[2, 1]
        temp <- list(x = sx/(max(x) - min(x)), y = sy/(max(y) - min(y)))
        cbind((x - mx) * temp$x, (y - my) * temp$y)
}

#detach(package:fields)
