2

I'm programming an implementation of the Peirce quincuncial map projection. The projection involves a stereographic projection of a hemisphere of the globe onto a circle (I've got that part), then mapping points on that circle onto a square with a conformal mapping.

Wikipedia describes the relationship between a point $(p, \theta)$ on the circle and a point $(x, y)$ on the square as

$$\tan \left( \frac{p}{2} \right) e^{i \theta} = \mathrm{cn} \left( z, \frac{1}{2} \right), \text{ where } z = x + i y.$$

I don't understand the notation $\mathrm{cn} \left( z, \frac{1}{2} \right)$. Can it be written using algebraic and trigonometric functions?

That is, can you rewrite the above like this?

$\tan \left( \frac{p}{2} \right) \cos\theta = $ something in terms of $x$ and $y$

$\tan \left( \frac{p}{2} \right) \sin\theta = $ something in terms of $x$ and $y$

Thanks.

bugloaf
  • 123
  • since 'w'is hanging , maybe it's mis-transcribed 'w'? Still doesn't make sense to me. You can use complex log/exp - but your circle will be an annulus. – greggo Nov 10 '14 at 15:56
  • @greggo $w$ is not hanging. $z$ and $w$ are point and image point, and $w$ enters on the left of the equation (using its polar components $p$ and $\theta$), wheras $z$ enters on the right is inside a Jacobi elliptic function - not that this would facilitate things (else we might expect a simler formula in Wikipedia) – Hagen von Eitzen Nov 10 '14 at 16:00
  • (looks up pierce...) ok, weirder than I thought. The transform appears to reach singularities (infinite scale) at the square corners, allowing those corners to map to points at the boundary of the circle while still being conformal. Cool... – greggo Nov 10 '14 at 16:13
  • Sorry, the w is just a distraction. It's a relic of my copy and paste from Wikipedia. I removed it and also tried to clarify what I'm looking for in an answer. – bugloaf Nov 10 '14 at 16:20
  • http://en.wikipedia.org/wiki/Schwarz%E2%80%93Christoffel_mapping#Square there appear to be plenty of materials on numerical implementation of these – Will Jagy Nov 10 '14 at 18:16
  • I published a Python package that implements some mappings: pip install squircle –  Oct 18 '21 at 22:32

2 Answers2

3

I've found this implementation to work, using the scipy package in python. The implementation is actually just the 'peirce_map' function at the bottom; the rest of it is to obtain a cn() function that works on complex numbers.

import numpy
from scipy.special import ellipj, ellipk

#
# The scipy implementation of ellipj only works on reals;
# this gives cn(z,k) for complex z. 
# It works with array or scalar input.
#
def cplx_cn( z, k):
    z = numpy.asarray(z)
    if z.dtype != complex:
        return ellipj(z,k)[1]

    # note, 'dn' result of ellipj is buggy, as of Mar 2015
    # see https://github.com/scipy/scipy/issues/3904
    ss,cc = ellipj( z.real, k )[:2]
    dd = numpy.sqrt(1-k*ss**2)   # make our own dn
    s1,c1 = ellipj( z.imag, 1-k )[:2]
    d1 = numpy.sqrt(1-k*s1**2)

    # UPDATE: scipy bug seems to have been fixed mid 2016, so 
    # four lines above could be done as these two, if you have that.
    #   ss,cc,dd = ellipj( z.real, k )
    #   s1,c1,d1 = ellipj( z.imag, 1-k )

    ds1 = dd*s1
    den = (1-ds1**2)
    rx = cc*c1/den
    ry = ss*ds1*d1/den
    return rx - 1j*ry
#
# Kval is the first solution to cn(x,1/2) = 0
# This is K(k) (where 4*K(k) is the period of the function).
Kval = ellipk(0.5) # 1.8540746773013719

