convert2DPointToSphereCoordinates function

GlobeCoordinates? convert2DPointToSphereCoordinates(
  1. Offset hoverOffset,
  2. Offset sphereCenter,
  3. double radius,
  4. double rotationY,
  5. double rotationZ,
)

Converts the 2D offset to spherical coordinates.

Takes hoverOffset, sphereCenter, radius, rotationY, and rotationZ as input parameters. hoverOffset is the 2D position of the point on the screen. sphereCenter is the center of the sphere. radius is the radius of the sphere. rotationY and rotationZ are rotation angles around the Y and Z axes, respectively.

Returns a GlobeCoordinates object representing the spherical coordinates of the point. Returns null if the point is not on the sphere.

Implementation

GlobeCoordinates? convert2DPointToSphereCoordinates(Offset hoverOffset,
    Offset sphereCenter, double radius, double rotationY, double rotationZ) {
  // Convert 2D screen coordinate to 3D position relative to center
  double y = hoverOffset.dx - sphereCenter.dx;
  double z = -(hoverOffset.dy - sphereCenter.dy);

  // Check if the point is within the circle in 2D
  double distSq = y * y + z * z;
  if (distSq > radius * radius) return null;

  // Derive X coordinate from the sphere's equation: x^2 + y^2 + z^2 = R^2
  // We take the positive root because it's the front of the sphere (facing the camera)
  double x = sqrt(radius * radius - distSq);

  Vector3 currentVec = Vector3(x, y, z);

  // Undo the rotation in reverse order: first undo Z, then undo Y
  Matrix4 undoRotation = Matrix4.identity()
    ..rotateZ(rotationZ)
    ..rotateY(rotationY);

  Vector3 originalVec = undoRotation.transform3(currentVec);

  // Convert back to latitude and longitude
  // lat = asin(z / R)
  // lon = atan2(y, x)
  double latRad = asin((originalVec.z / radius).clamp(-1.0, 1.0));
  double lonRad = atan2(originalVec.y, originalVec.x);

  return GlobeCoordinates(radiansToDegrees(latRad), radiansToDegrees(lonRad));
}