0
votes

I have a set of 3d points (I generate the positions of planets and moons in a stellar system from Keplers equations) I have the coordinates of all points as x,y,z, where the central star is 0,0,0. The code to produce the points works perfectly.

However, at the moment I plot a visualisation of this system from above - so I just ignore the z component for the purposes of visualisation and plot the x and y to the canvas as-is. This works as intended.

How would I generate x and y coordinates for plotting to the canvas that take into account the z coordinate, so that I can plot a view from another angle apart from directly above?

The only library I can use apart from the standard one would be numpy. I cannot use Matplotlib.

edit thanks to the comments I can now clarify with some psudocode.

Assume I have a bunch of points that have an xyz position.

What I currently do:

canvas.plot(point.x)

canvas.plot(point.y)

ignoring point z - so that it is as if all z's are 0 and it is viewed from 'above'

So that I can use my current plotting code - which takes into account scale and offsets to do with the canvas, I need new x and y coordinates that are as if the view is from another angle other than 'above'.

It seems from the helpful comments what I have to do is rotate the whole coordinate system so that it has a new z axis that is a result of a rotation of the whole system about the x and y axis.

Something like the following psudocode would do.

def rotate_about_axis(x_rotation_degrees, y_rotation_degrees, point.x, point.y, point.z):
    new_plot_x = canvas_point_to_plot after magic code to rotate coordinates x_rotation_degrees about x axis
    new_plot_y = canvas_point_to_plot after magic code to rotate coordinates y_rotation_degrees about y axis

return new_plot_x, new_plot_y

Then I could apply this to all the points I plot.

How would I do this in python?

1
How do you currently plot your visualization? - tom10
There are a few ways. The simplest is I just plot the x and y coordinates to a html canvas. I have the z but I don't use it. - deMangler
so you only have access to numpy? Numpy is not a plotting library, how would reckon to plot anything without a graphical back-end? There are other libraries; vispy, plotly, ggplot [...]. Other than a terminal output I am not sure what this post wants. - cvanelteren
I can, and do plot to an html canvas. I could scale apropriately and plot ascii to a text file. Lots of ways are available. That isn't my problem. I just don't know how to produce x and y from the x, y and z, in python. Pretty sure there is a way with numpy. Matplotlib would just do it, but there we go... - deMangler
The basic idea here is to rotate the coordinate system to one where the z-axis is along the view angle that you want, and then plot x' and y' like you currently do. That is, find a rotation matrix R, and multiply all your (x, y, z) points by that. Finding R is the only involved step, but there are numpy examples available, or you could build R from multiple 2D rotations (from R0 = [cos sin 0; -sin cos 0, 0 0 1], or you could use scipy.spatial.transform.Rotation, etc. - tom10

1 Answers

0
votes

I have come up with an answer, I hope it helps someone.

import numpy, math

def rotate_about_axis(x_rotation_degrees, y_rotation_degrees, point_x, point_y, point_z):

    xrads = math.radians(x_rotation_degrees)
    yrads = math.radians(y_rotation_degrees)
    rotation = [xrads, yrads, 0]
    rotation_angle = numpy.linalg.norm(rotation)
    norm_rotation = rotation / numpy.linalg.norm(rotation)
    base_points = [point_x, point_y, point_z]
    points = numpy.dot(base_points, norm_rotation) * norm_rotation
    points_difference = base_points - points
    points_transform = numpy.cross(norm_rotation, base_points)
    rotated_points = points + points_difference * numpy.cos(rotation_angle) + points_transform * numpy.sin(rotation_angle)

    rotated_point_x = rotated_points[0]
    rotated_point_y = rotated_points[1]

    return(rotated_point_x, rotated_point_y)