#######################################################
# map a complex point in unit square to unit circle
# The following points are the corners of the square (and map to themselves):
#     1    -1     j    -j
#  The origin also maps to itself.
# Points which are in : abs( re(z)) <=1, abs(im(z)) <=1, but outside the square, will map to
# points outside the unit circle, but are still consistent with mapping a full-sphere
# peirce projection to a full-sphere stereographic projection; however that means that
# the corners 1+j, 1-j, -1+j -1-j all map to the 'south pole' at infinity. You will get
# a divide-by-zero, or near to it, at or near those points.
# It works with array or scalar input.
#
def peirce_map( z ):
    return cplx_cn( Kval*(1-z), 0.5 )
greggo
  • 338
  • Thanks! Got here googling for a complex implementation of the Jacobi elliptic function and this did the trick. – Nick Alger Sep 06 '17 at 20:29
1

The $\mathrm{cn}$ function is a Jacobi elliptic function of $z=x+iy$; to get $z$, you require the corresponding inverse Jacobi elliptic function. By analogy with trig functions, these go by $\mathrm{arccn}$, $\mathrm{arcsn}$, etc. For your case, we have $$ z = \mathrm{arccn}\left(\tan\left(\frac{p}{2}\right)e^{i\theta},\frac{1}{2}\right) $$

The inverse Jacobi elliptic function $\mathrm{arccn}$ has an expression in terms of an elliptic integral. In general, it is given by

$$ \mathrm{arccn}\left(a,k\right) = \int_{a}^1 \frac{1}{\sqrt{(1-t^2)(k'^2+k^2t^2)}} dt, $$

where $k' = \sqrt{1-k^2}$ (see here). In your case, $k=1/2$ and so $k'=\sqrt{3}/2$, and $a=\tan\left(\frac{p}{2}\right)e^{i\theta}$. So,

$$ z = \int_{\tan\left(\frac{p}{2}\right)e^{i\theta}}^1 \frac{1}{\sqrt{(1-t^2)\left(\frac{3}{4}+\frac{1}{4}t^2\right)}} dt $$

So, for a given $p$ and $\theta$, you have to crunch that integral numerically. Or, you maybe be able to find a good elliptical integral package that does this for you, for complex arguments. The real part would be your $x$, and the imaginary part your $y$. As a final note, I'm not sure about the value $k=1/2$ from the Wikipedia article; this article seems to use the value of $k=k'=\frac{1}{\sqrt{2}}$.

rajb245
  • 4,755
  • 15
  • 34
  • Awesome answer! And thanks for the link to that article. I was hoping to avoid integrals so I could run my code as a graphics shader, but there's no reason I couldn't just precompute the projection. – bugloaf Nov 10 '14 at 20:25
  • Indeed I agree that the k value you suggest seems correct, since it results in the singularities being at {-1,1,i,-i} which are the points on the circle (equator of the polar conformal proj, which is the space of the '=' of OP's equation) that map to corners of the square; with k=1/2 you have {+/-1,+/- i*sqrt(3) }. The wikipedia formula appears to have been sourced from the paper you have linked (same description of p and w, rendered confusing in the WP due to removal from context ) and originally had k=sqrt(1/2) but the k was 'corrected' in Aug 2012... – greggo Mar 10 '15 at 16:31
  • ... except - the extrema of Im(cm(z,1/2)) along the other diagonal appear to be +/-1 as expected, so, I'm guessing this may be an issue with different conventions about the 2nd parameter of cm.. http://www.wolframalpha.com/input/?i=plot+%5B++cn%281.85+%2B+x%2AI%2C1%2F2%29%5D+from+-2.1+to+2.1 – greggo Mar 10 '15 at 16:44
  • @greggo Good sleuthing regarding the WP page; I did not think to look into the history of that page, but it did strike me that the notation was identical between the two sources. I suspect you're right about conventions for the parameters of these functions; there are always slightly different meanings/normalizations/scalings of what are essentially the same special function. If I get time, I'll implement the projection and visually inspect the results; it should be obvious which is the "correct" $k$ value. – rajb245 Mar 10 '15 at 17:21
  • The definite integral you give -- if I write the bottom right factor as (1/2 + 1/2 t^2) -- seems to exactly match the inverse of cn(z, 1/2), as wolfram evaluates it. – greggo Mar 10 '15 at 23:59