Search code examples
pythonnumpyangle

Complete turn x angle values are mapped to half turn using asin function, how to mirror them back?


I have angles that form a complete turn in an array x, from -90 to 270 e.g. (it may be defined otherwise, like from 0 to 360 or -180 to 180) with step 1 or whatever.

asin function is valid only between -90 and +90.

Thus, angles < -90 or > 90 would be "mapped" between these values.

E.g. y = some_asin_func(over_sin(x)) will end up in an y value that is always between -90 and +90. So y is stuck between -90 and +90.

I do need to retrieve to which x-input is y related, because it's ambiguous yet: for example, the function over (x) will give the same y values for x = 120 and x = 60, or x = -47 and x = 223. Which is not what I want.
Put an other way; I need y making a complete turn as x does, ranging from where x starts up to where x ends.

An image will be better:

original_curves1

Here, x ranges between -90 (left) to 270 (right of the graph).
The valid part of the curve is between x=-90 and x=+90 (left half of the graph).
All other values are like mirrored about y=90 or y=-90.
For x=180 for example, I got y=0 and it should be y=180.
For x=270, I have y=-90 but it should be y=270, thus +360.

Here's a code sample:

A   = 50 # you can make this value vary to have different curves like in the images, when A=0 -> shape is triangle-like, when A=90-> shape is square-like.
x   = np.linspace(-90,270,int(1e3))
u   = np.sin(math.pi*A/180)*np.cos(math.pi*x/180)
v   = 180*(np.arcsin(u))/math.pi
y   = 180*np.arcsin(np.sin(math.pi*x/180)/np.cos(math.pi*v/180))/math.pi
plt.plot(x,y)
plt.grid(True)

Once again, first left half of the graph is completely correct. The right half is also correct in its behavior, but in final, here, it must be mirrored about an horizontal axis at position y=+90 when x>90, like this:

wanted_curves1

That is, it's like the function is mirrored about y=-90 and y=+90 for y where x is out of the range [-90,+90] and only where where x is out of the range [-90,+90].

I want to un-mirror it outside the valid [-90,+90] range:
about y=-90 where y is lower than -90
about y=+90 where y is greater than +90

And of course, modulo each complete turn.

Here an other example where x ranges from -180 to 180 and the desired behavior:

Yet:

original_curves2

Wanted:

wanted_curves2

I have first tested some simple thing up now:

A = 50
x = np.linspace(-180,180,int(1e3))
u = np.sin(math.pi*A/180)*np.cos(math.pi*x/180)
v = 180*(np.arcsin(u))/math.pi 
y = 180*np.arcsin(np.sin(math.pi*x/180)/np.cos(math.pi*v/180))/math.pi
for i,j in np.ndenumerate(x):
    xval = (j-180)%180-180
    if (xval < -90):
        y[i] = y[i]-val
    elif (xval > 90):
        y[i] = y[i]+val

plt.plot(x,y);
plt.grid(True)
plt.show()

which doesn't work at all but I think the background idea is there...
I guess it may be some kind of modulo trick but can't figure it out.


Solution

  • Thank you @Thomas Kühn, it seems fine except I wanted to restrict the function in a single same turn in respect to y-values. Anyway, it's only aesthetics.

    Here's what I found by my side. It's maybe not perfect but it works:

    A = 50
    u = np.sin(math.pi*A/180)*np.cos(math.pi*x/180)
    v = 180*(np.arcsin(u))/math.pi
    y = 180*np.arcsin(np.sin(math.pi*x/180)/np.cos(math.pi*v/180))/math.pi
    for i,j in np.ndenumerate(x):
        val = (j-180)%360-180
        if (val < -90):
            y[i] = -180-y[i]
        elif (val > 90):
            y[i] = 180-y[i]
    

    Here are some expected results:

    Results1

    Range from -180 to +180

    Results1

    Range from 0 to +360

    Results3

    Range from -720 to +720

    Results4

    Range from -360 to +360 with some different A values.

    Funny thing is that it reminds me some electronics diagrams as well.
    Periodic phenomenons are everywhere!