http://mathling.com/geometric/coordinates library module
http://mathling.com/geometric/coordinates
Coordinate system mappings
Copyright© Mary Holstege 2021-2023
CC-BY (https://creativecommons.org/licenses/by/4.0/)
Status: New
Imports
http://mathling.com/core/utilitiesimport module namespace util="http://mathling.com/core/utilities" at "../core/utilities.xqy"http://mathling.com/geometric/curve
import module namespace curve="http://mathling.com/geometric/curve" at "../geo/curves.xqy"http://mathling.com/geometric/affine
import module namespace affine="http://mathling.com/geometric/affine" at "../geo/affine.xqy"http://mathling.com/core/config
import module namespace config="http://mathling.com/core/config" at "../core/config.xqy"http://mathling.com/core/errors
import module namespace errors="http://mathling.com/core/errors" at "../core/errors.xqy"http://mathling.com/geometric/point
import module namespace point="http://mathling.com/geometric/point" at "../geo/point.xqy"
Functions
Function: bipolar
declare function bipolar($u as xs:double,
$v as xs:double) as map(xs:string,item()*)
declare function bipolar($u as xs:double, $v as xs:double) as map(xs:string,item()*)
Bipolar coordinates
x = sinh(v) / (cosh(v) - cos(u))
y = sin(u) / (cosh(v) - cos(u))
for 0 <= u < 2π; -∞ < v < ∞
Make parametric in t; v=f(t) + c
Params
- u as xs:double
- v as xs:double
Returns
- map(xs:string,item()*)
declare function this:bipolar( $u as xs:double, $v as xs:double ) as map(xs:string,item()*) { let $divisor := util:cosh($v) - math:cos($u) let $x := util:sinh($v) div $divisor let $y := math:sin($u) div $divisor return ( point:point($x, $y) ) }
Function: bipolar
declare function bipolar($t as xs:double,
$f as function(xs:double) as xs:double,
$c as xs:double) as map(xs:string,item()*)
declare function bipolar($t as xs:double, $f as function(xs:double) as xs:double, $c as xs:double) as map(xs:string,item()*)
Bipolar coordinates
x = a sinh(v) / (cosh(v) - cos(u))
y = a sin(u) / (cosh(v) - cos(u))
for 0 <= u < 2π; -∞ < v < ∞
Make parametric in u=t; v=f(t) + c
Which allows a nice sliced rendering via curve:multi-plot()
Params
- t as xs:double
- f as function(xs:double)asxs:double
- c as xs:double
Returns
- map(xs:string,item()*)
declare function this:bipolar( $t as xs:double, $f as function(xs:double) as xs:double, $c as xs:double ) as map(xs:string,item()*) { this:bipolar($t, $f($t) + $c) }
Function: circular
declare function circular($u as xs:double,
$v as xs:double) as map(xs:string, item()*)
declare function circular($u as xs:double, $v as xs:double) as map(xs:string, item()*)
Circular coordinates:
Elliot Tanis and Lee Kuivinen, Circular Coordinates and Computer Drawn
Designs. Mathematics Magazine. Vol 52 No 3. May, 1979:
Coordinates with two perpendicular axes U and V where each point on the
axes is center of circle through origin; (u,v) is intersection of
circle whose center is at u on horizontal axis w/ circle whose center v
is on vertical axis.
(s,t) =>
s = g(u) = 2uv²/(u²+v²)
t = h(u) = 2u²v/(u²+v²)
Params
- u as xs:double
- v as xs:double
Returns
- map(xs:string,item()*)
declare function this:circular( $u as xs:double, $v as xs:double ) as map(xs:string, item()*) { let $divisor := $u*$u + $v*$v let $x := (2*$u*$v*$v) div $divisor let $y := (2*$u*$u*$v) div $divisor return point:point($x, $y) }
Function: circular
declare function circular($t as xs:double,
$f as function(xs:double) as xs:double,
$c as xs:double) as map(xs:string,item()*)
declare function circular($t as xs:double, $f as function(xs:double) as xs:double, $c as xs:double) as map(xs:string,item()*)
Circular coordinates:
Elliot Tanis and Lee Kuivinen, Circular Coordinates and Computer Drawn
Designs. Mathematics Magazine. Vol 52 No 3. May, 1979:
Coordinates with two perpendicular axes U and V where each point on the
axes is center of circle through origin; (u,v) is intersection of
circle whose center is at u on horizontal axis w/ circle whose center v
is on vertical axis.
(s,t) =>
s = g(u) = 2uv²/(u²+v²)
t = h(u) = 2u²v/(u²+v²)
Make parametric in t: u=t, v=f(t) + c
Which allows a nice sliced rendering, e.g.
curve:multi-plot(n-points, n-slices,
function($t, $c) { coord:circular($t, $f, $c) },
$t-extent, $t-symmetric,
$do-spline
)
https://www.johndcook.com/blog/2020/11/09/some-mathematical-art/
Given f(t) compute
x(t) = 2t(f(t))²/(t²+(f(t))²)
y(t) = 2t²f(t)/(t²+(f(t))²)
where f(t) = d(t) + c for x = -10, -9, -8 etc.
Params
- t as xs:double
- f as function(xs:double)asxs:double
- c as xs:double
Returns
- map(xs:string,item()*)
declare function this:circular( $t as xs:double, $f as function(xs:double) as xs:double, $c as xs:double ) as map(xs:string,item()*) { this:circular($t, $f($t) + $c) }
Function: parabolic
declare function parabolic($u as xs:double,
$v as xs:double) as map(xs:string,item()*)
declare function parabolic($u as xs:double, $v as xs:double) as map(xs:string,item()*)
parabolic()
Parabolic coordinates
x = uv
y = 1/2(v² - u²)
Params
- u as xs:double
- v as xs:double
Returns
- map(xs:string,item()*)
declare function this:parabolic( $u as xs:double, $v as xs:double ) as map(xs:string,item()*) { point:point( $u * $v, ($v*$v - $u*$u) div 2 ) }
Function: parabolic
declare function parabolic($t as xs:double,
$f as function(xs:double) as xs:double,
$c as xs:double) as map(xs:string,item()*)
declare function parabolic($t as xs:double, $f as function(xs:double) as xs:double, $c as xs:double) as map(xs:string,item()*)
Params
- t as xs:double
- f as function(xs:double)asxs:double
- c as xs:double
Returns
- map(xs:string,item()*)
declare function this:parabolic( $t as xs:double, $f as function(xs:double) as xs:double, $c as xs:double ) as map(xs:string,item()*) { this:parabolic($t, $f($t) + $c) }
Function: elliptic
declare function elliptic($u as xs:double,
$v as xs:double) as map(xs:string,item()*)
declare function elliptic($u as xs:double, $v as xs:double) as map(xs:string,item()*)
elliptic()
Elliptic coordinates
x = cosh u cos v
y = sinh u sin v
u >= 0, 0 <= v <= 2π
Params
- u as xs:double
- v as xs:double
Returns
- map(xs:string,item()*)
declare function this:elliptic( $u as xs:double, $v as xs:double ) as map(xs:string,item()*) { point:point( util:cosh($u) * math:cos($v), util:sinh($u) * math:sin($v) ) }
Function: elliptic
declare function elliptic($t as xs:double,
$f as function(xs:double) as xs:double,
$c as xs:double) as map(xs:string,item()*)
declare function elliptic($t as xs:double, $f as function(xs:double) as xs:double, $c as xs:double) as map(xs:string,item()*)
Params
- t as xs:double
- f as function(xs:double)asxs:double
- c as xs:double
Returns
- map(xs:string,item()*)
declare function this:elliptic( $t as xs:double, $f as function(xs:double) as xs:double, $c as xs:double ) as map(xs:string,item()*) { this:elliptic($t, $f($t) + $c) }
Function: affine2
declare function affine2($u as xs:double,
$v as xs:double,
$matrix as xs:double*) as map(xs:string,item()*)
declare function affine2($u as xs:double, $v as xs:double, $matrix as xs:double*) as map(xs:string,item()*)
affine2()
Affine coordinates
(x, y) = affine2((u, v))
Params
- u as xs:double
- v as xs:double
- matrix as xs:double*
Returns
- map(xs:string,item()*)
declare function this:affine2( $u as xs:double, $v as xs:double, $matrix as xs:double* (: 2D affine matrix :) ) as map(xs:string,item()*) { point:vector( affine:affine2(($u, $v), $matrix) ) }
Function: affine2
declare function affine2($t as xs:double,
$f as function(xs:double) as xs:double,
$c as xs:double,
$matrix as xs:double*) as map(xs:string,item()*)
declare function affine2($t as xs:double, $f as function(xs:double) as xs:double, $c as xs:double, $matrix as xs:double*) as map(xs:string,item()*)
Params
- t as xs:double
- f as function(xs:double)asxs:double
- c as xs:double
- matrix as xs:double*
Returns
- map(xs:string,item()*)
declare function this:affine2( $t as xs:double, $f as function(xs:double) as xs:double, $c as xs:double, $matrix as xs:double* ) as map(xs:string,item()*) { this:affine2($t, $f($t) + $c, $matrix) }
Function: curvilinear2
declare function curvilinear2($u as xs:double,
$v as xs:double,
$ptmap as function(xs:double*) as xs:double*) as map(xs:string,item()*)
declare function curvilinear2($u as xs:double, $v as xs:double, $ptmap as function(xs:double*) as xs:double*) as map(xs:string,item()*)
curvilinear2()
Curvilinear coordinates
Params
- u as xs:double
- v as xs:double
- ptmap as function(xs:double*)asxs:double*
Returns
- map(xs:string,item()*)
declare function this:curvilinear2( $u as xs:double, $v as xs:double, $ptmap as function(xs:double*) as xs:double* ) as map(xs:string,item()*) { point:vector( $ptmap(($u, $v)) ) }
Function: curvilinear2
declare function curvilinear2($t as xs:double,
$f as function(xs:double) as xs:double,
$c as xs:double,
$ptmap as function(xs:double*) as xs:double*) as map(xs:string,item()*)
declare function curvilinear2($t as xs:double, $f as function(xs:double) as xs:double, $c as xs:double, $ptmap as function(xs:double*) as xs:double*) as map(xs:string,item()*)
Params
- t as xs:double
- f as function(xs:double)asxs:double
- c as xs:double
- ptmap as function(xs:double*)asxs:double*
Returns
- map(xs:string,item()*)
declare function this:curvilinear2( $t as xs:double, $f as function(xs:double) as xs:double, $c as xs:double, $ptmap as function(xs:double*) as xs:double* ) as map(xs:string,item()*) { this:curvilinear2($t, $f($t) + $c, $ptmap) }
Function: bipolar-cylindrical
declare function bipolar-cylindrical($u as xs:double,
$v as xs:double,
$w as xs:double) as map(xs:string,item()*)
declare function bipolar-cylindrical($u as xs:double, $v as xs:double, $w as xs:double) as map(xs:string,item()*)
bipolar-cylindical()
x = sinh(v)/(cosh(v) - cos(u))
y = sin(u)/(cosh(v) - cos(u))
z = w
Params
- u as xs:double
- v as xs:double
- w as xs:double
Returns
- map(xs:string,item()*)
declare function this:bipolar-cylindrical( $u as xs:double, $v as xs:double, $w as xs:double ) as map(xs:string,item()*) { let $divisor := util:cosh($v) - math:cos($u) return ( point:point( util:sinh($v) div $divisor, math:sin($u) div $divisor, $w ) ) }
Function: bipolar-cylindrical
declare function bipolar-cylindrical($t as xs:double,
$f as function(xs:double) as xs:double,
$g as function(xs:double) as xs:double,
$c as xs:double) as map(xs:string,item()*)
declare function bipolar-cylindrical($t as xs:double, $f as function(xs:double) as xs:double, $g as function(xs:double) as xs:double, $c as xs:double) as map(xs:string,item()*)
bipolar-cylindical()
Make parametric in t
u = t, v = f(t), w = g(t)
Params
- t as xs:double
- f as function(xs:double)asxs:double
- g as function(xs:double)asxs:double
- c as xs:double
Returns
- map(xs:string,item()*)
declare function this:bipolar-cylindrical( $t as xs:double, $f as function(xs:double) as xs:double, $g as function(xs:double) as xs:double, $c as xs:double ) as map(xs:string,item()*) { this:bipolar-cylindrical($t, $f($t) + $c, $g($t)) }
Function: bispherical
declare function bispherical($u as xs:double,
$v as xs:double,
$w as xs:double) as map(xs:string,item()*)
declare function bispherical($u as xs:double, $v as xs:double, $w as xs:double) as map(xs:string,item()*)
bispherical()
x = (sin(v)/(cosh(u)-cos(v)))*cos(w)
y = (sin(v)/(cosh(u)-cos(v)))*sin(w)
z = sinh(u)/(cosh(u)-cos(v)))
Params
- u as xs:double
- v as xs:double
- w as xs:double
Returns
- map(xs:string,item()*)
declare function this:bispherical( $u as xs:double, $v as xs:double, $w as xs:double ) as map(xs:string,item()*) { let $divisor := util:cosh($u) - math:cos($v) return ( point:point( (math:sin($v) div $divisor)*math:cos($w), (math:sin($v) div $divisor)*math:sin($w), util:sinh($u) div $divisor ) ) }
Function: bispherical
declare function bispherical($t as xs:double,
$f as function(xs:double) as xs:double,
$g as function(xs:double) as xs:double,
$c as xs:double) as map(xs:string,item()*)
declare function bispherical($t as xs:double, $f as function(xs:double) as xs:double, $g as function(xs:double) as xs:double, $c as xs:double) as map(xs:string,item()*)
bispherical()
Make parametric in t
u = t, v = f(t), w = g(t)
Params
- t as xs:double
- f as function(xs:double)asxs:double
- g as function(xs:double)asxs:double
- c as xs:double
Returns
- map(xs:string,item()*)
declare function this:bispherical( $t as xs:double, $f as function(xs:double) as xs:double, $g as function(xs:double) as xs:double, $c as xs:double ) as map(xs:string,item()*) { this:bispherical($t, $f($t) + $c, $g($t)) }
Function: toroidal
declare function toroidal($u as xs:double,
$v as xs:double,
$w as xs:double) as map(xs:string,item()*)
declare function toroidal($u as xs:double, $v as xs:double, $w as xs:double) as map(xs:string,item()*)
toroidal()
x = (sinh(u)/(cosh(u)-cos(v)))*cos(w)
y = (sinh(u)/(cosh(u)-cos(v)))*sin(w)
z = sin(v)/(cosh(u)-cos(v))
Params
- u as xs:double
- v as xs:double
- w as xs:double
Returns
- map(xs:string,item()*)
declare function this:toroidal( $u as xs:double, $v as xs:double, $w as xs:double ) as map(xs:string,item()*) { let $divisor := util:cosh($u) - math:cos($v) return ( point:point( (util:sinh($u) div $divisor)*math:cos($w), (util:sinh($u) div $divisor)*math:sin($w), math:sin($v) div $divisor ) ) }
Function: toroidal
declare function toroidal($t as xs:double,
$f as function(xs:double) as xs:double,
$g as function(xs:double) as xs:double,
$c as xs:double) as map(xs:string,item()*)
declare function toroidal($t as xs:double, $f as function(xs:double) as xs:double, $g as function(xs:double) as xs:double, $c as xs:double) as map(xs:string,item()*)
toroidal()
Make parametric in t
u = t, v = f(t), w = g(t)
Params
- t as xs:double
- f as function(xs:double)asxs:double
- g as function(xs:double)asxs:double
- c as xs:double
Returns
- map(xs:string,item()*)
declare function this:toroidal( $t as xs:double, $f as function(xs:double) as xs:double, $g as function(xs:double) as xs:double, $c as xs:double ) as map(xs:string,item()*) { this:toroidal($t, $f($t) + $c, $g($t)) }
Function: ellipsoidal
declare function ellipsoidal($u as xs:double,
$v as xs:double,
$w as xs:double,
$abc as xs:double*) as map(xs:string,item()*)
declare function ellipsoidal($u as xs:double, $v as xs:double, $w as xs:double, $abc as xs:double*) as map(xs:string,item()*)
ellipsoidal()
x = a u sin(v)cos(w)
y = b u sin(v)sin(w)
z = c u cos(v)
u > 0; 0 <= v <= π; 0 <= w <= 2π
Params
- u as xs:double
- v as xs:double
- w as xs:double
- abc as xs:double*
Returns
- map(xs:string,item()*)
declare function this:ellipsoidal( $u as xs:double, $v as xs:double, $w as xs:double, $abc as xs:double* ) as map(xs:string,item()*) { let $ak := ($abc[1], 1)[1] let $bk := ($abc[2], 1)[1] let $ck := ($abc[3], 1)[1] return ( point:point( $ak * $u * math:sin($v) * math:cos($w), $bk * $u * math:sin($v) * math:sin($w), $ck * $u * math:cos($v) ) ) }
Function: ellipsoidal
declare function ellipsoidal($u as xs:double,
$v as xs:double,
$w as xs:double) as map(xs:string,item()*)
declare function ellipsoidal($u as xs:double, $v as xs:double, $w as xs:double) as map(xs:string,item()*)
Params
- u as xs:double
- v as xs:double
- w as xs:double
Returns
- map(xs:string,item()*)
declare function this:ellipsoidal( $u as xs:double, $v as xs:double, $w as xs:double ) as map(xs:string,item()*) { this:ellipsoidal($u, $v, $w, (1.0, 1.0, 1.0)) (: A unit sphere, actually :) }
Function: ellipsoidal
declare function ellipsoidal($t as xs:double,
$f as function(xs:double) as xs:double,
$g as function(xs:double) as xs:double,
$c as xs:double,
$abc as xs:double*) as map(xs:string,item()*)
declare function ellipsoidal($t as xs:double, $f as function(xs:double) as xs:double, $g as function(xs:double) as xs:double, $c as xs:double, $abc as xs:double*) as map(xs:string,item()*)
ellipsoidal()
Make parametric in t
u = t, v = f(t), w = g(t)
Params
- t as xs:double
- f as function(xs:double)asxs:double
- g as function(xs:double)asxs:double
- c as xs:double
- abc as xs:double*
Returns
- map(xs:string,item()*)
declare function this:ellipsoidal( $t as xs:double, $f as function(xs:double) as xs:double, $g as function(xs:double) as xs:double, $c as xs:double, $abc as xs:double* ) as map(xs:string,item()*) { this:ellipsoidal($t, $f($t) + $c, $g($t), $abc) }
Function: spherical
declare function spherical($u as xs:double,
$v as xs:double,
$w as xs:double) as map(xs:string,item()*)
declare function spherical($u as xs:double, $v as xs:double, $w as xs:double) as map(xs:string,item()*)
spherical()
x = u sin(v)cos(w)
y = u sin(v)sin(w)
z = u cos(v)
u > 0; 0 <= v <= π; 0 <= w <= 2π
Params
- u as xs:double
- v as xs:double
- w as xs:double
Returns
- map(xs:string,item()*)
declare function this:spherical( $u as xs:double, $v as xs:double, $w as xs:double ) as map(xs:string,item()*) { point:point( $u * math:sin($v) * math:cos($w), $u * math:sin($v) * math:sin($w), $u * math:cos($v) ) }
Function: spherical
declare function spherical($t as xs:double,
$f as function(xs:double) as xs:double,
$g as function(xs:double) as xs:double,
$c as xs:double) as map(xs:string,item()*)
declare function spherical($t as xs:double, $f as function(xs:double) as xs:double, $g as function(xs:double) as xs:double, $c as xs:double) as map(xs:string,item()*)
spherical()
Make parametric in t
u = t, v = f(t), w = g(t)
Params
- t as xs:double
- f as function(xs:double)asxs:double
- g as function(xs:double)asxs:double
- c as xs:double
Returns
- map(xs:string,item()*)
declare function this:spherical( $t as xs:double, $f as function(xs:double) as xs:double, $g as function(xs:double) as xs:double, $c as xs:double ) as map(xs:string,item()*) { this:spherical($t, $f($t) + $c, $g($t)) }
Function: affine3
declare function affine3($u as xs:double,
$v as xs:double,
$w as xs:double,
$matrix as xs:double*) as map(xs:string,item()*)
declare function affine3($u as xs:double, $v as xs:double, $w as xs:double, $matrix as xs:double*) as map(xs:string,item()*)
affine3()
Affine coordinates
(x, y) = affine((u, v))
Params
- u as xs:double
- v as xs:double
- w as xs:double
- matrix as xs:double*
Returns
- map(xs:string,item()*)
declare function this:affine3( $u as xs:double, $v as xs:double, $w as xs:double, $matrix as xs:double* (: 3D affine matrix :) ) as map(xs:string,item()*) { point:vector( affine:affine3(($u, $v, $w), $matrix) ) }
Function: affine3
declare function affine3($t as xs:double,
$f as function(xs:double) as xs:double,
$g as function(xs:double) as xs:double,
$c as xs:double,
$matrix as xs:double*) as map(xs:string,item()*)
declare function affine3($t as xs:double, $f as function(xs:double) as xs:double, $g as function(xs:double) as xs:double, $c as xs:double, $matrix as xs:double*) as map(xs:string,item()*)
Params
- t as xs:double
- f as function(xs:double)asxs:double
- g as function(xs:double)asxs:double
- c as xs:double
- matrix as xs:double*
Returns
- map(xs:string,item()*)
declare function this:affine3( $t as xs:double, $f as function(xs:double) as xs:double, $g as function(xs:double) as xs:double, $c as xs:double, $matrix as xs:double* ) as map(xs:string,item()*) { this:affine3($t, $f($t) + $c, $g($t), $matrix) }
Function: curvilinear3
declare function curvilinear3($u as xs:double,
$v as xs:double,
$w as xs:double,
$ptmap as function(xs:double*) as xs:double*) as map(xs:string,item()*)
declare function curvilinear3($u as xs:double, $v as xs:double, $w as xs:double, $ptmap as function(xs:double*) as xs:double*) as map(xs:string,item()*)
curvilinear3()
Curvilinear coordinates
Params
- u as xs:double
- v as xs:double
- w as xs:double
- ptmap as function(xs:double*)asxs:double*
Returns
- map(xs:string,item()*)
declare function this:curvilinear3( $u as xs:double, $v as xs:double, $w as xs:double, $ptmap as function(xs:double*) as xs:double* ) as map(xs:string,item()*) { point:vector( $ptmap(($u, $v, $w)) ) }
Function: curvilinear3
declare function curvilinear3($t as xs:double,
$f as function(xs:double) as xs:double,
$g as function(xs:double) as xs:double,
$c as xs:double,
$ptmap as function(xs:double*) as xs:double*) as map(xs:string,item()*)
declare function curvilinear3($t as xs:double, $f as function(xs:double) as xs:double, $g as function(xs:double) as xs:double, $c as xs:double, $ptmap as function(xs:double*) as xs:double*) as map(xs:string,item()*)
Params
- t as xs:double
- f as function(xs:double)asxs:double
- g as function(xs:double)asxs:double
- c as xs:double
- ptmap as function(xs:double*)asxs:double*
Returns
- map(xs:string,item()*)
declare function this:curvilinear3( $t as xs:double, $f as function(xs:double) as xs:double, $g as function(xs:double) as xs:double, $c as xs:double, $ptmap as function(xs:double*) as xs:double* ) as map(xs:string,item()*) { this:curvilinear3($t, $f($t) + $c, $g($t), $ptmap) }
Function: stereographic
declare function stereographic($pt as map(xs:string,item()*)*) as map(xs:string,item()*)
declare function stereographic($pt as map(xs:string,item()*)*) as map(xs:string,item()*)
stereographic()
Stereographic mapping from sphere to plane.
Point is expected to be on unit sphere, so you'll need to do some scaling
and translating. (See geom:stereographic())
Params
- pt as map(xs:string,item()*)*
Returns
- map(xs:string,item()*)
declare function this:stereographic( $pt as map(xs:string,item()*)* ) as map(xs:string,item()*) { point:point( point:px($pt) div (1 - point:pz($pt)), point:py($pt) div (1 - point:pz($pt)) ) }
Function: stereographic3D
declare function stereographic3D($pt as map(xs:string,item()*)*) as map(xs:string,item()*)
declare function stereographic3D($pt as map(xs:string,item()*)*) as map(xs:string,item()*)
stereographic3D()
Inverse stereographic mapping. Returns 3D point on unit sphere, so you'll
need to do some scaling and translating (see geom:stereographic3D())
Params
- pt as map(xs:string,item()*)*
Returns
- map(xs:string,item()*)
declare function this:stereographic3D( $pt as map(xs:string,item()*)* ) as map(xs:string,item()*) { let $divisor := 1 + point:px($pt)*point:px($pt) + point:py($pt)*point:py($pt) return point:point( 2 * point:px($pt) div $divisor, 2 * point:py($pt) div $divisor, (-1 + point:px($pt)*point:px($pt) + point:py($pt)*point:py($pt)) div $divisor ) }
Original Source Code
xquery version "3.1"; (:~ : Coordinate system mappings : : Copyright© Mary Holstege 2021-2023 : CC-BY (https://creativecommons.org/licenses/by/4.0/) : @since December 2022 : @custom:Status New :) module namespace this="http://mathling.com/geometric/coordinates"; import module namespace config="http://mathling.com/core/config" at "../core/config.xqy"; import module namespace errors="http://mathling.com/core/errors" at "../core/errors.xqy"; import module namespace util="http://mathling.com/core/utilities" at "../core/utilities.xqy"; import module namespace point="http://mathling.com/geometric/point" at "../geo/point.xqy"; import module namespace affine="http://mathling.com/geometric/affine" at "../geo/affine.xqy"; import module namespace curve="http://mathling.com/geometric/curve" at "../geo/curves.xqy"; declare namespace map="http://www.w3.org/2005/xpath-functions/map"; declare namespace array="http://www.w3.org/2005/xpath-functions/array"; declare namespace math="http://www.w3.org/2005/xpath-functions/math"; (:~ : Bipolar coordinates : x = sinh(v) / (cosh(v) - cos(u)) : y = sin(u) / (cosh(v) - cos(u)) : for 0 <= u < 2π; -∞ < v < ∞ : Make parametric in t; v=f(t) + c :) declare function this:bipolar( $u as xs:double, $v as xs:double ) as map(xs:string,item()*) { let $divisor := util:cosh($v) - math:cos($u) let $x := util:sinh($v) div $divisor let $y := math:sin($u) div $divisor return ( point:point($x, $y) ) }; (:~ : Bipolar coordinates : x = a sinh(v) / (cosh(v) - cos(u)) : y = a sin(u) / (cosh(v) - cos(u)) : for 0 <= u < 2π; -∞ < v < ∞ : Make parametric in u=t; v=f(t) + c : Which allows a nice sliced rendering via curve:multi-plot() :) declare function this:bipolar( $t as xs:double, $f as function(xs:double) as xs:double, $c as xs:double ) as map(xs:string,item()*) { this:bipolar($t, $f($t) + $c) }; (:~ : Circular coordinates: : Elliot Tanis and Lee Kuivinen, Circular Coordinates and Computer Drawn : Designs. Mathematics Magazine. Vol 52 No 3. May, 1979: : : Coordinates with two perpendicular axes U and V where each point on the : axes is center of circle through origin; (u,v) is intersection of : circle whose center is at u on horizontal axis w/ circle whose center v : is on vertical axis. : : (s,t) => : s = g(u) = 2uv²/(u²+v²) : t = h(u) = 2u²v/(u²+v²) :) declare function this:circular( $u as xs:double, $v as xs:double ) as map(xs:string, item()*) { let $divisor := $u*$u + $v*$v let $x := (2*$u*$v*$v) div $divisor let $y := (2*$u*$u*$v) div $divisor return point:point($x, $y) }; (:~ : Circular coordinates: : Elliot Tanis and Lee Kuivinen, Circular Coordinates and Computer Drawn : Designs. Mathematics Magazine. Vol 52 No 3. May, 1979: : : Coordinates with two perpendicular axes U and V where each point on the : axes is center of circle through origin; (u,v) is intersection of : circle whose center is at u on horizontal axis w/ circle whose center v : is on vertical axis. : : (s,t) => : s = g(u) = 2uv²/(u²+v²) : t = h(u) = 2u²v/(u²+v²) : Make parametric in t: u=t, v=f(t) + c : Which allows a nice sliced rendering, e.g. : curve:multi-plot(n-points, n-slices, : function($t, $c) { coord:circular($t, $f, $c) }, : $t-extent, $t-symmetric, : $do-spline : ) : : https://www.johndcook.com/blog/2020/11/09/some-mathematical-art/ : Given f(t) compute : x(t) = 2t(f(t))²/(t²+(f(t))²) : y(t) = 2t²f(t)/(t²+(f(t))²) : where f(t) = d(t) + c for x = -10, -9, -8 etc. :) declare function this:circular( $t as xs:double, $f as function(xs:double) as xs:double, $c as xs:double ) as map(xs:string,item()*) { this:circular($t, $f($t) + $c) }; (:~ : parabolic() : Parabolic coordinates : x = uv : y = 1/2(v² - u²) :) declare function this:parabolic( $u as xs:double, $v as xs:double ) as map(xs:string,item()*) { point:point( $u * $v, ($v*$v - $u*$u) div 2 ) }; declare function this:parabolic( $t as xs:double, $f as function(xs:double) as xs:double, $c as xs:double ) as map(xs:string,item()*) { this:parabolic($t, $f($t) + $c) }; (:~ : elliptic() : Elliptic coordinates : x = cosh u cos v : y = sinh u sin v : u >= 0, 0 <= v <= 2π :) declare function this:elliptic( $u as xs:double, $v as xs:double ) as map(xs:string,item()*) { point:point( util:cosh($u) * math:cos($v), util:sinh($u) * math:sin($v) ) }; declare function this:elliptic( $t as xs:double, $f as function(xs:double) as xs:double, $c as xs:double ) as map(xs:string,item()*) { this:elliptic($t, $f($t) + $c) }; (:~ : affine2() : Affine coordinates : (x, y) = affine2((u, v)) :) declare function this:affine2( $u as xs:double, $v as xs:double, $matrix as xs:double* (: 2D affine matrix :) ) as map(xs:string,item()*) { point:vector( affine:affine2(($u, $v), $matrix) ) }; declare function this:affine2( $t as xs:double, $f as function(xs:double) as xs:double, $c as xs:double, $matrix as xs:double* ) as map(xs:string,item()*) { this:affine2($t, $f($t) + $c, $matrix) }; (:~ : curvilinear2() : Curvilinear coordinates :) declare function this:curvilinear2( $u as xs:double, $v as xs:double, $ptmap as function(xs:double*) as xs:double* ) as map(xs:string,item()*) { point:vector( $ptmap(($u, $v)) ) }; declare function this:curvilinear2( $t as xs:double, $f as function(xs:double) as xs:double, $c as xs:double, $ptmap as function(xs:double*) as xs:double* ) as map(xs:string,item()*) { this:curvilinear2($t, $f($t) + $c, $ptmap) }; (:=== 3D ===:) (:~ : bipolar-cylindical() : x = sinh(v)/(cosh(v) - cos(u)) : y = sin(u)/(cosh(v) - cos(u)) : z = w :) declare function this:bipolar-cylindrical( $u as xs:double, $v as xs:double, $w as xs:double ) as map(xs:string,item()*) { let $divisor := util:cosh($v) - math:cos($u) return ( point:point( util:sinh($v) div $divisor, math:sin($u) div $divisor, $w ) ) }; (:~ : bipolar-cylindical() : Make parametric in t : u = t, v = f(t), w = g(t) :) declare function this:bipolar-cylindrical( $t as xs:double, $f as function(xs:double) as xs:double, $g as function(xs:double) as xs:double, $c as xs:double ) as map(xs:string,item()*) { this:bipolar-cylindrical($t, $f($t) + $c, $g($t)) }; (:~ : bispherical() : x = (sin(v)/(cosh(u)-cos(v)))*cos(w) : y = (sin(v)/(cosh(u)-cos(v)))*sin(w) : z = sinh(u)/(cosh(u)-cos(v))) :) declare function this:bispherical( $u as xs:double, $v as xs:double, $w as xs:double ) as map(xs:string,item()*) { let $divisor := util:cosh($u) - math:cos($v) return ( point:point( (math:sin($v) div $divisor)*math:cos($w), (math:sin($v) div $divisor)*math:sin($w), util:sinh($u) div $divisor ) ) }; (:~ : bispherical() : Make parametric in t : u = t, v = f(t), w = g(t) :) declare function this:bispherical( $t as xs:double, $f as function(xs:double) as xs:double, $g as function(xs:double) as xs:double, $c as xs:double ) as map(xs:string,item()*) { this:bispherical($t, $f($t) + $c, $g($t)) }; (:~ : toroidal() : x = (sinh(u)/(cosh(u)-cos(v)))*cos(w) : y = (sinh(u)/(cosh(u)-cos(v)))*sin(w) : z = sin(v)/(cosh(u)-cos(v)) :) declare function this:toroidal( $u as xs:double, $v as xs:double, $w as xs:double ) as map(xs:string,item()*) { let $divisor := util:cosh($u) - math:cos($v) return ( point:point( (util:sinh($u) div $divisor)*math:cos($w), (util:sinh($u) div $divisor)*math:sin($w), math:sin($v) div $divisor ) ) }; (:~ : toroidal() : Make parametric in t : u = t, v = f(t), w = g(t) :) declare function this:toroidal( $t as xs:double, $f as function(xs:double) as xs:double, $g as function(xs:double) as xs:double, $c as xs:double ) as map(xs:string,item()*) { this:toroidal($t, $f($t) + $c, $g($t)) }; (:~ : ellipsoidal() : x = a u sin(v)cos(w) : y = b u sin(v)sin(w) : z = c u cos(v) : u > 0; 0 <= v <= π; 0 <= w <= 2π :) declare function this:ellipsoidal( $u as xs:double, $v as xs:double, $w as xs:double, $abc as xs:double* ) as map(xs:string,item()*) { let $ak := ($abc[1], 1)[1] let $bk := ($abc[2], 1)[1] let $ck := ($abc[3], 1)[1] return ( point:point( $ak * $u * math:sin($v) * math:cos($w), $bk * $u * math:sin($v) * math:sin($w), $ck * $u * math:cos($v) ) ) }; declare function this:ellipsoidal( $u as xs:double, $v as xs:double, $w as xs:double ) as map(xs:string,item()*) { this:ellipsoidal($u, $v, $w, (1.0, 1.0, 1.0)) (: A unit sphere, actually :) }; (:~ : ellipsoidal() : Make parametric in t : u = t, v = f(t), w = g(t) :) declare function this:ellipsoidal( $t as xs:double, $f as function(xs:double) as xs:double, $g as function(xs:double) as xs:double, $c as xs:double, $abc as xs:double* ) as map(xs:string,item()*) { this:ellipsoidal($t, $f($t) + $c, $g($t), $abc) }; (:~ : spherical() : x = u sin(v)cos(w) : y = u sin(v)sin(w) : z = u cos(v) : u > 0; 0 <= v <= π; 0 <= w <= 2π :) declare function this:spherical( $u as xs:double, $v as xs:double, $w as xs:double ) as map(xs:string,item()*) { point:point( $u * math:sin($v) * math:cos($w), $u * math:sin($v) * math:sin($w), $u * math:cos($v) ) }; (:~ : spherical() : Make parametric in t : u = t, v = f(t), w = g(t) :) declare function this:spherical( $t as xs:double, $f as function(xs:double) as xs:double, $g as function(xs:double) as xs:double, $c as xs:double ) as map(xs:string,item()*) { this:spherical($t, $f($t) + $c, $g($t)) }; (:~ : affine3() : Affine coordinates : (x, y) = affine((u, v)) :) declare function this:affine3( $u as xs:double, $v as xs:double, $w as xs:double, $matrix as xs:double* (: 3D affine matrix :) ) as map(xs:string,item()*) { point:vector( affine:affine3(($u, $v, $w), $matrix) ) }; declare function this:affine3( $t as xs:double, $f as function(xs:double) as xs:double, $g as function(xs:double) as xs:double, $c as xs:double, $matrix as xs:double* ) as map(xs:string,item()*) { this:affine3($t, $f($t) + $c, $g($t), $matrix) }; (:~ : curvilinear3() : Curvilinear coordinates :) declare function this:curvilinear3( $u as xs:double, $v as xs:double, $w as xs:double, $ptmap as function(xs:double*) as xs:double* ) as map(xs:string,item()*) { point:vector( $ptmap(($u, $v, $w)) ) }; declare function this:curvilinear3( $t as xs:double, $f as function(xs:double) as xs:double, $g as function(xs:double) as xs:double, $c as xs:double, $ptmap as function(xs:double*) as xs:double* ) as map(xs:string,item()*) { this:curvilinear3($t, $f($t) + $c, $g($t), $ptmap) }; (: 2D <=> 3D :) (:~ : stereographic() : Stereographic mapping from sphere to plane. : Point is expected to be on unit sphere, so you'll need to do some scaling : and translating. (See geom:stereographic()) :) declare function this:stereographic( $pt as map(xs:string,item()*)* ) as map(xs:string,item()*) { point:point( point:px($pt) div (1 - point:pz($pt)), point:py($pt) div (1 - point:pz($pt)) ) }; (:~ : stereographic3D() : Inverse stereographic mapping. Returns 3D point on unit sphere, so you'll : need to do some scaling and translating (see geom:stereographic3D()) :) declare function this:stereographic3D( $pt as map(xs:string,item()*)* ) as map(xs:string,item()*) { let $divisor := 1 + point:px($pt)*point:px($pt) + point:py($pt)*point:py($pt) return point:point( 2 * point:px($pt) div $divisor, 2 * point:py($pt) div $divisor, (-1 + point:px($pt)*point:px($pt) + point:py($pt)*point:py($pt)) div $divisor ) };