By which I specifically mean drawing a sphere of arbitrary orientation on an HTML canvas as well as parallels and meridians and points on that sphere specified by latitude and longitude. ---- Let's initially assume that the "arbitrary orientation" of the sphere is restricted to a single angle `alpha`. In other words, the prime meridian is always drawn as a line but the equator may be a line, an ellipse or even a circle (if the sphere is viewed from overhead). ---- For other meridians we're eventually going to need to draw ellipses that are rotated. Here is some code for drawing a rotated ellipse on an HTML canvas: context.save(); context.beginPath(); context.translate(center_x, center_y); context.rotate(rotation); context.scale(radius_a, radius_b); context.arc(0, 0, 1, 0, 2* Math.PI, false); context.restore(); context.stroke(); ---- Drawing lines of latitude is fairly easy. If `cx` and `cy` are the center of the sphere and `r` is the radius... The center of the ellipse for a given latitude is: (cx, cy + r * Math.sin(latitude) * Math.cos(alpha)) the major radius is: r * Math.cos(latitude) and the minor radius is: r * Math.cos(latitude) * Math.sin(alpha) ---- Here is the result: ![latitude.png](/media/140/latitude.png) for an alpha of `Math.PI / 6` ---- Eventually I'll calculate which part of the ellipse is visible to shade the hidden side differently (or not at all) but first I want to work out how to draw the meridians. ---- The only two parameters I believe will vary in the drawing of the ellipses for the meridians are the minor radius (the major radius will always be the same as the radius of the sphere) and the 2D rotation of the ellipse. For the prime meridian, the rotation is `0` and the minor radius is effectively `0` as well. For the meridian at longitude 90º, the rotation is 90º (`Math.PI / 2`) and the minor radius is `Math.cos(alpha)`. ---- This suggests the minor radius could be `r * Math.sin(longitude) * Math.cos(alpha)` and the rotation `longitude` but this doesn't work out for other values. ---- Note that if `alpha` is `0` then the rotation of the ellipses has to basically be `0` too. ---- And if `alpha` is `Math.PI / 2` (top down view), the rotation of the ellipses would be `longitude`. ---- This has me somewhat confused (concerned?) because I think the rotation of the ellipse for the 90º meridian, regardless of `alpha`, is actually always `Math.PI / 2` (which, for circles is the same as `0` hence why it works for an `alpha` of `0`). ---- What other constraints can be said to exist on the meridians? Well, they have to pass through the poles and the center has to be the center of the sphere. I wonder if those facts alone can be used to derive the ellipse rotation and minor radius given only the longitude (as `alpha` determines the position of the poles). ---- The equation of an ellipse rotated by `A` is ((x * cos(A) + y * sin(A)) / a) ** 2 + ((x * sin(A) - y * cos(A)) / b) ** 2 == 1 We know the `(x, y)` of two points (the poles) and the major radius `a` so, in theory we could solve for `A` and `b`, the two parameters we need. ---- Just plugging in numbers and seeing what looks good, a minor radius and rotation of the form: r * Math.sin(t) * Math.cos(alpha) and Math.sin(alpha) * t work very well for high `alpha` and low `t` but get progressively worse as `alpha` approaches zero or `t` approaches `Math.PI / 2`. `t` here could be longitude but I'm not yet committing to that, it may just be something derived from longitude. ---- Based on the previous card, this works surprisingly well for the minor radius: r * Math.sin(Math.sin(t) * Math.cos(alpha)) but it still isn't quite right. ---- It just occurred to me that the rotation of the great circle ellipse is the same as the latitude it touches on the edge of the sphere. With a non-zero `alpha`, the vertical offset of the latitude line, as shown earlier, is: r * Math.sin(latitude) * Math.cos(alpha) Which means the rotation of the great circle that touches that latitude is Math.asin(Math.sin(latitude) * Math.cos(alpha)) ---- Although looking at this (with a line instead of the ellipse) ![great-circle-latitude.png](/media/141/great-circle-latitude.png) I wonder if that's correct :-( ---- This shows the problem more clearly: ![mismatch2.png](/media/147/mismatch2.png) ---- I might have to resort to drawing ellipses as points under a 3D transform rather than attempting to do everything with canvas `arc`. ---- Here's a sphere (`alpha` of `Math.PI / 6`) with latitude lines drawn not with `arc` but with individual points transformed: ![latitude-manual.png](/media/149/latitude-manual.png) ---- Now drawing lines of longitude are trivial ![lat-long.png](/media/150/lat-long.png) ---- And with the transform approach, it's also very easy to do hidden point elimination: ![hidden.png](/media/151/hidden.png) ---- I'll have to test whether this is fast enough for my needs but, while I do want to solve the `arc`-based approach at some point, this will let me move forward easily with what I want to use this for. Source code will be on Github shortly. ---- The drag controls aren't right yet but here's where I'm at with the sphere drawing: