| Title: | Spherical Descriptors of Geographic Distributions |
|---|---|
| Description: | Characterization of distribution data on the surface of a sphere. The primary group of these metrics describe the extent of a distribution, geographic ranges. The calculation of geographic descriptors can be executed using point coordinate data, vector polygons, as well as cells on a discretized sphere. Besides using spherical implementations, the package offers the exploration of partial results for visual diagnostics. |
| Authors: | Adam T. Kocsis [cre, aut] (ORCID: <https://orcid.org/0000-0002-9028-665X>), Elizabeth M. Dowding [ctb] (ORCID: <https://orcid.org/0000-0002-2423-8254>), FAU GeoZentrum Nordbayern [fnd] |
| Maintainer: | Adam T. Kocsis <[email protected]> |
| License: | GPL-3 |
| Version: | 0.1.0 |
| Built: | 2026-09-16 15:23:13 UTC |
| Source: | https://github.com/adamkocsis/orange |
This is an example occurrence record data.frame of a single terrestrial species.
GBIF.org (30 June 2026) GBIF Occurrence Download https://doi.org/10.15468/dl.s7zhvp
data(bradypus)data(bradypus)
A data.frame with 1466 observations and 6 variables:
scientificNameTaxon name.
basisOfRecordThe basis of the record.
elevationElevation of recors
decimalLongitudeLongitude in decimal degrees.
decimalLatitudeLatitude in decimal degrees.
Calculate centroid of a point cloud
centroid(x, ...) ## S4 method for signature 'matrix' centroid( x, long = NULL, lat = NULL, duplicates = FALSE, plot = FALSE, plot.args = NULL ) ## S4 method for signature 'data.frame' centroid( x, tax = NULL, long = "long", lat = "lat", duplicates = FALSE, plot = FALSE, plot.args = NULL )centroid(x, ...) ## S4 method for signature 'matrix' centroid( x, long = NULL, lat = NULL, duplicates = FALSE, plot = FALSE, plot.args = NULL ) ## S4 method for signature 'data.frame' centroid( x, tax = NULL, long = "long", lat = "lat", duplicates = FALSE, plot = FALSE, plot.args = NULL )
x |
Eiher a 2-column numeric matrix with two columns: longitudes and latitudes, or a |
... |
Additional arguments passed to class-specific methods. |
long |
|
lat |
|
duplicates |
|
plot |
Logical, should the result be plotted? Will plot over active plot (as in |
plot.args |
List arguments passed to the plotting function: |
tax |
|
Either a single numeric or a list with an estimate and other information.
# Records data(pinna) nobilis <- pinna[pinna$species=="Pinna nobilis", ] plot(nobilis[c("decimalLongitude", "decimalLatitude")], pch=16, col="#00BBAA66") # Number of unique coordinate pairs cent <- centroid(nobilis, long="decimalLongitude", lat="decimalLatitude") points(cent[1], cent[2], col="darkred", pch=3, lwd=4, cex=4)# Records data(pinna) nobilis <- pinna[pinna$species=="Pinna nobilis", ] plot(nobilis[c("decimalLongitude", "decimalLatitude")], pch=16, col="#00BBAA66") # Number of unique coordinate pairs cent <- centroid(nobilis, long="decimalLongitude", lat="decimalLatitude") points(cent[1], cent[2], col="darkred", pch=3, lwd=4, cex=4)
Empty world map (Plate Carée)
emptymap( xlim = c(-180, 180), ylim = c(-90, 90), grat = c(30, 30), col = "#DDDDFE", grat.col = "#FFFFFF", lwd = 2, thick = lwd * 2, border = grat.col )emptymap( xlim = c(-180, 180), ylim = c(-90, 90), grat = c(30, 30), col = "#DDDDFE", grat.col = "#FFFFFF", lwd = 2, thick = lwd * 2, border = grat.col )
xlim |
Standard |
ylim |
Standard |
grat |
Graticule resolution. Use |
col |
Plot background, RGBA possible. |
grat.col |
Graticule color RGBA possible. |
lwd |
The baseline thickness of the lines. |
thick |
The 0-coordinate circles are highlighted with thicker lines, given here. |
border |
Border color of rectange on the outside of the plot. |
The function has no return value.
data(kentsamples) emptymap() points(kentsamples$central_s, pch=16, col=1) points(kentsamples$arctic_m, pch=16, col=2) points(kentsamples$antarctic_l, pch=16, col=3) points(kentsamples$dateline_l, pch=16, col=4)data(kentsamples) emptymap() points(kentsamples$central_s, pch=16, col=1) points(kentsamples$arctic_m, pch=16, col=2) points(kentsamples$antarctic_l, pch=16, col=3) points(kentsamples$dateline_l, pch=16, col=4)
Proportion of gap cells in an icosahedral grid.
gappiness(x, s, ...) ## S4 method for signature 'character,trigrid' gappiness(x, s, exclude = NULL, full = FALSE) ## S4 method for signature 'matrix,trigrid' gappiness( x, s, long = NULL, lat = NULL, duplicates = FALSE, plot = FALSE, plot.args = NULL, full = FALSE, exclude = NULL )gappiness(x, s, ...) ## S4 method for signature 'character,trigrid' gappiness(x, s, exclude = NULL, full = FALSE) ## S4 method for signature 'matrix,trigrid' gappiness( x, s, long = NULL, lat = NULL, duplicates = FALSE, plot = FALSE, plot.args = NULL, full = FALSE, exclude = NULL )
x |
The list of faces that are part of the shape. |
s |
Spatial discretization strucutre (currently only |
... |
Arguments passed to class-specific methods. |
exclude |
The list of faces that is to be excluded from the calculation |
full |
|
long |
|
lat |
|
duplicates |
|
plot |
Logical, should the result be plotted? Will plot over active plot (as in |
plot.args |
List arguments passed to the plotting function: |
Gappiness refers to proporion of area that are covered by the internal gaps that defined by a set of discretized cells or a point set that covers some cells in a discretization structre.
A proportion that gives the ratio of hole-cells compared to all occupied cells.
# 1. Only cells # create a grid hex <- hexagrid(2, sf=TRUE) # an example shape shape <- paste0("F", c(4, 5, 11, 13, 15, 21, 24, 26, 32, 33, 34, 35, 36)) plot(hex, border="gray80") plot(hex, shape, col="red", add=TRUE) # the gappiness gap <- gappiness(shape, hex, full=TRUE) gap # plot the first gap plot(hex, names(gap$holes[gap$holes==1]), col="#00555577", add=TRUE) # points set.seed(7) rand <- icosa::rpsphere(20, output="polar") occ <- locate(hex, rand) plot(hex, border="gray80") plot(hex, occ, col="red", add=TRUE) points(rand, col="green", pch=3, cex=2) # gappiness gap <- gappiness(occ, hex, full=TRUE) plot(hex, names(gap$holes), col="orange", add=TRUE)# 1. Only cells # create a grid hex <- hexagrid(2, sf=TRUE) # an example shape shape <- paste0("F", c(4, 5, 11, 13, 15, 21, 24, 26, 32, 33, 34, 35, 36)) plot(hex, border="gray80") plot(hex, shape, col="red", add=TRUE) # the gappiness gap <- gappiness(shape, hex, full=TRUE) gap # plot the first gap plot(hex, names(gap$holes[gap$holes==1]), col="#00555577", add=TRUE) # points set.seed(7) rand <- icosa::rpsphere(20, output="polar") occ <- locate(hex, rand) plot(hex, border="gray80") plot(hex, occ, col="red", add=TRUE) points(rand, col="green", pch=3, cex=2) # gappiness gap <- gappiness(occ, hex, full=TRUE) plot(hex, names(gap$holes), col="orange", add=TRUE)
Geographic test and demonstration sample set
data(kentsamples)data(kentsamples)
A liest with 16 matrices (1000 x 2) with columns being equal to longitudes and latitudes.
scientificnameTaxon name.
central_sCentral position, small spread.
central_mCentral position, medium spread.
central_lCentral position, large spread.
central_xlCentral position, extra large spread.
arctic_sArctic position, small spread.
arctic_mArctic position, medium spread.
arctic_lArctic position, large spread.
arctic_xlArctic position, extra large spread.
antarctic_sAntarctic position, small spread.
antarctic_mAntarctic position, medium spread.
antarctic_lAntarctic position, large spread.
antarctic_xlAntarctic position, extra large spread.
dateline_sDateline position, small spread.
dateline_mDateline position, medium spread.
dateline_lDateline position, large spread.
dateline_xlDateline position, extra large spread.
A set of coordinates generated from Kent distributions with the sample number n = 1000. The samples are elements of a list, 16 in total with the combination of location and spread (i.e. the kappa parameter or the Kent distribution). There are four locations: central (0°N 0°E), arctic (85°N 5°E), antarctic (85°S 5°E) and dateline (170°E 5°N), and there are four sizes: small (s, kappa = 50), medium (m, kappa = 15), large (l, kappa = 5), and extra-large (xl, kappa = 2).
Calculate latitudinal ranges
latrange(x, ...) ## S4 method for signature 'matrix' latrange( x, long = NULL, lat = NULL, q = 1, duplicates = FALSE, plot = FALSE, plot.args = NULL, full = FALSE ) ## S4 method for signature 'data.frame' latrange( x, tax = NULL, q = 1, long = "long", lat = "lat", duplicates = FALSE, plot = FALSE, plot.args = NULL, full = FALSE )latrange(x, ...) ## S4 method for signature 'matrix' latrange( x, long = NULL, lat = NULL, q = 1, duplicates = FALSE, plot = FALSE, plot.args = NULL, full = FALSE ) ## S4 method for signature 'data.frame' latrange( x, tax = NULL, q = 1, long = "long", lat = "lat", duplicates = FALSE, plot = FALSE, plot.args = NULL, full = FALSE )
x |
Either a 2D numeric |
... |
Arguments passed to class-specific methods. |
long |
|
lat |
|
q |
|
duplicates |
|
plot |
Logical, should the result be plotted? Will plot over active plot (as in |
plot.args |
List arguments passed to the plotting function: |
full |
|
tax |
|
Either a single numeric or a list with an estimate and other information. If iterated using 'tax', then either a named vector or list of lists.
# 1. Records data(pinna) # Subset to Pinna nobilis nobilis <- pinna[pinna$species=="Pinna nobilis", ] plot(nobilis[c("decimalLongitude", "decimalLatitude")], pch=16, col="#00BBAA66") # Number of unique coordinate pairs lr <- latrange(nobilis, long="decimalLongitude", lat="decimalLatitude", full=TRUE) abline(h=lr$range, col="darkred", lty=3, lwd=4)# 1. Records data(pinna) # Subset to Pinna nobilis nobilis <- pinna[pinna$species=="Pinna nobilis", ] plot(nobilis[c("decimalLongitude", "decimalLatitude")], pch=16, col="#00BBAA66") # Number of unique coordinate pairs lr <- latrange(nobilis, long="decimalLongitude", lat="decimalLatitude", full=TRUE) abline(h=lr$range, col="darkred", lty=3, lwd=4)
This family of metrics rely on the maximum distance within a point cloud
maxdist(x, s, ...) mgcd(x, ...) ## S4 method for signature 'matrix,missing' maxdist( x, dm = NULL, long = NULL, lat = NULL, duplicates = FALSE, plot = FALSE, plot.args = NULL, full = FALSE, q = 1 ) ## S4 method for signature 'data.frame,missing' maxdist( x, long = "long", lat = "lat", tax = NULL, dm = NULL, duplicates = FALSE, q = 1, plot = FALSE, plot.args = NULL, full = FALSE )maxdist(x, s, ...) mgcd(x, ...) ## S4 method for signature 'matrix,missing' maxdist( x, dm = NULL, long = NULL, lat = NULL, duplicates = FALSE, plot = FALSE, plot.args = NULL, full = FALSE, q = 1 ) ## S4 method for signature 'data.frame,missing' maxdist( x, long = "long", lat = "lat", tax = NULL, dm = NULL, duplicates = FALSE, q = 1, plot = FALSE, plot.args = NULL, full = FALSE )
x |
Either a 2D numeric |
s |
Substitute spatial structure. An icosahedral grid object the inherits from the |
... |
Additional arguments passed to class-specific methods. |
dm |
If there is a pre-made distance matrix, it can be plugged in here. If this is provided, the default coordinates will not be used. |
long |
|
lat |
|
duplicates |
|
plot |
Logical, should the result be plotted? Will plot over active plot (as in |
plot.args |
List arguments passed to the plotting function: |
full |
|
q |
|
tax |
|
This metrics includes maximum great circle distance and similar methods.
A list with an estimate an two indices the rows of the input matrix that represent the longest great circle (or one of them).
# 1. Records data(pinna) # Subset to Pinna nobilis nobilis <- pinna[pinna$species=="Pinna nobilis", ] plot(nobilis[c("decimalLongitude", "decimalLatitude")], pch=16, col="#00BBAA66") # 2. calculate and visualize mgcd <- maxdist(nobilis, long="decimalLongitude", lat="decimalLatitude", plot=TRUE, full=TRUE)# 1. Records data(pinna) # Subset to Pinna nobilis nobilis <- pinna[pinna$species=="Pinna nobilis", ] plot(nobilis[c("decimalLongitude", "decimalLatitude")], pch=16, col="#00BBAA66") # 2. calculate and visualize mgcd <- maxdist(nobilis, long="decimalLongitude", lat="decimalLatitude", plot=TRUE, full=TRUE)
This family of metrics rely on constructing a minimum spanning tree from the distances between the points, and use its length to describe spreading.
mstlength(x, s, ...) ## S4 method for signature 'matrix,missing' mstlength( x, dm = NULL, long = NULL, lat = NULL, duplicates = FALSE, plot = FALSE, plot.args = NULL, full = FALSE, q = 1 ) ## S4 method for signature 'data.frame,missing' mstlength( x, long = "long", lat = "lat", tax = NULL, dm = NULL, duplicates = FALSE, q = 1, plot = FALSE, plot.args = NULL, full = FALSE )mstlength(x, s, ...) ## S4 method for signature 'matrix,missing' mstlength( x, dm = NULL, long = NULL, lat = NULL, duplicates = FALSE, plot = FALSE, plot.args = NULL, full = FALSE, q = 1 ) ## S4 method for signature 'data.frame,missing' mstlength( x, long = "long", lat = "lat", tax = NULL, dm = NULL, duplicates = FALSE, q = 1, plot = FALSE, plot.args = NULL, full = FALSE )
x |
Either a 2D numeric |
s |
Structure to replace the points, either missing (coordinate pairs) or a |
... |
Additional arguments passed to class-specific methods. |
dm |
If there is a pre-made distance matrix, it can be plugged in here. If this is provided, the default coordinates will not be used. |
long |
|
lat |
|
duplicates |
|
plot |
Logical, should the result be plotted? Will plot over active plot (as in |
plot.args |
List arguments passed to the plotting function: |
full |
|
q |
|
tax |
|
This metrics includes maximum great circle distance and similar methods.
A list with an estimate an two indices the rows of the input matrix that represent the length of the tree (or one of them).
# 1. Records data(pinna) # Subset to Pinna nobilis nobilis <- pinna[pinna$species=="Pinna nobilis", ] plot(nobilis[c("decimalLongitude", "decimalLatitude")], pch=16, col="#00BBAA66") # 2. calculate and visualize mst <- mstlength(nobilis, long="decimalLongitude", lat="decimalLatitude", plot=TRUE, full=TRUE) mst$estimate# 1. Records data(pinna) # Subset to Pinna nobilis nobilis <- pinna[pinna$species=="Pinna nobilis", ] plot(nobilis[c("decimalLongitude", "decimalLatitude")], pch=16, col="#00BBAA66") # 2. calculate and visualize mst <- mstlength(nobilis, long="decimalLongitude", lat="decimalLatitude", plot=TRUE, full=TRUE) mst$estimate
High-level, abstract function to calculate how many or what proporotion of components in a pre-specified spatial structure is occupied by a distribution dataset
occupancy(x, s, ...) ## S4 method for signature 'matrix,missing' occupancy(x, long = NULL, lat = NULL, full = FALSE, prop = NULL) ## S4 method for signature 'data.frame,missing' occupancy( x, tax = NULL, long = "long", lat = "lat", full = FALSE, listarray = TRUE, prop = NULL ) ## S4 method for signature 'data.frame,character' occupancy(x, s, tax = NULL, full = FALSE, prop = NULL, listarray = TRUE) ## S4 method for signature 'matrix,trigrid' occupancy( x, s, long = NULL, lat = NULL, q = 1, plot = FALSE, plot.args = NULL, full = FALSE, prop = NULL ) ## S4 method for signature 'data.frame,trigrid' occupancy( x, s, long = "long", lat = "lat", tax = NULL, q = 1, plot = FALSE, plot.args = NULL, full = FALSE, prop = NULL )occupancy(x, s, ...) ## S4 method for signature 'matrix,missing' occupancy(x, long = NULL, lat = NULL, full = FALSE, prop = NULL) ## S4 method for signature 'data.frame,missing' occupancy( x, tax = NULL, long = "long", lat = "lat", full = FALSE, listarray = TRUE, prop = NULL ) ## S4 method for signature 'data.frame,character' occupancy(x, s, tax = NULL, full = FALSE, prop = NULL, listarray = TRUE) ## S4 method for signature 'matrix,trigrid' occupancy( x, s, long = NULL, lat = NULL, q = 1, plot = FALSE, plot.args = NULL, full = FALSE, prop = NULL ) ## S4 method for signature 'data.frame,trigrid' occupancy( x, s, long = "long", lat = "lat", tax = NULL, q = 1, plot = FALSE, plot.args = NULL, full = FALSE, prop = NULL )
x |
Eiher a 2-column numeric matrix with two columns: longitudes and latitudes, or a |
s |
Structure to be occupied, either |
... |
Additional arguments passed to class-specific methods. |
long |
|
lat |
|
full |
Logical switch indicating whether only the estimate should be shown ( |
prop |
Should counts be returned ( |
tax |
|
listarray |
If the full traceable output is required, should this be organized with list-array (native output of tapply). |
q |
Minimum occupancy with |
plot |
Logical, should the result be plotted? Will plot over active plot (as in |
plot.args |
List arguments passed to the plotting function: |
The function by default returns counts (i.e. natural numbers) of how many discrete units are occupied.
However, there are many cases, when proportions are much more useful, which can be set with the prop argument.
Proportions are either global (prop="global") or relative (prop="relative"). Global proportions express how much of the overall spatial structure (s) is occupied; for example, what is the proportion of cells in a grid that are occupied.
This method is only applicable, when s is defined as a spatial structure that is independent from x.
In contrast, relative proportional occupancies express proportions in the sampled set, i.e. what proportion of the overall sampled grid cells or localities are occupied by a taxon. This is particularly useful when tax!=NULL.
For single subsets (tax=NULL) either a single numeric or an orange list with an estimate and other information. Iterations for multiple taxa result in a named numeric vector or a list.
# I. Single taxon: Pinna nobils # 1. Records data(pinna) # Subset to Pinna nobilis nobilis <- pinna[pinna$species=="Pinna nobilis", ] # Number of unique coordinate pairs cpairs <- occupancy(nobilis, long="decimalLongitude", lat="decimalLatitude") # 2. Occupancy in icosahedral grid hex <- hexagrid(deg=5, sf=TRUE) plot(nobilis[c("decimalLongitude", "decimalLatitude")], pch=16, col="#00BBAA66", xlim=c(-20,45), ylim=c(20,60)) plot(hex, border="gray70", add=TRUE) # calculate occupancy occ <- occupancy(nobilis, s=hex, plot=TRUE, long="decimalLongitude", lat="decimalLatitude", full=TRUE) # manual coloring from full output plot(hex, occ$occupied, add=TRUE, col="#00BB0088")# I. Single taxon: Pinna nobils # 1. Records data(pinna) # Subset to Pinna nobilis nobilis <- pinna[pinna$species=="Pinna nobilis", ] # Number of unique coordinate pairs cpairs <- occupancy(nobilis, long="decimalLongitude", lat="decimalLatitude") # 2. Occupancy in icosahedral grid hex <- hexagrid(deg=5, sf=TRUE) plot(nobilis[c("decimalLongitude", "decimalLatitude")], pch=16, col="#00BBAA66", xlim=c(-20,45), ylim=c(20,60)) plot(hex, border="gray70", add=TRUE) # calculate occupancy occ <- occupancy(nobilis, s=hex, plot=TRUE, long="decimalLongitude", lat="decimalLatitude", full=TRUE) # manual coloring from full output plot(hex, occ$occupied, add=TRUE, col="#00BB0088")
Spherical Ranges and Parametrization of Geographic Shapes
A collation of tools and metrics to characterize distribution data on the surface of a sphere or an ellipsoid. The primary group of these metrics is those that describe the extent of a distribution (geographic ranges). The calculation of geographic ranges can be executed using point coordinates data, vector polygons, as well as cells on a discretized sphere. Besides ensuring the use a geometrically correct implementations, the package offers the exploration of partial results for visual diagnostics. This is still the pre-alpha version. Notes about found bugs and suggestions are more than welcome!
Adam T. Kocsis ([email protected])
Useful links:
This is an example occurrence record data.frame with multiple taxa. Occurrence records downloaded from OBIS on 2026-07-01.
data(pinna)data(pinna)
A data.frame with 1466 observations and 6 variables:
scientificNameTaxon name.
speciesSpecies name.
basisOfRecordThe basis of the record.
yearYear.
depthDepth in meters.
decimalLongitudeLongitude in decimal degrees.
decimalLatitudeLatitude in decimal degrees.
Plotting of spherical hulls
## S3 method for class 'shull' plot(x, add = FALSE, ...)## S3 method for class 'shull' plot(x, add = FALSE, ...)
x |
Spherical hull object. |
add |
Logical parameter specifying whether the previous plot should be overwritten. |
... |
Additional plotting parameters as defined in par. |
The function has no return value.
This family of metrics rely on estimating the distance of an extent from a fixed point.
radius(x, s, ...) ## S4 method for signature 'matrix,missing' radius( x, p = NULL, long = NULL, lat = NULL, duplicates = FALSE, plot = FALSE, plot.args = NULL, full = FALSE, q = 1 ) ## S4 method for signature 'data.frame,missing' radius( x, p = NULL, long = "long", lat = "lat", tax = NULL, duplicates = FALSE, q = 1, plot = FALSE, plot.args = NULL, full = FALSE )radius(x, s, ...) ## S4 method for signature 'matrix,missing' radius( x, p = NULL, long = NULL, lat = NULL, duplicates = FALSE, plot = FALSE, plot.args = NULL, full = FALSE, q = 1 ) ## S4 method for signature 'data.frame,missing' radius( x, p = NULL, long = "long", lat = "lat", tax = NULL, duplicates = FALSE, q = 1, plot = FALSE, plot.args = NULL, full = FALSE )
x |
Either a 2D numeric |
s |
Structure to substitute the points, either missing (using coordinate pairs) or a |
... |
Additional arguments passed to class-specific methods. |
p |
A single point of reference (longitude/latitude). If missing, the point of reference will be the centroid given by |
long |
|
lat |
|
duplicates |
|
plot |
Logical, should the result be plotted? Will plot over active plot (as in |
plot.args |
List arguments passed to the plotting function: |
full |
|
q |
|
tax |
|
This group of methods rely on calculating single distances.
A list with an estimate an two indices the rows of the input matrix that represent the length of the tree (or one of them).
# 1. Records data(pinna) # Subset to Pinna nobilis nobilis <- pinna[pinna$species=="Pinna nobilis", ] plot(nobilis[c("decimalLongitude", "decimalLatitude")], pch=16, col="#00BBAA66") # 2. calculate and visualize rad <- radius(nobilis, long="decimalLongitude", lat="decimalLatitude", plot=TRUE, full=TRUE)# 1. Records data(pinna) # Subset to Pinna nobilis nobilis <- pinna[pinna$species=="Pinna nobilis", ] plot(nobilis[c("decimalLongitude", "decimalLatitude")], pch=16, col="#00BBAA66") # 2. calculate and visualize rad <- radius(nobilis, long="decimalLongitude", lat="decimalLatitude", plot=TRUE, full=TRUE)
Identify the center of a small circle based on three points of a sphere
sc_center(x, origin = c(0, 0, 0), output = "polar")sc_center(x, origin = c(0, 0, 0), output = "polar")
x |
A matrix of 3 points, either polar longitude and latitude coordinates, or XYZ Cartesian coordinates. |
origin |
The origin of the sphere. |
output |
If set to "polar" then the function will return the longitude and latitude of the small circle center. |
A list with two elements, the center o the small circle and the surface radius of the small circle.
# generate 3 points on a sphere set.seed(2) ps <- icosa::rpsphere(3, output="polar") small <- sc_center(x=ps) circle<- sc_shape(x=small$center, r=small$r, output="polar") plot(NULL, NULL, xlim=c(-180, 180), ylim=c(-90, 90)) points(ps, col="red", pch=3, cex=4) points(small$center, col="blue", pch=16) points(circle, col="green", pch=16)# generate 3 points on a sphere set.seed(2) ps <- icosa::rpsphere(3, output="polar") small <- sc_center(x=ps) circle<- sc_shape(x=small$center, r=small$r, output="polar") plot(NULL, NULL, xlim=c(-180, 180), ylim=c(-90, 90)) points(ps, col="red", pch=3, cex=4) points(small$center, col="blue", pch=16) points(circle, col="green", pch=16)
This method calculates the plane of the small circle and uses the normal to evaluate whether points are in or outside the small circle.
sc_in(x, center, r, origin = c(0, 0, 0))sc_in(x, center, r, origin = c(0, 0, 0))
x |
A set of points to be determined a matrix of longtidues and latitudes. |
center |
The center of a small circle |
r |
The surface radius of a small circle. |
origin |
The origin of the sphere. |
A numeric vector indicating whether the points are in (1), on (0) or outside of the small circle.
# set.seed(1) # generate a random small circle set.seed(1) pol <- icosa::rpsphere(1000, output="polar") # use the first as a small circle's center center <- pol[1, , drop=FALSE] radius <- 5000 # define radius in km # draw a small circle circle <- sc_shape(x=center, r=radius, breaks=200) # visualize plot(NULL, NULL, xlim=c(-180, 180), ylim=c(-90, 90)) points(pol, col="red", pch=3, cex=2) arcs(circle, col="blue", lwd=2) # find points in small circle (about 10x faster than distance evaluation) inside <- sc_in(x=pol, center=center, r=radius) points(pol[inside==1, ], col="green", pch=3, cex=2)# set.seed(1) # generate a random small circle set.seed(1) pol <- icosa::rpsphere(1000, output="polar") # use the first as a small circle's center center <- pol[1, , drop=FALSE] radius <- 5000 # define radius in km # draw a small circle circle <- sc_shape(x=center, r=radius, breaks=200) # visualize plot(NULL, NULL, xlim=c(-180, 180), ylim=c(-90, 90)) points(pol, col="red", pch=3, cex=2) arcs(circle, col="blue", lwd=2) # find points in small circle (about 10x faster than distance evaluation) inside <- sc_in(x=pol, center=center, r=radius) points(pol[inside==1, ], col="green", pch=3, cex=2)
Creating points along small circles
sc_shape( x = "random", r = NULL, r.ex = NULL, r.rad = NULL, r.deg = NULL, n = NULL, breaks = 100, radius = 6371.007, origin = c(0, 0, 0), output = "polar", sf.type = "polygon", sf.wrap.dateline = TRUE, drop = TRUE )sc_shape( x = "random", r = NULL, r.ex = NULL, r.rad = NULL, r.deg = NULL, n = NULL, breaks = 100, radius = 6371.007, origin = c(0, 0, 0), output = "polar", sf.type = "polygon", sf.wrap.dateline = TRUE, drop = TRUE )
x |
Numeric matrix or character string. Coordinates of the centers of the small circles |
r |
The surface radius of the small circle expressed as great circle distance of the small circle's points from the center of the small circles. |
r.ex |
The extrinsic radius of the small circles, i.e. the radius of the circle in the plane of the small circle. |
r.rad |
The angle of the small circle in radians. |
r.deg |
The angle of the small circle in degrees. |
n |
Integer or NULL. only used if "x= random" |
breaks |
Integer. The number of points to create from the small circle. |
radius |
The radius of the sphere, defaults to the authalic radius of Earth - relevant only for Cartesian output. |
origin |
The center of the sphere (don't touch this, unless you really think you know what you are doing!). |
output |
Output structure for the function. The value output="polar" will return the polar (longitude-latitude) coordinates of the small circles in an array. The setting output="cartesian" will return the 3D cartesian coordinates of the small circles in an array. The option output="sf" will return an sfc geometry collection. |
sf.type |
The type of sf object to be returned. |
sf.wrap.dateline |
Argument indicating whether returned sf object should be wrapped around the dateline. |
drop |
If there is a single small circle to be generated, should its array wrapper be dropped? |
The function generates a single reference (standard) small circle around the (0,0) long-lat coordinates using a given radius. This reference circle is then rotated to match a given center. The function is iterated for multiple radiiand centers (separately!).
Either a numeric array or and sfc geometry collection.
set.seed(1) # generate a random small circle central <- sc_shape(r=6000, breaks=40) plot(NULL, xlim=c(-180, 180), ylim=c(-90,90), xlab="longitude", ylab="latitude") points(central, pch=17, col="gray") # repeat, same radius multiple centers smaller <- sc_shape(x=central, r=1000, breaks=100) for(i in 1:nrow(central)) points(smaller[,,i], col=i, pch=16) # Random circles with different radii diff200 <- sc_shape(r=runif(200, 100, 10000)) plot(NULL, xlim=c(-180, 180), ylim=c(-90,90), xlab="", ylab="", axes=FALSE) for(i in 1:(dim(diff200)[3])){ points(diff200[,,i], col=i,pch=16) } # Same center, different radius cent <- central[10, ,drop=FALSE] outward <- sc_shape(cent, r=seq(100, 15000, length.out=20)) plot(NULL, xlim=c(-180, 180), ylim=c(-90,90), xlab="", ylab="", axes=FALSE) for(i in 1:(dim(outward)[3])){ points(outward[,,i], col=i,pch=16) }set.seed(1) # generate a random small circle central <- sc_shape(r=6000, breaks=40) plot(NULL, xlim=c(-180, 180), ylim=c(-90,90), xlab="longitude", ylab="latitude") points(central, pch=17, col="gray") # repeat, same radius multiple centers smaller <- sc_shape(x=central, r=1000, breaks=100) for(i in 1:nrow(central)) points(smaller[,,i], col=i, pch=16) # Random circles with different radii diff200 <- sc_shape(r=runif(200, 100, 10000)) plot(NULL, xlim=c(-180, 180), ylim=c(-90,90), xlab="", ylab="", axes=FALSE) for(i in 1:(dim(diff200)[3])){ points(diff200[,,i], col=i,pch=16) } # Same center, different radius cent <- central[10, ,drop=FALSE] outward <- sc_shape(cent, r=seq(100, 15000, length.out=20)) plot(NULL, xlim=c(-180, 180), ylim=c(-90,90), xlab="", ylab="", axes=FALSE) for(i in 1:(dim(outward)[3])){ points(outward[,,i], col=i,pch=16) }
Calculation of hull geometries in spherical space
shull(x, s, ...) ## S4 method for signature 'matrix,missing' shull( x, method, long = NULL, lat = NULL, duplicates = FALSE, plot = FALSE, plot.args = NULL, sphererad = authRadius ) ## S4 method for signature 'data.frame,missing' shull(x, long = "long", lat = "lat", ...) ## S4 method for signature 'matrix,trigrid' shull( x, s, method, long = NULL, lat = NULL, duplicates = FALSE, plot = FALSE, plot.args = NULL, sphererad = authRadius, drop = TRUE ) shullarea(x, ...) ## Default S3 method: shullarea( x, method, metric = "area", full = FALSE, sphererad = authRadius, ... ) ## S3 method for class 'shull' shullarea(x, metric = "area", s = NULL, full = FALSE, ...)shull(x, s, ...) ## S4 method for signature 'matrix,missing' shull( x, method, long = NULL, lat = NULL, duplicates = FALSE, plot = FALSE, plot.args = NULL, sphererad = authRadius ) ## S4 method for signature 'data.frame,missing' shull(x, long = "long", lat = "lat", ...) ## S4 method for signature 'matrix,trigrid' shull( x, s, method, long = NULL, lat = NULL, duplicates = FALSE, plot = FALSE, plot.args = NULL, sphererad = authRadius, drop = TRUE ) shullarea(x, ...) ## Default S3 method: shullarea( x, method, metric = "area", full = FALSE, sphererad = authRadius, ... ) ## S3 method for class 'shull' shullarea(x, metric = "area", s = NULL, full = FALSE, ...)
x |
Either a 2-column numeric matrix with two columns: longitudes and latitudes, or a |
s |
An external spatial structure to resolve the hull (e.g. a |
... |
Additional arguments passed to class-specific methods. |
method |
|
long |
|
lat |
|
duplicates |
|
plot |
Logical, should the result be plotted? Will plot over active plot (as in |
plot.args |
List arguments passed to the plotting function: |
sphererad |
|
drop |
|
metric |
|
full |
Logical switch indicating whether only the estimate should be shown ( |
Constructing and enclosing geometry around a distribution on the surface of a sphere represent unique challenges.
The "centroidcircle" method is using the centroid of the distribution as the center of small circle that defines a spherical cap. This is likely not the smallest possible cap to cover the distribution and takes the heterogeneous density of the distribution into account.
A hull-class object, a vector of identifiers (if applicable and drop=FALSE) or the area of te hull as a numeric.
# example data data(kentsamples) p <- kentsamples$dateline_m # plotting plot(NULL, NULL, xlim=c(-180, 180), ylim=c(-90,90), xlab="", ylab="") points(p, pch=3, col="red") # basic spherical hull definition (native) cc <- shull(p, method="centroidcircle") plot(cc, add=TRUE) # spherical hull area calculation shullarea(cc) # basic hull definition (icosahedral grid) hex <- icosa::hexagrid(spacing=8, sf=TRUE) # dropping hull container cc_hex <- shull(p, s=hex, method="centroidcircle") plot(hex, cc_hex, col="#0000DD33", border="#FFFFFF77", add=TRUE) # with shull container cc_hex2 <- shull(p, s=hex, method="centroidcircle", drop=FALSE) shullarea(cc_hex2, s=hex, metric="prop")# example data data(kentsamples) p <- kentsamples$dateline_m # plotting plot(NULL, NULL, xlim=c(-180, 180), ylim=c(-90,90), xlab="", ylab="") points(p, pch=3, col="red") # basic spherical hull definition (native) cc <- shull(p, method="centroidcircle") plot(cc, add=TRUE) # spherical hull area calculation shullarea(cc) # basic hull definition (icosahedral grid) hex <- icosa::hexagrid(spacing=8, sf=TRUE) # dropping hull container cc_hex <- shull(p, s=hex, method="centroidcircle") plot(hex, cc_hex, col="#0000DD33", border="#FFFFFF77", add=TRUE) # with shull container cc_hex2 <- shull(p, s=hex, method="centroidcircle", drop=FALSE) shullarea(cc_hex2, s=hex, metric="prop")