R/distance.r

Defines functions distance3d_coord3d_plane3d distance3d_coord3d_coord3d distance3d_plane3d distance3d_coord3d distance3d distance2d_coord2d_line2d distance2d_coord2d_coord2d distance2d_line2d distance2d_coord2d distance2d distance1d_coord1d_point1d distance1d_coord1d_coord1d distance1d_point1d distance1d_coord1d distance1d abs.Coord3D abs.Coord2D abs.Coord1D

Documented in abs.Coord1D abs.Coord2D abs.Coord3D distance1d distance2d distance3d

#' Compute Euclidean norm
#'
#' `abs()` computes the Euclidean norm for [Coord2D] class objects and [Coord3D] class objects.
#' @param x A [Coord2D] class object or [Coord2D] class object.
#' @examples
#'   z <- complex(real = 1:4, imaginary = 1:4)
#'   p <- as_coord2d(z)
#'   abs(p) # Euclidean norm
#'   # Less efficient ways to calculate same Euclidean norms
#'   sqrt(p * p) # `*` dot product
#'   distance2d(p, as_coord2d(0, 0, 0))
#'
#'   # In {base} R `abs()` calculates Euclidean norm of complex numbers
#'   all.equal(abs(p), abs(z))
#'   all.equal(Mod(p), Mod(z))
#'
#'   p3 <- as_coord3d(x = 1:4, y = 1:4, z = 1:4)
#'   abs(p3)
#' @return A numeric vector
#' @rdname abs.Coord
#' @export
abs.Coord1D <- function(x) {
    abs(x$x)
}


#' @rdname abs.Coord
#' @export
abs.Coord2D <- function(x) {
    sqrt(rowSums(x$xyw[, 1:2, drop = FALSE]^2))
}

#' @rdname abs.Coord
#' @export
abs.Coord3D <- function(x) {
    sqrt(rowSums(x$xyzw[, 1:3, drop = FALSE]^2))
}

#' 1D Euclidean distances
#'
#' `distance1d()` computes 1D Euclidean distances.
#'
#' @param x Either a [Coord1D] or [Point1D] class object
#' @param y Either a [Coord1D] or [Point1D] class object
#' @examples
#' p <- as_coord1d(x = 1:4)
#' distance1d(p, as_coord1d(0))
#' @export
distance1d <- function(x, y) {
    if (is_coord1d(x)) {
        distance1d_coord1d(x, y)
    } else if (is_point1d(x)) {
        distance1d_point1d(x, y)
    } else {
        stop(paste("Don't know how to handle", dQuote(class(x)), "class object"))
    }
}

distance1d_coord1d <- function(x, y) {
    if (is_coord1d(y)) {
        distance1d_coord1d_coord1d(x, y)
    } else if (is_point1d(y)) {
        distance1d_coord1d_point1d(x, y)
    } else {
        stop(paste("Don't know how to handle", dQuote(class(y)), "class object"))
    }
}

distance1d_point1d <- function(x, y) {
    if (is_coord1d(y)) {
        distance1d_coord1d_point1d(y, x)
    } else {
        stop(paste("Don't know how to handle", dQuote(class(y)), "class object"))
    }
}

distance1d_coord1d_coord1d <- function(x, y) {
    n <- max(length(x), length(y))
    x <- rep_len(x, n)
    y <- rep_len(y, n)
    abs(x$x - y$x)
}

distance1d_coord1d_point1d <- function(x, y) {
    distance1d_coord1d_coord1d(x, as_coord1d(y))
}

#' 2D Euclidean distances
#'
#' `distance2d()` computes 2D Euclidean distances.
#'
#' @param x Either a [Coord2D] or [Line2D] class object
#' @param y Either a [Coord2D] or [Line2D] class object
#' @examples
#' p <- as_coord2d(x = 1:4, y = 1:4)
#' distance2d(p, as_coord2d(0, 0))
#' @export
distance2d <- function(x, y) {
    if (is_coord2d(x)) {
        distance2d_coord2d(x, y)
    } else if (is_line2d(x)) {
        distance2d_line2d(x, y)
    } else {
        stop(paste("Don't know how to handle", dQuote(class(x)), "class object"))
    }
}

distance2d_coord2d <- function(x, y) {
    if (is_coord2d(y)) {
        distance2d_coord2d_coord2d(x, y)
    } else if (is_line2d(y)) {
        distance2d_coord2d_line2d(x, y)
    } else {
        stop(paste("Don't know how to handle", dQuote(class(y)), "class object"))
    }
}

distance2d_line2d <- function(x, y) {
    if (is_coord2d(y)) {
        distance2d_coord2d_line2d(y, x)
    } else {
        stop(paste("Don't know how to handle", dQuote(class(y)), "class object"))
    }
}

distance2d_coord2d_coord2d <- function(x, y) {
    n <- max(length(x), length(y))
    x <- rep_len(x, n)
    y <- rep_len(y, n)
    sqrt(rowSums((x$xyw[, 1:2, drop = FALSE] - y$xyw[, 1:2, drop = FALSE])^2))
}

distance2d_coord2d_line2d <- function(x, y) {
    abs(y$a * x$x + y$b * x$y + y$c) / sqrt(y$a^2 + y$b^2)
}

#' 3D Euclidean distances
#'
#' `distance3d()` computes 3D Euclidean distances.
#'
#' @param x Either a [Coord3D] or [Plane3D] class object
#' @param y Either a [Coord3D] or [Plane3D] class object
#' @examples
#' p <- as_coord3d(x = 1:4, y = 1:4, z = 1:4)
#' distance3d(p, as_coord3d("origin"))
#' @export
distance3d <- function(x, y) {
    if (is_coord3d(x)) {
        distance3d_coord3d(x, y)
    } else if (is_plane3d(x)) {
        distance3d_plane3d(x, y)
    } else {
        stop(paste("Don't know how to handle", dQuote(class(x)), "class object"))
    }
}

distance3d_coord3d <- function(x, y) {
    if (is_coord3d(y)) {
        distance3d_coord3d_coord3d(x, y)
    } else if (is_plane3d(y)) {
        distance3d_coord3d_plane3d(x, y)
    } else {
        stop(paste("Don't know how to handle", dQuote(class(y)), "class object"))
    }
}

distance3d_plane3d <- function(x, y) {
    if (is_coord3d(y)) {
        distance3d_coord3d_plane3d(y, x)
    } else {
        stop(paste("Don't know how to handle", dQuote(class(y)), "class object"))
    }
}

distance3d_coord3d_coord3d <- function(x, y) {
    n <- max(length(x), length(y))
    x <- rep_len(x, n)
    y <- rep_len(y, n)
    sqrt(rowSums((x$xyzw[, 1:3, drop = FALSE] - y$xyzw[, 1:3, drop = FALSE])^2))
}

distance3d_coord3d_plane3d <- function(x, y) {
    n <- max(length(x), length(y))
    x <- rep_len(x, n)
    y <- rep_len(y, n)
    abs(y$a * x$x + y$b * x$y + y$c * x$z + y$d) / sqrt(y$a^2 + y$b^2 + y$c^2)
}

Try the affiner package in your browser

Any scripts or data that you put into this service are public.

affiner documentation built on April 4, 2025, 4:42 a.m.