| Title: | A Finer Way to Render 3D Illustrated Objects in 'grid' Using Affine Transformations |
|---|---|
| Description: | Dilate, permute, project, reflect, rotate, shear, and translate 2D and 3D points. Supports parallel projections including oblique projections such as the cabinet projection as well as axonometric projections such as the isometric projection. Use 'grid's "affine transformation" feature to render illustrated flat surfaces. |
| Authors: | Trevor L. Davis [aut, cre] (ORCID: <https://orcid.org/0000-0001-6341-4639>) |
| Maintainer: | Trevor L. Davis <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.4.0-4 |
| Built: | 2026-05-17 06:23:07 UTC |
| Source: | https://github.com/trevorld/affiner |
Dilate, permute, project, reflect, rotate, shear, and translate 2D and 3D points. Supports parallel projections including oblique projections such as the cabinet projection as well as axonometric projections such as the isometric projection. Use 'grid's "affine transformation" feature to render illustrated flat surfaces.
The following affiner function arguments may be set globally via base::options():
The default for the unit argument used by angle() and as_angle().
The default for this option is "degrees".
The default for the unit argument used by affine_settings().
The default for this option is "inches".
The following cli options may also be of interest:
Whether UTF-8 character support should be assumed.
Along with l10n_info() used to determine the default of the
use_unicode argument of format.angle() and print.angle().
Maintainer: Trevor L. Davis [email protected] (ORCID)
Authors:
Trevor L. Davis [email protected] (ORCID)
Useful links:
aabb_polygon2d() creates an axis-aligned bounding box Polygon2D object
covering the range of x.
aabb_polygon2d(x, ...)aabb_polygon2d(x, ...)
x |
A 2D object with a |
... |
Passed to |
A Polygon2D object with $is_convex == TRUE whose vertices are in
counter-clockwise order.
rectangle_polygon2d() for creating a rectangle by center and
dimensions. range() for the bounding-range methods.
# Bounding box for a set of points pts <- as_coord2d( x = runif(20, min = 1, max = 3), y = runif(20, min = 1, max = 5) ) p <- aabb_polygon2d(pts) p$is_convex plot(p, border = "black", col = "cyan") points(pts, pch = 16, cex = 1.5) # Bounding box for an ellipse e <- as_ellipse2d(as_coord2d(1, 1), rx = 2, ry = 1, theta = degrees(30)) p2 <- aabb_polygon2d(e) plot(p2, border = "black", col = "cyan") lines(e, col = "black", lwd = 2)# Bounding box for a set of points pts <- as_coord2d( x = runif(20, min = 1, max = 3), y = runif(20, min = 1, max = 5) ) p <- aabb_polygon2d(pts) p$is_convex plot(p, border = "black", col = "cyan") points(pts, pch = 16, cex = 1.5) # Bounding box for an ellipse e <- as_ellipse2d(as_coord2d(1, 1), rx = 2, ry = 1, theta = degrees(30)) p2 <- aabb_polygon2d(e) plot(p2, border = "black", col = "cyan") lines(e, col = "black", lwd = 2)
abs() computes the Euclidean norm for Coord2D class objects and Coord3D class objects.
## S3 method for class 'Coord1D' abs(x) ## S3 method for class 'Coord2D' abs(x) ## S3 method for class 'Coord3D' abs(x)## S3 method for class 'Coord1D' abs(x) ## S3 method for class 'Coord2D' abs(x) ## S3 method for class 'Coord3D' abs(x)
x |
A numeric vector
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)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)
grid affine transformation feature viewports and transformation functionsaffine_settings() computes grid group affine transformation feature viewport and transformation
function settings given the (x,y) coordinates of the corners of the
affine transformed "viewport" one wishes to draw in.
affine_settings( xy = data.frame(x = c(0, 0, 1, 1), y = c(1, 0, 0, 1)), unit = getOption("affiner_grid_unit", "inches") )affine_settings( xy = data.frame(x = c(0, 0, 1, 1), y = c(1, 0, 0, 1)), unit = getOption("affiner_grid_unit", "inches") )
xy |
An R object with named elements |
unit |
Which |
A named list with the following group affine transformation feature viewport and functions settings:
An affine transformation function to pass to affineGrob() or useGrob().
If getRversion() is less than "4.2.0" will instead be NULL.
A grid::viewport() object to pass to affineGrob() or useGrob().
x-axis sx factor
whether the affine transformed "viewport" is "flipped" horizontally
x-coordinate for viewport
y-coordinate for viewport
Width of viewport
Height of viewport
Default grid::unit() for viewport
angle for viewport
To avoid taking a dependency on affiner you may copy the source of affine_settings()
into your own package under the permissive Unlicense. Either use
usethis::use_standalone("trevorld/affiner", "standalone-affine-settings.r") or
copy the file standalone-affine-settings.r into your R directory and add grid
to the Imports of your DESCRIPTION file.
Intended for use with affineGrob() and grid::useGrob().
See https://www.stat.auckland.ac.nz/~paul/Reports/GraphicsEngine/groups/groups.html
for more information about the group affine transformation feature.
if (require("grid")) { grob <- grobTree(rectGrob(gp = gpar(fill = "blue", col = NA)), circleGrob(gp=gpar(fill="yellow", col = NA)), textGrob("RSTATS", gp=gpar(fontsize=32))) grid.newpage() pushViewport(viewport(width=unit(4, "in"), height=unit(2, "in"))) grid.draw(grob) popViewport() } if (require("grid") && getRversion() >= "4.2.0" && isTRUE(dev.capabilities()$transformations)) { # Only works if active graphics device supports affine transformations # such as `png(type="cairo")` on R 4.2+ vp_define <- viewport(width=unit(2, "in"), height=unit(2, "in")) settings <- affine_settings(xy = list(x = c(1/3, 0/3, 2/3, 3/3), y = c(2/3, 1/3, 1/3, 2/3)), unit = "snpc") affine <- affineGrob(grob, vp_define=vp_define, transform = settings$transform, vp_use = settings$vp) grid.newpage() grid.draw(affine) } if (require("grid") && getRversion() >= "4.2.0" && isTRUE(dev.capabilities()$transformations)) { # Only works if active graphics device supports affine transformations # such as `png(type="cairo")` on R 4.2+ settings <- affine_settings(xy = list(x = c(3/3, 2/3, 0/3, 1/3), y = c(2/3, 1/3, 1/3, 2/3)), unit = "snpc") affine <- affineGrob(grob, vp_define=vp_define, transform = settings$transform, vp_use = settings$vp) grid.newpage() grid.draw(affine) }if (require("grid")) { grob <- grobTree(rectGrob(gp = gpar(fill = "blue", col = NA)), circleGrob(gp=gpar(fill="yellow", col = NA)), textGrob("RSTATS", gp=gpar(fontsize=32))) grid.newpage() pushViewport(viewport(width=unit(4, "in"), height=unit(2, "in"))) grid.draw(grob) popViewport() } if (require("grid") && getRversion() >= "4.2.0" && isTRUE(dev.capabilities()$transformations)) { # Only works if active graphics device supports affine transformations # such as `png(type="cairo")` on R 4.2+ vp_define <- viewport(width=unit(2, "in"), height=unit(2, "in")) settings <- affine_settings(xy = list(x = c(1/3, 0/3, 2/3, 3/3), y = c(2/3, 1/3, 1/3, 2/3)), unit = "snpc") affine <- affineGrob(grob, vp_define=vp_define, transform = settings$transform, vp_use = settings$vp) grid.newpage() grid.draw(affine) } if (require("grid") && getRversion() >= "4.2.0" && isTRUE(dev.capabilities()$transformations)) { # Only works if active graphics device supports affine transformations # such as `png(type="cairo")` on R 4.2+ settings <- affine_settings(xy = list(x = c(3/3, 2/3, 0/3, 1/3), y = c(2/3, 1/3, 1/3, 2/3)), unit = "snpc") affine <- affineGrob(grob, vp_define=vp_define, transform = settings$transform, vp_use = settings$vp) grid.newpage() grid.draw(affine) }
affineGrob() is a grid grob function to facilitate
using the group affine transformation features introduced in R 4.2.
affineGrob( grob, vp_define = NULL, transform = NULL, vp_use = NULL, name = NULL, gp = grid::gpar(), vp = NULL ) grid.affine(...)affineGrob( grob, vp_define = NULL, transform = NULL, vp_use = NULL, name = NULL, gp = grid::gpar(), vp = NULL ) grid.affine(...)
grob |
A grid grob to perform affine transformations on. Passed to |
vp_define |
|
transform |
An affine transformation function.
If |
vp_use |
|
name |
A character identifier (for grid). |
gp |
A |
vp |
A |
... |
Passed to |
Not all graphics devices provided by grDevices or other R packages support the affine transformation feature introduced in R 4.2.
If isTRUE(getRversion() >= '4.2.0') then the active graphics device should support this feature if isTRUE(grDevices::dev.capabilities()$transformations).
In particular the following graphics devices should support the affine transformation feature:
R's grDevices::pdf() device
R's 'cairo' devices e.g. grDevices::cairo_pdf(), grDevices::png(type = 'cairo'), grDevices::svg(), grDevices::x11(type = 'cairo'), etc. If isTRUE(capabilities('cairo')) then R was compiled with support for the 'cairo' devices .
R's 'quartz' devices (since R 4.3.0) e.g. grDevices::quartz(), grDevices::png(type = 'quartz'), etc. If isTRUE(capabilities('aqua')) then R was compiled with support for the 'quartz' devices (generally only TRUE on macOS systems).
ragg's devices (since v1.3.0) e.g. ragg::agg_png(), ragg::agg_capture(), etc.
A grid::gTree() (grob) object of class "affine".
As a side effect grid.affine() draws to the active graphics device.
See affine_settings() for computing good transform and vp_use settings.
See https://www.stat.auckland.ac.nz/~paul/Reports/GraphicsEngine/groups/groups.html
for more information about the group affine transformation feature.
See isocubeGrob() which wraps this function to render isometric cubes.
if (require("grid")) { grob <- grobTree(rectGrob(gp = gpar(fill = "blue", col = NA)), circleGrob(gp=gpar(fill="yellow", col = NA)), textGrob("RSTATS", gp=gpar(fontsize=32))) grid.newpage() pushViewport(viewport(width=unit(4, "in"), height=unit(2, "in"))) grid.draw(grob) popViewport() } if (require("grid") && getRversion() >= "4.2.0" && isTRUE(dev.capabilities()$transformations)) { # Only works if active graphics device supports affine transformations # such as `png(type="cairo")` on R 4.2+ vp_define <- viewport(width=unit(2, "in"), height=unit(2, "in")) affine <- affineGrob(grob, vp_define=vp_define) grid.newpage() pushViewport(viewport(width=unit(4, "in"), height=unit(2, "in"))) grid.draw(affine) popViewport() } if (require("grid") && getRversion() >= "4.2.0" && isTRUE(dev.capabilities()$transformations)) { # Only works if active graphics device supports affine transformations # such as `png(type="cairo")` on R 4.2+ settings <- affine_settings(xy = list(x = c(3/3, 2/3, 0/3, 1/3), y = c(2/3, 1/3, 1/3, 2/3)), unit = "snpc") affine <- affineGrob(grob, vp_define = vp_define, transform = settings$transform, vp_use = settings$vp) grid.newpage() grid.draw(affine) }if (require("grid")) { grob <- grobTree(rectGrob(gp = gpar(fill = "blue", col = NA)), circleGrob(gp=gpar(fill="yellow", col = NA)), textGrob("RSTATS", gp=gpar(fontsize=32))) grid.newpage() pushViewport(viewport(width=unit(4, "in"), height=unit(2, "in"))) grid.draw(grob) popViewport() } if (require("grid") && getRversion() >= "4.2.0" && isTRUE(dev.capabilities()$transformations)) { # Only works if active graphics device supports affine transformations # such as `png(type="cairo")` on R 4.2+ vp_define <- viewport(width=unit(2, "in"), height=unit(2, "in")) affine <- affineGrob(grob, vp_define=vp_define) grid.newpage() pushViewport(viewport(width=unit(4, "in"), height=unit(2, "in"))) grid.draw(affine) popViewport() } if (require("grid") && getRversion() >= "4.2.0" && isTRUE(dev.capabilities()$transformations)) { # Only works if active graphics device supports affine transformations # such as `png(type="cairo")` on R 4.2+ settings <- affine_settings(xy = list(x = c(3/3, 2/3, 0/3, 1/3), y = c(2/3, 1/3, 1/3, 2/3)), unit = "snpc") affine <- affineGrob(grob, vp_define = vp_define, transform = settings$transform, vp_use = settings$vp) grid.newpage() grid.draw(affine) }
affiner_options() returns the affiner package's global options.
affiner_options(..., default = FALSE)affiner_options(..., default = FALSE)
... |
|
default |
If |
A list of option values.
Note this function does not set option values itself but
this list can be passed to options(), withr::local_options(), or withr::with_options().
affiner for a high-level description of relevant global options.
affiner_options() affiner_options(default = TRUE) affiner_options(affiner_angular_unit = "pi-radians")affiner_options() affiner_options(default = TRUE) affiner_options(affiner_angular_unit = "pi-radians")
angle() creates angle vectors with user specified angular unit.
around as_angle() for those angular units.
angle(x = numeric(), unit = getOption("affiner_angular_unit", "degrees")) degrees(x) gradians(x) pi_radians(x) radians(x) turns(x)angle(x = numeric(), unit = getOption("affiner_angular_unit", "degrees")) degrees(x) gradians(x) pi_radians(x) radians(x) turns(x)
x |
An angle vector or an object to convert to it (such as a numeric vector) |
unit |
A string of the desired angular unit. Supports the following strings
(note we ignore any punctuation and space characters as well as any trailing
|
A numeric vector of class "angle". Its "unit" attribute is a standardized string of the specified angular unit.
as_angle(), angular_unit(), and angle-methods.
https://en.wikipedia.org/wiki/Angle#Units for more information about angular units.
# Different representations of the "same" angle angle(180, "degrees") angle(pi, "radians") angle(0.5, "turns") angle(200, "gradians") pi_radians(1) a1 <- angle(180, "degrees") angular_unit(a1) is_angle(a1) as.numeric(a1, "radians") cos(a1) a2 <- as_angle(a1, "radians") angular_unit(a2) is_congruent(a1, a2)# Different representations of the "same" angle angle(180, "degrees") angle(pi, "radians") angle(0.5, "turns") angle(200, "gradians") pi_radians(1) a1 <- angle(180, "degrees") angular_unit(a1) is_angle(a1) as.numeric(a1, "radians") cos(a1) a2 <- as_angle(a1, "radians") angular_unit(a2) is_congruent(a1, a2)
We implemented methods for several base generics for the angle() vectors.
## S3 method for class 'angle' as.double(x, unit = angular_unit(x), ...) ## S3 method for class 'angle' as.complex(x, modulus = 1, ...) ## S3 method for class 'angle' format(x, unit = angular_unit(x), ..., use_unicode = is_utf8_output()) ## S3 method for class 'angle' print(x, unit = angular_unit(x), ..., use_unicode = is_utf8_output()) ## S3 method for class 'angle' abs(x)## S3 method for class 'angle' as.double(x, unit = angular_unit(x), ...) ## S3 method for class 'angle' as.complex(x, modulus = 1, ...) ## S3 method for class 'angle' format(x, unit = angular_unit(x), ..., use_unicode = is_utf8_output()) ## S3 method for class 'angle' print(x, unit = angular_unit(x), ..., use_unicode = is_utf8_output()) ## S3 method for class 'angle' abs(x)
x |
|
unit |
A string of the desired angular unit. Supports the following strings
(note we ignore any punctuation and space characters as well as any trailing
|
... |
Passed to |
modulus |
Numeric vector representing the complex numbers' modulus |
use_unicode |
If |
Mathematical Ops (in particular + and -)
for two angle vectors will (if necessary)
set the second vector's angular_unit() to match the first.
as.numeric() takes a unit argument which can be used to convert angles into other angular units
e.g. angle(x, "degrees") |> as.numeric("radians") to cast a numeric vector x from degrees to radians.
abs() will calculate the angle modulo full turns.
Use is_congruent() to test if two angles are congruent instead of == or all.equal().
Not all implemented methods are documented here and since angle() is a
numeric() class many other S3 generics
besides the explicitly implemented ones should also work with it.
Typical values as usually returned by these base generics.
# Two "congruent" angles a1 <- angle(180, "degrees") a2 <- angle(pi, "radians") print(a1) print(a1, unit = "radians") print(a1, unit = "pi-radians") cos(a1) sin(a1) tan(a1) # mathematical operations will coerce second `angle()` object to # same `angular_unit()` as the first one a1 + a2 a1 - a2 as.numeric(a1) as.numeric(a1, "radians") as.numeric(a1, "turns") # Use `is_congruent()` to check if two angles are "congruent" a1 == a2 isTRUE(all.equal(a1, a2)) is_congruent(a1, a2) is_congruent(a1, a2, mod_turns = FALSE) a3 <- angle(-180, "degrees") # Only congruent modulus full turns a1 == a3 isTRUE(all.equal(a1, a2)) is_congruent(a1, a3) is_congruent(a1, a3, mod_turns = FALSE)# Two "congruent" angles a1 <- angle(180, "degrees") a2 <- angle(pi, "radians") print(a1) print(a1, unit = "radians") print(a1, unit = "pi-radians") cos(a1) sin(a1) tan(a1) # mathematical operations will coerce second `angle()` object to # same `angular_unit()` as the first one a1 + a2 a1 - a2 as.numeric(a1) as.numeric(a1, "radians") as.numeric(a1, "turns") # Use `is_congruent()` to check if two angles are "congruent" a1 == a2 isTRUE(all.equal(a1, a2)) is_congruent(a1, a2) is_congruent(a1, a2, mod_turns = FALSE) a3 <- angle(-180, "degrees") # Only congruent modulus full turns a1 == a3 isTRUE(all.equal(a1, a2)) is_congruent(a1, a3) is_congruent(a1, a3, mod_turns = FALSE)
angular_unit() gets/sets the angular unit of angle() vectors.
angular_unit(x) angular_unit(x) <- valueangular_unit(x) angular_unit(x) <- value
x |
An |
value |
A string of the desired angular unit. See |
angular_unit() returns a string of x's angular unit.
a <- angle(seq(0, 360, by = 90), "degrees") angular_unit(a) print(a) angular_unit(a) <- "turns" angular_unit(a) print(a)a <- angle(seq(0, 360, by = 90), "degrees") angular_unit(a) print(a) angular_unit(a) <- "turns" angular_unit(a) print(a)
as_angle() casts to an angle() vector
as_angle(x, unit = getOption("affiner_angular_unit", "degrees"), ...) ## S3 method for class 'angle' as_angle(x, unit = getOption("affiner_angular_unit", "degrees"), ...) ## S3 method for class 'character' as_angle(x, unit = getOption("affiner_angular_unit", "degrees"), ...) ## S3 method for class 'complex' as_angle(x, unit = getOption("affiner_angular_unit", "degrees"), ...) ## S3 method for class 'Coord2D' as_angle(x, unit = getOption("affiner_angular_unit", "degrees"), ...) ## S3 method for class 'Coord3D' as_angle( x, unit = getOption("affiner_angular_unit", "degrees"), type = c("azimuth", "inclination"), ... ) ## S3 method for class 'Line2D' as_angle(x, unit = getOption("affiner_angular_unit", "degrees"), ...) ## S3 method for class 'Plane3D' as_angle( x, unit = getOption("affiner_angular_unit", "degrees"), type = c("azimuth", "inclination"), ... ) ## S3 method for class 'numeric' as_angle(x, unit = getOption("affiner_angular_unit", "degrees"), ...)as_angle(x, unit = getOption("affiner_angular_unit", "degrees"), ...) ## S3 method for class 'angle' as_angle(x, unit = getOption("affiner_angular_unit", "degrees"), ...) ## S3 method for class 'character' as_angle(x, unit = getOption("affiner_angular_unit", "degrees"), ...) ## S3 method for class 'complex' as_angle(x, unit = getOption("affiner_angular_unit", "degrees"), ...) ## S3 method for class 'Coord2D' as_angle(x, unit = getOption("affiner_angular_unit", "degrees"), ...) ## S3 method for class 'Coord3D' as_angle( x, unit = getOption("affiner_angular_unit", "degrees"), type = c("azimuth", "inclination"), ... ) ## S3 method for class 'Line2D' as_angle(x, unit = getOption("affiner_angular_unit", "degrees"), ...) ## S3 method for class 'Plane3D' as_angle( x, unit = getOption("affiner_angular_unit", "degrees"), type = c("azimuth", "inclination"), ... ) ## S3 method for class 'numeric' as_angle(x, unit = getOption("affiner_angular_unit", "degrees"), ...)
x |
An R object to convert to a |
unit |
A string of the desired angular unit. Supports the following strings
(note we ignore any punctuation and space characters as well as any trailing
|
... |
Further arguments passed to or from other methods |
type |
Use "azimuth" to calculate the azimuthal angle and "inclination" to calculate the inclination angle aka polar angle. |
An angle() vector
as_angle(angle(pi, "radians"), "pi-radians") as_angle(complex(real = 0, imaginary = 1), "degrees") as_angle(as_coord2d(x = 0, y = 1), "turns") as_angle(200, "gradians")as_angle(angle(pi, "radians"), "pi-radians") as_angle(complex(real = 0, imaginary = 1), "degrees") as_angle(as_coord2d(x = 0, y = 1), "turns") as_angle(200, "gradians")
as_coord1d() casts to a Coord1D class object
as_coord1d(x, ...) ## S3 method for class 'character' as_coord1d(x, ...) ## S3 method for class 'Coord2D' as_coord1d( x, permutation = c("xy", "yx"), ..., line = as_line2d("x-axis"), scale = 0 ) ## S3 method for class 'data.frame' as_coord1d(x, ...) ## S3 method for class 'list' as_coord1d(x, ...) ## S3 method for class 'matrix' as_coord1d(x, ...) ## S3 method for class 'numeric' as_coord1d(x, ...) ## S3 method for class 'Coord1D' as_coord1d(x, ...) ## S3 method for class 'Point1D' as_coord1d(x, ...)as_coord1d(x, ...) ## S3 method for class 'character' as_coord1d(x, ...) ## S3 method for class 'Coord2D' as_coord1d( x, permutation = c("xy", "yx"), ..., line = as_line2d("x-axis"), scale = 0 ) ## S3 method for class 'data.frame' as_coord1d(x, ...) ## S3 method for class 'list' as_coord1d(x, ...) ## S3 method for class 'matrix' as_coord1d(x, ...) ## S3 method for class 'numeric' as_coord1d(x, ...) ## S3 method for class 'Coord1D' as_coord1d(x, ...) ## S3 method for class 'Point1D' as_coord1d(x, ...)
x |
An object that can be cast to a Coord1D class object such as a numeric vector of x-coordinates. |
... |
Further arguments passed to or from other methods |
permutation |
Either "xy" (no permutation) or "yx" (permute x and y axes) |
line |
A Line2D object of length one representing the line
you with to reflect across or project to or an object coercible to one by |
scale |
Oblique projection scale factor.
A degenerate |
A Coord1D class object
as_coord1d(x = rnorm(10))as_coord1d(x = rnorm(10))
as_coord2d() casts to a Coord2D class object
as_coord2d(x, ...) ## S3 method for class 'angle' as_coord2d(x, radius = 1, ...) ## S3 method for class 'character' as_coord2d(x, ...) ## S3 method for class 'complex' as_coord2d(x, ...) ## S3 method for class 'Coord3D' as_coord2d( x, permutation = c("xyz", "xzy", "yxz", "yzx", "zyx", "zxy"), ..., plane = as_plane3d("xy-plane"), scale = 0, alpha = angle(45, "degrees"), roll = angle(0, "degrees") ) ## S3 method for class 'data.frame' as_coord2d(x, ...) ## S3 method for class 'list' as_coord2d(x, ...) ## S3 method for class 'matrix' as_coord2d(x, ...) ## S3 method for class 'numeric' as_coord2d(x, y = rep_len(0, length(x)), ...) ## S3 method for class 'Coord2D' as_coord2d(x, ...)as_coord2d(x, ...) ## S3 method for class 'angle' as_coord2d(x, radius = 1, ...) ## S3 method for class 'character' as_coord2d(x, ...) ## S3 method for class 'complex' as_coord2d(x, ...) ## S3 method for class 'Coord3D' as_coord2d( x, permutation = c("xyz", "xzy", "yxz", "yzx", "zyx", "zxy"), ..., plane = as_plane3d("xy-plane"), scale = 0, alpha = angle(45, "degrees"), roll = angle(0, "degrees") ) ## S3 method for class 'data.frame' as_coord2d(x, ...) ## S3 method for class 'list' as_coord2d(x, ...) ## S3 method for class 'matrix' as_coord2d(x, ...) ## S3 method for class 'numeric' as_coord2d(x, y = rep_len(0, length(x)), ...) ## S3 method for class 'Coord2D' as_coord2d(x, ...)
x |
An object that can be cast to a Coord2D class object such as a matrix or data frame of coordinates. |
... |
Further arguments passed to or from other methods |
radius |
A numeric vector of radial distances. |
permutation |
Either "xyz" (no permutation), "xzy" (permute y and z axes), "yxz" (permute x and y axes), "yzx" (x becomes z, y becomes x, z becomes y), "zxy" (x becomes y, y becomes z, z becomes x), "zyx" (permute x and z axes). This permutation is applied before the (oblique) projection. |
plane |
A Plane3D class object representing the plane
you wish to project to or an object coercible to one using |
scale |
Oblique projection foreshortening scale factor.
A (degenerate) |
alpha |
Oblique projection angle (the angle the third axis is projected going off at).
An |
roll |
Rotation of the in-plane coordinate frame around the plane normal
after the azimuth/inclination alignment.
An |
y |
Numeric vector of y-coordinates to be used. |
A Coord2D class object
df <- data.frame(x = sample.int(10, 3), y = sample.int(10, 3)) as_coord2d(df) as_coord2d(complex(real = 3, imaginary = 2)) as_coord2d(angle(90, "degrees"), radius = 2) as_coord2d(as_coord3d(1, 2, 2), alpha = degrees(90), scale = 0.5)df <- data.frame(x = sample.int(10, 3), y = sample.int(10, 3)) as_coord2d(df) as_coord2d(complex(real = 3, imaginary = 2)) as_coord2d(angle(90, "degrees"), radius = 2) as_coord2d(as_coord3d(1, 2, 2), alpha = degrees(90), scale = 0.5)
as_coord3d() casts to a Coord3D class object
as_coord3d(x, ...) ## S3 method for class 'angle' as_coord3d(x, radius = 1, inclination = NULL, z = NULL, ...) ## S3 method for class 'character' as_coord3d(x, ...) ## S3 method for class 'data.frame' as_coord3d(x, ..., z = NULL) ## S3 method for class 'list' as_coord3d(x, ..., z = NULL) ## S3 method for class 'matrix' as_coord3d(x, ...) ## S3 method for class 'numeric' as_coord3d(x, y = rep_len(0, length(x)), z = rep_len(0, length(x)), ...) ## S3 method for class 'Coord3D' as_coord3d(x, ...) ## S3 method for class 'Coord2D' as_coord3d(x, z = rep_len(0, length(x)), ...)as_coord3d(x, ...) ## S3 method for class 'angle' as_coord3d(x, radius = 1, inclination = NULL, z = NULL, ...) ## S3 method for class 'character' as_coord3d(x, ...) ## S3 method for class 'data.frame' as_coord3d(x, ..., z = NULL) ## S3 method for class 'list' as_coord3d(x, ..., z = NULL) ## S3 method for class 'matrix' as_coord3d(x, ...) ## S3 method for class 'numeric' as_coord3d(x, y = rep_len(0, length(x)), z = rep_len(0, length(x)), ...) ## S3 method for class 'Coord3D' as_coord3d(x, ...) ## S3 method for class 'Coord2D' as_coord3d(x, z = rep_len(0, length(x)), ...)
x |
An object that can be cast to a Coord3D class object such as a matrix or data frame of coordinates. |
... |
Further arguments passed to or from other methods |
radius |
A numeric vector. If |
inclination |
Spherical coordinates inclination angle aka polar angle.
|
z |
Numeric vector of z-coordinates to be used |
y |
Numeric vector of y-coordinates to be used
if |
A Coord3D class object
as_coord3d(x = 1, y = 2, z = 3) df <- data.frame(x = sample.int(10, 3), y = sample.int(10, 3), z = sample.int(10, 3)) as_coord3d(df) # Cylindrical coordinates as_coord3d(degrees(90), z = 1, radius = 1) # Spherical coordinates as_coord3d(degrees(90), inclination = degrees(90), radius = 1)as_coord3d(x = 1, y = 2, z = 3) df <- data.frame(x = sample.int(10, 3), y = sample.int(10, 3), z = sample.int(10, 3)) as_coord3d(df) # Cylindrical coordinates as_coord3d(degrees(90), z = 1, radius = 1) # Spherical coordinates as_coord3d(degrees(90), inclination = degrees(90), radius = 1)
as_ellipse2d() casts to an Ellipse2D object.
as_ellipse2d(x, ...) ## S3 method for class 'Coord2D' as_ellipse2d(x, ..., r = 0.5, rx = r, ry = r, theta = angle(0)) ## S3 method for class 'numeric' as_ellipse2d(x, y = 0, ..., r = 0.5, rx = r, ry = rx, theta = angle(0))as_ellipse2d(x, ...) ## S3 method for class 'Coord2D' as_ellipse2d(x, ..., r = 0.5, rx = r, ry = r, theta = angle(0)) ## S3 method for class 'numeric' as_ellipse2d(x, y = 0, ..., r = 0.5, rx = r, ry = rx, theta = angle(0))
x |
Object to cast. Either a Coord2D object of center(s) or a numeric vector of x-coordinates of center(s). |
... |
Ignored; only included for S3 method consistency. |
r |
Numeric vector of (circular) radii (default |
rx |
Numeric vector of x-axis semi-radii (default |
ry |
Numeric vector of y-axis semi-radii (default |
theta |
An |
y |
Numeric vector of y-coordinates of center(s) (used when |
An Ellipse2D object.
# Ellipse from Coord2D center e <- as_ellipse2d(as_coord2d(0, 0), rx = 2, ry = 1, theta = degrees(30)) plot(e) # Multiple ellipses e2 <- as_ellipse2d(x = c(0, 1), y = c(0, 1), rx = c(1, 2), ry = c(0.5, 1)) plot(e2) # Multiple circles from x, y, r vectors c2 <- as_ellipse2d(x = c(0, 1), y = c(0, 1), rx = c(0.3, 0.4)) plot(c2)# Ellipse from Coord2D center e <- as_ellipse2d(as_coord2d(0, 0), rx = 2, ry = 1, theta = degrees(30)) plot(e) # Multiple ellipses e2 <- as_ellipse2d(x = c(0, 1), y = c(0, 1), rx = c(1, 2), ry = c(0.5, 1)) plot(e2) # Multiple circles from x, y, r vectors c2 <- as_ellipse2d(x = c(0, 1), y = c(0, 1), rx = c(0.3, 0.4)) plot(c2)
as_line2d() casts to a Line2D object.
as_line2d(...) ## S3 method for class 'numeric' as_line2d(a, b, c, ...) ## S3 method for class 'angle' as_line2d(theta, p1 = as_coord2d("origin"), ...) ## S3 method for class 'character' as_line2d(x, ...) ## S3 method for class 'Coord2D' as_line2d(normal, p1 = as_coord3d("origin"), p2, ...) ## S3 method for class 'Line2D' as_line2d(line, ...) ## S3 method for class 'Point1D' as_line2d(point, b = 0, ...)as_line2d(...) ## S3 method for class 'numeric' as_line2d(a, b, c, ...) ## S3 method for class 'angle' as_line2d(theta, p1 = as_coord2d("origin"), ...) ## S3 method for class 'character' as_line2d(x, ...) ## S3 method for class 'Coord2D' as_line2d(normal, p1 = as_coord3d("origin"), p2, ...) ## S3 method for class 'Line2D' as_line2d(line, ...) ## S3 method for class 'Point1D' as_line2d(point, b = 0, ...)
... |
Passed to other function such as |
a, b, c
|
Numeric vectors that parameterize the line via the equation |
theta |
Angle of the line represented by an |
p1 |
Point on the line represented by a Coord2D class object. |
x |
A (character) vector to be cast to a Line2D object |
normal |
Normal vector to the line represented by a Coord2D class object. |
p2 |
Another point on the line represented by a Coord2D class object. |
line |
A Line2D object |
point |
A Point1D object |
p1 <- as_coord2d(x = 5, y = 10) p2 <- as_coord2d(x = 7, y = 12) theta <- degrees(45) as_line2d(theta, p1) as_line2d(p1, p2)p1 <- as_coord2d(x = 5, y = 10) p2 <- as_coord2d(x = 7, y = 12) theta <- degrees(45) as_line2d(theta, p1) as_line2d(p1, p2)
as_plane3d() casts to a Plane3D object.
as_plane3d(...) ## S3 method for class 'numeric' as_plane3d(a, b, c, d, ...) ## S3 method for class 'character' as_plane3d(x, ...) ## S3 method for class 'Coord3D' as_plane3d(normal, p1 = as_coord3d("origin"), p2, p3, ...) ## S3 method for class 'Plane3D' as_plane3d(plane, ...) ## S3 method for class 'Point1D' as_plane3d(point, b = 0, c = 0, ...) ## S3 method for class 'Line2D' as_plane3d(line, c = 0, ...)as_plane3d(...) ## S3 method for class 'numeric' as_plane3d(a, b, c, d, ...) ## S3 method for class 'character' as_plane3d(x, ...) ## S3 method for class 'Coord3D' as_plane3d(normal, p1 = as_coord3d("origin"), p2, p3, ...) ## S3 method for class 'Plane3D' as_plane3d(plane, ...) ## S3 method for class 'Point1D' as_plane3d(point, b = 0, c = 0, ...) ## S3 method for class 'Line2D' as_plane3d(line, c = 0, ...)
... |
Passed to other function such as |
a, b, c, d
|
Numeric vectors that parameterize the plane via the equation |
x |
A (character) vector to be cast to a Plane3D object |
normal |
Normal vector to the plane represented by a Coord3D class object. |
p1 |
Point on the plane represented by a Coord3D class object. |
p2, p3
|
Points on the plane represented by Coord3D class objects. |
plane |
A Plane3D object |
point |
A Point1D object |
line |
A Line2D object |
as_point1d() casts to a Point1D object.
as_point1d(...) ## S3 method for class 'numeric' as_point1d(a, b, ...) ## S3 method for class 'character' as_point1d(x, ...) ## S3 method for class 'Coord1D' as_point1d(normal, ...) ## S3 method for class 'Point1D' as_point1d(point, ...)as_point1d(...) ## S3 method for class 'numeric' as_point1d(a, b, ...) ## S3 method for class 'character' as_point1d(x, ...) ## S3 method for class 'Coord1D' as_point1d(normal, ...) ## S3 method for class 'Point1D' as_point1d(point, ...)
... |
Passed to other function such as |
a, b
|
Numeric vectors that parameterize the point via the equation |
x |
A (character) vector to be cast to a Point1D object |
normal |
Coord1D class object. |
point |
A Point1D object |
p1 <- as_point1d(a = 1, b = 0)p1 <- as_point1d(a = 1, b = 0)
as_polygon2d() casts to a Polygon2D object.
as_polygon2d(x, ...) ## S3 method for class 'Coord2D' as_polygon2d(x, convex = NA, ...) ## S3 method for class 'Polygon2D' as_polygon2d(x, convex = NA, ...) ## S3 method for class 'numeric' as_polygon2d(x, y = 0, convex = NA, ...) ## S3 method for class 'Ellipse2D' as_polygon2d(x, n = 60L, type = c("inner", "outer"), ...)as_polygon2d(x, ...) ## S3 method for class 'Coord2D' as_polygon2d(x, convex = NA, ...) ## S3 method for class 'Polygon2D' as_polygon2d(x, convex = NA, ...) ## S3 method for class 'numeric' as_polygon2d(x, y = 0, convex = NA, ...) ## S3 method for class 'Ellipse2D' as_polygon2d(x, n = 60L, type = c("inner", "outer"), ...)
x |
Object to cast. Either a Coord2D object of vertices or a numeric vector of x-coordinates. |
... |
Ignored; only included for S3 method consistency. |
convex |
|
y |
Numeric vector of y-coordinates (used when |
n |
Number of vertices in the approximating polygon (default |
type |
|
A Polygon2D object.
isotoxal_2ngon_polygon2d() and regular_ngon_polygon2d() to
directly construct common polygon shapes.
vertices <- as_coord2d(x = c(0, 1, 1, 0), y = c(0, 0, 1, 1)) p <- as_polygon2d(vertices) p$is_convex print(p) plot(p)vertices <- as_coord2d(x = c(0, 1, 1, 0), y = c(0, 0, 1, 1)) p <- as_polygon2d(vertices) p$is_convex print(p) plot(p)
as_segment2d() creates a Segment2D object.
as_segment2d(...) ## S3 method for class 'Coord2D' as_segment2d(p1, ..., p2, vec) ## S3 method for class 'Polygon2D' as_segment2d(p, ...)as_segment2d(...) ## S3 method for class 'Coord2D' as_segment2d(p1, ..., p2, vec) ## S3 method for class 'Polygon2D' as_segment2d(p, ...)
... |
Ignored. |
p1 |
A Coord2D object of first endpoints. |
p2 |
A Coord2D object of second endpoints.
If missing, |
vec |
A Coord2D object of edge vectors ( |
p |
A Polygon2D object whose edges should be returned. |
A Segment2D object.
p1 <- as_coord2d(x = c(0, 1), y = c(0, 0)) p2 <- as_coord2d(x = c(1, 1), y = c(0, 1)) s <- as_segment2d(p1, p2 = p2) s$p1 s$p2 s$mid_point # From a polygon's edges poly <- as_polygon2d(as_coord2d(x = c(0, 1, 1, 0), y = c(0, 0, 1, 1))) as_segment2d(poly)p1 <- as_coord2d(x = c(0, 1), y = c(0, 0)) p2 <- as_coord2d(x = c(1, 1), y = c(0, 1)) s <- as_segment2d(p1, p2 = p2) s$p1 s$p2 s$mid_point # From a polygon's edges poly <- as_polygon2d(as_coord2d(x = c(0, 1, 1, 0), y = c(0, 0, 1, 1))) as_segment2d(poly)
as_transform1d() casts to a transform1d() affine transformation matrix
as_transform1d(x, ...) ## S3 method for class 'transform1d' as_transform1d(x, ...) ## Default S3 method: as_transform1d(x, ...)as_transform1d(x, ...) ## S3 method for class 'transform1d' as_transform1d(x, ...) ## Default S3 method: as_transform1d(x, ...)
x |
An object that can be cast to a |
... |
Further arguments passed to or from other methods |
A transform1d() object
m <- diag(2L) as_transform1d(m)m <- diag(2L) as_transform1d(m)
as_transform2d() casts to a transform2d() affine transformation matrix
as_transform2d(x, ...) ## S3 method for class 'transform2d' as_transform2d(x, ...) ## Default S3 method: as_transform2d(x, ...)as_transform2d(x, ...) ## S3 method for class 'transform2d' as_transform2d(x, ...) ## Default S3 method: as_transform2d(x, ...)
x |
An object that can be cast to a |
... |
Further arguments passed to or from other methods |
A transform2d() object
m <- diag(3L) as_transform2d(m)m <- diag(3L) as_transform2d(m)
as_transform3d() casts to a transform3d() affine transformation matrix
as_transform3d(x, ...) ## S3 method for class 'transform3d' as_transform3d(x, ...) ## Default S3 method: as_transform3d(x, ...)as_transform3d(x, ...) ## S3 method for class 'transform3d' as_transform3d(x, ...) ## Default S3 method: as_transform3d(x, ...)
x |
An object that can be cast to a |
... |
Further arguments passed to or from other methods |
A transform3d() object
m <- diag(4L) as_transform3d(m)m <- diag(4L) as_transform3d(m)
range() computes axis-aligned ranges for Coord1D, Coord2D,
Coord3D, Ellipse2D, Line2D, Plane3D, Point1D, and Segment2D
class objects.
Note that for Line2D and Plane3D objects the range may be -Inf to
Inf in one or more dimensions since lines and planes have infinite extent.
## S3 method for class 'Coord1D' range(..., na.rm = FALSE) ## S3 method for class 'Coord2D' range(..., na.rm = FALSE) ## S3 method for class 'Coord3D' range(..., na.rm = FALSE) ## S3 method for class 'Segment2D' range(..., na.rm = FALSE) ## S3 method for class 'Ellipse2D' range(..., na.rm = FALSE) ## S3 method for class 'Point1D' range(..., na.rm = FALSE) ## S3 method for class 'Line2D' range(..., na.rm = FALSE) ## S3 method for class 'Plane3D' range(..., na.rm = FALSE)## S3 method for class 'Coord1D' range(..., na.rm = FALSE) ## S3 method for class 'Coord2D' range(..., na.rm = FALSE) ## S3 method for class 'Coord3D' range(..., na.rm = FALSE) ## S3 method for class 'Segment2D' range(..., na.rm = FALSE) ## S3 method for class 'Ellipse2D' range(..., na.rm = FALSE) ## S3 method for class 'Point1D' range(..., na.rm = FALSE) ## S3 method for class 'Line2D' range(..., na.rm = FALSE) ## S3 method for class 'Plane3D' range(..., na.rm = FALSE)
... |
Coord1D, Coord2D, Coord3D, Ellipse2D, Line2D, Plane3D, Point1D, or Segment2D object(s) |
na.rm |
logical, indicating if |
Either a Coord1D, Coord2D, or Coord3D object of length two. The first element will have the minimum x/y(/z) coordinates and the second element will have the maximum x/y(/z) coordinates of the axis-aligned ranges.
range(as_coord2d(rnorm(5), rnorm(5))) range(as_coord3d(rnorm(5), rnorm(5), rnorm(5))) e <- as_ellipse2d(as_coord2d(c(0, 1), c(0, 1)), rx = c(1, 2), ry = c(0.5, 1)) range(e) # A vertical line (x = 2) and a horizontal line (y = 3): # x range covers only {2}, but y is Inf for the vertical line l <- as_line2d(a = c(1, 0), b = c(0, 1), c = c(-2, -3)) range(l) # A plane perpendicular to the x-axis at x = 5 range(as_plane3d(a = 1, b = 0, c = 0, d = -5)) range(as_point1d(a = c(1, 1), b = c(-2, -5))) s <- as_segment2d(as_coord2d(c(0, 1), c(0, 0)), p2 = as_coord2d(c(1, 1), c(0, 1))) range(s)range(as_coord2d(rnorm(5), rnorm(5))) range(as_coord3d(rnorm(5), rnorm(5), rnorm(5))) e <- as_ellipse2d(as_coord2d(c(0, 1), c(0, 1)), rx = c(1, 2), ry = c(0.5, 1)) range(e) # A vertical line (x = 2) and a horizontal line (y = 3): # x range covers only {2}, but y is Inf for the vertical line l <- as_line2d(a = c(1, 0), b = c(0, 1), c = c(-2, -3)) range(l) # A plane perpendicular to the x-axis at x = 5 range(as_plane3d(a = 1, b = 0, c = 0, d = -5)) range(as_point1d(a = c(1, 1), b = c(-2, -5))) s <- as_segment2d(as_coord2d(c(0, 1), c(0, 0)), p2 = as_coord2d(c(1, 1), c(0, 1))) range(s)
mean()computes centroids for Coord1D, Coord2D, and Coord3D class objects
## S3 method for class 'Coord1D' mean(x, ...) ## S3 method for class 'Coord2D' mean(x, ...) ## S3 method for class 'Coord3D' mean(x, ...)## S3 method for class 'Coord1D' mean(x, ...) ## S3 method for class 'Coord2D' mean(x, ...) ## S3 method for class 'Coord3D' mean(x, ...)
x |
|
... |
Passed to |
A Coord1D, Coord2D, or Coord3D class object of length one
p <- as_coord2d(x = 1:4, y = 1:4) print(mean(p)) print(sum(p) / length(p)) # less efficient alternative p <- as_coord3d(x = 1:4, y = 1:4, z = 1:4) print(mean(p))p <- as_coord2d(x = 1:4, y = 1:4) print(mean(p)) print(sum(p) / length(p)) # less efficient alternative p <- as_coord3d(x = 1:4, y = 1:4, z = 1:4) print(mean(p))
convex_hull2d() is a S3 generic for computing the convex hull of an
object. It is implemented for Coord2D and Polygon2D objects using
grDevices::chull().
convex_hull2d(x, ...) ## S3 method for class 'Coord2D' convex_hull2d(x, ...) ## S3 method for class 'Polygon2D' convex_hull2d(x, ...)convex_hull2d(x, ...) ## S3 method for class 'Coord2D' convex_hull2d(x, ...) ## S3 method for class 'Polygon2D' convex_hull2d(x, ...)
x |
An object to compute the convex hull of, such as a Coord2D or Polygon2D object. |
... |
Further arguments passed to or from other methods. |
A Polygon2D object representing the convex hull whose vertices are in counter-clockwise order.
pts <- as_coord2d(x = rnorm(20), y = rnorm(20)) hull <- convex_hull2d(pts) is_polygon2d(hull) hull$is_convex plot(hull) points(pts)pts <- as_coord2d(x = rnorm(20), y = rnorm(20)) hull <- convex_hull2d(pts) is_polygon2d(hull) hull$is_convex plot(hull) points(pts)
Coord1D is an R6::R6Class() object representing one-dimensional points
represented by Cartesian Coordinates.
xwA two-column matrix representing the homogeneous coordinates. The first column is the "x" coordinates and the second column is all ones.
xA numeric vector of x-coordinates.
Coord1D$new()Coord1D$new(xw)
xwA matrix with three columns representing (homogeneous) coordinates. The first column represents x coordinates and the last column is all ones. Column names should be "x" and "w".
Coord1D$print()Coord1D$print(n = NULL, ...)
nNumber of coordinates to print. If NULL print all of them.
...Passed to format.default().
Coord1D$project()Coord1D$project(point = as_point1d("origin"), ...)
pointA Point1D object of length one representing the point
you with to reflect across or project to or an object coercible to one by as_point1d(point, ...)
such as "origin".
...Passed to project1d().
Coord1D$reflect()Coord1D$reflect(point = as_point1d("origin"), ...)
pointA Point1D object of length one representing the point
you with to reflect across or project to or an object coercible to one by as_point1d(point, ...)
such as "origin".
...Passed to reflect1d().
Coord1D$scale()Coord1D$scale(x_scale = 1)
x_scaleScaling factor to apply to x coordinates
Coord1D$translate()Coord1D$translate(x = as_coord1d(0), ...)
Coord1D$transform()Coord1D$transform(mat = transform1d())
matA 2x2 matrix representing a post-multiplied affine transformation matrix.
The last column must be equal to c(0, 1).
If the last row is c(0, 1) you may need to transpose it
to convert it from a pre-multiplied affine transformation matrix to a post-multiplied one.
If a 1x1 matrix we'll quietly add a final column/row equal to c(0, 1).
Coord1D$clone()The objects of this class are cloneable with this method.
Coord1D$clone(deep = FALSE)
deepWhether to make a deep clone.
p <- as_coord1d(x = rnorm(100, 2)) print(p, n = 10L) pc <- mean(p) # Centroid # method chained affine transformation matrices are auto-pre-multiplied p$ translate(-pc)$ reflect("origin")$ print(n = 10L)p <- as_coord1d(x = rnorm(100, 2)) print(p, n = 10L) pc <- mean(p) # Centroid # method chained affine transformation matrices are auto-pre-multiplied p$ translate(-pc)$ reflect("origin")$ print(n = 10L)
Coord2D is an R6::R6Class() object representing two-dimensional points
represented by Cartesian Coordinates.
xywA three-column matrix representing the homogeneous coordinates. The first two columns are "x" and "y" coordinates and the third column is all ones.
xA numeric vector of x-coordinates.
yA numeric vector of y-coordinates.
Coord2D$new()Coord2D$new(xyw)
xywA matrix with three columns representing (homogeneous) coordinates. The first two columns represent x and y coordinates and the last column is all ones. Column names should be "x", "y", and "w".
Coord2D$permute()Coord2D$permute(permutation = c("xy", "yx"))
permutationEither "xy" (no permutation) or "yx" (permute x and y axes)
Coord2D$print()Coord2D$print(n = NULL, ...)
nNumber of coordinates to print. If NULL print all of them.
...Passed to format.default().
Coord2D$project()Coord2D$project(line = as_line2d("x-axis"), ..., scale = 0)
lineA Line2D object of length one representing the line
you with to reflect across or project to or an object coercible to one by as_line2d(line, ...)
such as "x-axis" or "y-axis".
...Passed to project2d()
scaleOblique projection scale factor.
A degenerate 0 value indicates an orthogonal projection.
Coord2D$reflect()Coord2D$reflect(line = as_line2d("x-axis"), ...)
lineA Line2D object of length one representing the line
you with to reflect across or project to or an object coercible to one by as_line2d(line, ...)
such as "x-axis" or "y-axis".
...Passed to reflect2d().
Coord2D$rotate()Coord2D$rotate(theta = angle(0), ...)
thetaAn angle() object of length one or an object coercible to one by as_angle(theta, ...).
...Passed to as_angle().
Coord2D$scale()Coord2D$scale(x_scale = 1, y_scale = x_scale)
x_scaleScaling factor to apply to x coordinates
y_scaleScaling factor to apply to y coordinates
Coord2D$shear()Coord2D$shear(xy_shear = 0, yx_shear = 0)
xy_shearHorizontal shear factor: x = x + xy_shear * y
yx_shearVertical shear factor: y = yx_shear * x + y
Coord2D$translate()Coord2D$translate(x = as_coord2d(0, 0), ...)
Coord2D$transform()Coord2D$transform(mat = transform2d())
matA 3x3 matrix representing a post-multiplied affine transformation matrix.
The last column must be equal to c(0, 0, 1).
If the last row is c(0, 0, 1) you may need to transpose it
to convert it from a pre-multiplied affine transformation matrix to a post-multiplied one.
If a 2x2 matrix (such as a 2x2 post-multiplied 2D rotation matrix)
we'll quietly add a final column/row equal to c(0, 0, 1).
Coord2D$clone()The objects of this class are cloneable with this method.
Coord2D$clone(deep = FALSE)
deepWhether to make a deep clone.
p <- as_coord2d(x = rnorm(100, 2), y = rnorm(100, 2)) print(p, n = 10) pc <- mean(p) # Centroid # method chained affine transformation matrices are auto-pre-multiplied p$ translate(-pc)$ shear(x = 1, y = 0)$ reflect("x-axis")$ rotate(90, "degrees")$ print(n = 10)p <- as_coord2d(x = rnorm(100, 2), y = rnorm(100, 2)) print(p, n = 10) pc <- mean(p) # Centroid # method chained affine transformation matrices are auto-pre-multiplied p$ translate(-pc)$ shear(x = 1, y = 0)$ reflect("x-axis")$ rotate(90, "degrees")$ print(n = 10)
Coord3D is an R6::R6Class() object representing three-dimensional points
represented by Cartesian Coordinates.
xyzwA four-column matrix representing the homogeneous coordinates. The first three columns are "x", "y", and "z" coordinates and the fourth column is all ones.
xA numeric vector of x-coordinates.
yA numeric vector of y-coordinates.
zA numeric vector of z-coordinates.
Coord3D$new()Coord3D$new(xyzw)
xyzwA matrix with four columns representing (homogeneous) coordinates. The first three columns represent x, y, and z coordinates and the last column is all ones. Column names should be "x", "y", "z", and "w".
Coord3D$permute()Coord3D$permute(permutation = c("xyz", "xzy", "yxz", "yzx", "zyx", "zxy"))
permutationEither "xyz" (no permutation), "xzy" (permute y and z axes), "yxz" (permute x and y axes), "yzx" (x becomes z, y becomes x, z becomes y), "zxy" (x becomes y, y becomes z, z becomes x), "zyx" (permute x and z axes)
Coord3D$print()Coord3D$print(n = NULL, ...)
nNumber of coordinates to print. If NULL print all of them.
...Passed to format.default().
Coord3D$project()Coord3D$project(
plane = as_plane3d("xy-plane"),
...,
scale = 0,
alpha = angle(45, "degrees")
)
planeA Plane3D object of length one representing the plane
you wish to reflect across or project to or an object coercible to one using as_plane3d(plane, ...)
such as "xy-plane", "xz-plane", or "yz-plane".
...Passed to project3d().
scaleOblique projection foreshortening scale factor.
A (degenerate) 0 value indicates an orthographic projection.
A value of 0.5 is used by a “cabinet projection”
while a value of 1.0 is used by a “cavalier projection”.
alphaOblique projection angle (the angle the third axis is projected going off at).
An angle() object or one coercible to one with as_angle(alpha, ...).
Popular angles are 45 degrees, 60 degrees, and arctangent(2) degrees.
Coord3D$reflect()Coord3D$reflect(plane = as_plane3d("xy-plane"), ...)
planeA Plane3D object of length one representing the plane
you wish to reflect across or project to or an object coercible to one using as_plane3d(plane, ...)
such as "xy-plane", "xz-plane", or "yz-plane".
...Passed to reflect3d().
Coord3D$rotate()Coord3D$rotate(axis = as_coord3d("z-axis"), theta = angle(0), ...)
axisA Coord3D class object or one that can coerced to one by as_coord3d(axis, ...).
The axis represents the axis to be rotated around.
thetaAn angle() object of length one or an object coercible to one by as_angle(theta, ...).
...Passed to rotate3d().
Coord3D$scale()Coord3D$scale(x_scale = 1, y_scale = x_scale, z_scale = x_scale)
x_scaleScaling factor to apply to x coordinates
y_scaleScaling factor to apply to y coordinates
z_scaleScaling factor to apply to z coordinates
Coord3D$shear()Coord3D$shear( xy_shear = 0, xz_shear = 0, yx_shear = 0, yz_shear = 0, zx_shear = 0, zy_shear = 0 )
xy_shearShear factor: x = x + xy_shear * y + xz_shear * z
xz_shearShear factor: x = x + xy_shear * y + xz_shear * z
yx_shearShear factor: y = yx_shear * x + y + yz_shear * z
yz_shearShear factor: y = yx_shear * x + y + yz_shear * z
zx_shearShear factor: z = zx_shear * x + zy_shear * y + z
zy_shearShear factor: z = zx_shear * x + zy_shear * y + z
Coord3D$translate()Coord3D$translate(x = as_coord3d(0, 0, 0), ...)
Coord3D$transform()Coord3D$transform(mat = transform3d())
matA 4x4 matrix representing a post-multiplied affine transformation matrix.
The last column must be equal to c(0, 0, 0, 1).
If the last row is c(0, 0, 0, 1) you may need to transpose it
to convert it from a pre-multiplied affine transformation matrix to a post-multiplied one.
If a 3x3 matrix (such as a 3x3 post-multiplied 3D rotation matrix)
we'll quietly add a final column/row equal to c(0, 0, 0, 1).
Coord3D$clone()The objects of this class are cloneable with this method.
Coord3D$clone(deep = FALSE)
deepWhether to make a deep clone.
p <- as_coord3d(x = rnorm(100, 2), y = rnorm(100, 2), z = rnorm(100, 2)) print(p, n = 10) pc <- mean(p) # Centroid # method chained affine transformation matrices are auto-pre-multiplied p$ translate(-pc)$ reflect("xy-plane")$ rotate("z-axis", degrees(90))$ print(n = 10)p <- as_coord3d(x = rnorm(100, 2), y = rnorm(100, 2), z = rnorm(100, 2)) print(p, n = 10) pc <- mean(p) # Centroid # method chained affine transformation matrices are auto-pre-multiplied p$ translate(-pc)$ reflect("xy-plane")$ rotate("z-axis", degrees(90))$ print(n = 10)
cross_product2d() computes the 2D cross product (also known as the
perp dot product) of two Coord2D class vectors.
The 2D cross product of vectors and is the
scalar .
cross_product2d(x, y)cross_product2d(x, y)
x |
A Coord2D class vector. |
y |
A Coord2D class vector. |
A numeric vector of 2D cross products.
dot_product2d() for the dot product of two Coord2D vectors.
cross_product3d() for the cross product of two Coord3D vectors.
x <- as_coord2d(2, 3) y <- as_coord2d(5, 6) cross_product2d(x, y) if (getRversion() >= "4.4.0") { crossprod(x, y) }x <- as_coord2d(2, 3) y <- as_coord2d(5, 6) cross_product2d(x, y) if (getRversion() >= "4.4.0") { crossprod(x, y) }
cross_product3d() computes the cross product of two Coord3D class vectors.
cross_product3d(x, y)cross_product3d(x, y)
x |
A Coord3D class vector. |
y |
A Coord3D class vector. |
A Coord3D class vector
dot_product3d() for the dot product of two Coord3D vectors.
cross_product2d() for the cross product of two Coord2D vectors.
x <- as_coord3d(2, 3, 4) y <- as_coord3d(5, 6, 7) cross_product3d(x, y) if (getRversion() >= "4.4.0") { crossprod(x, y) }x <- as_coord3d(2, 3, 4) y <- as_coord3d(5, 6, 7) cross_product3d(x, y) if (getRversion() >= "4.4.0") { crossprod(x, y) }
distance1d() computes 1D Euclidean distances.
distance1d(x, y)distance1d(x, y)
x |
|
y |
p <- as_coord1d(x = 1:4) distance1d(p, as_coord1d(0))p <- as_coord1d(x = 1:4) distance1d(p, as_coord1d(0))
distance2d() computes 2D Euclidean distances.
distance2d(x, y)distance2d(x, y)
x |
|
y |
p <- as_coord2d(x = 1:4, y = 1:4) distance2d(p, as_coord2d(0, 0))p <- as_coord2d(x = 1:4, y = 1:4) distance2d(p, as_coord2d(0, 0))
distance3d() computes 3D Euclidean distances.
distance3d(x, y)distance3d(x, y)
x |
|
y |
p <- as_coord3d(x = 1:4, y = 1:4, z = 1:4) distance3d(p, as_coord3d("origin"))p <- as_coord3d(x = 1:4, y = 1:4, z = 1:4) distance3d(p, as_coord3d("origin"))
dot_product1d(), dot_product2d(), and dot_product3d() compute the
dot (inner) product of two coordinate vectors.
You may also use the * operator and if R >= 4.3.0 you may also use the %*% operator to compute the dot (inner) product.
dot_product1d(x, y) dot_product2d(x, y) dot_product3d(x, y)dot_product1d(x, y) dot_product2d(x, y) dot_product3d(x, y)
x |
|
y |
A numeric vector of dot products.
cross_product2d() for the cross product of two Coord2D vectors.
cross_product3d() for the cross product of two Coord3D vectors.
p1 <- as_coord2d(x = c(1, 2), y = c(3, 4)) p2 <- as_coord2d(x = c(5, 6), y = c(7, 8)) dot_product2d(p1, p2) p1 * p2 # equivalent if (getRversion() >= "4.3.0") { p1 %*% p2 }p1 <- as_coord2d(x = c(1, 2), y = c(3, 4)) p2 <- as_coord2d(x = c(5, 6), y = c(7, 8)) dot_product2d(p1, p2) p1 * p2 # equivalent if (getRversion() >= "4.3.0") { p1 %*% p2 }
Ellipse2D is an R6::R6Class() object representing one or more
two-dimensional ellipses. It inherits from Coord2D so its center(s)
can be used with $x / $y / $xyw etc. The semi-axes rx/ry
and orientation angle theta are updated automatically by each
transformation method.
When rx == ry (within floating-point tolerance) the ellipse is a
circle, which can be tested with the $is_circle active binding.
Coord2D -> Ellipse2D
rxNumeric vector of x-axis semi-radii (in the ellipse local frame).
ryNumeric vector of y-axis semi-radii (in the ellipse local frame).
thetaAn angle() vector of rotation angles of the ellipse
x-axis relative to the global x-axis.
is_circleLogical vector; TRUE for each ellipse where
rx == ry within floating-point tolerance.
Ellipse2D$new()Ellipse2D$new(xyw, rx, ry, theta)
xywA matrix with three columns for homogeneous center coordinates
("x", "y", "w").
rxNumeric vector of x-axis semi-radii.
ryNumeric vector of y-axis semi-radii.
thetaAn angle() vector (or numeric, interpreted using
the default angular unit) of rotation angles.
Ellipse2D$print()Ellipse2D$print(n = NULL, ...)
nNumber of ellipses to print. If NULL print all.
...Passed to format.default().
Ellipse2D$transform()Ellipse2D$transform(mat = transform2d())
matA 3x3 matrix representing a post-multiplied affine transformation matrix.
The last column must be equal to c(0, 0, 1).
If the last row is c(0, 0, 1) you may need to transpose it
to convert it from a pre-multiplied affine transformation matrix to a post-multiplied one.
If a 2x2 matrix (such as a 2x2 post-multiplied 2D rotation matrix)
we'll quietly add a final column/row equal to c(0, 0, 1).
Ellipse2D$clone()The objects of this class are cloneable with this method.
Ellipse2D$clone(deep = FALSE)
deepWhether to make a deep clone.
# An ellipse e <- as_ellipse2d(as_coord2d(0, 0), rx = 2, ry = 1, theta = degrees(45)) print(e) e$is_circle # A circle (special case) c1 <- as_ellipse2d(as_coord2d(0.5, 0.5), rx = 0.5) print(c1) c1$is_circle# An ellipse e <- as_ellipse2d(as_coord2d(0, 0), rx = 2, ry = 1, theta = degrees(45)) print(e) e$is_circle # A circle (special case) c1 <- as_ellipse2d(as_coord2d(0.5, 0.5), rx = 0.5) print(c1) c1$is_circle
plot() plots Coord1D, Coord2D, Polygon2D, Ellipse2D, and
Segment2D class objects.
points() draws Coord1D and Coord2D class objects to an existing plot.
lines() draws Coord2D, Ellipse2D, Point1D, Line2D, and Segment2D
class objects to an existing plot.
If the suggested ggplot2 and rgl packages
are available we also register ggplot2::autolayer() methods for Coord1D,
Coord2D, Ellipse2D, Line2D, Point1D, Polygon2D, and Segment2D
class objects and rgl::plot3d() methods for Coord3D and Plane3D class
objects.
## S3 method for class 'Coord1D' plot(x, ...) ## S3 method for class 'Coord1D' points(x, ...) ## S3 method for class 'Point1D' lines(x, ...) ## S3 method for class 'Coord2D' plot(x, ..., asp = 1) ## S3 method for class 'Coord2D' points(x, ...) ## S3 method for class 'Coord2D' lines(x, ...) ## S3 method for class 'Polygon2D' lines(x, ...) ## S3 method for class 'Ellipse2D' lines(x, n = 60L, ...) ## S3 method for class 'Polygon2D' plot( x, ..., col = NA, border = NULL, density = NULL, angle = 45, fillOddEven = FALSE, asp = 1 ) ## S3 method for class 'Ellipse2D' plot( x, n = 60L, ..., col = NA, border = NULL, density = NULL, angle = 45, fillOddEven = FALSE, asp = 1 ) ## S3 method for class 'Line2D' lines(x, ...) ## S3 method for class 'Segment2D' plot(x, ..., asp = 1) ## S3 method for class 'Segment2D' lines(x, ...)## S3 method for class 'Coord1D' plot(x, ...) ## S3 method for class 'Coord1D' points(x, ...) ## S3 method for class 'Point1D' lines(x, ...) ## S3 method for class 'Coord2D' plot(x, ..., asp = 1) ## S3 method for class 'Coord2D' points(x, ...) ## S3 method for class 'Coord2D' lines(x, ...) ## S3 method for class 'Polygon2D' lines(x, ...) ## S3 method for class 'Ellipse2D' lines(x, n = 60L, ...) ## S3 method for class 'Polygon2D' plot( x, ..., col = NA, border = NULL, density = NULL, angle = 45, fillOddEven = FALSE, asp = 1 ) ## S3 method for class 'Ellipse2D' plot( x, n = 60L, ..., col = NA, border = NULL, density = NULL, angle = 45, fillOddEven = FALSE, asp = 1 ) ## S3 method for class 'Line2D' lines(x, ...) ## S3 method for class 'Segment2D' plot(x, ..., asp = 1) ## S3 method for class 'Segment2D' lines(x, ...)
x |
A supported object to plot. |
... |
Passed to the underlying plot method. |
asp |
the y/x aspect ratio. |
n |
Number of vertices used to approximate each ellipse (default |
col, border, density, angle, fillOddEven
|
Passed to |
Used for its side effect of drawing to the graphics device.
c1 <- as_coord2d(x = 0, y = 1:10) l <- as_line2d(a = 1, b = -1, c = 0) # y = x c2 <- c1$clone()$reflect(l) plot(c1, xlim = c(-1, 11), ylim = c(-1, 11), main = "2D reflection across a line") lines(l) points(c2, col = "red") c1 <- as_coord2d(x = 1:10, y = 1:10) l <- as_line2d(a = -1, b = 0, c = 0) # x = 0 c2 <- c1$clone()$project(l) if (require("ggplot2", quietly = TRUE, include.only = c("ggplot", "autolayer", "labs"))) { ggplot() + autolayer(c1) + autolayer(l) + autolayer(c2, color = "red") + labs(title = "2D projection onto a line") } c1 <- as_coord1d(x = seq.int(-4, -1)) pt <- as_point1d(a = 1, b = 0) # x = 0 c2 <- c1$clone()$reflect(pt) plot(c1, xlim = c(-5, 5), main = "1D reflection across a point") lines(pt) points(c2, col = "red") # 3D reflection across a plane c1 <- as_coord3d(x = 1:10, y = 1:10, z = 1:10) pl <- as_plane3d(a = 0, b = 0, c = -1, d = 2) # z = 2 c2 <- c1$clone()$reflect(pl) if (require("rgl", quietly = TRUE, include.only = "plot3d")) { plot3d(c1, col = "blue", size = 8) plot3d(pl, color = "grey", alpha = 0.6) plot3d(c2, add = TRUE, col = "red", size = 8) }c1 <- as_coord2d(x = 0, y = 1:10) l <- as_line2d(a = 1, b = -1, c = 0) # y = x c2 <- c1$clone()$reflect(l) plot(c1, xlim = c(-1, 11), ylim = c(-1, 11), main = "2D reflection across a line") lines(l) points(c2, col = "red") c1 <- as_coord2d(x = 1:10, y = 1:10) l <- as_line2d(a = -1, b = 0, c = 0) # x = 0 c2 <- c1$clone()$project(l) if (require("ggplot2", quietly = TRUE, include.only = c("ggplot", "autolayer", "labs"))) { ggplot() + autolayer(c1) + autolayer(l) + autolayer(c2, color = "red") + labs(title = "2D projection onto a line") } c1 <- as_coord1d(x = seq.int(-4, -1)) pt <- as_point1d(a = 1, b = 0) # x = 0 c2 <- c1$clone()$reflect(pt) plot(c1, xlim = c(-5, 5), main = "1D reflection across a point") lines(pt) points(c2, col = "red") # 3D reflection across a plane c1 <- as_coord3d(x = 1:10, y = 1:10, z = 1:10) pl <- as_plane3d(a = 0, b = 0, c = -1, d = 2) # z = 2 c2 <- c1$clone()$reflect(pl) if (require("rgl", quietly = TRUE, include.only = "plot3d")) { plot3d(c1, col = "blue", size = 8) plot3d(pl, color = "grey", alpha = 0.6) plot3d(c2, add = TRUE, col = "red", size = 8) }
has_intersection() is an S3 method that returns whether two objects intersect.
has_intersection(x, y, ...) ## Default S3 method: has_intersection(x, y, ...) ## S3 method for class 'Point1D' has_intersection(x, y, ..., tolerance = sqrt(.Machine$double.eps)) ## S3 method for class 'Line2D' has_intersection(x, y, ..., tolerance = sqrt(.Machine$double.eps)) ## S3 method for class 'Plane3D' has_intersection(x, y, ..., tolerance = sqrt(.Machine$double.eps))has_intersection(x, y, ...) ## Default S3 method: has_intersection(x, y, ...) ## S3 method for class 'Point1D' has_intersection(x, y, ..., tolerance = sqrt(.Machine$double.eps)) ## S3 method for class 'Line2D' has_intersection(x, y, ..., tolerance = sqrt(.Machine$double.eps)) ## S3 method for class 'Plane3D' has_intersection(x, y, ..., tolerance = sqrt(.Machine$double.eps))
x, y
|
The two objects to check if they intersect. |
... |
Passed to other methods (or ignored). |
tolerance |
Numerics with differences smaller
than |
affiner::has_intersection() has the same S3 signature and default method as
euclid::has_intersection() (so it shouldn't matter if one masks the other).
A logical vector.
line1 <- as_line2d("x-axis") line2 <- as_line2d("y-axis") line3 <- as_line2d(a = 0, b = 1, c = 2) # y + 2 = 0 has_intersection(line1, line1) has_intersection(line1, line2) has_intersection(line1, line3)line1 <- as_line2d("x-axis") line2 <- as_line2d("y-axis") line3 <- as_line2d(a = 0, b = 1, c = 2) # y + 2 = 0 has_intersection(line1, line1) has_intersection(line1, line2) has_intersection(line1, line3)
has_overlap2d() is an S3 generic that returns whether two 2D shapes
have a non-zero-area overlap (i.e. their interiors intersect).
has_overlap2d(x, y, ...) ## S3 method for class 'Polygon2D' has_overlap2d(x, y, ..., n = 64L, tol = sqrt(.Machine$double.eps)) ## S3 method for class 'Ellipse2D' has_overlap2d(x, y, ..., n = 64L, tol = sqrt(.Machine$double.eps))has_overlap2d(x, y, ...) ## S3 method for class 'Polygon2D' has_overlap2d(x, y, ..., n = 64L, tol = sqrt(.Machine$double.eps)) ## S3 method for class 'Ellipse2D' has_overlap2d(x, y, ..., n = 64L, tol = sqrt(.Machine$double.eps))
x, y
|
The two shapes to check. Supported classes are Polygon2D and Ellipse2D. |
... |
Ignored; only included for S3 method consistency. |
n |
Number of vertices used to approximate non-circular Ellipse2D
objects (default |
tol |
Numeric tolerance for overlap comparisons (default |
For two convex shapes the function uses the
Separating Axis Theorem (SAT).
For concave Polygon2D objects the function first checks whether the
axis-aligned bounding box and convex hull overlap; if neither rules out
overlap it returns NA with a warning because exact detection is not yet
supported.
For non-circular Ellipse2D objects the function approximates the ellipse
with inner and outer polygons: if the outer polygon does not overlap the
result is FALSE; if the inner polygon overlaps the result is TRUE;
otherwise NA is returned with a warning.
A logical vector (or NA) of length equal to the longer of x
and y (for Ellipse2D objects; Polygon2D objects are always scalar).
# Two overlapping squares sq1 <- as_polygon2d(as_coord2d( x = c(0, 1, 1, 0), y = c(0, 0, 1, 1) )) sq2 <- as_polygon2d(as_coord2d( x = c(0.5, 1.5, 1.5, 0.5), y = c(0.5, 0.5, 1.5, 1.5) )) sq3 <- as_polygon2d(as_coord2d( x = c(2, 3, 3, 2), y = c(2, 2, 3, 3) )) has_overlap2d(sq1, sq2) has_overlap2d(sq1, sq3) # Circle vs polygon circ <- as_ellipse2d(as_coord2d(0.5, 0.5), rx = 0.4) has_overlap2d(sq1, circ) has_overlap2d(sq3, circ) # Two circles c1 <- as_ellipse2d(as_coord2d(0, 0), rx = 1) c2 <- as_ellipse2d(as_coord2d(1.5, 0), rx = 1) c3 <- as_ellipse2d(as_coord2d(3, 0), rx = 1) has_overlap2d(c1, c2) has_overlap2d(c1, c3)# Two overlapping squares sq1 <- as_polygon2d(as_coord2d( x = c(0, 1, 1, 0), y = c(0, 0, 1, 1) )) sq2 <- as_polygon2d(as_coord2d( x = c(0.5, 1.5, 1.5, 0.5), y = c(0.5, 0.5, 1.5, 1.5) )) sq3 <- as_polygon2d(as_coord2d( x = c(2, 3, 3, 2), y = c(2, 2, 3, 3) )) has_overlap2d(sq1, sq2) has_overlap2d(sq1, sq3) # Circle vs polygon circ <- as_ellipse2d(as_coord2d(0.5, 0.5), rx = 0.4) has_overlap2d(sq1, circ) has_overlap2d(sq3, circ) # Two circles c1 <- as_ellipse2d(as_coord2d(0, 0), rx = 1) c2 <- as_ellipse2d(as_coord2d(1.5, 0), rx = 1) c3 <- as_ellipse2d(as_coord2d(3, 0), rx = 1) has_overlap2d(c1, c2) has_overlap2d(c1, c3)
intersection() is an S3 method that returns the intersection of two objects.
intersection(x, y, ...) ## S3 method for class 'Point1D' intersection(x, y, ..., tolerance = sqrt(.Machine$double.eps)) ## S3 method for class 'Line2D' intersection(x, y, ..., tolerance = sqrt(.Machine$double.eps)) ## S3 method for class 'Plane3D' intersection(x, y, ..., tolerance = sqrt(.Machine$double.eps)) ## S3 method for class 'Coord1D' intersection(x, y, ..., tolerance = sqrt(.Machine$double.eps)) ## S3 method for class 'Coord2D' intersection(x, y, ..., tolerance = sqrt(.Machine$double.eps)) ## S3 method for class 'Ellipse2D' intersection(x, y, ..., tolerance = sqrt(.Machine$double.eps)) ## S3 method for class 'Coord3D' intersection(x, y, ..., tolerance = sqrt(.Machine$double.eps))intersection(x, y, ...) ## S3 method for class 'Point1D' intersection(x, y, ..., tolerance = sqrt(.Machine$double.eps)) ## S3 method for class 'Line2D' intersection(x, y, ..., tolerance = sqrt(.Machine$double.eps)) ## S3 method for class 'Plane3D' intersection(x, y, ..., tolerance = sqrt(.Machine$double.eps)) ## S3 method for class 'Coord1D' intersection(x, y, ..., tolerance = sqrt(.Machine$double.eps)) ## S3 method for class 'Coord2D' intersection(x, y, ..., tolerance = sqrt(.Machine$double.eps)) ## S3 method for class 'Ellipse2D' intersection(x, y, ..., tolerance = sqrt(.Machine$double.eps)) ## S3 method for class 'Coord3D' intersection(x, y, ..., tolerance = sqrt(.Machine$double.eps))
x, y
|
The two objects to compute intersection for. |
... |
Passed to other methods (or ignored). |
tolerance |
Numerics with differences smaller
than |
affiner::intersection() has the same S3 signature as
euclid::intersection() (so it shouldn't matter if one masks the other).
A list of the object intersections (or NULL if no intersection).
For Line2D-Ellipse2D intersections each list element is a Coord2D
of length 2 (two crossing points), length 1 (tangent), or NULL
(no intersection).
line1 <- as_line2d("x-axis") line2 <- as_line2d("y-axis") line3 <- as_line2d(a = 0, b = 1, c = 2) # y + 2 = 0 intersection(line1, line1) intersection(line1, line2) intersection(line1, line3) # Unit circle vs x-axis: two points at (1, 0) and (-1, 0) circ <- as_ellipse2d(as_coord2d("origin"), r = 1) intersection(circ, line1) # Tangent: circle vs line y = 1 (touches top of circle) line_top <- as_line2d(a = 0, b = 1, c = -1) # y - 1 = 0 intersection(circ, line_top) # No intersection: circle vs y = 2 line_above <- as_line2d(a = 0, b = 1, c = -2) # y - 2 = 0 intersection(circ, line_above)line1 <- as_line2d("x-axis") line2 <- as_line2d("y-axis") line3 <- as_line2d(a = 0, b = 1, c = 2) # y + 2 = 0 intersection(line1, line1) intersection(line1, line2) intersection(line1, line3) # Unit circle vs x-axis: two points at (1, 0) and (-1, 0) circ <- as_ellipse2d(as_coord2d("origin"), r = 1) intersection(circ, line1) # Tangent: circle vs line y = 1 (touches top of circle) line_top <- as_line2d(a = 0, b = 1, c = -1) # y - 1 = 0 intersection(circ, line_top) # No intersection: circle vs y = 2 line_above <- as_line2d(a = 0, b = 1, c = -2) # y - 2 = 0 intersection(circ, line_above)
arcsine(), arccosine(), arctangent(),
arcsecant(), arccosecant(), and arccotangent() are
inverse trigonometric functions that return angle() vectors
with a user chosen angular unit.
arcsine( x, unit = getOption("affiner_angular_unit", "degrees"), tolerance = sqrt(.Machine$double.eps) ) arccosine( x, unit = getOption("affiner_angular_unit", "degrees"), tolerance = sqrt(.Machine$double.eps) ) arctangent(x, unit = getOption("affiner_angular_unit", "degrees"), y = NULL) arcsecant(x, unit = getOption("affiner_angular_unit", "degrees")) arccosecant(x, unit = getOption("affiner_angular_unit", "degrees")) arccotangent(x, unit = getOption("affiner_angular_unit", "degrees"))arcsine( x, unit = getOption("affiner_angular_unit", "degrees"), tolerance = sqrt(.Machine$double.eps) ) arccosine( x, unit = getOption("affiner_angular_unit", "degrees"), tolerance = sqrt(.Machine$double.eps) ) arctangent(x, unit = getOption("affiner_angular_unit", "degrees"), y = NULL) arcsecant(x, unit = getOption("affiner_angular_unit", "degrees")) arccosecant(x, unit = getOption("affiner_angular_unit", "degrees")) arccotangent(x, unit = getOption("affiner_angular_unit", "degrees"))
x |
A numeric vector |
unit |
A string of the desired angular unit. Supports the following strings
(note we ignore any punctuation and space characters as well as any trailing
|
tolerance |
If |
y |
A numeric vector or |
An angle() vector
arccosine(-1, "degrees") arcsine(0, "turns") arctangent(0, "gradians") arccosecant(-1, "degrees") arcsecant(1, "degrees") arccotangent(1, "half-turns") # `base::atan2(y, x)` computes the angle of the vector from origin to (x, y) as_angle(as_coord2d(x = 1, y = 1), "degrees")arccosine(-1, "degrees") arcsine(0, "turns") arctangent(0, "gradians") arccosecant(-1, "degrees") arcsecant(1, "degrees") arccotangent(1, "half-turns") # `base::atan2(y, x)` computes the angle of the vector from origin to (x, y) as_angle(as_coord2d(x = 1, y = 1), "degrees")
is_angle() tests whether an object is an angle vector
is_angle(x)is_angle(x)
x |
An object |
A logical value
a <- angle(180, "degrees") is_angle(a) is_angle(pi)a <- angle(180, "degrees") is_angle(a) is_angle(pi)
is_congruent() is a S3 generic that tests whether two different objects are “congruent”.
The is_congruent() method for angle() classes tests whether two angles are congruent.
is_congruent(x, y, ...) ## S3 method for class 'numeric' is_congruent(x, y, ..., tolerance = sqrt(.Machine$double.eps)) ## S3 method for class 'angle' is_congruent( x, y, ..., mod_turns = TRUE, tolerance = sqrt(.Machine$double.eps) )is_congruent(x, y, ...) ## S3 method for class 'numeric' is_congruent(x, y, ..., tolerance = sqrt(.Machine$double.eps)) ## S3 method for class 'angle' is_congruent( x, y, ..., mod_turns = TRUE, tolerance = sqrt(.Machine$double.eps) )
x, y
|
Two objects to test whether they are “"congruent"”. |
... |
Further arguments passed to or from other methods. |
tolerance |
Angles (coerced to half-turns) or numerics with differences smaller
than |
mod_turns |
If |
A logical vector
# Use `is_congruent()` to check if two angles are "congruent" a1 <- angle(180, "degrees") a2 <- angle(pi, "radians") a3 <- angle(-180, "degrees") # Only congruent modulus full turns a1 == a2 isTRUE(all.equal(a1, a2)) is_congruent(a1, a2) is_congruent(a1, a2, mod_turns = FALSE) a1 == a3 isTRUE(all.equal(a1, a3)) is_congruent(a1, a3) is_congruent(a1, a3, mod_turns = FALSE)# Use `is_congruent()` to check if two angles are "congruent" a1 <- angle(180, "degrees") a2 <- angle(pi, "radians") a3 <- angle(-180, "degrees") # Only congruent modulus full turns a1 == a2 isTRUE(all.equal(a1, a2)) is_congruent(a1, a2) is_congruent(a1, a2, mod_turns = FALSE) a1 == a3 isTRUE(all.equal(a1, a3)) is_congruent(a1, a3) is_congruent(a1, a3, mod_turns = FALSE)
is_coord1d() tests whether an object has a "Coord1D" class
is_coord1d(x)is_coord1d(x)
x |
An object |
A logical value
p <- as_coord1d(x = sample.int(10, 3)) is_coord1d(p)p <- as_coord1d(x = sample.int(10, 3)) is_coord1d(p)
is_coord2d() tests whether an object has a "Coord2D" class
is_coord2d(x)is_coord2d(x)
x |
An object |
A logical value
p <- as_coord2d(x = sample.int(10, 3), y = sample.int(10, 3)) is_coord2d(p)p <- as_coord2d(x = sample.int(10, 3), y = sample.int(10, 3)) is_coord2d(p)
is_coord3d() tests whether an object has a "Coord3D" class
is_coord3d(x)is_coord3d(x)
x |
An object |
A logical value
p <- as_coord3d(x = sample.int(10, 3), y = sample.int(10, 3), z = sample.int(10, 3)) is_coord3d(p)p <- as_coord3d(x = sample.int(10, 3), y = sample.int(10, 3), z = sample.int(10, 3)) is_coord3d(p)
is_ellipse2d() tests whether an object has an "Ellipse2D" class
is_ellipse2d(x)is_ellipse2d(x)
x |
An object |
A logical value
c1 <- as_ellipse2d(as_coord2d(0.5, 0.5), r = 0.5) is_ellipse2d(c1) is_ellipse2d(c1) && all(c1$is_circle) e1 <- as_ellipse2d(as_coord2d(0, 0), rx = 2, ry = 1) is_ellipse2d(e1) is_ellipse2d(e1) && all(e1$is_circle)c1 <- as_ellipse2d(as_coord2d(0.5, 0.5), r = 0.5) is_ellipse2d(c1) is_ellipse2d(c1) && all(c1$is_circle) e1 <- as_ellipse2d(as_coord2d(0, 0), rx = 2, ry = 1) is_ellipse2d(e1) is_ellipse2d(e1) && all(e1$is_circle)
is_equivalent() is a S3 generic that tests whether two different objects are “equivalent”.
The is_equivalent() method for angle() classes tests whether two angles are congruent.
The is_equivalent() method for Point1D, Line2D, Plane3D classes tests whether they are the same point/line/plane after standardization.
is_equivalent(x, y, ...) ## S3 method for class 'angle' is_equivalent( x, y, ..., mod_turns = TRUE, tolerance = sqrt(.Machine$double.eps) ) ## S3 method for class 'numeric' is_equivalent(x, y, ..., tolerance = sqrt(.Machine$double.eps)) ## S3 method for class 'Coord1D' is_equivalent(x, y, ..., tolerance = sqrt(.Machine$double.eps)) ## S3 method for class 'Coord2D' is_equivalent(x, y, ..., tolerance = sqrt(.Machine$double.eps)) ## S3 method for class 'Coord3D' is_equivalent(x, y, ..., tolerance = sqrt(.Machine$double.eps)) ## S3 method for class 'Point1D' is_equivalent(x, y, ..., tolerance = sqrt(.Machine$double.eps)) ## S3 method for class 'Line2D' is_equivalent(x, y, ..., tolerance = sqrt(.Machine$double.eps)) ## S3 method for class 'Plane3D' is_equivalent(x, y, ..., tolerance = sqrt(.Machine$double.eps))is_equivalent(x, y, ...) ## S3 method for class 'angle' is_equivalent( x, y, ..., mod_turns = TRUE, tolerance = sqrt(.Machine$double.eps) ) ## S3 method for class 'numeric' is_equivalent(x, y, ..., tolerance = sqrt(.Machine$double.eps)) ## S3 method for class 'Coord1D' is_equivalent(x, y, ..., tolerance = sqrt(.Machine$double.eps)) ## S3 method for class 'Coord2D' is_equivalent(x, y, ..., tolerance = sqrt(.Machine$double.eps)) ## S3 method for class 'Coord3D' is_equivalent(x, y, ..., tolerance = sqrt(.Machine$double.eps)) ## S3 method for class 'Point1D' is_equivalent(x, y, ..., tolerance = sqrt(.Machine$double.eps)) ## S3 method for class 'Line2D' is_equivalent(x, y, ..., tolerance = sqrt(.Machine$double.eps)) ## S3 method for class 'Plane3D' is_equivalent(x, y, ..., tolerance = sqrt(.Machine$double.eps))
x, y
|
Two objects to test whether they are “"equivalent"”. |
... |
Further arguments passed to or from other methods. |
mod_turns |
If |
tolerance |
Numerics with differences smaller
than |
A logical vector
line1 <- as_line2d(a = 1, b = 2, c = 3) # 1 * x + 2 * y + 3 = 0 line2 <- as_line2d(a = 2, b = 4, c = 6) # 2 * x + 4 * y + 6 = 0 is_equivalent(line1, line2)line1 <- as_line2d(a = 1, b = 2, c = 3) # 1 * x + 2 * y + 3 = 0 line2 <- as_line2d(a = 2, b = 4, c = 6) # 2 * x + 4 * y + 6 = 0 is_equivalent(line1, line2)
is_line2d() tests whether an object has a "Line2D" class
is_line2d(x)is_line2d(x)
x |
An object |
A logical value
l <- as_line2d(a = 1, b = 2, c = 3) is_line2d(l)l <- as_line2d(a = 1, b = 2, c = 3) is_line2d(l)
is_parallel() is a S3 method that tests whether two objects are parallel.
is_parallel(x, y, ...) ## S3 method for class 'Line2D' is_parallel(x, y, ..., tolerance = sqrt(.Machine$double.eps)) ## S3 method for class 'Plane3D' is_parallel(x, y, ..., tolerance = sqrt(.Machine$double.eps))is_parallel(x, y, ...) ## S3 method for class 'Line2D' is_parallel(x, y, ..., tolerance = sqrt(.Machine$double.eps)) ## S3 method for class 'Plane3D' is_parallel(x, y, ..., tolerance = sqrt(.Machine$double.eps))
x, y
|
The two objects to compute if they are parallel. |
... |
Passed to other methods (or ignored). |
tolerance |
Numerics with differences smaller
than |
A logical vector.
line1 <- as_line2d("x-axis") line2 <- as_line2d("y-axis") line3 <- as_line2d(a = 0, b = 1, c = 2) # y + 2 = 0 is_parallel(line1, line1) is_parallel(line1, line2) is_parallel(line1, line3)line1 <- as_line2d("x-axis") line2 <- as_line2d("y-axis") line3 <- as_line2d(a = 0, b = 1, c = 2) # y + 2 = 0 is_parallel(line1, line1) is_parallel(line1, line2) is_parallel(line1, line3)
is_plane3d() tests whether an object has a "Plane3D" class
is_plane3d(x)is_plane3d(x)
x |
An object |
A logical value
p <- as_plane3d(a = 1, b = 2, c = 3, 4) is_plane3d(p)p <- as_plane3d(a = 1, b = 2, c = 3, 4) is_plane3d(p)
is_point1d() tests whether an object has a "Point1D" class
is_point1d(x)is_point1d(x)
x |
An object |
A logical value
p <- as_point1d(a = 1, b = 5) is_point1d(p)p <- as_point1d(a = 1, b = 5) is_point1d(p)
is_polygon2d() tests whether an object has a "Polygon2D" class
is_polygon2d(x)is_polygon2d(x)
x |
An object |
A logical value
p <- as_polygon2d(as_coord2d(x = c(0, 1, 1, 0), y = c(0, 0, 1, 1))) is_polygon2d(p)p <- as_polygon2d(as_coord2d(x = c(0, 1, 1, 0), y = c(0, 0, 1, 1))) is_polygon2d(p)
is_segment2d() tests whether an object has a "Segment2D" class
is_segment2d(x)is_segment2d(x)
x |
An object |
A logical value
p1 <- as_coord2d(x = c(0, 1), y = c(0, 0)) p2 <- as_coord2d(x = c(1, 1), y = c(0, 1)) s <- as_segment2d(p1, p2 = p2) is_segment2d(s)p1 <- as_coord2d(x = c(0, 1), y = c(0, 0)) p2 <- as_coord2d(x = c(1, 1), y = c(0, 1)) s <- as_segment2d(p1, p2 = p2) is_segment2d(s)
is_transform1d() tests if object is a transform1d() affine transformation matrix
is_transform1d(x)is_transform1d(x)
x |
An object |
A logical value
m <- transform1d(diag(2L)) is_transform1d(m) is_transform1d(diag(2L))m <- transform1d(diag(2L)) is_transform1d(m) is_transform1d(diag(2L))
is_transform2d() tests if object is a transform2d() affine transformation matrix
is_transform2d(x)is_transform2d(x)
x |
An object |
A logical value
m <- transform2d(diag(3L)) is_transform2d(m) is_transform2d(diag(3L))m <- transform2d(diag(3L)) is_transform2d(m) is_transform2d(diag(3L))
is_transform3d() tests if object is a transform3d() affine transformation matrix
is_transform3d(x)is_transform3d(x)
x |
An object |
A logical value
m <- transform3d(diag(4L)) is_transform3d(m) is_transform3d(diag(4L))m <- transform3d(diag(4L)) is_transform3d(m) is_transform3d(diag(4L))
isometricCube() is a grid grob function to render
isometric cube faces by automatically wrapping around affineGrob().
isocubeGrob( top, right, left, gp_border = grid::gpar(col = "black", lwd = 12), name = NULL, gp = grid::gpar(), vp = NULL ) grid.isocube(...)isocubeGrob( top, right, left, gp_border = grid::gpar(col = "black", lwd = 12), name = NULL, gp = grid::gpar(), vp = NULL ) grid.isocube(...)
top |
A grid grob object to use as the top side of the cube. ggplot2 objects will be coerced by |
right |
A grid grob object to use as the right side of the cube. ggplot2 objects will be coerced by |
left |
A grid grob object to use as the left side of the cube. ggplot2 objects will be coerced by |
gp_border |
A |
name |
A character identifier (for grid). |
gp |
A |
vp |
A |
... |
Passed to |
Any ggplot2 objects are coerced to grobs by ggplot2::ggplotGrob(). Depending on what you'd like
to do you may want to instead manually convert a ggplot2 object gg to a grob with gtable::gtable_filter(ggplot2::ggplotGrob(gg), "panel").
Not all graphics devices provided by grDevices or other R packages support the affine transformation feature introduced in R 4.2.
If isTRUE(getRversion() >= '4.2.0') then the active graphics device should support this feature if isTRUE(grDevices::dev.capabilities()$transformations).
In particular the following graphics devices should support the affine transformation feature:
R's grDevices::pdf() device
R's 'cairo' devices e.g. grDevices::cairo_pdf(), grDevices::png(type = 'cairo'), grDevices::svg(), grDevices::x11(type = 'cairo'), etc. If isTRUE(capabilities('cairo')) then R was compiled with support for the 'cairo' devices .
R's 'quartz' devices (since R 4.3.0) e.g. grDevices::quartz(), grDevices::png(type = 'quartz'), etc. If isTRUE(capabilities('aqua')) then R was compiled with support for the 'quartz' devices (generally only TRUE on macOS systems).
ragg's devices (since v1.3.0) e.g. ragg::agg_png(), ragg::agg_capture(), etc.
A grid::gTree() (grob) object of class "isocube".
As a side effect grid.isocube() draws to the active graphics device.
# Only works if active graphics device supports affine transformations # such as `png(type="cairo")` on R 4.2+ can_run_grid_example <- require("grid", quietly = TRUE) && getRversion() >= "4.2.0" && isTRUE(dev.capabilities()$transformations) if (can_run_grid_example) { grid.newpage() gp_text <- gpar(fontsize = 72) grid.isocube(top = textGrob("top", gp = gp_text), right = textGrob("right", gp = gp_text), left = textGrob("left", gp = gp_text)) } if (can_run_grid_example) { colors <- c("#D55E00", "#009E73", "#56B4E9") spacings <- c(0.25, 0.2, 0.25) texts <- c("pkgname", "left\nface", "right\nface") rots <- c(45, 0, 0) fontsizes <- c(52, 80, 80) sides <- c("top", "left", "right") types <- gridpattern::names_polygon_tiling[c(5, 7, 9)] l_grobs <- list() grid.newpage() for (i in 1:3) { if (requireNamespace("gridpattern", quietly = TRUE)) { bg <- gridpattern::grid.pattern_polygon_tiling( colour = "grey80", fill = c(colors[i], "white"), type = types[i], spacing = spacings[i], draw = FALSE) } else { bg <- rectGrob(gp = gpar(col = NA, fill = colors[i])) } text <- textGrob(texts[i], rot = rots[i], gp = gpar(fontsize = fontsizes[i])) l_grobs[[sides[i]]] <- grobTree(bg, text) } grid.newpage() grid.isocube(top = l_grobs$top, right = l_grobs$right, left = l_grobs$left) } # May take more than 5 seconds on CRAN machines can_run_artsy_example <- can_run_grid_example && require("aRtsy", quietly = TRUE) && require("ggplot2", quietly = TRUE) && requireNamespace("gtable", quietly = TRUE) if (can_run_artsy_example) { gg <- canvas_planet(colorPalette("lava"), threshold = 3) + scale_x_continuous(expand = c(0, 0)) + scale_y_continuous(expand = c(0, 0)) grob <- ggplotGrob(gg) grob <- gtable::gtable_filter(grob, "panel") # grab just the panel grid.newpage() grid.isocube(top = grob, left = grob, right = grob, gp_border = grid::gpar(col = "darkorange", lwd = 12)) }# Only works if active graphics device supports affine transformations # such as `png(type="cairo")` on R 4.2+ can_run_grid_example <- require("grid", quietly = TRUE) && getRversion() >= "4.2.0" && isTRUE(dev.capabilities()$transformations) if (can_run_grid_example) { grid.newpage() gp_text <- gpar(fontsize = 72) grid.isocube(top = textGrob("top", gp = gp_text), right = textGrob("right", gp = gp_text), left = textGrob("left", gp = gp_text)) } if (can_run_grid_example) { colors <- c("#D55E00", "#009E73", "#56B4E9") spacings <- c(0.25, 0.2, 0.25) texts <- c("pkgname", "left\nface", "right\nface") rots <- c(45, 0, 0) fontsizes <- c(52, 80, 80) sides <- c("top", "left", "right") types <- gridpattern::names_polygon_tiling[c(5, 7, 9)] l_grobs <- list() grid.newpage() for (i in 1:3) { if (requireNamespace("gridpattern", quietly = TRUE)) { bg <- gridpattern::grid.pattern_polygon_tiling( colour = "grey80", fill = c(colors[i], "white"), type = types[i], spacing = spacings[i], draw = FALSE) } else { bg <- rectGrob(gp = gpar(col = NA, fill = colors[i])) } text <- textGrob(texts[i], rot = rots[i], gp = gpar(fontsize = fontsizes[i])) l_grobs[[sides[i]]] <- grobTree(bg, text) } grid.newpage() grid.isocube(top = l_grobs$top, right = l_grobs$right, left = l_grobs$left) } # May take more than 5 seconds on CRAN machines can_run_artsy_example <- can_run_grid_example && require("aRtsy", quietly = TRUE) && require("ggplot2", quietly = TRUE) && requireNamespace("gtable", quietly = TRUE) if (can_run_artsy_example) { gg <- canvas_planet(colorPalette("lava"), threshold = 3) + scale_x_continuous(expand = c(0, 0)) + scale_y_continuous(expand = c(0, 0)) grob <- ggplotGrob(gg) grob <- gtable::gtable_filter(grob, "panel") # grab just the panel grid.newpage() grid.isocube(top = grob, left = grob, right = grob, gp_border = grid::gpar(col = "darkorange", lwd = 12)) }
2n-gon inner radiusisotoxal_2ngon_inner_radius() computes the inner radius
of an isotoxal 2n-gon polygon.
star_inner_radius() is an alias.
isotoxal_2ngon_inner_radius( n, outer_radius = 1, ..., alpha = NULL, beta_ext = NULL, d = NULL ) star_inner_radius( n, outer_radius = 1, ..., alpha = NULL, beta_ext = NULL, d = NULL )isotoxal_2ngon_inner_radius( n, outer_radius = 1, ..., alpha = NULL, beta_ext = NULL, d = NULL ) star_inner_radius( n, outer_radius = 1, ..., alpha = NULL, beta_ext = NULL, d = NULL )
n |
The number of outer vertices. |
outer_radius |
The outer radius of the isotoxal |
... |
Ignored. |
alpha |
The interior angle of an outer vertex. Will be coerced by |
beta_ext |
The exterior angle of an inner vertex. Will be coerced by |
d |
The density aka winding number of the regular star polygon (outline) in which case this star is represented by |
Isotoxal 2n-gon polygons are polygons with:
2n vertices alternating between n "outer" vertices evenly spaced on one circle and n "inner" vertices evenly spaced on smaller circle with the same center.
Each edge of the polygon is of the same length.
The outer vertices all have the same interior angle alpha and the
inner vertices all have the same interior angle beta.
They are a generalization of (the outlines of) concave simple "star" polygons that also includes convex polygons with an even number of vertices.
A numeric vector
isotoxal_2ngon_polygon2d() to construct an isotoxal 2n-gon
Polygon2D object.
https://en.wikipedia.org/wiki/Isotoxal_figure#Isotoxal_polygons and
https://en.wikipedia.org/wiki/Star_polygon#Isotoxal_star_simple_polygons
for more information on isotoxal polygons.
# |8/3| star has outer vertex internal angle 45 degrees # and inner vertex external angle 90 degrees isotoxal_2ngon_inner_radius(8, d = 3) isotoxal_2ngon_inner_radius(8, alpha = 45) isotoxal_2ngon_inner_radius(8, beta_ext = 90)# |8/3| star has outer vertex internal angle 45 degrees # and inner vertex external angle 90 degrees isotoxal_2ngon_inner_radius(8, d = 3) isotoxal_2ngon_inner_radius(8, alpha = 45) isotoxal_2ngon_inner_radius(8, beta_ext = 90)
2n-gon and star polygonisotoxal_2ngon_polygon2d() creates an isotoxal 2n-gon Polygon2D
object centered at (x, y).
star_polygon2d() is an alias.
isotoxal_2ngon_polygon2d( n, x = 0, y = 0, radius = 0.5, radial_scale = isotoxal_2ngon_inner_radius(n, alpha = alpha, beta_ext = beta_ext, d = d), theta = degrees(90), ..., alpha = NULL, beta_ext = NULL, d = NULL ) star_polygon2d( n, x = 0, y = 0, radius = 0.5, radial_scale = isotoxal_2ngon_inner_radius(n, alpha = alpha, beta_ext = beta_ext, d = d), theta = degrees(90), ..., alpha = NULL, beta_ext = NULL, d = NULL )isotoxal_2ngon_polygon2d( n, x = 0, y = 0, radius = 0.5, radial_scale = isotoxal_2ngon_inner_radius(n, alpha = alpha, beta_ext = beta_ext, d = d), theta = degrees(90), ..., alpha = NULL, beta_ext = NULL, d = NULL ) star_polygon2d( n, x = 0, y = 0, radius = 0.5, radial_scale = isotoxal_2ngon_inner_radius(n, alpha = alpha, beta_ext = beta_ext, d = d), theta = degrees(90), ..., alpha = NULL, beta_ext = NULL, d = NULL )
n |
Number of outer vertices. |
x |
X-coordinate of the center (default |
y |
Y-coordinate of the center (default |
radius |
Outer circumradius (default |
radial_scale |
Inner radius as a fraction of |
theta |
Angle of the first outer vertex (default |
... |
Ignored. |
alpha |
Interior angle of an outer vertex. Will be coerced by
|
beta_ext |
Exterior angle of an inner vertex. Will be coerced by
|
d |
Density (winding number) of the star polygon |
Isotoxal 2n-gon polygons have 2n vertices alternating between n
outer vertices on a circle of radius radius and n inner vertices on
a concentric circle of radius radial_scale * radius.
A Polygon2D object whose vertices are in counter-clockwise order.
isotoxal_2ngon_inner_radius() to compute the radial scale.
rectangle_polygon2d() for rectangles.
regular_ngon_polygon2d() for regular convex polygons.
https://en.wikipedia.org/wiki/Isotoxal_figure#Isotoxal_polygons and
https://en.wikipedia.org/wiki/Star_polygon#Isotoxal_star_simple_polygons
for more information on isotoxal polygons.
# |5/2| star (the verda stelo) p <- isotoxal_2ngon_polygon2d(5, d = 2) p$is_convex plot(p, col = "#008000", border = NA) # `star_polygon2d()` is an alias p2 <- star_polygon2d(5, d = 2) all.equal(p, p2)# |5/2| star (the verda stelo) p <- isotoxal_2ngon_polygon2d(5, d = 2) p$is_convex plot(p, col = "#008000", border = NA) # `star_polygon2d()` is an alias p2 <- star_polygon2d(5, d = 2) all.equal(p, p2)
Line2D is an R6::R6Class() object representing two-dimensional lines.
aNumeric vector that parameterizes the line via the equation a * x + b * y + c = 0.
bNumeric vector that parameterizes the line via the equation a * x + b * y + c = 0.
cNumeric vector that parameterizes the line via the equation a * x + b * y + c = 0.
Line2D$new()Line2D$new(a, b, c)
aNumeric vector that parameterizes the line via the equation a * x + b * y + c = 0.
bNumeric vector that parameterizes the line via the equation a * x + b * y + c = 0.
cNumeric vector that parameterizes the line via the equation a * x + b * y + c = 0.
Line2D$print()Line2D$print(n = NULL, ...)
nNumber of lines to print. If NULL print all of them.
...Passed to format.default().
Line2D$clone()The objects of this class are cloneable with this method.
Line2D$clone(deep = FALSE)
deepWhether to make a deep clone.
p1 <- as_coord2d(x = 5, y = 10) p2 <- as_coord2d(x = 7, y = 12) theta <- degrees(45) as_line2d(theta, p1) as_line2d(p1, p2)p1 <- as_coord2d(x = 5, y = 10) p2 <- as_coord2d(x = 7, y = 12) theta <- degrees(45) as_line2d(theta, p1) as_line2d(p1, p2)
normal2d() is an S3 generic that computes a 2D normal vector.
normal2d(x, ...) ## S3 method for class 'Coord2D' normal2d(x, ..., normalize = TRUE) ## S3 method for class 'Line2D' normal2d(x, ..., normalize = TRUE)normal2d(x, ...) ## S3 method for class 'Coord2D' normal2d(x, ..., normalize = TRUE) ## S3 method for class 'Line2D' normal2d(x, ..., normalize = TRUE)
x |
Object to compute a 2D normal vector for such as a Line2D object. |
... |
Passed to or from other methods. |
normalize |
If |
A Coord2D (normal) vector
p <- as_coord2d(x = 2, y = 3) normal2d(p) normal2d(p, normalize = FALSE)p <- as_coord2d(x = 2, y = 3) normal2d(p) normal2d(p, normalize = FALSE)
normal3d() is an S3 generic that computes a 3D normal vector.
normal3d(x, ...) ## S3 method for class 'Coord3D' normal3d(x, cross, ..., normalize = TRUE) ## S3 method for class 'character' normal3d(x, ..., normalize = TRUE) ## S3 method for class 'Plane3D' normal3d(x, ..., normalize = TRUE)normal3d(x, ...) ## S3 method for class 'Coord3D' normal3d(x, cross, ..., normalize = TRUE) ## S3 method for class 'character' normal3d(x, ..., normalize = TRUE) ## S3 method for class 'Plane3D' normal3d(x, ..., normalize = TRUE)
x |
Object to compute a 3D normal vector for such as a Plane3D object |
... |
Passed to other methods such as |
cross |
A Coord3D vector.
We'll compute the normal of |
normalize |
If |
A Coord3D (normal) vector
normal3d("xy-plane") normal3d(as_coord3d(2, 0, 0), cross = as_coord3d(0, 2, 0))normal3d("xy-plane") normal3d(as_coord3d(2, 0, 0), cross = as_coord3d(0, 2, 0))
painter_depth() computes depth values for use with the painter's algorithm.
For parallel (orthographic or oblique) projections, depth is a dot product
of the point with the projection direction vector derived from the plane and
oblique parameters.
painter_order() wraps painter_depth() and order() to return the integer
indices that sort objects farthest-first (the draw order for the painter's
algorithm).
sort.Coord2D() and sort.Coord3D() wrap
painter_order() to return the sorted object directly.
sort.Coord2D() also handles Segment2D objects via inheritance.
painter_depth(x, ...) ## S3 method for class 'Coord2D' painter_depth(x, ..., scale = 1, alpha = angle(45, "degrees")) ## S3 method for class 'Coord3D' painter_depth( x, permutation = c("xyz", "xzy", "yxz", "yzx", "zyx", "zxy"), ..., plane = as_plane3d("xy-plane"), scale = 0, alpha = angle(45, "degrees"), roll = angle(0, "degrees") ) ## S3 method for class 'Segment2D' painter_depth(x, ..., scale = 1, alpha = angle(45, "degrees")) ## S3 method for class 'Polygon2D' painter_depth(x, ..., scale = 1, alpha = angle(45, "degrees")) painter_order(x, ...) ## S3 method for class 'Coord2D' painter_order( x, ..., decreasing = FALSE, scale = 1, alpha = angle(45, "degrees") ) ## S3 method for class 'Coord3D' painter_order( x, permutation = c("xyz", "xzy", "yxz", "yzx", "zyx", "zxy"), ..., decreasing = FALSE, plane = as_plane3d("xy-plane"), scale = 0, alpha = angle(45, "degrees"), roll = angle(0, "degrees") ) ## S3 method for class 'Polygon2D' painter_order( x, ..., decreasing = FALSE, scale = 1, alpha = angle(45, "degrees") ) ## S3 method for class 'Coord2D' sort(x, decreasing = FALSE, ..., scale = 1, alpha = angle(45, "degrees")) ## S3 method for class 'Coord3D' sort( x, decreasing = FALSE, ..., permutation = c("xyz", "xzy", "yxz", "yzx", "zyx", "zxy"), plane = as_plane3d("xy-plane"), scale = 0, alpha = angle(45, "degrees"), roll = angle(0, "degrees") )painter_depth(x, ...) ## S3 method for class 'Coord2D' painter_depth(x, ..., scale = 1, alpha = angle(45, "degrees")) ## S3 method for class 'Coord3D' painter_depth( x, permutation = c("xyz", "xzy", "yxz", "yzx", "zyx", "zxy"), ..., plane = as_plane3d("xy-plane"), scale = 0, alpha = angle(45, "degrees"), roll = angle(0, "degrees") ) ## S3 method for class 'Segment2D' painter_depth(x, ..., scale = 1, alpha = angle(45, "degrees")) ## S3 method for class 'Polygon2D' painter_depth(x, ..., scale = 1, alpha = angle(45, "degrees")) painter_order(x, ...) ## S3 method for class 'Coord2D' painter_order( x, ..., decreasing = FALSE, scale = 1, alpha = angle(45, "degrees") ) ## S3 method for class 'Coord3D' painter_order( x, permutation = c("xyz", "xzy", "yxz", "yzx", "zyx", "zxy"), ..., decreasing = FALSE, plane = as_plane3d("xy-plane"), scale = 0, alpha = angle(45, "degrees"), roll = angle(0, "degrees") ) ## S3 method for class 'Polygon2D' painter_order( x, ..., decreasing = FALSE, scale = 1, alpha = angle(45, "degrees") ) ## S3 method for class 'Coord2D' sort(x, decreasing = FALSE, ..., scale = 1, alpha = angle(45, "degrees")) ## S3 method for class 'Coord3D' sort( x, decreasing = FALSE, ..., permutation = c("xyz", "xzy", "yxz", "yzx", "zyx", "zxy"), plane = as_plane3d("xy-plane"), scale = 0, alpha = angle(45, "degrees"), roll = angle(0, "degrees") )
x |
Object to compute painter's depth/order for, or to sort. |
... |
Passed to |
scale |
Oblique projection foreshortening scale factor.
The 2D methods default to |
alpha |
Oblique projection angle (the angle the off-axis direction is
projected going off at).
An |
permutation |
Either "xyz" (no permutation), "xzy" (permute y and z axes), "yxz" (permute x and y axes), "yzx" (x becomes z, y becomes x, z becomes y), "zxy" (x becomes y, y becomes z, z becomes x), "zyx" (permute x and z axes). This permutation is applied before the projection. |
plane |
A Plane3D class object representing the plane
projected onto, or an object coercible to one using
|
roll |
Rotation of the in-plane coordinate frame around the plane normal
after the azimuth/inclination alignment.
An |
decreasing |
If |
painter_order() returns an integer vector of indices.
sort.Coord2D() and sort.Coord3D() return a sorted object of the
same class as x.
# Coord2D: oblique projection with scale = 1, alpha = 45 degrees p <- as_coord2d(x = c(1, 2, 3), y = c(3, 1, 2)) painter_depth(p) painter_order(p) sort(p) # Coord3D: orthographic projection onto xy-plane (depth = z) p3 <- as_coord3d(x = 1:3, y = 1:3, z = c(3, 1, 2)) painter_depth(p3) painter_order(p3) sort(p3) # Segment2D: depth/order at midpoints p1 <- as_coord2d(x = c(0, 2), y = c(0, 0)) p2 <- as_coord2d(x = c(2, 2), y = c(0, 2)) s <- as_segment2d(p1, p2 = p2) painter_depth(s) painter_order(s) sort(s) # Polygon2D: depth/order of each edge vertices <- as_coord2d(x = c(0, 0.5, 1, 0.5), y = c(0.5, 1, 0.5, 0)) poly <- as_polygon2d(vertices) painter_depth(poly) painter_order(poly)# Coord2D: oblique projection with scale = 1, alpha = 45 degrees p <- as_coord2d(x = c(1, 2, 3), y = c(3, 1, 2)) painter_depth(p) painter_order(p) sort(p) # Coord3D: orthographic projection onto xy-plane (depth = z) p3 <- as_coord3d(x = 1:3, y = 1:3, z = c(3, 1, 2)) painter_depth(p3) painter_order(p3) sort(p3) # Segment2D: depth/order at midpoints p1 <- as_coord2d(x = c(0, 2), y = c(0, 0)) p2 <- as_coord2d(x = c(2, 2), y = c(0, 2)) s <- as_segment2d(p1, p2 = p2) painter_depth(s) painter_order(s) sort(s) # Polygon2D: depth/order of each edge vertices <- as_coord2d(x = c(0, 0.5, 1, 0.5), y = c(0.5, 1, 0.5, 0)) poly <- as_polygon2d(vertices) painter_depth(poly) painter_order(poly)
Plane3D is an R6::R6Class() object representing three-dimensional planes.
aNumeric vector that parameterizes the plane via the equation a * x + b * y + c * z + d = 0.
bNumeric vector that parameterizes the plane via the equation a * x + b * y + c * z + d = 0.
cNumeric vector that parameterizes the plane via the equation a * x + b * y + c * z + d = 0.
dNumeric vector that parameterizes the plane via the equation a * x + b * y + c * z + d = 0.
Plane3D$new()Plane3D$new(a, b, c, d)
aNumeric vector that parameterizes the plane via the equation a * x + b * y + c * z + d = 0.
bNumeric vector that parameterizes the plane via the equation a * x + b * y + c * z + d = 0.
cNumeric vector that parameterizes the plane via the equation a * x + b * y + c * z + d = 0.
dNumeric vector that parameterizes the plane via the equation a * x + b * y + c * z + d = 0.
Plane3D$print()Plane3D$print(n = NULL, ...)
nNumber of lines to print. If NULL print all of them.
...Passed to format.default().
Plane3D$clone()The objects of this class are cloneable with this method.
Plane3D$clone(deep = FALSE)
deepWhether to make a deep clone.
Point1D is an R6::R6Class() object representing one-dimensional points.
aNumeric vector that parameterizes the point via the equation a * x + b = 0.
bNumeric vector that parameterizes the point via the equation a * x + b = 0.
Point1D$new()Point1D$new(a, b)
aNumeric vector that parameterizes the line via the equation a * x + b = 0.
bNumeric vector that parameterizes the line via the equation a * x + b = 0.
Point1D$print()Point1D$print(n = NULL, ...)
nNumber of lines to print. If NULL print all of them.
...Passed to format.default().
Point1D$clone()The objects of this class are cloneable with this method.
Point1D$clone(deep = FALSE)
deepWhether to make a deep clone.
p1 <- as_point1d(a = 1, b = 5)p1 <- as_point1d(a = 1, b = 5)
Polygon2D is an R6::R6Class() object representing a two-dimensional
polygon. It inherits from Coord2D so all transformation methods
(e.g. $rotate(), $translate()) and arithmetic operators work directly
on the polygon.
Coord2D -> Polygon2D
is_convexLogical indicating whether the polygon is convex
(TRUE), concave (FALSE), or unknown (NA).
convex_hullA Polygon2D object of the convex hull.
If the polygon is already convex ($convex == TRUE) it returns itself.
For concave polygons the hull is computed on demand and cached until the next transformation.
normalsA Coord2D object of unit edge normals
edgesA Segment2D object of the n polygon edges
(computed on demand and cached until the next transformation).
Polygon2D$new()Polygon2D$new(xyw, convex = NA)
xywA matrix with three columns representing (homogeneous)
coordinates. The first two columns are x/y coordinates and the
last column is all ones. Column names should be "x", "y",
and "w".
convexNA (default) to auto-detect convexity from xyw,
TRUE to assert convex (skip detection), or FALSE to mark as
concave.
Polygon2D$print()Polygon2D$print(n = NULL, ...)
nNumber of vertices to print. If NULL print all.
...Passed to format.default().
Polygon2D$transform()Polygon2D$transform(mat = transform2d())
matA 3x3 matrix representing a post-multiplied affine transformation matrix.
The last column must be equal to c(0, 0, 1).
If the last row is c(0, 0, 1) you may need to transpose it
to convert it from a pre-multiplied affine transformation matrix to a post-multiplied one.
If a 2x2 matrix (such as a 2x2 post-multiplied 2D rotation matrix)
we'll quietly add a final column/row equal to c(0, 0, 1).
Polygon2D$clone()The objects of this class are cloneable with this method.
Polygon2D$clone(deep = FALSE)
deepWhether to make a deep clone.
aabb_polygon2d(), isotoxal_2ngon_polygon2d(),
rectangle_polygon2d(), regular_ngon_polygon2d() for constructors
that return Polygon2D objects.
vertices <- as_coord2d(x = c(0, 0.5, 1, 0.5), y = c(0.5, 1, 0.5, 0)) p <- as_polygon2d(vertices) print(p) p$is_convex p$normals h <- p$convex_hull # Transformations are inherited from Coord2D p$rotate(degrees(45))vertices <- as_coord2d(x = c(0, 0.5, 1, 0.5), y = c(0.5, 1, 0.5, 0)) p <- as_polygon2d(vertices) print(p) p$is_convex p$normals h <- p$convex_hull # Transformations are inherited from Coord2D p$rotate(degrees(45))
rectangle_polygon2d() creates a rectangle Polygon2D object
centered at (x, y).
rectangle_polygon2d(width = 1, height = 1, x = 0, y = 0, theta = degrees(0))rectangle_polygon2d(width = 1, height = 1, x = 0, y = 0, theta = degrees(0))
width |
Width of the rectangle (default |
height |
Height of the rectangle (default |
x |
X-coordinate of the center (default |
y |
Y-coordinate of the center (default |
theta |
Rotation angle (default |
A Polygon2D object with $is_convex == TRUE whose vertices are in
counter-clockwise order.
aabb_polygon2d() for an axis-aligned bounding box polygon.
isotoxal_2ngon_polygon2d() for isotoxal star polygons.
regular_ngon_polygon2d() for regular convex polygons.
# A unit square p <- rectangle_polygon2d() p$is_convex plot(p) # A rotated rectangle p2 <- rectangle_polygon2d(width = 2, height = 1, theta = degrees(45)) plot(p2)# A unit square p <- rectangle_polygon2d() p$is_convex plot(p) # A rotated rectangle p2 <- rectangle_polygon2d(width = 2, height = 1, theta = degrees(45)) plot(p2)
regular_ngon_polygon2d() creates a regular n-gon Polygon2D object
centered at (x, y) with circumradius radius.
regular_ngon_polygon2d(n, x = 0, y = 0, radius = 0.5, theta = degrees(90))regular_ngon_polygon2d(n, x = 0, y = 0, radius = 0.5, theta = degrees(90))
n |
Number of vertices. |
x |
X-coordinate of the center (default |
y |
Y-coordinate of the center (default |
radius |
Circumradius: distance from center to each vertex
(default |
theta |
Angle of the first vertex (default |
A Polygon2D object with $is_convex == TRUE whose vertices are in
counter-clockwise order.
isotoxal_2ngon_polygon2d() for isotoxal star polygons.
rectangle_polygon2d() for rectangles.
# A regular hexagon p <- regular_ngon_polygon2d(6) p$is_convex plot(p)# A regular hexagon p <- regular_ngon_polygon2d(6) p$is_convex plot(p)
rotate3d_to_AA() converts from (post-multiplied) rotation matrix
to an axis-angle representation of 3D rotations.
rotate3d_to_AA( mat = diag(4), unit = getOption("affiner_angular_unit", "degrees") )rotate3d_to_AA( mat = diag(4), unit = getOption("affiner_angular_unit", "degrees") )
mat |
3D rotation matrix (post-multiplied).
If you have a pre-multiplied rotation matrix
simply transpose it with |
unit |
A string of the desired angular unit. Supports the following strings
(note we ignore any punctuation and space characters as well as any trailing
|
https://en.wikipedia.org/wiki/Axis-angle_representation for more details
about the Axis-angle representation of 3D rotations.
rotate3d() can be used to convert from an axis-angle representation to a rotation matrix.
# axis-angle representation of 90 degree rotation about the x-axis rotate3d_to_AA(rotate3d("x-axis", 90, unit = "degrees")) # find Axis-Angle representation of first rotating about x-axis 180 degrees # and then rotating about z-axis 45 degrees R <- rotate3d("x-axis", 180, unit = "degrees") %*% rotate3d("z-axis", 45, unit = "degrees") AA <- rotate3d_to_AA(R) # Can use `rotate3d()` to convert back to rotation matrix representation all.equal(R, do.call(rotate3d, AA))# axis-angle representation of 90 degree rotation about the x-axis rotate3d_to_AA(rotate3d("x-axis", 90, unit = "degrees")) # find Axis-Angle representation of first rotating about x-axis 180 degrees # and then rotating about z-axis 45 degrees R <- rotate3d("x-axis", 180, unit = "degrees") %*% rotate3d("z-axis", 45, unit = "degrees") AA <- rotate3d_to_AA(R) # Can use `rotate3d()` to convert back to rotation matrix representation all.equal(R, do.call(rotate3d, AA))
Segment2D is an R6::R6Class() object representing a vector of two-dimensional line segments.
It inherits from Coord2D using the first endpoint p1 as the coordinate data, so all transformation methods (e.g. $rotate(), $translate()) and arithmetic operators work directly on the segment vector.
The full edge vector to the second endpoint is stored privately and kept consistent under every transformation.
Coord2D -> Segment2D
Segment2D$new()Segment2D$new(xyw, vec)
xywA matrix with three columns for homogeneous p1 coordinates.
Column names should be "x", "y", and "w".
vecA two-column matrix of edge vectors p2 - p1.
Column names should be "x" and "y".
Segment2D$print()Segment2D$print(n = NULL, ...)
nNumber of segments to print. If NULL print all.
...Passed to format.default().
Segment2D$transform()Segment2D$transform(mat = transform2d())
matA 3x3 matrix representing a post-multiplied affine transformation matrix.
The last column must be equal to c(0, 0, 1).
If the last row is c(0, 0, 1) you may need to transpose it
to convert it from a pre-multiplied affine transformation matrix to a post-multiplied one.
If a 2x2 matrix (such as a 2x2 post-multiplied 2D rotation matrix)
we'll quietly add a final column/row equal to c(0, 0, 1).
Segment2D$clone()The objects of this class are cloneable with this method.
Segment2D$clone(deep = FALSE)
deepWhether to make a deep clone.
p1 <- as_coord2d(x = c(0, 1), y = c(0, 0)) p2 <- as_coord2d(x = c(1, 1), y = c(0, 1)) s <- as_segment2d(p1, p2 = p2) print(s) s$p1 s$p2 s$mid_point length(s) s[1]p1 <- as_coord2d(x = c(0, 1), y = c(0, 0)) p2 <- as_coord2d(x = c(1, 1), y = c(0, 1)) s <- as_segment2d(p1, p2 = p2) print(s) s$p1 s$p2 s$mid_point length(s) s[1]
transform1d(), reflect1d(), scale1d(),
and translate1d() create 1D affine transformation matrix objects.
transform1d(mat = diag(2L)) project1d(point = as_point1d("origin"), ...) reflect1d(point = as_point1d("origin"), ...) scale1d(x_scale = 1) translate1d(x = as_coord1d(0), ...)transform1d(mat = diag(2L)) project1d(point = as_point1d("origin"), ...) reflect1d(point = as_point1d("origin"), ...) scale1d(x_scale = 1) translate1d(x = as_coord1d(0), ...)
mat |
A 2x2 matrix representing a post-multiplied affine transformation matrix.
The last column must be equal to |
point |
A Point1D object of length one representing the point
you with to reflect across or project to or an object coercible to one by |
... |
Passed to |
x_scale |
Scaling factor to apply to x coordinates |
x |
A Coord1D object of length one or an object coercible to one by |
transform1d()User supplied (post-multiplied) affine transformation matrix
.
reflect1d()Reflections across a point.
scale1d()Scale the x-coordinates by multiplicative scale factors.
translate1d()Translate the coordinates by a Coord1D class object parameter.
transform1d() 1D affine transformation matrix objects are meant to be
post-multiplied and therefore should not be multiplied in reverse order.
Note the Coord1D class object methods auto-pre-multiply affine transformations
when "method chaining" so pre-multiplying affine transformation matrices
to do a single cumulative transformation instead of a method chain of multiple transformations
will not improve performance as much as it does in other R packages.
To convert a pre-multiplied 1D affine transformation matrix to a post-multiplied one
simply compute its transpose using t(). To get an inverse transformation matrix
from an existing transformation matrix that does the opposite transformations
simply compute its inverse using solve().
A 2x2 post-multiplied affine transformation matrix with classes "transform1d" and "at_matrix"
p <- as_coord1d(x = sample(1:10, 3)) # {affiner} affine transformation matrices are post-multiplied # and therefore should **not** go in reverse order mat <- transform1d(diag(2)) %*% scale1d(2) %*% translate1d(x = -1) p1 <- p$ clone()$ transform(mat) # The equivalent result applying affine transformations via method chaining p2 <- p$ clone()$ transform(diag(2))$ scale(2)$ translate(x = -1) all.equal(p1, p2)p <- as_coord1d(x = sample(1:10, 3)) # {affiner} affine transformation matrices are post-multiplied # and therefore should **not** go in reverse order mat <- transform1d(diag(2)) %*% scale1d(2) %*% translate1d(x = -1) p1 <- p$ clone()$ transform(mat) # The equivalent result applying affine transformations via method chaining p2 <- p$ clone()$ transform(diag(2))$ scale(2)$ translate(x = -1) all.equal(p1, p2)
transform2d(), project2d(), reflect2d(), rotate2d(), scale2d(), shear2d(),
and translate2d() create 2D affine transformation matrix objects.
transform2d(mat = diag(3L)) permute2d(permutation = c("xy", "yx")) project2d(line = as_line2d("x-axis"), ..., scale = 0) reflect2d(line = as_line2d("x-axis"), ...) rotate2d(theta = angle(0), ...) scale2d(x_scale = 1, y_scale = x_scale) shear2d(xy_shear = 0, yx_shear = 0) translate2d(x = as_coord2d(0, 0), ...)transform2d(mat = diag(3L)) permute2d(permutation = c("xy", "yx")) project2d(line = as_line2d("x-axis"), ..., scale = 0) reflect2d(line = as_line2d("x-axis"), ...) rotate2d(theta = angle(0), ...) scale2d(x_scale = 1, y_scale = x_scale) shear2d(xy_shear = 0, yx_shear = 0) translate2d(x = as_coord2d(0, 0), ...)
mat |
A 3x3 matrix representing a post-multiplied affine transformation matrix.
The last column must be equal to |
permutation |
Either "xy" (no permutation) or "yx" (permute x and y axes) |
line |
A Line2D object of length one representing the line
you with to reflect across or project to or an object coercible to one by |
... |
Passed to |
scale |
Oblique projection scale factor.
A degenerate |
theta |
An |
x_scale |
Scaling factor to apply to x coordinates |
y_scale |
Scaling factor to apply to y coordinates |
xy_shear |
Horizontal shear factor: |
yx_shear |
Vertical shear factor: |
x |
A Coord2D object of length one or an object coercible to one by |
transform2d()User supplied (post-multiplied) affine transformation matrix
.
project2d()Oblique vector projections onto a line parameterized by an oblique projection scale factor. A (degenerate) scale factor of zero results in an orthogonal projection.
reflect2d()Reflections across a line.
To "flip" across both the x-axis and the y-axis use scale2d(-1).
rotate2d()Rotations around the origin parameterized by an angle().
scale2d()Scale the x-coordinates and/or the y-coordinates by multiplicative scale factors.
shear2d()Shear the x-coordinates and/or the y-coordinates using shear factors.
translate2d()Translate the coordinates by a Coord2D class object parameter.
transform2d() 2D affine transformation matrix objects are meant to be
post-multiplied and therefore should not be multiplied in reverse order.
Note the Coord2D class object methods auto-pre-multiply affine transformations
when "method chaining" so pre-multiplying affine transformation matrices
to do a single cumulative transformation instead of a method chain of multiple transformations
will not improve performance as much as it does in other R packages.
To convert a pre-multiplied 2D affine transformation matrix to a post-multiplied one
simply compute its transpose using t(). To get an inverse transformation matrix
from an existing transformation matrix that does the opposite transformations
simply compute its inverse using solve().
A 3x3 post-multiplied affine transformation matrix with classes "transform2d" and "at_matrix"
p <- as_coord2d(x = sample(1:10, 3), y = sample(1:10, 3)) # {affiner} affine transformation matrices are post-multiplied # and therefore should **not** go in reverse order mat <- transform2d(diag(3)) %*% reflect2d(as_coord2d(-1, 1)) %*% rotate2d(90, "degrees") %*% scale2d(1, 2) %*% shear2d(0.5, 0.5) %*% translate2d(x = -1, y = -1) p1 <- p$ clone()$ transform(mat) # The equivalent result applying affine transformations via method chaining p2 <- p$ clone()$ transform(diag(3L))$ reflect(as_coord2d(-1, 1))$ rotate(90, "degrees")$ scale(1, 2)$ shear(0.5, 0.5)$ translate(x = -1, y = -1) all.equal(p1, p2)p <- as_coord2d(x = sample(1:10, 3), y = sample(1:10, 3)) # {affiner} affine transformation matrices are post-multiplied # and therefore should **not** go in reverse order mat <- transform2d(diag(3)) %*% reflect2d(as_coord2d(-1, 1)) %*% rotate2d(90, "degrees") %*% scale2d(1, 2) %*% shear2d(0.5, 0.5) %*% translate2d(x = -1, y = -1) p1 <- p$ clone()$ transform(mat) # The equivalent result applying affine transformations via method chaining p2 <- p$ clone()$ transform(diag(3L))$ reflect(as_coord2d(-1, 1))$ rotate(90, "degrees")$ scale(1, 2)$ shear(0.5, 0.5)$ translate(x = -1, y = -1) all.equal(p1, p2)
transform3d(), project3d(), reflect3d(), rotate3d(), scale3d(), shear3d(),
and translate3d() create 3D affine transformation matrix objects.
transform3d(mat = diag(4L)) permute3d(permutation = c("xyz", "xzy", "yxz", "yzx", "zyx", "zxy")) project3d( plane = as_plane3d("xy-plane"), ..., scale = 0, alpha = angle(45, "degrees") ) reflect3d(plane = as_plane3d("xy-plane"), ...) rotate3d(axis = as_coord3d("z-axis"), theta = angle(0), ...) scale3d(x_scale = 1, y_scale = x_scale, z_scale = x_scale) shear3d( xy_shear = 0, xz_shear = 0, yx_shear = 0, yz_shear = 0, zx_shear = 0, zy_shear = 0 ) translate3d(x = as_coord3d(0, 0, 0), ...)transform3d(mat = diag(4L)) permute3d(permutation = c("xyz", "xzy", "yxz", "yzx", "zyx", "zxy")) project3d( plane = as_plane3d("xy-plane"), ..., scale = 0, alpha = angle(45, "degrees") ) reflect3d(plane = as_plane3d("xy-plane"), ...) rotate3d(axis = as_coord3d("z-axis"), theta = angle(0), ...) scale3d(x_scale = 1, y_scale = x_scale, z_scale = x_scale) shear3d( xy_shear = 0, xz_shear = 0, yx_shear = 0, yz_shear = 0, zx_shear = 0, zy_shear = 0 ) translate3d(x = as_coord3d(0, 0, 0), ...)
mat |
A 4x4 matrix representing a post-multiplied affine transformation matrix.
The last column must be equal to |
permutation |
Either "xyz" (no permutation), "xzy" (permute y and z axes), "yxz" (permute x and y axes), "yzx" (x becomes z, y becomes x, z becomes y), "zxy" (x becomes y, y becomes z, z becomes x), "zyx" (permute x and z axes) |
plane |
A Plane3D object of length one representing the plane
you wish to reflect across or project to or an object coercible to one using |
... |
Passed to |
scale |
Oblique projection foreshortening scale factor.
A (degenerate) |
alpha |
Oblique projection angle (the angle the third axis is projected going off at).
An |
axis |
A Coord3D class object or one that can coerced to one by |
theta |
An |
x_scale |
Scaling factor to apply to x coordinates |
y_scale |
Scaling factor to apply to y coordinates |
z_scale |
Scaling factor to apply to z coordinates |
xy_shear |
Shear factor: |
xz_shear |
Shear factor: |
yx_shear |
Shear factor: |
yz_shear |
Shear factor: |
zx_shear |
Shear factor: |
zy_shear |
Shear factor: |
x |
A Coord3D object of length one or an object coercible to one by |
transform3d()User supplied (post-multiplied) affine transformation matrix
.
scale3d()Scale the x-coordinates and/or the y-coordinates and/or the z-coordinates by multiplicative scale factors.
shear3d()Shear the x-coordinates and/or the y-coordinates and/or the z-coordinates using shear factors.
translate3d()Translate the coordinates by a Coord3D class object parameter.
transform3d() 3D affine transformation matrix objects are meant to be
post-multiplied and therefore should not be multiplied in reverse order.
Note the Coord3D class object methods auto-pre-multiply affine transformations
when "method chaining" so pre-multiplying affine transformation matrices
to do a single cumulative transformation instead of a method chain of multiple transformations
will not improve performance as much as it does in other R packages.
To convert a pre-multiplied 3D affine transformation matrix to a post-multiplied one
simply compute its transpose using t(). To get an inverse transformation matrix
from an existing transformation matrix that does the opposite transformations
simply compute its inverse using solve().
A 4x4 post-multiplied affine transformation matrix with classes "transform3d" and "at_matrix"
p <- as_coord3d(x = sample(1:10, 3), y = sample(1:10, 3), z = sample(1:10, 3)) # {affiner} affine transformation matrices are post-multiplied # and therefore should **not** go in reverse order mat <- transform3d(diag(4L)) %*% rotate3d("z-axis", degrees(90)) %*% scale3d(1, 2, 1) %*% translate3d(x = -1, y = -1, z = -1) p1 <- p$ clone()$ transform(mat) # The equivalent result applying affine transformations via method chaining p2 <- p$ clone()$ transform(diag(4L))$ rotate("z-axis", degrees(90))$ scale(1, 2, 1)$ translate(x = -1, y = -1, z = -1) all.equal(p1, p2)p <- as_coord3d(x = sample(1:10, 3), y = sample(1:10, 3), z = sample(1:10, 3)) # {affiner} affine transformation matrices are post-multiplied # and therefore should **not** go in reverse order mat <- transform3d(diag(4L)) %*% rotate3d("z-axis", degrees(90)) %*% scale3d(1, 2, 1) %*% translate3d(x = -1, y = -1, z = -1) p1 <- p$ clone()$ transform(mat) # The equivalent result applying affine transformations via method chaining p2 <- p$ clone()$ transform(diag(4L))$ rotate("z-axis", degrees(90))$ scale(1, 2, 1)$ translate(x = -1, y = -1, z = -1) all.equal(p1, p2)
sine(), cosine(), tangent(), secant(), cosecant(), and cotangent() are
angle() aware trigonometric functions that allow for a user chosen angular unit.
sine(x, unit = getOption("affiner_angular_unit", "degrees")) cosine(x, unit = getOption("affiner_angular_unit", "degrees")) tangent(x, unit = getOption("affiner_angular_unit", "degrees")) secant(x, unit = getOption("affiner_angular_unit", "degrees")) cosecant(x, unit = getOption("affiner_angular_unit", "degrees")) cotangent(x, unit = getOption("affiner_angular_unit", "degrees"))sine(x, unit = getOption("affiner_angular_unit", "degrees")) cosine(x, unit = getOption("affiner_angular_unit", "degrees")) tangent(x, unit = getOption("affiner_angular_unit", "degrees")) secant(x, unit = getOption("affiner_angular_unit", "degrees")) cosecant(x, unit = getOption("affiner_angular_unit", "degrees")) cotangent(x, unit = getOption("affiner_angular_unit", "degrees"))
x |
An angle vector or an object to convert to it (such as a numeric vector) |
unit |
A string of the desired angular unit. Supports the following strings
(note we ignore any punctuation and space characters as well as any trailing
|
A numeric vector
sine(pi, "radians") cosine(180, "degrees") tangent(0.5, "turns") a <- angle(0.5, "turns") secant(a) cosecant(a) cotangent(a)sine(pi, "radians") cosine(180, "degrees") tangent(0.5, "turns") a <- angle(0.5, "turns") secant(a) cosecant(a) cotangent(a)